[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*.{csproj,props,targets}]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Set the default behavior, in case people don't have core.autocrlf set.\n* text=auto\n\n# Keep LF in shell scripts\n*.sh text eol=lf\n\n# Preserve line endings in gradle scripts\ngradlew* -text diff\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build UnrealLink\non:\n  push:\n    branches: [ 'net212**' ]\n    paths-ignore:\n      - src/rider/test\n      - testData\n      - README.md\n      - CHANGELOG.md\n  pull_request:\n    branches: [ 'net212**' ]\n    paths-ignore:\n      - src/rider/test\n      - testData\n      - README.md\n      - CHANGELOG.md\n  workflow_dispatch:\n    inputs:\n      arguments:\n        description: 'Additional attributes to gradle buildPlugin'\n        required: false\n        default: ''\njobs:\n  build:\n    name: ${{ matrix.config.name }}\n    runs-on: ${{ matrix.config.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        config:\n        - { name: \"Windows Latest\", artifact-prefix: \"UnrealLink-\",\n            os: windows-latest,\n            SEP: \\ }\n\n    # Steps represent a sequence of tasks that will be executed as part of the job\n    steps:\n      - uses: actions/checkout@v2 # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it\n      - uses: actions/cache@v2\n        with:\n          path: ~/.gradle/caches\n          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}\n          restore-keys: ${{ runner.os }}-gradle-\n\n      - name: Build Plugin\n        run: gradlew.bat buildPlugin -PbuildCounter=${{ github.run_number }} -PbuildConfiguration=Release ${{ github.event.inputs.arguments }}\n        shell: cmd\n\n      - name: Upload artifacts\n        if: success()\n        uses: actions/upload-artifact@v2\n        with:\n          name: ${{ matrix.config.artifact-prefix }}artifacts\n          path: output/**\n"
  },
  {
    "path": ".gitignore",
    "content": "# Build artifacts\n[Bb]in/\n[Oo]bj/\nbuild\noutput\n.gradle\n.tmp\nout/*\n*.generated.*\nNuGet.Config\n\n# User-specific files\n*.suo\n*.user\n*.sln.docstates\n*.sln.binlog\n*.cache\n\n# IDEs\n.idea\n.vs\n_ReSharper*\n_dotTrace*\n\n# Unreal Plugin generated files\nsrc/cpp/RiderLink/RiderLink.uplugin\nsrc/cpp/RiderLink/checksum\nsrc/cpp/RiderLink/Binaries\nsrc/cpp/RiderLink/Intermediate\nsrc/cpp/RiderLink/Source/RiderLink/Public/Model\n# rd-cpp extra files\nCMakeLists.txt\nsrc/cpp/RiderLink/Source/RD/**/.*\nsrc/cpp/RiderLink/Source/RD/**/*.yml\nsrc/cpp/RiderLink/Source/RD/**/test\nsrc/cpp/RiderLink/Source/RD/**/tests\nsrc/cpp/RiderLink/Source/RD/**/bench\nsrc/cpp/RiderLink/Source/RD/**/example\nsrc/cpp/RiderLink/Source/RD/**/pch.*\nsrc/cpp/RiderLink/Source/RD/**/INSTALL\nsrc/cpp/RiderLink/Source/RD/**/doxygen.conf\n\n# Local setup specific files\nUnrealEngineProjectPath.txt\ndependencies/*\n/.intellijPlatform/\n\n# Tmp release files\nrelease_notes.md\n\n# Zipper\ntools/Zipper/*\n!tools/Zipper/Program.cs\n!tools/Zipper/Zipper.csproj\n!tools/Zipper/Zipper.sln\n/src/cpp/RiderLink/Resources/checksum\n"
  },
  {
    "path": ".run/Debug backend.run.xml",
    "content": "<component name=\"ProjectRunConfigurationManager\">\n  <configuration default=\"false\" name=\"Debug backend\" type=\"RunNativeExe\" factoryName=\"Native Executable\">\n    <option name=\"EXE_PATH\" value=\"$PROJECT_DIR$/gradlew.bat\" />\n    <option name=\"PROGRAM_PARAMETERS\" value=\"runIde\" />\n    <option name=\"WORKING_DIRECTORY\" value=\"$PROJECT_DIR$\" />\n    <option name=\"PASS_PARENT_ENVS\" value=\"1\" />\n    <envs>\n      <env name=\"RESHARPER_HOST_DEBUG_SELF\" value=\"1\" />\n    </envs>\n    <option name=\"USE_EXTERNAL_CONSOLE\" value=\"0\" />\n    <method v=\"2\">\n      <option name=\"Build Solution\" enabled=\"true\" />\n    </method>\n  </configuration>\n</component>"
  },
  {
    "path": ".run/UnrealLink [runIde].run.xml",
    "content": "<component name=\"ProjectRunConfigurationManager\">\n  <configuration default=\"false\" name=\"UnrealLink [runIde]\" type=\"GradleRunConfiguration\" factoryName=\"Gradle\">\n    <ExternalSystemSettings>\n      <option name=\"executionName\" />\n      <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n      <option name=\"externalSystemIdString\" value=\"GRADLE\" />\n      <option name=\"scriptParameters\" value=\"\" />\n      <option name=\"taskDescriptions\">\n        <list />\n      </option>\n      <option name=\"taskNames\">\n        <list>\n          <option value=\"runIde\" />\n        </list>\n      </option>\n      <option name=\"vmOptions\" />\n    </ExternalSystemSettings>\n    <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>\n    <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>\n    <DebugAllEnabled>false</DebugAllEnabled>\n    <RunAsTest>false</RunAsTest>\n    <method v=\"2\" />\n  </configuration>\n</component>"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0). Note that this project does not follow\nsemantic versioning but uses version numbers based on JetBrains [Rider](https://www.jetbrains.com/rider/) releases.\n\nThis plugin contains a plugin for the Unreal Editor (RiderLink) that is used to communicate with Rider. Changes marked\nwith a \"Rider:\" prefix are specific to Rider, while changes for the Unreal Editor plugin are marked with a \"Unreal\nEditor:\" prefix. No prefix means that the change is common to both Rider and ReSharper.\n\nThe plugin is always bundled with Rider.\n\n## [Unreleased]\n\n## [2023.1.0.282]\n\n### Fixed\n\n- [RIDER-93789](https://youtrack.jetbrains.com/issue/RIDER-93789)\n\n## [2023.1.0.188]\n\n### Fixed\n\n- Navigating from Rider to Unreal Editor for DataAssets\n\n## [2022.3.0.200]\n\n### Changed\n\n- Add option to specify intermediate folder for building RiderLink plugin (File | Settings | Languages & Frameworks | Unreal Engine). \n  - If you have non-ASCII symbols in the path, your RiderLink build might fail.\n- Add option to specify behavior of the auto-update\n  - Select between automatically building and installing plugin, or simply extracting sources of RiderLink and building them yourselves\n  - Extracting plugin might be a better option for RiderLink installed in the Game projects, or Engine project built from the sources\n\n### Fixed\n\n- Support installing RiderLink into the pre-built version of the UE5 (eg installed through Epic Games Launcher) \n  - From now on, RiderLink will be installed in the `Engine/Plugins/Marketplace/Developer/RiderLink` folder, if you chose to install it in the Engine\n- Initially, RiderLink will be installed into `Plugins/Developer/RiderLink` for Game project and `Engine/Plugins/Marketplace/Developer/RiderLink` for Engine project, but if you wish to move it to another folder, Rider will take into the account the new location and will be updating the plugin in place.\n\n## [2022.3.0.178]\n\n### Changed\n\n- Disable installation to Engine for UE 5\n  - [RIDER-71374](https://youtrack.jetbrains.com/issue/RIDER-71374)\n\n- Unreal log panel was made more consistent with output log window in Unreal Editor\n  - Log categories are now sorted in popup ([RIDER-61132](https://youtrack.jetbrains.com/issue/RIDER-61132))\n  - Log verbosity and category popups do not hide on item toggling\n  - Full log messages are colorized, not only category name\n\n### Fixed\n\n- Fix [RIDER-69165](https://youtrack.jetbrains.com/issue/RIDER-69165)\n- Fix [DEXP-642989](https://youtrack.jetbrains.com/issue/DEXP-642989)\n\n## [2021.2.1.4]\n\n### Fixed\n\n- Fix [RIDER-66784](https://youtrack.jetbrains.com/issue/RIDER-66784)\n- Possibly fix [RIDER-67192](https://youtrack.jetbrains.com/issue/RIDER-67192)\n\n## [2021.2.1.3]\n\n### Fixed\n\n- [GITHUB-135](https://github.com/JetBrains/UnrealLink/issues/135)\n\n## [2021.2.1.2]\n\n### Fixed\n\n- [GITHUB-135](https://github.com/JetBrains/UnrealLink/issues/135)\n\n## [2021.2.1.1]\n\n### Changed\n\n- Sending logs from Unreal Editor to Rider moved to separate thread, less load on UE UI thread\n\n### Fixed\n\n- [RIDER-68865](https://youtrack.jetbrains.com/issue/RIDER-68865)\n- Unreal log messages are not limited anymore with 4KB size\n\n## [2021.2.0.659]\n\n### Fixed\n\n- Finally fix for [GITHUB-99](https://github.com/JetBrains/UnrealLink/issues/99)\n- as well as [GITHUB-97](https://github.com/JetBrains/UnrealLink/issues/97)\n- Number of fixes for clashing \"Project Model Generation\" with \"Building RiderLink\" actions blocking UnrealBuildTool.\n  They don't have dedicated issues in YT or GH, but has producing annoying results like:\n    - \"can't generate project model, because UBT is running\" message;\n    - Building RiderLink and failing would leave a hanging UBT process.\n\n### Known Issues\n\n## [2021.1.12]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- HOTFIX building RideLink on MacOS\n\n### Known Issues\n\n## [2021.1.11]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- [RIDER-63716](https://youtrack.jetbrains.com/issue/RIDER-63716)\n- [RIDER-63584](https://youtrack.jetbrains.com/issue/RIDER-63584)\n- [RIDER-64422](https://youtrack.jetbrains.com/issue/RIDER-64422)\n- [GITHUB-109](https://github.com/JetBrains/UnrealLink/issues/109)\n- [GITHUB-112](https://github.com/JetBrains/UnrealLink/issues/112)\n- Possible fix for [GITHUB-99](https://github.com/JetBrains/UnrealLink/issues/99)\n- Fix build RiderLink for UE5 main branch\n\n### Known Issues\n\n## [2021.1.10]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- [RIDER-63716](https://youtrack.jetbrains.com/issue/RIDER-63716)\n- [RIDER-63584](https://youtrack.jetbrains.com/issue/RIDER-63584)\n- [GITHUB-109](https://github.com/JetBrains/UnrealLink/issues/109)\n- Possible fix for [GITHUB-99](https://github.com/JetBrains/UnrealLink/issues/99)\n- Fix build RiderLink for UE5 main branch\n\n### Known Issues\n\n## [2021.1.9]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- [RIDER-63716](https://youtrack.jetbrains.com/issue/RIDER-63716)\n- [RIDER-63584](https://youtrack.jetbrains.com/issue/RIDER-63584)\n- [GITHUB-109](https://github.com/JetBrains/UnrealLink/issues/109)\n- Possible fix for [GITHUB-99](https://github.com/JetBrains/UnrealLink/issues/99)\n- Fix build RiderLink for UE5 main branch\n\n### Known Issues\n\n## [2021.1.8]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Possible fix for https://youtrack.jetbrains.com/issue/RIDER-62012\n    - UE crashing on exit in RiderLink\n- Fix building RiderLink on UE5\n- Fix https://github.com/JetBrains/UnrealLink/issues/93\n\n### Known Issues\n\n## [2021.1.7]\n\n### Added\n\n- Option to cancell installation of RiderLink\n\n### Changed\n\n### Deprecated\n\n- Dropped support for versions of UE 4.22 and older\n\n### Removed\n\n### Fixed\n\n- Fixed [Rider-51111](https://youtrack.jetbrains.com/issue/RIDER-51111)\n- Fixed installation on macOS\n- Failing to install RiderLink due to other UBT processes running\n\n### Known Issues\n\n## [2021.1.6]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fixed [Rider-51111](https://youtrack.jetbrains.com/issue/RIDER-51111)\n- Fixed installation on macOS\n\n### Known Issues\n\n## [2021.1.5]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fixed [Rider-51111](https://youtrack.jetbrains.com/issue/RIDER-51111)\n- Fixed installation on macOS\n\n### Known Issues\n\n## [2021.1.4]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fixed potential issues with inconsistent protocol state on disconnects\n    - Reinitialize protocol each time\n- Fixed bunch of issues with game control actions\n    - Use PIE actions logic from UE4 instead of reimplementing it\n    - Actions are no more stuck in disabled state after engine unexpected shutdowns\n\n### Known Issues\n\n- \"Compile before play\" option is not properly supported\n- Actions visibility and availability states are not synchronized with editor\n\n## [2021.1.3]\n\n### Added\n\n- Disabling Play and Play settings button after press\n    - Rider should reflect state of Unreal Editor. Play buttons should change only when Unreal Editor notifies that they\n      have changed\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fix: sync state of play buttons and play settings buttns between Rider and Unreal Editor\n- Fix: don't install RiderLink into `UnrealLaunchDaemon` project\n\n### Known Issues\n\n## [2021.1.2]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Exception on generitng project files during installation of RiderLink plugin\n- Rider not being able to connect to Unreal Editor\n\n### Known Issues\n\n## [2021.1.1]\n\n### Added\n\n- Support MacOS and Linux\n- Installing RiderLink plugin logs show in Build panel\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n### Known Issues\n\n## [2020.3.116]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fix https://github.com/JetBrains/UnrealLink/issues/62\n\n### Known Issues\n\n## [2020.3.113]\n\n### Added\n\n### Changed\n\n- Build RiderLink plugin from source on user PC instead of bundling dll files.\n    - Reason: frequent changes of toolchains and breaking of ABI compatibility in MSVC toolchain render this practice\n      impossible.\n\n### Deprecated\n\n- Drop support for UE 4.21 and older\n    - Reason: RD framework doesn't use PCH files and doesn't comply with UE rules for include files. It's impossible to\n      state that module doesn't use PCH files in UE 4.21 and older.\n\n### Removed\n\n### Fixed\n\n### Known Issues\n\n## [2020.3.104]\n\n### Added\n\n- Proper README for the https://github.com/JetBrains/UnrealLink\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fix memory leak in log panel on exit of Rider\n- Fix deprecated code\n\n### Known Issues\n\n## [2020.3.85]\n\n### Added\n\n- Supported Rider 2020.3\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n### Known Issues\n\n## [2020.2.83]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- More fixes to https://youtrack.jetbrains.com/issue/RIDER-50354\n\n### Known Issues\n\n## [2020.2.79]\n\n### Added\n\n- More info and notifications when RiderLink can't be built\n- Unable auto-update plugin from JetBrains Marketplace\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n- Removed verbose log messages from RD framework in stdout\n\n### Fixed\n\n- Fix https://youtrack.jetbrains.com/issue/RIDER-50354\n- Fix corrupted hyperlinks after toggling timestamps\n\n### Known Issues\n\n## [2020.2.69]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fix https://github.com/JetBrains/UnrealLink/issues/46\n\n### Known Issues\n\n## [2020.2.67]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fix showing popup \"update project file\" after installing RiderLink\n    - After pressing \"update project file\", it'd update {GameProject}.uproject file, adding reference to RiderLink. This\n      is not necessary for RiderLink to work properly, but it'll break project for people that will sink to\n      {GameProject}.uproject, but who doesn't have RiderLink installed\n\n### Known Issues\n\n## [2020.2.66]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fix https://github.com/JetBrains/UnrealLink/issues/40\n- Fix https://youtrack.jetbrains.com/issue/RIDER-47839\n\n### Known Issues\n\n## [2020.2.62]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fixed: https://github.com/JetBrains/UnrealLink/issues/19\n\n### Known Issues\n\n## [2020.2.61]\n\n### Added\n\n- Unreal log filters\n    - Verbosity\n    - Category\n    - Show/hide timestamps\n\n### Changed\n\n- Generated files for RD protocol will have \".Generated.h\" suffix\n\n### Deprecated\n\n### Removed\n\n- Packing plugin for ReSharper\n    - Not supported yet\n\n### Fixed\n\n- Fixed: building RiderLink with Unity build disabled\n- Fixed: Wording in \"Install RiderLink\" popup\n- Fixed: Wording in UnrealEngine settings\n    - No more auto-install plugin, only auto-update plugin\n\n### Known Issues\n\n## [2020.2.36]\n\n### Added\n\n### Changed\n\n- rd-cpp updated to 201.1.85\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fixed stackoverflow crash on exit of Unreal Editor\n\n### Known Issues\n\n## [2020.2.34]\n\n### Added\n\n### Changed\n\n- move plugin installation in backend thread - no more freeze of UI when installing RiderLink\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- fix loading RiderLink plugin on cooking\n- fix crash on closing UnrealEditor in RiderLoggingExtension\n- fixed number of problems discovering Unreal Editor installation, should fix a lot of false failing installations of\n  RiderLink\n- fix wording in RiderLink settings panel ( auto update and install -> auto update)\n- fix UnrealBuildTool removing EnableByDefault: true from RiderLink.uplugin\n    - No more modification of {GameName}.uproject file to enable RiderLink\n\n### Known Issues\n\n## [2020.1.10]\n\n### Added\n\n- Add option to install plugin to either Engine or Game\n    - Installing to Engine from EGS requires building plugin\n    - Old versions of plugins will be backed up\n    - New version will be copied to %USER% folder and built\n    - Result binaries copyied to Engine or Game\n    - Sln will be refreshed\n    - In case of errors, all the results will be reverted\n\n### Changed\n\n- Moved thirdparty dependencies of RD to submodules, fixed build.kts for it\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- [Extremely long log entry causes RiderLink to lose connection to Unreal Engine](https://github.com/JetBrains/UnrealLink/issues/17)\n- Fix looking for Unreal Engine root when Game is placed in the same folder as Engine\n- Fix RiderLink for non-Unity builds\n\n### Known Issues\n\n## [2020.1.8]\n\n### Added\n\n- Add progress bar when installing \"RiderLink\" plugin\n- Hide notification suggesting installing RiderLink after selecting \"Install plugin\"\n- [Add option to Compile Game Project before starting PIE](https://github.com/JetBrains/UnrealLink/issues/9)\n\n### Changed\n\n- Installation to Engine instead of game Project\n    - [Add option to install RiderLink to Engine instead of Game Project](https://github.com/JetBrains/UnrealLink/issues/7)\n    - During installation process, RiderLink will be built and put into correct folder\n    - No more gimmicks with \"build plugin in Game project, then copy-paste it in Engine project\"\n- Refactored \"RiderLink\"\n    - Separated \"RiderLink\" into separate module with different loading steps\n    - e.g. For \"RiderLink', start as soon as possible, for \"RiderLinkGameControlExtension\" start after Unreal Editor is\n      fully loaded, etc\n    - Fixed all warnings (TEXT macro redefined, obsolete API, etc)\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Lower verbosity of RD protocol logger\n    - Less noise in debug console\n- [Build on non-unity projects](https://github.com/JetBrains/UnrealLink/issues/10)\n- [Exception during installation of RiderLink](https://github.com/JetBrains/UnrealLink/issues/5)\n- [Multiple popups suggesting installing RiderLink](https://youtrack.jetbrains.com/issue/RIDER-43928)\n- Bunch of issues:\n    - https://youtrack.jetbrains.com/issue/RIDER-44056\n    - https://youtrack.jetbrains.com/issue/RIDER-44027\n    - https://youtrack.jetbrains.com/issue/RIDER-43929\n\n### Known Issues\n\n## [2020.1.7]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- [Incorrect time in log](https://github.com/JetBrains/UnrealLink/issues/8)\n- [Infinite process: RiderLink Discovering Asset Data](https://youtrack.jetbrains.com/issue/RIDER-43353)\n- Spawn of multiple tabs when sending huge log message from Unreal Editor to Rider\n\n### Known Issues\n\n## [2020.1.6]\n\n### Added\n\n- FileWatcher initialization moved to separate thread, speed up startup time for plugin on RIder side\n- New icons for Play actions and connection status\n\n### Changed\n\n- Cleaned up severity of internal logs\n    - Were polluting package logs\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Connecting to Unreal Editor when plugin is installed in Engine\n\n### Known Issues\n\n## [2020.1.5]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- [Cant close Unreal log window](https://github.com/JetBrains/UnrealLink/issues/2)\n    - Disabled spawning multiple tabs for logs. Only one log tab for Unreal Editor log will be available at all times\n- [Rider installs plugins to Programs](https://github.com/JetBrains/UnrealLink/issues/6)\n- [Exception: The process cannot access the file because it is being used by another process](https://github.com/JetBrains/UnrealLink/issues/5)\n- [Crash in RiderLink when packaging project](https://github.com/JetBrains/UnrealLink/issues/4)\n\n### Known Issues\n\n## [2020.1.4]\n\n### Added\n\n- Option to enable auto-update Unreal Editor (RiderLink) plugin\n- Notification after plugin installation\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Not finding uproject files on loading solution\n- [UnrealLink plugin generates wrong sln for Rocket builds of UE](https://github.com/JetBrains/UnrealLink/issues/1)\n\n### Known Issues\n\n## [2020.1.2]\n\n### Added\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n- Fixed: when adding RiderLink plugin to project, Rider would regenerate sln and It would add Programs folder to\n  solution tree for Rocket builds (UE from EGS)\n- Fixed: building plugin on v4.20+\n- Fixed: Use user temp folder instead of the project folder for intermediate file operations to avoid asking for\n  elevated options\n\n### Known Issues\n\n## [2020.1.1]\n\n### Added\n\n- Open Blueprints from Rider\n- Show logs of Unreal Editor inside Rider with hyperlinks to Blueprints inside Rider\n- Toolbar buttons to control playback of the game inside Unreal Editor\n    - Play, Pause, Stop, Skip frame;\n    - Setup multiplayer: number of players, dedicated server, etc.\n- Notification if connection to Unreal Editor is established or not (bottom right corner of status bar);\n- Auto-install plugins in project;\n    - Setting to enable auto-install (`true` by default).\n    - If auto-install is disabled - notification will show up with quick-fix action.\n\n### Changed\n\n### Deprecated\n\n### Removed\n\n### Fixed\n\n### Known Issues\n\n- Service for opening assets in Unreal Editor has changed starting with UE 4.24 - opening same BP multiple times will\n  open multiple tabs instead of re-using already opened one;\n- Icon for connection status looks weird, waiting for new icons from designers\n- Connecting to multiple instances of Unreal Editor is not working correctly\n    - Toolbar controls will be affecting only the last connected editor\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "## Code of Conduct\n\nThis project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). Please make sure you read it. \n"
  },
  {
    "path": "License.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        https://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       https://www.apache.org/licenses/LICENSE-2.0.txt\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "README.md",
    "content": "[![official JetBrains project](https://jb.gg/badges/official-flat-square.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)\n\n# UnrealLink for Unreal Engine\n\n<p>The UnrealLink plugin enables advanced integration between JetBrains <a href=\"https://www.jetbrains.com/lp/rider-unreal/\">Rider</a> and Epic Games’ <a href=\"https://www.unrealengine.com/en-US/\">Unreal Editor</a>.</p>\n\n<p>Rider is a fast and powerful IDE for Unreal Engine and C++ development. It provides rich code navigation, inspections, refactorings, understands Blueprints and the Unreal Engine reflection mechanism, and supports HLSL.</p>\n\n<p>The plugin brings Blueprints information to the editor, adds settings to manage game launch, and provides a more convenient version of the Unreal Editor log.</p>\n\n<ul>\n    <li>\n        <a href=\"#plugin-structure\">Plugin structure</a>\n    </li>\n    <li>\n        <a href=\"#installation\">Installation</a>\n    </li>\n    <li>\n        <a href=\"#contribution\">Contribution</a>\n    </li>\n    <li>\n        <a href=\"#features\">Features</a>\n    </li>\n    <li>\n        <a href=\"#what-could-possibly-go-wrong\">What could possibly go wrong?</a>\n    </li>\n</ul>\n \n<h2 id=\"plugin-structure\">Plugin structure</h2>\n<p>There are two plugins under the hood, the <strong>UnrealLink</strong> plugin for Rider and the <strong>RiderLink</strong> plugin for Unreal Editor, packed together.</p>\n\n<h2 id=\"installation\">Installation</h2>\n<p><strong>UnrealLink</strong> is bundled with Rider and also distributed via the JetBrains plugin <a href=\"https://plugins.jetbrains.com/plugin/14989-unreal-link\">marketplace</a>.</p>\n\n<p><strong>RiderLink</strong> is installed by Rider itself, there is no need to install it manually. The first time you open an Unreal Engine project in Rider, you'll see a notification that the RiderLink plugin is missing and an invitation to install it. If you skip this popup message, you can install the plugin later by going to the Rider settings on the <em>Languages and Frameworks | Unreal Engine</em> page.</p>\n\n<p>Both the popup message and the settings page offer two installation options:</p>\n<ul>\n    <li>\n        <em>Engine</em>: Select this option to install the plugin in the engine and use it for all game projects based on the current engine version. The plugin will appear in the <code>Engine/Plugins/Developer</code> folder.\n    </li>\n    <li>\n        <em>Game</em>: Select this option to install the plugin in the game project and use it for the current project only. The plugin will appear in the <code>Game/Plugins/Developer</code> folder.\n    </li>\n</ul>\n\n<h2 id=\"contribution\">Contribute to the plugin</h2>\n<p>We love contributions! If you want to contribute to the UnrealLink plugin, fork this repository and follow the instructions on <a href=\"SETUP.md\">how to set up a development environment</a>.</p>\n\n<h2 id=\"features\">Features</h2>\n<h3 id=\"interact_with_blueprints\">Interact with blueprints</h3>\n<p>Blueprint files are written in binary form and are usually edited visually. However, they contain a whole lot of useful information for the developers of the C++ part of the game.</p>\n\n<p>Rider reads Blueprints and allows you to see the bigger picture behind your code:</p>\n<ul>\n    <li>\n        There may be derived blueprint classes, which you can see by invoking <em>Find Usages</em> on a C++ class or when you're browsing your C++ code in the editor.\n    </li>\n    <li>\n        You can see the values of overridden properties.\n    </li>\n</ul>\n\n<p>UnrealLink extends this functionality and introduces the ability to navigate to the Blueprint inside the Unreal Editor from your C++ code.</p>\n<img alt=\"Interact with blueprints\" width=\"800\" src=\"https://plugins.jetbrains.com/files/14989/screenshot_23450.png\"/>\n\n<h3 id=\"manage_the_game\">Manage the game</h3>\n<p>The plugin allows you to manage your game right inside the IDE: select the running mode, run a server for your multiplayer game, specify the number of players, and more.</p>\n<img alt=\"Manage the game\" width=\"800\" src=\"https://plugins.jetbrains.com/files/14989/screenshot_23451.png\"/>\n\n<h3 id=\"browse_the_unreal_editor_log\">Browse the Unreal Editor log</h3>\n<p>UnrealLink offers you an enhanced version of the Unreal Editor log output panel with colored text for easy reading, as well as verbosity and event category filters. You can also click on any highlighted link to navigate to the related source code line.</p>\n<img alt=\"Browse the Unreal Editor log\" width=\"800\" src=\"https://plugins.jetbrains.com/files/14989/screenshot_23452.png\"/>\n\n<a href=\"https://www.jetbrains.com/help/rider/Working_with_Unreal_Engine.html\">Learn more about Rider for Unreal Engine >></a>\n\n<h2 id=\"what-could-possibly-go-wrong\">What could possibly go wrong?</h2>\n<p>The plugin and Rider for Unreal Engine itself are in active development now, so there could be some issues. Please share your feedback and report any bugs you encounter:</p>\n<ul>\n    <li>\n        Submit plugin-specific issues to the <a href=\"https://github.com/JetBrains/UnrealLink/issues\">GitHub Issues page</a>.\n    </li>\n    <li>\n        Rider-specific issues should be directed to the <a href=\"https://youtrack.jetbrains.com/issues/RIDER\">Rider tracker</a>.\n    </li>\n    <li>\n        Send a message with any questions and feature suggestions to our support engineers and the Rider for Unreal Engine developers at <a href=\"mailto:rider-cpp-support@jetbrains.com\">rider-cpp-support@jetbrains.com</a>. We really love hearing from you!\n    </li>\n</ul>\n\n<p>A few typical issues, and what to do in such cases:</p>\n\n<h5 id=failed_build>Failed to build RiderLink plugin</h5>\n\n```\nFailed to build RiderLink plugin\nCheck build logs for more info\nHelp > Diagnostic Tools > Show Log in Explorer\nAnd contact dev team for help at GitHub Issues page\n```\n\n<p>There are several reasons you might get this message:</p>\n<ul>\n    <li>\n        There’s a problem with your current Game or Unreal Engine code. Please make sure that you can build them correctly.\n    </li>\n    <li>\n        You have an instance of Unreal Editor with the RiderLink plugin running. Please close Unreal Editor and try installing RiderLink again.\n    </li>\n    <li>\n        Finally, if Unreal Editor is closed and your project builds fine, and you have an old version of RiderLink installed, please move the old version of RiderLink to a temp folder manually and try reinstalling RiderLink.\n    </li>\n</ul>\n\n<h5 id=failed_backup>Failed to backup old plugin</h5>\n\n```\nFailed to backup old plugin\nClose all running instances of Unreal Editor and try again\nPath to old plugin:\n```\n\n<p>You tried to install a new version of RiderLink while you have a running instance of Unreal Editor with the plugin installed. Please close Unreal Editor and try again to install the plugin.</p>\n\n<h5 id=failed_refresh>Failed to refresh project files</h5>\n\n<p>This warning message means that installation was successful, but updating the project files in Rider failed. Everything should work fine, except the plugin will not appear in the <code>/Plugins/Developer</code> folder in the Explorer view.</p>\n\n<p>If you have any issues with the plugin that you can’t resolve, please contact the developers via <a href=\"https://github.com/JetBrains/UnrealLink/issues\">GitHub Issues</a>.</p>\n"
  },
  {
    "path": "SETUP.md",
    "content": "<h1>Setting up development environment</h1>\n\n<p>After cloning the repository, you need to perform some actions to set up the environment.</p>\n\n<h2>[TBD] Setting up UnrealLink frontend</h2>\n\n<h2>Setting up UnrealLink backend</h2>\n<ul>\n    <li>    \n        Run the console under the folder where you have cloned the repository.\n        <p><strong>NOTE:</strong> Make sure that you have Java installed on your machine and you have environmental variable JAVA_HOME set to the value of the path to your JDK folder. Otherwise, it won't work.</p>\n    </li>\n    <li>\n        Use the following command <code>gradlew buildResharperHost</code> to install all the requirements for proper work\n    </li>\n</ul>\n<p>Here you go! Now you can open UnrealLink.sln and work on backend code.</p>\n\n<h2>Setting up RiderLink, Unreal Editor plugin</h2>\n<p>Code for the Unreal Editor part is stored inside UnrealLink repository, but in order to work with cpp code, it should be a part of Unreal Engine project.\nAs a workaround, we provide an option to create a junction from RiderLink source folder to Unreal Engine game project.\nThat way, when you make changes to RiderLink plugin inside Unreal Engine project, they will be picked up automatically in git.</p>\n<ul>\n    <li>Run the console under the folder where you have cloned the repository</li>\n    <li>Use the following command <code>gradlew symlinkPluginToUnrealProject</code>\n        <ul>\n            <li>It will fail the first time with the message \"Add path to a valid UnrealEngine project folder to: {UnrealLinkRoot}\\UnrealEngineProjectPath.txt\"</li>\n            <li>and will create \"UnrealEngineProjectPath.txt\" for you.</li>\n        </ul>\n    </li>\n    <li>Add path to the root folder of your game project into \"UnrealEngineProjectPath.txt\" eg \"D:/PROJECTS/UE/basic_4_26\"</li>\n    <li>Run <code>gradlew symlinkPluginToUnrealProject</code> again.</li>\n    <li>Refresh project files for your Game project</li>\n</ul>\n<p>RiderLink plugin will be available under <code>{GameProjectRoot}/Plugins/Development/RiderLink</code></p>\n\n\n\n"
  },
  {
    "path": "SdkBasedPluginEmbedding.Root",
    "content": ""
  },
  {
    "path": "SubplatformsCollection.Root",
    "content": ""
  },
  {
    "path": "UnrealLink.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.29123.88\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"RiderPlugin.UnrealLink\", \"src\\dotnet\\RiderPlugin.UnrealLink\\RiderPlugin.UnrealLink.csproj\", \"{084172D1-A9C6-46D0-96AD-05C5B09A5E5D}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"misc\", \"misc\", \"{4A9ABB95-3762-448B-B5BF-099E46DB22DE}\"\n\tProjectSection(SolutionItems) = preProject\n\t\tCHANGELOG.md = CHANGELOG.md\n\t\tsrc\\dotnet\\Plugin.props = src\\dotnet\\Plugin.props\n\t\tsrc\\rider\\main\\resources\\META-INF\\plugin.xml = src\\rider\\main\\resources\\META-INF\\plugin.xml\n\t\tREADME.md = README.md\n\tEndProjectSection\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{084172D1-A9C6-46D0-96AD-05C5B09A5E5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{084172D1-A9C6-46D0-96AD-05C5B09A5E5D}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{084172D1-A9C6-46D0-96AD-05C5B09A5E5D}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{084172D1-A9C6-46D0-96AD-05C5B09A5E5D}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {AE34A340-CA1E-400F-9367-864EEF8033C7}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "build.gradle.kts",
    "content": "import com.jetbrains.plugin.structure.base.utils.isFile\nimport org.apache.tools.ant.taskdefs.condition.Os\nimport org.gradle.api.tasks.testing.logging.TestExceptionFormat\nimport org.jetbrains.changelog.Changelog\nimport org.jetbrains.intellij.platform.gradle.tasks.PrepareSandboxTask\nimport org.jetbrains.intellij.platform.gradle.tasks.RunIdeTask\nimport org.jetbrains.kotlin.gradle.dsl.JvmTarget\nimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile\nimport java.io.ByteArrayOutputStream\nimport java.security.MessageDigest\nimport javax.inject.Inject\nimport org.gradle.process.ExecOperations\nimport kotlin.io.path.absolute\nimport kotlin.io.path.isDirectory\nimport org.jetbrains.intellij.platform.gradle.Constants\nimport org.jetbrains.intellij.platform.gradle.TestFrameworkType\nimport kotlin.io.path.pathString\n\nplugins {\n    id(\"me.filippov.gradle.jvm.wrapper\") version \"0.16.0\"\n    id(\"org.jetbrains.changelog\") version \"2.0.0\"\n    id(\"org.jetbrains.intellij.platform\")\n    kotlin(\"jvm\")\n}\n\ninterface Injected {\n    @get:Inject val exec: ExecOperations\n}\nval injected = objects.newInstance<Injected>()\n\njava {\n    sourceCompatibility = JavaVersion.VERSION_25\n    targetCompatibility = JavaVersion.VERSION_25\n}\n\nrepositories {\n    maven(\"https://cache-redirector.jetbrains.com/intellij-dependencies\")\n    maven(\"https://cache-redirector.jetbrains.com/intellij-repository/releases\")\n    maven(\"https://cache-redirector.jetbrains.com/intellij-repository/snapshots\")\n    maven(\"https://cache-redirector.jetbrains.com/maven-central\")\n    intellijPlatform {\n        defaultRepositories()\n        jetbrainsRuntime()\n    }\n}\n\ndependencies {\n    testImplementation(\"com.fasterxml.jackson.core:jackson-databind:2.14.0\")\n}\n\napply {\n    plugin(\"kotlin\")\n}\n\nkotlin {\n    sourceSets {\n        main {\n            kotlin.srcDir(\"src/rider/main/kotlin\")\n        }\n        test {\n            kotlin.srcDir(\"src/rider/test/kotlin\")\n        }\n    }\n}\n\nsourceSets {\n    main {\n        kotlin.srcDir(\"src/rider/generated/kotlin\")\n        resources.srcDir(\"src/rider/main/resources\")\n    }\n}\n\nproject.version = \"${property(\"majorVersion\")}.\" +\n                  \"${property(\"minorVersion\")}.\" +\n                  \"${property(\"buildCounter\")}\"\n\nif (System.getenv(\"TEAMCITY_VERSION\") != null) {\n    logger.lifecycle(\"##teamcity[buildNumber '${project.version}']\")\n} else {\n    logger.lifecycle(\"Plugin version: ${project.version}\")\n}\n\nval buildConfigurationProp = project.property(\"buildConfiguration\").toString()\n\nval repoRoot by extra { project.rootDir }\nval isWindows by extra { Os.isFamily(Os.FAMILY_WINDOWS) }\nval idePluginId by extra { \"RiderPlugin\" }\nval dotNetSolutionId by extra { \"UnrealLink\" }\nval dotNetDir by extra { File(repoRoot, \"src/dotnet\") }\nval dotNetBinDir by extra { dotNetDir.resolve(\"$idePluginId.$dotNetSolutionId\").resolve(\"bin\") }\nval dotNetPluginId by extra { \"$idePluginId.${project.name}\" }\nval dotNetSolution by extra { File(repoRoot, \"$dotNetSolutionId.sln\") }\nval modelDir = File(repoRoot, \"protocol/src/main/kotlin/model\")\nval hashBaseDir = File(repoRoot, \"build/rdgen\")\nval ktOutputRelativePath = \"src/rider/main/kotlin/com/jetbrains/rider/model\"\nval cppOutputRoot = File(repoRoot, \"src/cpp/RiderLink/Source/RiderLink/Public/Model\")\nval csOutputRoot = File(repoRoot, \"src/dotnet/RiderPlugin.UnrealLink/obj/model\")\nval ktOutputRoot = File(repoRoot, ktOutputRelativePath)\nval riderLinkDir = File(\"$rootDir/src/cpp/RiderLink\")\n\nval currentBranchName = getBranchName()\n\nfun TaskContainerScope.setupCleanup(task: Task) {\n    withType<Delete> {\n        delete(task.outputs.files)\n    }\n}\n\nfun getBranchName(): String {\n    val execResult = providers.exec {\n        executable = \"git\"\n        args(\"rev-parse\", \"--abbrev-ref\", \"HEAD\")\n        workingDir = projectDir\n        isIgnoreExitValue = true\n    }\n    if (execResult.result.get().exitValue == 0) {\n        val output = execResult.standardOutput.asText.get().trim()\n        if (output.isNotEmpty())\n            return output\n    }\n    return \"net222\"\n}\n\nfun getProductMonorepoRoot(): File? {\n    var currentDir = repoRoot\n\n    while (currentDir.parent != null) {\n        if (currentDir.resolve(\".ultimate.root.marker\").exists()) {\n            return currentDir\n        }\n        currentDir = currentDir.parentFile\n    }\n\n    return null\n}\n\nchangelog {\n    version.set(project.version.toString())\n    // https://github.com/JetBrains/gradle-changelog-plugin/blob/main/src/main/kotlin/org/jetbrains/changelog/Changelog.kt#L23\n    // This is just common semVerRegex with the addition of a forth optional group (number) ( x.x.x[.x][-alpha43] )\n    headerParserRegex.set(\n        \"\"\"^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.?(0|[1-9]\\d*)?(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)\n            (?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?${'$'}\"\"\"\n            .trimMargin().toRegex())\n    groups.set(listOf(\"Added\", \"Changed\", \"Deprecated\", \"Removed\", \"Fixed\", \"Known Issues\"))\n    keepUnreleasedSection.set(true)\n    itemPrefix.set(\"-\")\n}\n\ndependencies {\n    intellijPlatform {\n        val dependencyPath = File(projectDir, \"dependencies\")\n        if (dependencyPath.exists()) {\n            val localPath = dependencyPath.canonicalPath\n            local(localPath)\n            logger.lifecycle(\"Will use ${File(localPath, \"build.txt\").readText()} from $localPath as RiderSDK\")\n        } else {\n            val version = \"${project.property(\"majorVersion\")}-SNAPSHOT\"\n            logger.lifecycle(\"*** Using Rider SDK $version from intellij-snapshots repository\")\n            rider(version, useInstaller = false)\n        }\n\n        jetbrainsRuntime()\n\n        // Workaround for https://youtrack.jetbrains.com/issue/IDEA-179607\n        bundledPlugin(\"rider.intellij.plugin.appender\")\n\n        bundledPlugin(\"com.intellij.cidr.debugger\")\n        bundledPlugin(\"com.jetbrains.rider-cpp\")\n\n        // TODO: Temporary I hope hope hope\n        bundledLibrary(provider {\n            project.intellijPlatform.platformPath.resolve(\"lib/testFramework.jar\").pathString\n        })\n    }\n}\n\nintellijPlatform {\n    tasks {\n        val currentReleaseNotesAsHtml = \"\"\"\n            <body>\n            <p><b>New in \"${project.version}\"</b></p>\n            <p>${changelog.renderItem(changelog.getLatest(), Changelog.OutputType.HTML)}</p>\n            <p>See the <a href=\"https://github.com/JetBrains/UnrealLink/blob/$currentBranchName/CHANGELOG.md\">CHANGELOG</a> for more details and history.</p>\n            </body>\n        \"\"\".trimIndent()\n\n        val currentReleaseNotesAsMarkdown = \"\"\"\n            ## New in ${project.version}\n            ${changelog.renderItem(changelog.getLatest())}\n            See the [CHANGELOG](https://github.com/JetBrains/UnrealLink/blob/$currentBranchName/CHANGELOG.md) for more details and history.\n        \"\"\".trimIndent()\n        val dumpCurrentChangelog by registering {\n            val outputFile = layout.buildDirectory.file(\"release_notes.md\")\n            outputs.file(outputFile)\n            doLast { file(outputFile).writeText(currentReleaseNotesAsMarkdown) }\n        }\n\n        // PatchPluginXml gets the latest (always Unreleased) section from the current changelog and writes it into plugin.xml\n        // dumpCurrentChangelog dumps the same section to file (for Marketplace changelog)\n        // After, patchChangelog rename [Unreleased] to [202x.x.x.x] and create new empty Unreleased.\n        // So order is important!\n        patchPluginXml { changeNotes.set( provider { currentReleaseNotesAsHtml }) }\n        patchChangelog { mustRunAfter(patchPluginXml, dumpCurrentChangelog) }\n\n        publishPlugin {\n            dependsOn(patchPluginXml, dumpCurrentChangelog, patchChangelog)\n            token.set(System.getenv(\"UNREALLINK_intellijPublishToken\"))\n\n            val pubChannels = project.findProperty(\"publishChannels\")\n            if ( pubChannels != null) {\n                val chan = pubChannels.toString().split(',')\n                println(\"Channels for publish $chan\")\n                channels.set(chan)\n            } else {\n                channels.set(listOf(\"alpha\"))\n            }\n        }\n    }\n}\n\nval riderModel: Configuration by configurations.creating {\n    isCanBeConsumed = true\n    isCanBeResolved = false\n}\n\nartifacts {\n    add(riderModel.name, provider {\n        intellijPlatform.platformPath.resolve(\"lib/rd/rider-model.jar\").also {\n            check(it.isFile) {\n                \"rider-model.jar is not found at $riderModel\"\n            }\n        }\n    }) {\n        builtBy(Constants.Tasks.INITIALIZE_INTELLIJ_PLATFORM_PLUGIN)\n    }\n}\n\ntasks {\n    val dotNetSdkPath by lazy {\n        val sdkPath = intellijPlatform.platformPath.resolve(\"lib/DotNetSdkForRdPlugins\").absolute()\n        assert(sdkPath.isDirectory())\n        println(\".NET SDK path: $sdkPath\")\n\n        return@lazy sdkPath.toRealPath()\n    }\n\n    instrumentCode {\n        enabled = false\n    }\n\n    withType<RunIdeTask>().configureEach {\n        maxHeapSize = \"4096m\"\n    }\n\n    withType<Test>().configureEach {\n        maxHeapSize = \"4096m\"\n        if (project.hasProperty(\"ignoreFailures\")) { ignoreFailures = true }\n        useTestNG {\n        }\n        testLogging {\n            showStandardStreams = true\n            showExceptions = true\n            exceptionFormat = TestExceptionFormat.FULL\n        }\n    }\n\n    withType<KotlinCompile>().configureEach {\n        dependsOn(\"generateModels\")\n        compilerOptions {\n            jvmTarget.set(JvmTarget.JVM_25)\n        }\n    }\n\n    val prepareRiderBuildProps by registering {\n        group = \"RiderBackend\"\n        val generatedFile = layout.buildDirectory.file(\"DotNetSdkPath.generated.props\")\n\n        inputs.property(\"dotNetSdkFile\", { dotNetSdkPath.toString() })\n        outputs.file(generatedFile)\n\n        doLast {\n            project.file(generatedFile).writeText(\n                \"\"\"<Project>\n            |  <PropertyGroup>\n            |    <DotNetSdkPath>$dotNetSdkPath</DotNetSdkPath>\n            |  </PropertyGroup>\n            |</Project>\"\"\".trimMargin()\n            )\n        }\n    }\n\n    val prepareNuGetConfig by registering {\n        group = \"RiderBackend\"\n        dependsOn(prepareRiderBuildProps)\n\n        val generatedFile = project.projectDir.resolve(\"NuGet.Config\")\n        inputs.property(\"dotNetSdkFile\", { dotNetSdkPath.toString() })\n        outputs.file(generatedFile)\n        doLast {\n            val dotNetSdkFile = dotNetSdkPath\n            logger.info(\"dotNetSdk location: '$dotNetSdkFile'\")\n\n            val nugetConfigText = \"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n        |<configuration>\n        |  <packageSources>\n        |    <clear />\n        |    <add key=\"local-dotnet-sdk\" value=\"$dotNetSdkFile\" />\n        |    <add key=\"nuget.org\" value=\"https://api.nuget.org/v3/index.json\" />\n        |  </packageSources>\n        |</configuration>\n        \"\"\".trimMargin()\n            generatedFile.writeText(nugetConfigText)\n\n            logger.info(\"Generated content:\\n$nugetConfigText\")\n        }\n    }\n\n    val buildResharperHost by registering {\n        group = \"RiderBackend\"\n        description = \"Build backend for Rider\"\n        dependsOn(\":generateModels\", prepareNuGetConfig)\n\n        inputs.file(file(dotNetSolution))\n        inputs.dir(file(\"$repoRoot/src/dotnet\"))\n        outputs.dir(file(\"$repoRoot/src/dotnet/RiderPlugin.UnrealLink/bin/RiderPlugin.UnrealLink/$buildConfigurationProp\"))\n\n        doLast {\n            val warningsAsErrors: String by project.extra\n            val buildArguments = listOf(\n                \"build\",\n                dotNetSolution.canonicalPath,\n                \"-consoleLoggerParameters:ErrorsOnly\",\n                \"/p:Configuration=$buildConfigurationProp\",\n                \"/p:Version=${project.version}\",\n                \"/p:TreatWarningsAsErrors=$warningsAsErrors\",\n                \"/bl:${dotNetSolution.name}.binlog\",\n                \"/nologo\"\n            )\n            logger.info(\"call dotnet.cmd with '{}'\", buildArguments)\n            injected.exec.exec {\n                executable = \"$rootDir/tools/dotnet.cmd\"\n                args = buildArguments\n                workingDir = dotNetSolution.parentFile\n            }\n        }\n    }\n\n    val patchUpluginVersion by register(\"patchUpluginVersion\") {\n        val pathToUpluginTemplate = File(\"${project.rootDir}/src/cpp/RiderLink/RiderLink.uplugin.template\")\n        val filePathToUplugin = File(\"${project.rootDir}/src/cpp/RiderLink/RiderLink.uplugin\")\n        inputs.file(pathToUpluginTemplate)\n        inputs.property(\"version\", project.version)\n        outputs.file(filePathToUplugin)\n        doLast {\n            if(filePathToUplugin.exists())\n                filePathToUplugin.delete()\n\n            pathToUpluginTemplate.copyTo(filePathToUplugin)\n\n            val text = filePathToUplugin.readLines().map {\n                it.replace(\"%PLUGIN_VERSION%\", \"${project.version}\")\n            }\n            filePathToUplugin.writeText(text.joinToString(System.lineSeparator()))\n        }\n    }\n    withType<Delete> {\n        delete(patchUpluginVersion.outputs.files)\n    }\n\n    val generateChecksum by register(\"generateChecksum\") {\n        dependsOn(\":generateModels\")\n        val upluginFile = riderLinkDir.resolve(\"RiderLink.uplugin.template\")\n        val resourcesDir = riderLinkDir.resolve(\"Resources\")\n        val sourceDir = riderLinkDir.resolve(\"Source\")\n        val checksumFile = riderLinkDir.resolve(\"Resources/checksum\")\n        inputs.file(upluginFile)\n        inputs.dir(resourcesDir)\n        inputs.dir(sourceDir)\n        outputs.file(checksumFile)\n        doLast {\n            checksumFile.delete()\n            val inputFiles = sequence{\n                yield(upluginFile)\n                resourcesDir.walkTopDown().forEach { if(it.isFile && (it.nameWithoutExtension != \"checksum\")) yield(it) }\n                sourceDir.walkTopDown().forEach { if(it.isFile) yield(it) }\n            }\n            val instance = MessageDigest.getInstance(\"MD5\")\n            inputFiles.forEach { instance.update(it.readBytes()) }\n            checksumFile.writeBytes(instance.digest())\n        }\n    }\n    withType<Delete> {\n        delete(generateChecksum.outputs.files)\n    }\n\n    val packCppSide by registering(Zip::class) {\n        dependsOn(patchUpluginVersion)\n        dependsOn(\":generateModels\")\n        dependsOn(generateChecksum)\n\n        archiveFileName.set(\"RiderLink.zip\")\n        excludes.addAll(arrayOf(\"RiderLink.uplugin.template\", \"Intermediate\", \"Binaries\"))\n        destinationDirectory.set(File(\"$rootDir/build/distributions\"))\n        from(\"$rootDir/src/cpp/RiderLink\")\n    }\n\n    withType<PrepareSandboxTask> {\n        dependsOn(buildResharperHost, packCppSide)\n\n        outputs.upToDateWhen { false } //need to dotnet artifacts be included when only dotnet sources were changed\n\n        val outputFolder = dotNetBinDir\n            .resolve(dotNetPluginId)\n            .resolve(buildConfigurationProp)\n\n        val dllFiles = listOf(\n            File(outputFolder, \"$dotNetPluginId.dll\"),\n            File(outputFolder, \"$dotNetPluginId.pdb\")\n        )\n\n        dllFiles.forEach {\n            from(it) { into(\"${intellijPlatform.projectName.get()}/dotnet\") }\n        }\n\n\n        from(packCppSide.get().archiveFile) {\n            into(\"${intellijPlatform.projectName.get()}/EditorPlugin\")\n        }\n\n        doLast {\n            dllFiles.forEach { file ->\n                if (!file.exists()) throw RuntimeException(\"File $file does not exist\")\n            }\n        }\n    }\n\n    val generateModels by registering {\n        group = \"protocol\"\n        description = \"Generates protocol models.\"\n        dependsOn(\":protocol:rdgen\")\n    }\n\n    withType<Delete> {\n        delete(csOutputRoot, cppOutputRoot, ktOutputRoot)\n    }\n\n    buildSearchableOptions { }\n\n    val getUnrealEngineProject by register(\"getUnrealEngineProject\") {\n        doLast {\n            val ueProjectPathTxt = rootDir.resolve(\"UnrealEngineProjectPath.txt\")\n            if (ueProjectPathTxt.exists()) {\n                val ueProjectPath = ueProjectPathTxt.readText()\n                val ueProjectPathDir = File(ueProjectPath)\n                if (!ueProjectPathDir.exists()) throw AssertionError(\"$ueProjectPathDir doesn't exist\")\n                if (!ueProjectPathDir.isDirectory) throw AssertionError(\"$ueProjectPathDir is not directory\")\n\n                val isUEProject = ueProjectPathDir.listFiles()?.any {\n                    it.extension == \"uproject\"\n                }\n                if (isUEProject == true) {\n                    extra[\"UnrealProjectPath\"] = ueProjectPathDir\n                } else {\n                    throw AssertionError(\"Add path to a valid UnrealEngine project folder to: $ueProjectPathTxt\")\n                }\n            } else {\n                ueProjectPathTxt.createNewFile()\n                throw AssertionError(\"Add path to a valid UnrealEngine project folder to: $ueProjectPathTxt\")\n            }\n        }\n    }\n\n    val symlinkPluginToUnrealProject by registering {\n        dependsOn(getUnrealEngineProject)\n        dependsOn(patchUpluginVersion)\n        doLast {\n            val unrealProjectPath = getUnrealEngineProject.extra[\"UnrealProjectPath\"] as File\n            val targetDir = File(\"$unrealProjectPath/Plugins/Developer/RiderLink\")\n\n            if(targetDir.exists()) {\n                val stdOut = ByteArrayOutputStream()\n                // Check if it's Junction\n                val result = injected.exec.exec {\n                    commandLine = if(isWindows)\n                        listOf(\"cmd.exe\", \"/c\", \"fsutil\", \"reparsepoint\", \"query\", targetDir.absolutePath, \"|\", \"find\", \"Print Name:\")\n                    else\n                        listOf(\"find\", targetDir.absolutePath, \"-maxdepth\", \"1\", \"-type\", \"l\", \"-ls\")\n\n                    isIgnoreExitValue = true\n                    standardOutput = stdOut\n                }\n\n                // Check if it's Junction to local RiderLink\n                if(result.exitValue == 0) {\n                    val output = stdOut.toString().trim()\n                    if (output.isNotEmpty()) {\n                        val pathToJunction = if (isWindows)\n                            output.substringAfter(\"Print Name:\").trim()\n                        else\n                            output.substringAfter(\"->\").trim()\n                        if (File(pathToJunction) == riderLinkDir) {\n                            println(\"Junction is already correct\")\n                            throw StopExecutionException()\n                        }\n                    }\n                }\n\n                // If it's not Junction or if it's a Junction but doesn't point to local RiderLink - delete it\n                targetDir.delete()\n            }\n\n            targetDir.parentFile.mkdirs()\n            val stdOut = ByteArrayOutputStream()\n            val result = injected.exec.exec {\n                commandLine = if(isWindows)\n                    listOf(\"cmd.exe\", \"/c\", \"mklink\", \"/J\", targetDir.absolutePath, riderLinkDir.absolutePath)\n                else\n                    listOf(\"ln\", \"-s\", riderLinkDir.absolutePath, targetDir.absolutePath)\n                errorOutput = stdOut\n                isIgnoreExitValue = true\n            }\n            if (result.exitValue != 0) {\n                println(stdOut.toString().trim())\n            }\n        }\n    }\n\n    wrapper {\n        gradleVersion = \"9.4.1\"\n        distributionUrl = \"https://cache-redirector.jetbrains.com/services.gradle.org/distributions/gradle-${gradleVersion}-bin.zip\"\n    }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://cache-redirector.jetbrains.com/services.gradle.org/distributions/gradle-9.4.1-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Properties for the build. Override on the command line with -Pprop=value\n# E.g. -PBuildConfiguration=Release\n# Note that these values are strings!\n# Local builds and installs will have this ridiculours number 20xx.x.x.9999\n# Teamcity overrides buildCounter to %build.counter% (Teamcity counter)\n# majorVersion is used as SDK version when no SDK in UnrealLink/dependencies\n# Downloads \"majorVersion-SNAPSHOT\" from https://cache-redirector.jetbrains.com/intellij-repository/snapshots\nmajorVersion=2026.3\nminorVersion=0\nbuildCounter=9999\n# Overrides on Teamcity to Release\nbuildConfiguration=Debug\nwarningsAsErrors=false\n# List of channels to publish. Defined as comma-separated string (publishChannels=\"alpha,beta,eap\")\n# Alpha channel uses by default =)\n#publishChannels=alpha\n# We need it to avoid bundle Kotlin jars into plugin\nkotlin.stdlib.default.dependency=false\n# Updated automatically on idea sync\nrdVersion=2026.1.3\nrdKotlinVersion=2.3.0\nintellijPlatformGradlePluginVersion=2.11.0\ngradleJvmWrapperVersion=0.15.0\n\norg.gradle.jvmargs=-Xmx4g\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd -P \"${APP_HOME:-./}\" > /dev/null && printf '%s\\n' \"$PWD\" ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\n\n\n# GRADLE JVM WRAPPER START MARKER\nBUILD_DIR=\"${HOME}/.local/share/gradle-jvm\"\nJVM_ARCH=$(uname -m)\nJVM_TEMP_FILE=$BUILD_DIR/gradle-jvm-temp.tar.gz\nif [ \"$darwin\" = \"true\" ]; then\n    case $JVM_ARCH in\n    x86_64)\n        JVM_URL=https://download.oracle.com/java/25/archive/jdk-25.0.2_macos-x64_bin.tar.gz\n        JVM_TARGET_DIR=$BUILD_DIR/jdk-25.0.2_macos-x64_bin-99fbca\n        ;;\n    arm64)\n        JVM_URL=https://download.oracle.com/java/25/archive/jdk-25.0.2_macos-aarch64_bin.tar.gz\n        JVM_TARGET_DIR=$BUILD_DIR/jdk-25.0.2_macos-aarch64_bin-d7817e\n        ;;\n    *) \n        die \"Unknown architecture $JVM_ARCH\"\n        ;;\n    esac\nelif [ \"$cygwin\" = \"true\" ] || [ \"$msys\" = \"true\" ]; then\n    JVM_URL=https://download.oracle.com/java/25/archive/jdk-25.0.2_windows-x64_bin.zip\n    JVM_TARGET_DIR=$BUILD_DIR/jdk-25.0.2_windows-x64_bin-96701c\nelse\n    JVM_ARCH=$(linux$(getconf LONG_BIT) uname -m)\n     case $JVM_ARCH in\n        x86_64)\n            JVM_URL=https://download.oracle.com/java/25/archive/jdk-25.0.2_linux-x64_bin.tar.gz\n            JVM_TARGET_DIR=$BUILD_DIR/jdk-25.0.2_linux-x64_bin-3c4431\n            ;;\n        aarch64)\n            JVM_URL=https://download.oracle.com/java/25/archive/jdk-25.0.2_linux-aarch64_bin.tar.gz\n            JVM_TARGET_DIR=$BUILD_DIR/jdk-25.0.2_linux-aarch64_bin-a88282\n            ;;\n        *) \n            die \"Unknown architecture $JVM_ARCH\"\n            ;;\n        esac\nfi\n\nset -e\n\nif [ -e \"$JVM_TARGET_DIR/.flag\" ] && [ -n \"$(ls \"$JVM_TARGET_DIR\")\" ] && [ \"x$(cat \"$JVM_TARGET_DIR/.flag\")\" = \"x${JVM_URL}\" ]; then\n    # Everything is up-to-date in $JVM_TARGET_DIR, do nothing\n    true\nelse\n  echo \"Downloading $JVM_URL to $JVM_TEMP_FILE\"\n\n  rm -f \"$JVM_TEMP_FILE\"\n  mkdir -p \"$BUILD_DIR\"\n  if command -v curl >/dev/null 2>&1; then\n      if [ -t 1 ]; then CURL_PROGRESS=\"--progress-bar\"; else CURL_PROGRESS=\"--silent --show-error\"; fi\n      # shellcheck disable=SC2086\n      curl $CURL_PROGRESS -L --output \"${JVM_TEMP_FILE}\" \"$JVM_URL\" 2>&1\n  elif command -v wget >/dev/null 2>&1; then\n      if [ -t 1 ]; then WGET_PROGRESS=\"\"; else WGET_PROGRESS=\"-nv\"; fi\n      wget $WGET_PROGRESS -O \"${JVM_TEMP_FILE}\" \"$JVM_URL\" 2>&1\n  else\n      die \"ERROR: Please install wget or curl\"\n  fi\n\n  echo \"Extracting $JVM_TEMP_FILE to $JVM_TARGET_DIR\"\n  rm -rf \"$JVM_TARGET_DIR\"\n  mkdir -p \"$JVM_TARGET_DIR\"\n\n  case \"$JVM_URL\" in\n    *\".zip\") unzip \"$JVM_TEMP_FILE\" -d \"$JVM_TARGET_DIR\" ;;\n    *) tar -x -f \"$JVM_TEMP_FILE\" -C \"$JVM_TARGET_DIR\" ;;\n  esac\n  \n  rm -f \"$JVM_TEMP_FILE\"\n\n  echo \"$JVM_URL\" >\"$JVM_TARGET_DIR/.flag\"\nfi\n\nJAVA_HOME=\nfor d in \"$JVM_TARGET_DIR\" \"$JVM_TARGET_DIR\"/* \"$JVM_TARGET_DIR\"/Contents/Home \"$JVM_TARGET_DIR\"/*/Contents/Home; do\n  if [ -e \"$d/bin/java\" ]; then\n    JAVA_HOME=\"$d\"\n  fi\ndone\n\nif [ '!' -e \"$JAVA_HOME/bin/java\" ]; then\n  die \"Unable to find bin/java under $JVM_TARGET_DIR\"\nfi\n\n# Make it available for child processes\nexport JAVA_HOME\n\nset +e\n\n# GRADLE JVM WRAPPER END MARKER\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -jar \"$APP_HOME/gradle/wrapper/gradle-wrapper.jar\" \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n@rem SPDX-License-Identifier: Apache-2.0\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\n@rem This is normally unused\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem GRADLE JVM WRAPPER START MARKER\r\n\r\nsetlocal\r\nset BUILD_DIR=%LOCALAPPDATA%\\gradle-jvm\r\n\r\nfor /f \"tokens=3 delims= \" %%A in ('reg query \"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\" /v \"PROCESSOR_ARCHITECTURE\"') do set WIN_ARCH=%%A\r\nif \"%WIN_ARCH%\" equ \"AMD64\" (\r\n    set JVM_TARGET_DIR=%BUILD_DIR%\\jdk-25.0.2_windows-x64_bin-96701c\\\r\n    set JVM_URL=https://download.oracle.com/java/25/archive/jdk-25.0.2_windows-x64_bin.zip\r\n) else if \"%WIN_ARCH%\" equ \"ARM64\" (\r\n    set JVM_TARGET_DIR=%BUILD_DIR%\\microsoft-jdk-25.0.2-windows-aarch64-7d2a81\\\r\n    set JVM_URL=https://aka.ms/download-jdk/microsoft-jdk-25.0.2-windows-aarch64.zip\r\n) else (\r\n    echo Unknown architecture %WIN_ARCH%\r\n    goto fail\r\n)\r\n\r\nset IS_TAR_GZ=0\r\nset JVM_TEMP_FILE=gradle-jvm.zip\r\n\r\nif /I \"%JVM_URL:~-7%\"==\".tar.gz\" (\r\n    set IS_TAR_GZ=1\r\n    set JVM_TEMP_FILE=gradle-jvm.tar.gz\r\n)\r\n\r\nset POWERSHELL=%SystemRoot%\\system32\\WindowsPowerShell\\v1.0\\powershell.exe\r\n\r\nif not exist \"%JVM_TARGET_DIR%\" MD \"%JVM_TARGET_DIR%\"\r\n\r\nif not exist \"%JVM_TARGET_DIR%.flag\" goto downloadAndExtractJvm\r\n\r\nset /p CURRENT_FLAG=<\"%JVM_TARGET_DIR%.flag\"\r\nif \"%CURRENT_FLAG%\" == \"%JVM_URL%\" goto continueWithJvm\r\n\r\n:downloadAndExtractJvm\r\n\r\nPUSHD \"%BUILD_DIR%\"\r\nif errorlevel 1 goto fail\r\n\r\necho Downloading %JVM_URL% to %BUILD_DIR%\\%JVM_TEMP_FILE%\r\nif exist \"%JVM_TEMP_FILE%\" DEL /F \"%JVM_TEMP_FILE%\"\r\n\"%POWERSHELL%\" -nologo -noprofile -Command \"Set-StrictMode -Version 3.0; $ErrorActionPreference = \\\"Stop\\\"; (New-Object Net.WebClient).DownloadFile('%JVM_URL%', '%JVM_TEMP_FILE%')\"\r\nif errorlevel 1 goto fail\r\n\r\nPOPD\r\n\r\nRMDIR /S /Q \"%JVM_TARGET_DIR%\"\r\nif errorlevel 1 goto fail\r\n\r\nMKDIR \"%JVM_TARGET_DIR%\"\r\nif errorlevel 1 goto fail\r\n\r\nPUSHD \"%JVM_TARGET_DIR%\"\r\nif errorlevel 1 goto fail\r\n\r\necho Extracting %BUILD_DIR%\\%JVM_TEMP_FILE% to %JVM_TARGET_DIR%\r\n\r\nif \"%IS_TAR_GZ%\"==\"1\" (\r\n    tar xf \"..\\\\%JVM_TEMP_FILE%\"\r\n) else (\r\n    \"%POWERSHELL%\" -nologo -noprofile -command \"Set-StrictMode -Version 3.0; $ErrorActionPreference = \\\"Stop\\\"; Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('..\\\\%JVM_TEMP_FILE%', '.');\"\r\n)\r\nif errorlevel 1 goto fail\r\n\r\nDEL /F \"..\\%JVM_TEMP_FILE%\"\r\nif errorlevel 1 goto fail\r\n\r\nPOPD\r\n\r\necho %JVM_URL%>\"%JVM_TARGET_DIR%.flag\"\r\nif errorlevel 1 goto fail\r\n\r\n:continueWithJvm\r\n\r\nset JAVA_HOME=\r\nfor /d %%d in (\"%JVM_TARGET_DIR%\"*) do if exist \"%%d\\bin\\java.exe\" set JAVA_HOME=%%d\r\nif not exist \"%JAVA_HOME%\\bin\\java.exe\" (\r\n  echo Unable to find java.exe under %JVM_TARGET_DIR%\r\n  goto fail\r\n)\r\n\r\nendlocal & set JAVA_HOME=%JAVA_HOME%\r\n\r\n@rem GRADLE JVM WRAPPER END MARKER\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -jar \"%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\" %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "protocol/build.gradle.kts",
    "content": "import com.jetbrains.rd.generator.gradle.RdGenTask\n\nplugins {\n    // Version is configured in gradle.properties\n    id(\"com.jetbrains.rdgen\")\n    id(\"org.jetbrains.kotlin.jvm\")\n}\n\nrepositories {\n    maven(\"https://cache-redirector.jetbrains.com/intellij-dependencies\")\n    maven(\"https://cache-redirector.jetbrains.com/maven-central\")\n    val rd_version: String? by project\n    if (rd_version == \"SNAPSHOT\") {\n      mavenLocal()\n    }\n}\n\nval isMonorepo = rootProject.projectDir != projectDir.parentFile\nval unrealLinkRepoRoot: File = projectDir.parentFile\n\nsourceSets {\n    main {\n        kotlin {\n            srcDir(unrealLinkRepoRoot.resolve(\"protocol/src/main/kotlin/model\"))\n        }\n    }\n}\n\ndata class UnrealLinkGeneratorSettings(\n    val ue4LibCsLibraryOutput: File,\n    val ue4LibCppLibraryOutput: File,\n    val ue4LibKtLibraryOutput: File,\n    val riderModelCsOutput: File,\n    val riderModelKtOutput: File,\n    val csEditorOutput: File,\n    val cppEditorOutput: File,\n    val fileSuffix: String\n)\n\nval ktOutputRelativePath = \"src/rider/generated/kotlin/com/jetbrains/rider/model\"\n\nval unrealLinkGeneratorSettings = if (isMonorepo) {\n    val monorepoRoot =\n        buildscript.sourceFile?.parentFile?.parentFile?.parentFile?.parentFile?.parentFile ?: error(\"Cannot find products home\")\n    check(monorepoRoot.resolve(\".ultimate.root.marker\").isFile) {\n        error(\"Incorrect location in monorepo: monorepoRoot='$monorepoRoot'\")\n    }\n    val monorepoPreGeneratedRootDir = monorepoRoot.resolve(\"dotnet/Plugins/_UnrealLink.Pregenerated\")\n    val monorepoPreGeneratedFrontendDir = monorepoPreGeneratedRootDir.resolve(\"Frontend\")\n    val monorepoPreGeneratedBackendDir = monorepoPreGeneratedRootDir.resolve(\"BackendModel\")\n    val monorepoPreGeneratedCppDir = monorepoPreGeneratedRootDir.resolve(\"CppModel\")\n    val ktOutputMonorepoRoot = monorepoPreGeneratedFrontendDir.resolve(ktOutputRelativePath)\n\n    UnrealLinkGeneratorSettings(\n        monorepoPreGeneratedBackendDir.resolve(\"Library\"),\n        monorepoPreGeneratedCppDir.resolve( \"Library\"),\n        ktOutputMonorepoRoot.resolve(\"Library\"),\n        monorepoPreGeneratedBackendDir.resolve(\"RdRiderProtocol\"),\n        ktOutputMonorepoRoot.resolve(\"RdRiderProtocol\"),\n        monorepoPreGeneratedBackendDir.resolve(\"RdEditorProtocol\"),\n        monorepoPreGeneratedCppDir.resolve(\"RdEditorProtocol\"),\n        \".Pregenerated\"\n    )\n} else {\n    val csOutputRoot = File(unrealLinkRepoRoot, \"src/dotnet/RiderPlugin.UnrealLink/obj/model\")\n    val cppOutputRoot = File(unrealLinkRepoRoot, \"src/cpp/RiderLink/Source/RiderLink/Public/Model\")\n    val ktOutputRoot = File(unrealLinkRepoRoot, ktOutputRelativePath)\n    UnrealLinkGeneratorSettings(\n        csOutputRoot.resolve(\"Library\"),\n        cppOutputRoot.resolve( \"Library\"),\n        ktOutputRoot.resolve(\"Library\"),\n        csOutputRoot.resolve(\"RdRiderProtocol\"),\n        ktOutputRoot.resolve(\"RdRiderProtocol\"),\n        csOutputRoot.resolve(\"RdEditorProtocol\"),\n        cppOutputRoot.resolve(\"RdEditorProtocol\"),\n        \".Pregenerated\"\n    )\n}\n\nrdgen {\n    verbose = true\n    packages = \"model.editorPlugin,model.lib.ue4,model.rider\"\n\n    generator {\n        language = \"csharp\"\n        transform = \"symmetric\"\n        root = \"model.lib.ue4.UE4Library\"\n        directory = unrealLinkGeneratorSettings.ue4LibCsLibraryOutput.absolutePath\n        generatedFileSuffix = unrealLinkGeneratorSettings.fileSuffix\n    }\n\n    generator {\n        language = \"cpp\"\n        transform = \"reversed\"\n        root = \"model.lib.ue4.UE4Library\"\n        directory = unrealLinkGeneratorSettings.ue4LibCppLibraryOutput.absolutePath\n        generatedFileSuffix = unrealLinkGeneratorSettings.fileSuffix\n    }\n\n    generator {\n        language = \"kotlin\"\n        transform = \"asis\"\n        root = \"model.lib.ue4.UE4Library\"\n        directory = unrealLinkGeneratorSettings.ue4LibKtLibraryOutput.absolutePath\n        generatedFileSuffix = unrealLinkGeneratorSettings.fileSuffix\n    }\n\n    generator {\n        language = \"csharp\"\n        transform = \"reversed\"\n        root = \"com.jetbrains.rider.model.nova.ide.IdeRoot\"\n        directory = unrealLinkGeneratorSettings.riderModelCsOutput.absolutePath\n        generatedFileSuffix = unrealLinkGeneratorSettings.fileSuffix\n    }\n\n    generator {\n        language = \"kotlin\"\n        transform = \"asis\"\n        root = \"com.jetbrains.rider.model.nova.ide.IdeRoot\"\n        directory = unrealLinkGeneratorSettings.riderModelKtOutput.absolutePath\n        generatedFileSuffix = unrealLinkGeneratorSettings.fileSuffix\n    }\n\n    generator {\n        language = \"csharp\"\n        transform = \"asis\"\n        root = \"model.editorPlugin.RdEditorRoot\"\n        directory = unrealLinkGeneratorSettings.csEditorOutput.absolutePath\n        generatedFileSuffix = unrealLinkGeneratorSettings.fileSuffix\n    }\n\n    generator {\n        language = \"cpp\"\n        transform = \"reversed\"\n        root = \"model.editorPlugin.RdEditorRoot\"\n        directory = unrealLinkGeneratorSettings.cppEditorOutput.absolutePath\n        generatedFileSuffix = unrealLinkGeneratorSettings.fileSuffix\n    }\n}\n\ntasks.withType<RdGenTask> {\n    dependsOn(sourceSets[\"main\"].runtimeClasspath)\n    classpath(sourceSets[\"main\"].runtimeClasspath)\n}\n\ndependencies {\n    if (isMonorepo) {\n        implementation(project(\":rider-model\"))\n    } else {\n        val rdVersion: String by project\n        val rdKotlinVersion: String by project\n\n        implementation(\"com.jetbrains.rd:rd-gen:$rdVersion\")\n        implementation(\"org.jetbrains.kotlin:kotlin-stdlib:$rdKotlinVersion\")\n        implementation(\n            project(\n                mapOf(\n                    \"path\" to \":\",\n                    \"configuration\" to \"riderModel\"\n                )\n            )\n        )\n    }\n}\n"
  },
  {
    "path": "protocol/src/main/kotlin/model/editorPlugin/LiveCodingModel.kt",
    "content": "package model.editorPlugin\n\nimport com.jetbrains.rd.generator.nova.*\nimport com.jetbrains.rd.generator.nova.PredefinedType.*\n@Suppress(\"unused\")\nobject LiveCodingModel : Ext(RdEditorModel) {\n        init {\n                call(\"LC_IsEnabledByDefault\", void, bool)\n                source(\"LC_EnableByDefault\", bool)\n\n                call(\"LC_IsEnabledForSession\", void, bool)\n                call(\"LC_CanEnableForSession\", void, bool)\n                source(\"LC_EnableForSession\", bool)\n\n                call(\"LC_IsCompiling\", void, bool)\n                call(\"LC_HasStarted\", void, bool)\n                source(\"LC_Compile\", void)\n                sink(\"LC_OnPatchComplete\", void)\n        }\n}\n"
  },
  {
    "path": "protocol/src/main/kotlin/model/editorPlugin/RdEditorModel.kt",
    "content": "package model.editorPlugin\n\nimport com.jetbrains.rd.generator.nova.*\nimport com.jetbrains.rd.generator.nova.PredefinedType.*\nimport com.jetbrains.rd.generator.nova.cpp.Cpp17Generator\nimport com.jetbrains.rd.generator.nova.csharp.CSharp50Generator\nimport model.lib.ue4.UE4Library\n\n@Suppress(\"unused\")\nobject RdEditorRoot : Root() {\n    init {\n        setting(CSharp50Generator.Namespace, \"RiderPlugin.UnrealLink.Model.BackendUnreal\")\n        setting(Cpp17Generator.Namespace, \"JetBrains::EditorPlugin\")\n\n        setting(Cpp17Generator.AdditionalHeaders, listOf(\"UE4TypesMarshallers.h\"))\n        setting(Cpp17Generator.ExportMacroName,  \"RIDERLINK_API\")\n        setting(Cpp17Generator.GeneratePrecompiledHeaders, false)\n        setting(Cpp17Generator.UsePrecompiledHeaders, false)\n    }\n}\n\n@Suppress(\"unused\")\nobject RdEditorModel : Ext(RdEditorRoot) {\n    init {\n        property(\"connectionInfo\", UE4Library.ConnectionInfo).readonly\n\n        signal(\"unrealLog\", UE4Library.UnrealLogEvent).async\n\n        signal(\"openBlueprint\", UE4Library.BlueprintReference)\n\n        signal(\"onBlueprintAdded\", UE4Library.UClass).async\n        call(\"isBlueprintPathName\", UE4Library.FString, bool)\n        call(\"getPathNameByPath\", UE4Library.FString, UE4Library.FString.nullable)\n\n        callback(\"AllowSetForegroundWindow\", int, bool)\n\n        property(\"isGameControlModuleInitialized\", false).readonly\n        sink(\"PlayStateFromEditor\", UE4Library.PlayState)\n        source(\"RequestPlayFromRider\", int)\n        source(\"RequestPauseFromRider\", int)\n        source(\"RequestResumeFromRider\", int)\n        source(\"RequestStopFromRider\", int)\n        source(\"RequestFrameSkipFromRider\", int)\n        sink(\"NotificationReplyFromEditor\", UE4Library.RequestResultBase)\n\n        sink(\"PlayModeFromEditor\", int)\n        source(\"PlayModeFromRider\", int)\n\n        // Hot Reload here is not Unreal's HotReload but generic Hot Reload mechanism which can be either Unreal's HotReload or Unreal's LiveCoding\n        property(\"IsHotReloadAvailable\", false).readonly\n        property(\"IsHotReloadCompiling\", false).readonly\n        source(\"TriggerHotReload\", void)\n    }\n}\n"
  },
  {
    "path": "protocol/src/main/kotlin/model/lib/ue4/UE4Library.kt",
    "content": "package model.lib.ue4\n\nimport com.jetbrains.rd.generator.nova.*\nimport com.jetbrains.rd.generator.nova.PredefinedType.*\nimport com.jetbrains.rd.generator.nova.cpp.Cpp17Generator\nimport com.jetbrains.rd.generator.nova.cpp.CppIntrinsicType\nimport com.jetbrains.rd.generator.nova.csharp.CSharp50Generator\nimport com.jetbrains.rd.generator.nova.kotlin.Kotlin11Generator\n\nobject UE4Library : Root() {\n    init {\n        setting(Kotlin11Generator.Namespace, \"com.jetbrains.rider.plugins.unreal.model\")\n        setting(CSharp50Generator.Namespace, \"RiderPlugin.UnrealLink.Model\")\n        setting(Cpp17Generator.Namespace, \"JetBrains::EditorPlugin\")\n\n        setting(Cpp17Generator.AdditionalHeaders, listOf(\n                \"UE4TypesMarshallers.h\",\n                \"Runtime/Core/Public/Containers/Array.h\",\n                \"Runtime/Core/Public/Containers/ContainerAllocationPolicies.h\"\n        ))\n        setting(Cpp17Generator.ListType, CppIntrinsicType(null, \"TArray\", \"Containers/Array.h\"))\n        setting(Cpp17Generator.AllocatorType) { \"FDefaultAllocator\" }\n        setting(Cpp17Generator.ExportMacroName,  \"RIDERLINK_API\")\n        setting(Cpp17Generator.GeneratePrecompiledHeaders, false)\n        setting(Cpp17Generator.UsePrecompiledHeaders, false)\n    }\n\n    private fun <T : Declaration> declare(intrinsic: CppIntrinsicType, factory: Toplevel.() -> T): T {\n        return this.factory().apply {\n            intrinsic.namespace?.let { ns ->\n                setting(Cpp17Generator.Namespace, ns)\n            }\n            setting(Cpp17Generator.Intrinsic, intrinsic)\n        }\n    }\n\n    val StringRange = structdef(\"StringRange\") {\n        field(\"first\", int)\n        field(\"last\", int)\n    }\n\n    val FString = declare(CppIntrinsicType(null, \"FString\", \"Containers/UnrealString.h\")) {\n        structdef(\"FString\") {\n            field(\"data\", string)\n        }\n    }\n\n    val PlayState = enum(\"PlayState\") {\n        +\"Idle\"\n        +\"Play\"\n        +\"Pause\"\n    }\n\n    val RequestResultBase = basestruct(\"RequestResultBase\") {\n        field(\"requestID\", int)\n    }\n\n    @Suppress(\"unused\")\n    val RequestSucceed = structdef(\"RequestSucceed\") extends RequestResultBase {\n    }\n\n    @Suppress(\"unused\")\n    val RequestFailed = structdef(\"RequestFailed\") extends RequestResultBase {\n        field(\"type\", enum(\"NotificationType\") {\n            +\"Message\"\n            +\"Error\"\n        })\n        field(\"message\", FString)\n    }\n\n    val VerbosityType = declare(CppIntrinsicType(\"ELogVerbosity\", \"Type\", \"Logging/LogVerbosity.h\"))\n    {\n        setting(Cpp17Generator.IsNonScoped, \"uint8\")\n\n        enum(\"VerbosityType\") {\n            (+\"NoLogging\").doc(\"= 0\")\n\n\n            (+\"Fatal\").doc(\n                    \"Always prints a fatal error to console (and log file) and crashes (even if logging is disabled)\"\n            )\n\n            (+\"Error\").doc(\n                    \"Prints an error to console (and log file).\" +\n                            \"Command lets and the editor collect and report errors. Error messages result in command let failure.\"\n            )\n\n            (+\"Warning\").doc(\n                    \"Prints a warning to console (and log file).\" +\n                            \"Command lets and the editor collect and report warnings. Warnings can be treated as an error.\")\n\n            (+\"Display\").doc(\n                    \"Prints a message to console (and log file)\"\n            )\n\n            (+\"Log\").doc(\"Prints a message to a log file (does not print to console)\")\n\n            (+\"Verbose\").doc(\n                    \"Prints a verbose message to a log file (if Verbose logging is enabled for the given category, usually used for detailed logging)\"\n            )\n\n            (+\"VeryVerbose\").doc(\n                    \"Prints a verbose message to a log file (if VeryVerbose logging is enabled, usually used for detailed logging that would otherwise spam output)\"\n            )\n\n            // Log masks and special Enum values\n\n            (+\"All\")/*.setting(Cpp17Generator.EnumConstantValue, 7)*/.doc(\"=VeryVerbose\")\n            (+\"NumVerbosity\")\n            (+\"VerbosityMask\").setting(Cpp17Generator.EnumConstantValue, 0xf)\n            (+\"SetColor\").setting(Cpp17Generator.EnumConstantValue, 0x40).doc(\"not actually a verbosity, used to set the color of an output device\")\n            (+\"BreakOnLog\").setting(Cpp17Generator.EnumConstantValue, 0x80)\n        }\n    }\n\n    private val LogMessageInfo = structdef(\"LogMessageInfo\") {\n        field(\"type\", VerbosityType)\n        field(\"category\", FString)\n        field(\"time\", dateTime.nullable)\n    }\n\n    val UnrealLogEvent = structdef(\"UnrealLogEvent\") {\n        field(\"info\", LogMessageInfo)\n        field(\"text\", FString)\n        field(\"bpPathRanges\", immutableList(StringRange))\n        field(\"methodRanges\", immutableList(StringRange))\n    }\n\n    /*@Suppress(\"unused\")\n    private val LogMessageEvent = structdef(\"LogMessageEvent\") extends LogEvent {\n        field(\"message\", FString)\n    }*/\n\n    val UClass = structdef(\"UClass\") {\n        field(\"name\", FString)\n    }\n\n    @Suppress(\"unused\")\n    val BlueprintFunction = structdef(\"BlueprintFunction\") {\n        field(\"class\", UClass)\n        field(\"name\", FString)\n\n        const(\"separator\", string, \":\")\n    }\n\n    //region Script Call Stack\n    private val ScriptCallStackFrame = structdef(\"ScriptCallStackFrame\") {\n        //        field(\"header\", FString)\n//        field(\"blueprintFunction\", BlueprintFunction)\n        field(\"entry\", FString)\n    }\n\n    private val IScriptCallStack = basestruct(\"IScriptCallStack\") {\n        const(\"header\", string, \"Script call stack:\")\n    }\n\n    @Suppress(\"unused\")\n    private val EmptyScriptCallStack = structdef(\"EmptyScriptCallStack\") extends IScriptCallStack {\n        const(\"message\", string, \"Script call stack: [Empty] (FFrame::GetStackTrace() called from native code)\")\n    }\n\n    @Suppress(\"unused\")\n    private val ScriptCallStack = structdef(\"ScriptCallStack\") extends IScriptCallStack {\n        field(\"frames\", immutableList(ScriptCallStackFrame))\n    }\n\n    @Suppress(\"unused\")\n    private val UnableToDisplayScriptCallStack = structdef(\"UnableToDisplayScriptCallStack\") extends IScriptCallStack {\n        const(\"message\", string, \"Unable to display Script Callstack. Compile with DO_BLUEPRINT_GUARD=1\")\n    }\n\n    //endregion\n\n    //region ScriptMsg\n    private val IScriptMsg = basestruct(\"IScriptMsg\") {\n        const(\"header\", string, \"Script msg:\")\n    }\n\n    @Suppress(\"unused\")\n    private val ScriptMsgException = structdef(\"ScriptMsgException\") extends IScriptMsg {\n        field(\"message\", FString)\n    }\n\n    @Suppress(\"unused\")\n    private val ScriptMsgCallStack = structdef(\"ScriptMsgCallStack\") extends IScriptMsg {\n        field(\"message\", FString)\n        field(\"scriptCallStack\", IScriptCallStack)\n    }\n\n/*\n    @Suppress(\"unused\")\n    private val ScriptMsgEvent = structdef(\"ScriptMsgEvent\") extends LogPart {\n        field(\"scriptMsg\", IScriptMsg)\n    }\n*/\n\n    //endregion\n    @Suppress(\"unused\")\n    val BlueprintHighlighter = structdef(\"BlueprintHighlighter\") {\n        field(\"begin\", int)\n        field(\"end\", int)\n    }\n\n    val BlueprintReference = structdef(\"BlueprintReference\") {\n        field(\"pathName\", FString)\n        field(\"guid\", FString)\n    }\n\n    val ConnectionInfo = structdef(\"ConnectionInfo\") {\n        field(\"projectName\", string)\n        field(\"executableName\", string)\n        field(\"processId\", int)\n    }\n}\n\n"
  },
  {
    "path": "protocol/src/main/kotlin/model/rider/RdRiderModel.kt",
    "content": "package model.rider\n\nimport com.jetbrains.rd.generator.nova.*\nimport com.jetbrains.rd.generator.nova.PredefinedType.*\nimport com.jetbrains.rd.generator.nova.csharp.CSharp50Generator\nimport com.jetbrains.rd.generator.nova.kotlin.Kotlin11Generator\nimport com.jetbrains.rider.model.nova.ide.SolutionModel\nimport model.lib.ue4.UE4Library\n\n@Suppress(\"unused\")\nobject RdRiderModel : Ext(SolutionModel.Solution) {\n    init {\n        setting(Kotlin11Generator.Namespace, \"com.jetbrains.rider.plugins.unreal.model.frontendBackend\")\n        setting(CSharp50Generator.Namespace, \"RiderPlugin.UnrealLink.Model.FrontendBackend\")\n    }\n\n    private val LinkRequest = structdef(\"LinkRequest\") {\n        field(\"data\", UE4Library.FString)\n    }\n\n    val ILinkResponse = basestruct(\"ILinkResponse\") {}\n\n    val LinkResponseBlueprint = structdef(\"LinkResponseBlueprint\") extends ILinkResponse {\n        field(\"fullPath\", UE4Library.FString)\n        field(\"range\", UE4Library.StringRange)\n    }\n\n    val LinkResponseFilePath = structdef(\"LinkResponseFilePath\") extends ILinkResponse {\n        field(\"fullPath\", UE4Library.FString)\n        field(\"range\", UE4Library.StringRange)\n    }\n\n    val LinkResponseUnresolved = structdef(\"LinkResponseUnresolved\") extends ILinkResponse {}\n\n    private val MethodReference = structdef(\"MethodReference\") {\n        field(\"class\", UE4Library.UClass)\n        field(\"method\", UE4Library.FString)\n\n        const(\"separator\", string, \"::\")\n    }\n\n    private val PluginInstallStatus = enum(\"PluginInstallStatus\") {\n        +\"NoPlugin\"\n        +\"UpToDate\"\n        +\"InEngine\"\n        +\"InGame\"\n    }\n\n\n    private val EditorPluginOutOfSync = structdef(\"EditorPluginOutOfSync\") {\n        field(\"status\", PluginInstallStatus)\n        field(\"IsGameAvailable\", bool)\n    }\n\n    private val InstallMessage = structdef(\"InstallMessage\") {\n        field(\"text\", string)\n        field(\"type\", enum(\"ContentType\") {\n            +\"Normal\"\n            +\"Error\"\n        })\n    }\n\n    private val InstallPluginDescription = structdef(\"InstallPluginDescription\") {\n        field(\"location\", enum(\"PluginInstallLocation\") {\n            +\"Engine\"\n            +\"Game\"\n            +\"NotInstalled\"\n        })\n        field(\"forceInstall\", enum(\"ForceInstall\") {\n            +\"Yes\"\n            +\"No\"\n        })\n        field(\"buildRequired\", bool).default(true)\n        field(\"selectedUprojectPaths\", immutableList(string))\n        field(\"unselectedUprojectPaths\", immutableList(string))\n    }\n\n    private val GamePluginInstallInfo = structdef(\"GamePluginInstallInfo\") {\n        field(\"projectName\", string)\n        field(\"uprojectPath\", string)\n        field(\"isPluginAvailable\", bool)\n        field(\"isPluginSynced\", bool)\n    }\n\n    init {\n        property(\"editorId\", 0).readonly.async\n\n        signal(\"unrealLog\", UE4Library.UnrealLogEvent)\n\n        call(\"filterLinkCandidates\", immutableList(LinkRequest), array(ILinkResponse)).async\n        call(\"isMethodReference\", MethodReference, bool).async\n\n        signal(\"navigateToMethod\", MethodReference)\n        signal(\"navigateToClass\", UE4Library.UClass)\n\n        signal(\"openBlueprint\", UE4Library.BlueprintReference)\n\n        callback(\"AllowSetForegroundWindow\", int, bool)\n\n        property(\"isConnectedToUnrealEditor\", false).readonly.async\n        property(\"isUnrealEngineSolution\", false)\n        property(\"isPreBuiltEngine\", false)\n        property(\"connectionInfo\", UE4Library.ConnectionInfo).readonly\n\n        sink(\"onEditorPluginOutOfSync\", EditorPluginOutOfSync)\n        source(\"installEditorPlugin\", InstallPluginDescription)\n        source(\"refreshProjects\", void)\n        source(\"enableAutoupdatePlugin\", void)\n\n        property(\"isGameControlModuleInitialized\", false).readonly\n        sink(\"PlayStateFromEditor\", UE4Library.PlayState)\n        source(\"RequestPlayFromRider\", int)\n        source(\"RequestPauseFromRider\", int)\n        source(\"RequestResumeFromRider\", int)\n        source(\"RequestStopFromRider\", int)\n        source(\"RequestFrameSkipFromRider\", int)\n        sink(\"NotificationReplyFromEditor\", UE4Library.RequestResultBase)\n\n        sink(\"PlayModeFromEditor\", int)\n        source(\"PlayModeFromRider\", int)\n\n        sink(\"RiderLinkInstallPanelInit\", void)\n        sink(\"RiderLinkInstallMessage\", InstallMessage).async\n        sink(\"InstallPluginFinished\", bool).async\n        property(\"RiderLinkInstallationInProgress\", false)\n        property(\"RefreshInProgress\", false)\n        property(\"IsUproject\", false)\n        property(\"isInstallInfoAvailable\", false)\n        sink(\"gamePluginInstallInfos\", immutableList(GamePluginInstallInfo))\n\n        source(\"CancelRiderLinkInstall\", void)\n\n        // Hot Reload here is not Unreal's HotReload but generic Hot Reload mechanism which can be either Unreal's HotReload or Unreal's LiveCoding\n        property(\"IsHotReloadAvailable\", false).readonly\n        property(\"IsHotReloadCompiling\", false).readonly\n        signal(\"TriggerHotReload\", void)\n        signal(\"DeletePlugin\", void)\n    }\n}\n"
  },
  {
    "path": "settings.gradle.kts",
    "content": "rootProject.name = \"UnrealLink\"\n\npluginManagement {\n    val rdVersion: String by settings\n    val rdKotlinVersion: String by settings\n    val intellijPlatformGradlePluginVersion: String by settings\n    val gradleJvmWrapperVersion: String by settings\n\n    repositories {\n        maven(\"https://cache-redirector.jetbrains.com/intellij-dependencies\")\n        maven(\"https://cache-redirector.jetbrains.com/plugins.gradle.org\")\n        maven(\"https://cache-redirector.jetbrains.com/maven-central\")\n\n        if (rdVersion == \"SNAPSHOT\") {\n            mavenLocal()\n        }\n    }\n\n    plugins {\n        id(\"com.jetbrains.rdgen\") version rdVersion\n        id(\"org.jetbrains.kotlin.jvm\") version rdKotlinVersion\n        id(\"org.jetbrains.intellij.platform\") version intellijPlatformGradlePluginVersion\n        id(\"me.filippov.gradle.jvm.wrapper\") version gradleJvmWrapperVersion\n    }\n\n    resolutionStrategy {\n        eachPlugin {\n            when (requested.id.name) {\n                // This required to correctly rd-gen plugin resolution.\n                // Maybe we should switch our naming to match Gradle plugin naming convention.\n                \"rdgen\" -> {\n                    useModule(\"com.jetbrains.rd:rd-gen:${rdVersion}\")\n                }\n            }\n        }\n    }\n}\n\ninclude(\":protocol\")\n"
  },
  {
    "path": "setup_unreal_plugin.cmd",
    "content": ".\\gradlew -q symlinkPluginToUnrealProject"
  },
  {
    "path": "src/SubplatformsCollection.Root",
    "content": ""
  },
  {
    "path": "src/cpp/BuildScript/GenerateRiderLinkZip.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Collections.Immutable;\nusing System.Linq;\nusing System.Security.Cryptography;\nusing JetBrains.Application.BuildScript;\nusing JetBrains.Application.BuildScript.Compile;\nusing JetBrains.Application.BuildScript.Solution;\nusing JetBrains.Build;\nusing JetBrains.Extension;\nusing JetBrains.Util;\nusing JetBrains.Util.dataStructures;\nusing JetBrains.Util.Special;\nusing JetBrains.Util.Storage;\n\nnamespace Plugins.UnrealLink.src.cpp.BuildScript\n{\n  public class GenerateRiderLinkZip\n  {\n    [BuildStep]\n    public static SubplatformFileForPackaging[] Run(AllAssembliesOnEverything allass, ProductHomeDirArtifact homedir, ILogger logger)\n    {\n      if (allass.FindSubplatformByClass<GenerateRiderLinkZip>() is SubplatformOnSources subplatform)\n      {\n        FileSystemPath dirRiderLink = homedir.ProductHomeDir / subplatform.Name.RelativePath / \"RiderLink\";\n        FileSystemPath dirModel = dirRiderLink.Parent.Parent.Parent.Parent / \"_UnrealLink.Pregenerated\" / \"CppModel\";\n\n        IList<ImmutableFileItem> files = dirRiderLink.GetChildFiles(flags: PathSearchFlags.RecurseIntoSubdirectories)\n          .OrderBy().Select(file => ImmutableFileItem.CreateFromDisk(file).WithRelativePath(file.MakeRelativeTo(dirRiderLink))).ToList();\n\n        IList<ImmutableFileItem> models = dirModel.GetChildFiles(flags: PathSearchFlags.RecurseIntoSubdirectories)\n          .OrderBy().Select(file => ImmutableFileItem.CreateFromDisk(file).WithRelativePath((RelativePath)\"Source\" / \"RiderLink\" / \"Public\" / \"Model\" / file.MakeRelativeTo(dirModel))).ToList();\n        files.AddRange(models);\n\n        ImmutableFileItem fiUpluginTemplate = files.Single(fi => fi.RelativePath == \"RiderLink.uplugin.template\");\n        StreamEx.TextAndEncoding taeUpluginTemplate = fiUpluginTemplate.FileContent.ReadTextFromFile();\n        string sUpluginContent = taeUpluginTemplate.Text.Replace(\"%PLUGIN_VERSION%\", GlobalDefines.FullMarketingVersionString);\n        ImmutableFileItem fiUplugin = new ImmutableFileItem(fiUpluginTemplate.RelativePath.NameWithoutExtension, ImmutableByteStream.FromByteArray(taeUpluginTemplate.Encoding.GetBytes(sUpluginContent).ToImmutableArray()));\n\n        byte[] bytesChecksumContent = MD5.Create().WithDispose(hasher =>\n        {\n          foreach (var fi in files) hasher.TransformBlock(fi.FileContent);\n          hasher.TransformFinalBlock(Array.Empty<byte>(), 0, 0);\n          return hasher.Hash;\n        });\n        ImmutableFileItem fiChecksum = new ImmutableFileItem(\"Resources/checksum\", ImmutableByteStream.FromByteArray(bytesChecksumContent.ToImmutableArray()));\n\n        ImmutableFileItem fiZip = Compression.ZipCompress(dirRiderLink.Name + ExtensionConstants.Zip, files.Where(fi => fi != fiUpluginTemplate).Concat(fiUplugin, fiChecksum), logger, whencompress: Compression.WhenToCompressEntry.Always);\n        return new[] { new SubplatformFileForPackaging(subplatform.Name, fiZip) };\n      }\n\n      return Array.Empty<SubplatformFileForPackaging>();\n    }\n  }\n}"
  },
  {
    "path": "src/cpp/RiderLink/RiderLink.uplugin.template",
    "content": "{\n\t\"FileVersion\": 3,\n\t\"Version\": 1,\n\t\"VersionName\": \"%PLUGIN_VERSION%\",\n\t\"FriendlyName\": \"RiderLink\",\n\t\"Description\": \"Plugin for establishing IPC connection with JetBrains Rider IDE\",\n\t\"Category\": \"Programming\",\n\t\"CreatedBy\": \"JetBrains\",\n\t\"CreatedByURL\": \"https://www.jetbrains.com/\",\n\t\"DocsURL\": \"\",\n\t\"MarketplaceURL\": \"\",\n\t\"SupportURL\": \"\",\n\t\"EnabledByDefault\": true,\n\t\"CanContainContent\": false,\n\t\"IsBetaVersion\": false,\n\t\"Installed\": false,\n\t\"Modules\": [\n\t\t{\n\t\t\t\"Name\": \"RD\",\n\t\t\t\"Type\": \"EditorNoCommandlet\",\n\t\t\t\"LoadingPhase\": \"PreDefault\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"RiderLink\",\n\t\t\t\"Type\": \"EditorNoCommandlet\",\n\t\t\t\"LoadingPhase\": \"PreDefault\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"RiderLogging\",\n\t\t\t\"Type\": \"EditorNoCommandlet\",\n\t\t\t\"LoadingPhase\": \"PreDefault\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"RiderBlueprint\",\n\t\t\t\"Type\": \"EditorNoCommandlet\",\n\t\t\t\"LoadingPhase\": \"Default\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"RiderGameControl\",\n\t\t\t\"Type\": \"EditorNoCommandlet\",\n\t\t\t\"LoadingPhase\": \"Default\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"RiderShaderInfo\",\n\t\t\t\"Type\": \"EditorNoCommandlet\",\n\t\t\t\"LoadingPhase\": \"PostEngineInit\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"RiderLC\",\n\t\t\t\"Type\": \"EditorNoCommandlet\",\n\t\t\t\"LoadingPhase\": \"PostEngineInit\"\n\t\t},\n\t\t{\n\t\t\t\"Name\": \"RiderDebuggerSupport\",\n\t\t\t\"Type\": \"EditorNoCommandlet\",\n\t\t\t\"LoadingPhase\": \"PreDefault\",\n\t\t\t\"PlatformAllowList\": [\n\t\t\t\t\"Win64\"\n\t\t\t],\n\t\t\t\"WhitelistPlatforms\": [\n\t\t\t\t\"Win64\"\n\n\t\t\t]\n\t\t}\n\t]\n}"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/RD.Build.cs",
    "content": "using System.IO;\nusing UnrealBuildTool;\n\npublic class RD : ModuleRules\n{\n\tpublic RD(ReadOnlyTargetRules Target) : base(Target)\n\t{\n\t\tPublicDependencyModuleNames.Add(\"Core\");\n\t\tbUseRTTI = true;\n\n#if UE_5_2_OR_LATER\n\t\tbDisableStaticAnalysis = true;\n#endif\n\n#if UE_5_2_OR_LATER\n\t\tIWYUSupport = IWYUSupport.KeepAsIs;\n#else\n\t\tbEnforceIWYU = false;\n#endif\n\n#if UE_5_6_OR_LATER\n\t\tCppStandard = CppStandardVersion.Cpp20;\n#elif UE_4_22_OR_LATER\n\t\tCppStandard = CppStandardVersion.Cpp17;\n#endif\n\n#if UE_4_22_OR_LATER\n\t\tPCHUsage = PCHUsageMode.NoPCHs;\n#else\n\t\tPCHUsage = PCHUsageMode.NoSharedPCHs;\n#endif\n\n#if UE_5_6_OR_LATER\n\t\tCppCompileWarningSettings.ShadowVariableWarningLevel = WarningLevel.Off;\n#elif UE_4_24_OR_LATER\n\t\tShadowVariableWarningLevel = WarningLevel.Off;\n#else\n\t\tbEnableShadowVariableWarnings = false;\n#endif\n\n#if UE_4_24_OR_LATER\n\t\tbUseUnity = false;\n#else\n\t\tbFasterWithoutUnity = true;\n#endif\n\n\t\tPublicDefinitions.Add(\"_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS\");\n\n\t\tif (Target.Platform == UnrealTargetPlatform.Win64)\n\t\t{\n\t\t\tPublicDefinitions.Add(\"_WINSOCK_DEPRECATED_NO_WARNINGS\");\n\t\t\tPublicDefinitions.Add(\"_CRT_SECURE_NO_WARNINGS\");\n\t\t\tPublicDefinitions.Add(\"_CRT_NONSTDC_NO_DEPRECATE\");\n\t\t\tPublicDefinitions.Add(\"SPDLOG_WCHAR_FILENAMES\");\n\t\t\tPublicDefinitions.Add(\"SPDLOG_WCHAR_TO_UTF8_SUPPORT\");\n\t\t\tPrivateDefinitions.Add(\"WIN32_LEAN_AND_MEAN\");\n\t\t}\n\n\t\tif (Target.Platform == UnrealTargetPlatform.Mac)\n\t\t{\n\t\t\tPublicDefinitions.Add(\"_DARWIN\");\n\t\t}\n\n\t\t// Common dependencies\n\t\tPrivateDefinitions.Add(\"rd_framework_cpp_EXPORTS\");\n\t\tPrivateDefinitions.Add(\"rd_core_cpp_EXPORTS\");\n\t\tPrivateDefinitions.Add(\"spdlog_EXPORTS\");\n\t\tPrivateDefinitions.Add(\"FMT_EXPORT\");\n\t\tPrivateDefinitions.Add(\"_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR\");\n\n\t\tPublicDefinitions.Add(\"SPDLOG_NO_EXCEPTIONS\");\n\t\tPublicDefinitions.Add(\"SPDLOG_COMPILED_LIB\");\n\t\tPublicDefinitions.Add(\"SPDLOG_SHARED_LIB\");\n\t\tPublicDefinitions.Add(\n\t\t\t\"nssv_CONFIG_SELECT_STRING_VIEW=nssv_STRING_VIEW_NONSTD\");\n\t\tPublicDefinitions.Add(\"FMT_SHARED\");\n\n\t\tstring[] Paths =\n\t\t{\n\t\t\t\"src\", \"src/rd_core_cpp\", \"src/rd_core_cpp/src/main\"\n\t\t\t, \"src/rd_framework_cpp\", \"src/rd_framework_cpp/src/main\"\n\t\t\t, \"src/rd_framework_cpp/src/main/util\", \"src/rd_gen_cpp/src\"\n\t\t\t, \"thirdparty\", \"thirdparty/ordered-map/include\"\n\t\t\t, \"thirdparty/optional/tl\", \"thirdparty/variant/include\"\n\t\t\t, \"thirdparty/string-view-lite/include\", \"thirdparty/spdlog/include\"\n\t\t\t, \"thirdparty/clsocket/src\", \"thirdparty/CTPL/include\", \"thirdparty/utf-cpp/include\"\n\t\t};\n\n\t\tforeach (var Item in Paths)\n\t\t{\n\t\t\tPublicIncludePaths.Add(Path.Combine(ModuleDirectory, Item));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/RD.cpp",
    "content": "#include \"RD.h\"\n\n#include <Modules/ModuleManager.h>\n\n#define LOCTEXT_NAMESPACE \"RD\"\n\nDEFINE_LOG_CATEGORY(FLogRDModule);\n\nIMPLEMENT_MODULE(FRDModule, RD);\n\n#undef LOCTEXT_NAMESPACE"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/RD.h",
    "content": "// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.\n\n#pragma once\n\n#include \"Logging/LogMacros.h\"\n#include \"Logging/LogVerbosity.h\"\n#include \"Modules/ModuleInterface.h\"\n\nDECLARE_LOG_CATEGORY_EXTERN(FLogRDModule, Log, All);\n\nclass FRDModule : public IModuleInterface\n{\npublic:\n\tFRDModule() = default;\n\t~FRDModule() = default;\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/rd_core_export.h",
    "content": "\n#ifndef RD_CORE_API_H\n#define RD_CORE_API_H\n\n#if defined(_WIN32)\n#ifdef RD_CORE_STATIC_DEFINE\n#  define RD_CORE_API\n#  define RD_CORE_NO_EXPORT\n#else\n#  ifndef RD_CORE_API\n#    ifdef rd_core_cpp_EXPORTS\n        /* We are building this library */\n#      define RD_CORE_API __declspec(dllexport)\n#    else\n        /* We are using this library */\n#      define RD_CORE_API __declspec(dllimport)\n#    endif\n#  endif\n\n#  ifndef RD_CORE_NO_EXPORT\n#    define RD_CORE_NO_EXPORT\n#  endif\n#endif\n\n#ifndef RD_CORE_DEPRECATED\n#  define RD_CORE_DEPRECATED __declspec(deprecated)\n#endif\n\n#ifndef RD_CORE_DEPRECATED_EXPORT\n#  define RD_CORE_DEPRECATED_EXPORT RD_CORE_API RD_CORE_DEPRECATED\n#endif\n\n#ifndef RD_CORE_DEPRECATED_NO_EXPORT\n#  define RD_CORE_DEPRECATED_NO_EXPORT RD_CORE_NO_EXPORT RD_CORE_DEPRECATED\n#endif\n\n#if 0 /* DEFINE_NO_DEPRECATED */\n#  ifndef RD_CORE_NO_DEPRECATED\n#    define RD_CORE_NO_DEPRECATED\n#  endif\n#endif\n#endif\n\n#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__)\n#ifdef RD_CORE_STATIC_DEFINE\n#  define RD_CORE_API\n#  define RD_CORE_NO_EXPORT\n#else\n#  ifndef RD_CORE_API\n#    ifdef rd_core_cpp_EXPORTS\n        /* We are building this library */\n#      define RD_CORE_API __attribute__((visibility(\"default\")))\n#    else\n        /* We are using this library */\n#      define RD_CORE_API __attribute__((visibility(\"default\")))\n#    endif\n#  endif\n\n#  ifndef RD_CORE_NO_EXPORT\n#    define RD_CORE_NO_EXPORT __attribute__((visibility(\"hidden\")))\n#  endif\n#endif\n\n#ifndef RD_CORE_DEPRECATED\n#  define RD_CORE_DEPRECATED __attribute__ ((__deprecated__))\n#endif\n\n#ifndef RD_CORE_DEPRECATED_EXPORT\n#  define RD_CORE_DEPRECATED_EXPORT RD_CORE_API RD_CORE_DEPRECATED\n#endif\n\n#ifndef RD_CORE_DEPRECATED_NO_EXPORT\n#  define RD_CORE_DEPRECATED_NO_EXPORT RD_CORE_NO_EXPORT RD_CORE_DEPRECATED\n#endif\n\n#if 0 /* DEFINE_NO_DEPRECATED */\n#  ifndef RD_CORE_NO_DEPRECATED\n#    define RD_CORE_NO_DEPRECATED\n#  endif\n#endif\n#endif\n\n#endif /* RD_CORE_API_H */\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/lifetime/Lifetime.cpp",
    "content": "#include \"Lifetime.h\"\n\n#include <memory>\n\n#include <thirdparty.hpp>\n#include <spdlog/spdlog.h>\n#include <spdlog/sinks/stdout_color_sinks.h>\n\nnamespace rd\n{\n/*thread_local */ Lifetime::Allocator Lifetime::allocator;\n\nLifetimeImpl* Lifetime::operator->() const\n{\n\treturn ptr.operator->();\n}\n\nstd::once_flag onceFlag;\n\nLifetime::Lifetime(bool is_eternal) : ptr(std::allocate_shared<LifetimeImpl, Allocator>(allocator, is_eternal))\n{\n\tstd::call_once(onceFlag, [] {\n\t\tspdlog::set_default_logger(spdlog::stderr_color_mt<spdlog::synchronous_factory>(\"default\", spdlog::color_mode::automatic));\n\t});\n}\n\nLifetime Lifetime::create_nested() const\n{\n\tLifetime lw(false);\n\tptr->attach_nested(lw.ptr);\n\treturn lw;\n}\n\nLifetime const& Lifetime::Eternal()\n{\n\tstatic Lifetime ETERNAL(true);\n\treturn ETERNAL;\n}\n\nbool operator==(Lifetime const& lw1, Lifetime const& lw2)\n{\n\treturn lw1.ptr == lw2.ptr;\n}\n\nbool operator!=(Lifetime const& lw1, Lifetime const& lw2)\n{\n\treturn !(lw1 == lw2);\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/lifetime/Lifetime.h",
    "content": "#ifndef RD_CPP_CORE_LIFETIMEWRAPPER_H\n#define RD_CPP_CORE_LIFETIMEWRAPPER_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"LifetimeImpl.h\"\n\n#include <std/hash.h>\n\n#include <memory>\n\n#include <rd_core_export.h>\n\nnamespace rd\n{\nclass Lifetime;\n\ntemplate <>\nstruct RD_CORE_API hash<Lifetime>\n{\n\tsize_t operator()(const Lifetime& value) const noexcept;\n};\n\nclass RD_CORE_API Lifetime final\n{\nprivate:\n\tusing Allocator = std::allocator<LifetimeImpl>;\n\n\tstatic /*thread_local */ Allocator allocator;\n\n\tfriend class LifetimeDefinition;\n\n\tfriend struct hash<Lifetime>;\n\n\tstd::shared_ptr<LifetimeImpl> ptr;\n\npublic:\n\tstatic Lifetime const& Eternal();\n\n\t// region ctor/dtor\n\n\tLifetime(Lifetime const& other) = default;\n\n\tLifetime& operator=(Lifetime const& other) = default;\n\n\tLifetime(Lifetime&& other) noexcept = default;\n\n\tLifetime& operator=(Lifetime&& other) noexcept = default;\n\n\t~Lifetime() = default;\n\t// endregion\n\n\tfriend bool RD_CORE_API operator==(Lifetime const& lw1, Lifetime const& lw2);\n\tfriend bool RD_CORE_API operator!=(Lifetime const& lw1, Lifetime const& lw2);\n\n\texplicit Lifetime(bool is_eternal = false);\n\n\tLifetimeImpl* operator->() const;\n\n\tLifetime create_nested() const;\n};\n\ninline size_t hash<Lifetime>::operator()(const Lifetime& value) const noexcept\n{\n\treturn hash<std::shared_ptr<LifetimeImpl> >()(value.ptr);\n}\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_CORE_LIFETIMEWRAPPER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/lifetime/LifetimeDefinition.cpp",
    "content": "#include \"LifetimeDefinition.h\"\n\n#include <spdlog/spdlog.h>\n\nnamespace rd\n{\nLifetimeDefinition::LifetimeDefinition(bool eternaled) : eternaled(eternaled), lifetime(eternaled)\n{\n}\n\nLifetimeDefinition::LifetimeDefinition(const Lifetime& parent) : LifetimeDefinition(false)\n{\n\tparent->attach_nested(lifetime.ptr);\n}\n\nbool LifetimeDefinition::is_terminated() const\n{\n\treturn lifetime->is_terminated();\n}\n\nvoid LifetimeDefinition::terminate()\n{\n\tlifetime->terminate();\n}\n\nbool LifetimeDefinition::is_eternal() const\n{\n\treturn lifetime->is_eternal();\n}\n\nnamespace\n{\nLifetimeDefinition ETERNAL(true);\n}\n\nstd::shared_ptr<LifetimeDefinition> LifetimeDefinition::get_shared_eternal()\n{\n\treturn std::shared_ptr<LifetimeDefinition>(&ETERNAL, [](LifetimeDefinition* /*ld*/) {});\n}\n\nLifetimeDefinition::~LifetimeDefinition()\n{\n\tif (lifetime.ptr != nullptr)\n\t{\t // wasn't moved\n\t\tif (!is_eternal())\n\t\t{\n\t\t\tif (!lifetime->is_terminated())\n\t\t\t{\n\t\t\t\tlifetime->terminate();\n\t\t\t}\n\t\t}\n\t}\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/lifetime/LifetimeDefinition.h",
    "content": "#ifndef RD_CPP_CORE_LIFETIME_DEFINITION_H\n#define RD_CPP_CORE_LIFETIME_DEFINITION_H\n\n#include \"util/core_traits.h\"\n\n#include \"LifetimeImpl.h\"\n#include \"Lifetime.h\"\n\n#include <functional>\n#include <type_traits>\n\n#include <rd_core_export.h>\n\nnamespace rd\n{\nclass RD_CORE_API LifetimeDefinition\n{\nprivate:\n\tfriend class SequentialLifetimes;\n\n\tbool eternaled = false;\n\npublic:\n\tLifetime lifetime;\n\n\texplicit LifetimeDefinition(bool is_eternal = false);\n\n\texplicit LifetimeDefinition(const Lifetime& parent);\n\n\tLifetimeDefinition(LifetimeDefinition const& other) = delete;\n\n\tLifetimeDefinition& operator=(LifetimeDefinition const& other) = delete;\n\n\tLifetimeDefinition(LifetimeDefinition&& other) = default;\n\n\tLifetimeDefinition& operator=(LifetimeDefinition&& other) = default;\n\n\tvirtual ~LifetimeDefinition();\n\n\t//    static std::shared_ptr<LifetimeDefinition> eternal;\n\tstatic std::shared_ptr<LifetimeDefinition> get_shared_eternal();\n\n\tbool is_terminated() const;\n\n\tbool is_eternal() const;\n\n\tvoid terminate();\n\n\ttemplate <typename F>\n\tstatic auto use(F&& block) -> typename util::result_of_t<F(Lifetime)>\n\t{\n\t\tLifetimeDefinition definition(false);\n\t\tLifetime lw = definition.lifetime.create_nested();\n\t\treturn block(lw);\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_CORE_LIFETIME_DEFINITION_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/lifetime/LifetimeImpl.cpp",
    "content": "#include \"LifetimeImpl.h\"\n\n#include <utility>\n\nnamespace rd\n{\n#if __cplusplus < 201703L\nLifetimeImpl::counter_t LifetimeImpl::get_id = 0;\n#endif\n\nLifetimeImpl::LifetimeImpl(bool is_eternal) : eternaled(is_eternal), id(LifetimeImpl::get_id++)\n{\n}\n\nvoid LifetimeImpl::terminate()\n{\n\tif (is_eternal())\n\t\treturn;\n\n\tterminated = true;\n\n\t// region thread-safety section\n\n\tactions_t actions_copy;\n\t{\n\t\tstd::lock_guard<decltype(actions_lock)> guard(actions_lock);\n\t\tactions_copy = std::move(actions);\n\n\t\tactions.clear();\n\t}\n\t// endregion\n\n\tfor (auto it = actions_copy.rbegin(); it != actions_copy.rend(); ++it)\n\t{\n\t\tit->second();\n\t}\n}\n\nbool LifetimeImpl::is_terminated() const\n{\n\treturn terminated;\n}\n\nbool LifetimeImpl::is_eternal() const\n{\n\treturn eternaled;\n}\n\nvoid LifetimeImpl::attach_nested(std::shared_ptr<LifetimeImpl> nested)\n{\n\tif (nested->is_terminated() || is_eternal())\n\t\treturn;\n\n\tstd::function<void()> action = [nested] { nested->terminate(); };\n\tcounter_t action_id = add_action(action);\n\tnested->add_action([this, id = action_id] { actions.erase(id); });\n}\n\nLifetimeImpl::~LifetimeImpl()\n{\n\t/*if (!is_eternal() && !is_terminated()) {\n\t\tspdlog::error(\"forget to terminate lifetime with id: {}\", to_string(id));\n\t\tterminate();\n\t}*/\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/lifetime/LifetimeImpl.h",
    "content": "#ifndef RD_CPP_CORE_LIFETIME_H\n#define RD_CPP_CORE_LIFETIME_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <std/hash.h>\n\n#include <functional>\n#include <map>\n#include <memory>\n#include <mutex>\n#include <atomic>\n#include <utility>\n\n#include <thirdparty.hpp>\n\n#include <rd_core_export.h>\n\nnamespace rd\n{\nclass RD_CORE_API LifetimeImpl final\n{\npublic:\n\tfriend class LifetimeDefinition;\n\n\tfriend class Lifetime;\n\n\tusing counter_t = int32_t;\n\nprivate:\n\tbool eternaled = false;\n\tstd::atomic<bool> terminated{false};\n\n\tcounter_t id = 0;\n\n\tcounter_t action_id_in_map = 0;\n\tusing actions_t = ordered_map<int, std::function<void()>, rd::hash<int>>;\n\tactions_t actions;\n\n\tvoid terminate();\n\n\tstd::mutex actions_lock;\n\npublic:\n\t// region ctor/dtor\n\texplicit LifetimeImpl(bool is_eternal = false);\n\n\tLifetimeImpl(LifetimeImpl const& other) = delete;\n\n\t~LifetimeImpl();\n\t// endregion\n\n\ttemplate <typename F>\n\tcounter_t add_action(F&& action)\n\t{\n\t\tstd::lock_guard<decltype(actions_lock)> guard(actions_lock);\n\n\t\tif (is_eternal())\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\t\tif (is_terminated())\n\t\t{\n\t\t\tthrow std::invalid_argument(\"Already Terminated\");\n\t\t}\n\n\t\tactions[action_id_in_map] = std::forward<F>(action);\n\t\treturn action_id_in_map++;\n\t}\n\n\tvoid remove_action(counter_t i)\n\t{\n\t\tstd::lock_guard<decltype(actions_lock)> guard(actions_lock);\n\n\t\tactions.erase(i);\n\t}\n\n#if __cplusplus >= 201703L\n\tstatic inline counter_t get_id = 0;\n#else\n\tstatic counter_t get_id;\n#endif\n\n\ttemplate <typename F, typename G>\n\tvoid bracket(F&& opening, G&& closing)\n\t{\n\t\tif (is_terminated())\n\t\t\treturn;\n\t\topening();\n\t\tadd_action(std::forward<G>(closing));\n\t}\n\n\tbool is_terminated() const;\n\n\tbool is_eternal() const;\n\n\tvoid attach_nested(std::shared_ptr<LifetimeImpl> nested);\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_CORE_LIFETIME_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/lifetime/SequentialLifetimes.cpp",
    "content": "#include \"SequentialLifetimes.h\"\n\nnamespace rd\n{\nSequentialLifetimes::SequentialLifetimes(Lifetime parent_lifetime) : parent_lifetime(std::move(parent_lifetime))\n{\n\tthis->parent_lifetime->add_action([this] { set_current_lifetime(LifetimeDefinition::get_shared_eternal()); });\n}\n\nLifetime SequentialLifetimes::next()\n{\n\tstd::shared_ptr<LifetimeDefinition> new_def = std::make_shared<LifetimeDefinition>(parent_lifetime);\n\tset_current_lifetime(new_def);\n\treturn current_def->lifetime;\n}\n\nvoid SequentialLifetimes::terminate_current()\n{\n\tset_current_lifetime(LifetimeDefinition::get_shared_eternal());\n}\n\nbool SequentialLifetimes::is_terminated() const\n{\n\treturn current_def->is_eternal() || current_def->is_terminated();\n}\n\nvoid SequentialLifetimes::set_current_lifetime(std::shared_ptr<LifetimeDefinition> new_def)\n{\n\tstd::shared_ptr<LifetimeDefinition> prev = current_def;\n\tcurrent_def = new_def;\n\tprev->terminate();\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/lifetime/SequentialLifetimes.h",
    "content": "#ifndef RD_CPP_CORE_SEQUENTIAL_LIFETIMES_H\n#define RD_CPP_CORE_SEQUENTIAL_LIFETIMES_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"LifetimeDefinition.h\"\n#include \"Lifetime.h\"\n\n#include <rd_core_export.h>\n\nnamespace rd\n{\nclass RD_CORE_API SequentialLifetimes\n{\nprivate:\n\tstd::shared_ptr<LifetimeDefinition> current_def = LifetimeDefinition::get_shared_eternal();\n\tLifetime parent_lifetime;\n\npublic:\n\t// region ctor/dtor\n\tSequentialLifetimes() = delete;\n\n\tSequentialLifetimes(SequentialLifetimes const&) = delete;\n\n\tSequentialLifetimes& operator=(SequentialLifetimes const&) = delete;\n\n\tSequentialLifetimes(SequentialLifetimes&&) = delete;\n\n\tSequentialLifetimes& operator=(SequentialLifetimes&&) = delete;\n\n\texplicit SequentialLifetimes(Lifetime parent_lifetime);\n\t// endregion\n\n\tLifetime next();\n\n\tvoid terminate_current();\n\n\tbool is_terminated() const;\n\n\tvoid set_current_lifetime(std::shared_ptr<LifetimeDefinition> new_def);\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_CORE_SEQUENTIAL_LIFETIMES_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/Property.h",
    "content": "#ifndef RD_CPP_CORE_PROPERTY_H\n#define RD_CPP_CORE_PROPERTY_H\n\n#include \"base/IProperty.h\"\n#include \"reactive/base/SignalX.h\"\n\n#include <util/core_util.h>\n\nnamespace rd\n{\n/**\n * \\brief complete class which has \\a Property<T> 's properties.\n * \\tparam T type of stored value (may be abstract)\n */\ntemplate <typename T>\nclass Property : public IProperty<T>\n{\n\tusing WT = typename IProperty<T>::WT;\n\npublic:\n\t// region ctor/dtor\n\n\tProperty() = default;\n\n\tProperty(Property&& other) = default;\n\n\tProperty& operator=(Property&& other) = default;\n\n\tvirtual ~Property() = default;\n\n\ttemplate <typename F>\n\texplicit Property(F&& value) : IProperty<T>(std::forward<F>(value))\n\t{\n\t}\n\t// endregion\n\n\tT const& get() const override\n\t{\n\t\tRD_ASSERT_THROW_MSG(this->has_value(), \"get of uninitialized value from property\");\n\t\treturn *(this->value);\n\t}\n\n\tvoid set(WT new_value) const override\n\t{\n\t\tif (!this->has_value() || (this->get() != wrapper::get<T>(new_value)))\n\t\t{\n\t\t\tif (this->has_value())\n\t\t\t{\n\t\t\t\tthis->before_change.fire(*(this->value));\n\t\t\t}\n\t\t\tthis->value = std::move(new_value);\n\t\t\tthis->change.fire(*(this->value));\n\t\t}\n\t}\n\n\tfriend bool operator==(const Property& lhs, const Property& rhs)\n\t{\n\t\treturn &lhs == &rhs;\n\t}\n\n\tfriend bool operator!=(const Property& lhs, const Property& rhs)\n\t{\n\t\treturn !(rhs == lhs);\n\t}\n\n\tfriend std::string to_string(Property const& value)\n\t{\n\t\treturn value.has_value() ? to_string(value.get()) : \"empty property\"s;\n\t}\n};\n}\t // namespace rd\n\nstatic_assert(std::is_move_constructible<rd::Property<int>>::value, \"Is not move constructible from Property<int>\");\n\n#endif\t  // RD_CPP_CORE_PROPERTY_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/ViewableList.h",
    "content": "#ifndef RD_CPP_CORE_VIEWABLELIST_H\n#define RD_CPP_CORE_VIEWABLELIST_H\n\n#include \"base/IViewableList.h\"\n#include \"reactive/base/SignalX.h\"\n#include \"util/core_util.h\"\n\n#include <algorithm>\n#include <iterator>\n#include <utility>\n\nnamespace rd\n{\n/**\n * \\brief complete class which has @code IViewableList<T>'s properties\n */\ntemplate <typename T, typename A = allocator<T>>\nclass ViewableList : public IViewableList<T>\n{\npublic:\n\tusing Event = typename IViewableList<T>::Event;\n\nprivate:\n\tusing WA = typename std::allocator_traits<A>::template rebind_alloc<Wrapper<T>>;\n\n\tusing data_t = std::vector<Wrapper<T>, WA>;\n\tmutable data_t list;\n\tSignal<Event> change;\n\nprotected:\n\tusing WT = typename IViewableList<T>::WT;\n\n\tconst std::vector<Wrapper<T>>& getList() const override\n\t{\n\t\treturn list;\n\t}\n\npublic:\n\t// region ctor/dtor\n\n\tViewableList() = default;\n\n\tViewableList(ViewableList&&) = default;\n\n\tViewableList& operator=(ViewableList&&) = default;\n\n\tvirtual ~ViewableList() = default;\n\n\t// endregion\n\n\t// region iterators\npublic:\n\tclass iterator\n\t{\n\t\tfriend class ViewableList<T>;\n\n\t\ttypename data_t::iterator it_;\n\n\t\texplicit iterator(const typename data_t::iterator& it) : it_(it)\n\t\t{\n\t\t}\n\n\tpublic:\n\t\tusing iterator_category = std::random_access_iterator_tag;\n\t\tusing value_type = T;\n\t\tusing difference_type = std::ptrdiff_t;\n\t\tusing pointer = T const*;\n\t\tusing reference = T const&;\n\n\t\titerator(const iterator& other) = default;\n\n\t\titerator(iterator&& other) noexcept = default;\n\n\t\titerator& operator=(const iterator& other) = default;\n\n\t\titerator& operator=(iterator&& other) noexcept = default;\n\n\t\titerator& operator++()\n\t\t{\n\t\t\t++it_;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator operator++(int)\n\t\t{\n\t\t\tauto it = *this;\n\t\t\t++*this;\n\t\t\treturn it;\n\t\t}\n\n\t\titerator& operator--()\n\t\t{\n\t\t\t--it_;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator operator--(int)\n\t\t{\n\t\t\tauto it = *this;\n\t\t\t--*this;\n\t\t\treturn it;\n\t\t}\n\n\t\titerator& operator+=(difference_type delta)\n\t\t{\n\t\t\tit_ += delta;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator& operator-=(difference_type delta)\n\t\t{\n\t\t\tit_ -= delta;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator operator+(difference_type delta) const\n\t\t{\n\t\t\tauto it = *this;\n\t\t\treturn it += delta;\n\t\t}\n\n\t\titerator operator-(difference_type delta) const\n\t\t{\n\t\t\tauto it = *this;\n\t\t\treturn it -= delta;\n\t\t}\n\n\t\tdifference_type operator-(iterator const& other) const\n\t\t{\n\t\t\treturn it_ - other.it_;\n\t\t}\n\n\t\tbool operator<(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn this->it_ < other.it_;\n\t\t}\n\n\t\tbool operator>(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn this->it_ > other.it_;\n\t\t}\n\n\t\tbool operator==(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn this->it_ == other.it_;\n\t\t}\n\n\t\tbool operator!=(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn !(*this == other);\n\t\t}\n\n\t\tbool operator<=(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn (this->it_ < other.it_) || (*this == other);\n\t\t}\n\n\t\tbool operator>=(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn (this->it_ > other.it_) || (*this == other);\n\t\t}\n\n\t\treference operator*() noexcept\n\t\t{\n\t\t\treturn **it_;\n\t\t}\n\n\t\treference operator*() const noexcept\n\t\t{\n\t\t\treturn **it_;\n\t\t}\n\n\t\tpointer operator->() noexcept\n\t\t{\n\t\t\treturn (*it_).get();\n\t\t}\n\n\t\tpointer operator->() const noexcept\n\t\t{\n\t\t\treturn (*it_).get();\n\t\t}\n\t};\n\n\tusing reverse_iterator = std::reverse_iterator<iterator>;\n\n\titerator begin() const\n\t{\n\t\treturn iterator(list.begin());\n\t}\n\n\titerator end() const\n\t{\n\t\treturn iterator(list.end());\n\t}\n\n\treverse_iterator rbegin() const\n\t{\n\t\treturn reverse_iterator(end());\n\t}\n\n\treverse_iterator rend() const\n\t{\n\t\treturn reverse_iterator(begin());\n\t}\n\t// endregion\n\n\tvoid advise(Lifetime lifetime, std::function<void(Event const&)> handler) const override\n\t{\n\t\tif (lifetime->is_terminated())\n\t\t\treturn;\n\t\tchange.advise(lifetime, handler);\n\t\tfor (int32_t i = 0; i < static_cast<int32_t>(size()); ++i)\n\t\t{\n\t\t\thandler(typename Event::Add(i, &(*list[i])));\n\t\t}\n\t}\n\n\tbool add(WT element) const override\n\t{\n\t\tlist.emplace_back(std::move(element));\n\t\tchange.fire(typename Event::Add(static_cast<int32_t>(size()) - 1, &(*list.back())));\n\t\treturn true;\n\t}\n\n\tbool add(size_t index, WT element) const override\n\t{\n\t\tlist.emplace(list.begin() + index, std::move(element));\n\t\tchange.fire(typename Event::Add(static_cast<int32_t>(index), &(*list[index])));\n\t\treturn true;\n\t}\n\n\tWT removeAt(size_t index) const override\n\t{\n\t\tauto res = std::move(list[index]);\n\t\tlist.erase(list.begin() + index);\n\n\t\tchange.fire(typename Event::Remove(static_cast<int32_t>(index), &(*res)));\n\t\treturn wrapper::unwrap<T>(std::move(res));\n\t}\n\n\tbool remove(T const& element) const override\n\t{\n\t\tauto it = std::find_if(list.begin(), list.end(), [&element](auto const& p) { return *p == element; });\n\t\tif (it == list.end())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tViewableList::removeAt(std::distance(list.begin(), it));\n\t\treturn true;\n\t}\n\n\tT const& get(size_t index) const override\n\t{\n\t\treturn *list[index];\n\t}\n\n\tWT set(size_t index, WT element) const override\n\t{\n\t\tauto old_value = std::move(list[index]);\n\t\tlist[index] = Wrapper<T>(std::move(element));\n\t\tchange.fire(typename Event::Update(static_cast<int32_t>(index), &(*old_value), &(*list[index])));\t   //???\n\t\treturn wrapper::unwrap<T>(std::move(old_value));\n\t}\n\n\tbool addAll(size_t index, std::vector<WT> elements) const override\n\t{\n\t\tfor (auto& element : elements)\n\t\t{\n\t\t\tViewableList::add(index, std::move(element));\n\t\t\t++index;\n\t\t}\n\t\treturn true;\n\t}\n\n\tbool addAll(std::vector<WT> elements) const override\n\t{\n\t\tfor (auto&& element : elements)\n\t\t{\n\t\t\tViewableList::add(std::move(element));\n\t\t}\n\t\treturn true;\n\t}\n\n\tvoid clear() const override\n\t{\n\t\tstd::vector<Event> changes;\n\t\tfor (size_t i = size(); i > 0; --i)\n\t\t{\n\t\t\tchanges.push_back(typename Event::Remove(static_cast<int32_t>(i - 1), &(*list[i - 1])));\n\t\t}\n\t\tfor (auto const& e : changes)\n\t\t{\n\t\t\tchange.fire(e);\n\t\t}\n\t\tlist.clear();\n\t}\n\n\tbool removeAll(std::vector<WT> elements) const override\n\t{\n\t\t// TO-DO faster\n\t\t//        std::unordered_set<T> set(elements.begin(), elements.end());\n\n\t\tbool res = false;\n\t\tfor (size_t i = list.size(); i > 0; --i)\n\t\t{\n\t\t\tauto const& x = list[i - 1];\n\t\t\tif (std::count_if(elements.begin(), elements.end(),\n\t\t\t\t\t[&x](auto const& elem) { return wrapper::TransparentKeyEqual<T>()(elem, x); }) > 0)\n\t\t\t{\n\t\t\t\tremoveAt(i - 1);\n\t\t\t\tres = true;\n\t\t\t}\n\t\t}\n\t\treturn res;\n\t}\n\n\tsize_t size() const override\n\t{\n\t\treturn list.size();\n\t}\n\n\tbool empty() const override\n\t{\n\t\treturn list.empty();\n\t}\n};\n}\t // namespace rd\n\nstatic_assert(std::is_move_constructible<rd::ViewableList<int>>::value, \"Is move constructible from ViewableList<int>\");\n\n#endif\t  // RD_CPP_CORE_VIEWABLELIST_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/ViewableMap.h",
    "content": "#ifndef RD_CPP_CORE_VIEWABLE_MAP_H\n#define RD_CPP_CORE_VIEWABLE_MAP_H\n\n#include \"base/IViewableMap.h\"\n#include \"reactive/base/SignalX.h\"\n\n#include <util/core_util.h>\n#include <std/unordered_map.h>\n\n#include <thirdparty.hpp>\n\n#include <iterator>\n#include <utility>\n\nnamespace rd\n{\n/**\n * \\brief complete class which has @code IViewableMap<K, V>'s properties\n */\ntemplate <typename K, typename V, typename KA = std::allocator<K>, typename VA = std::allocator<V>>\nclass ViewableMap : public IViewableMap<K, V>\n{\npublic:\n\tusing Event = typename IViewableMap<K, V>::Event;\n\nprivate:\n\tusing WK = typename IViewableMap<K, V>::WK;\n\tusing WV = typename IViewableMap<K, V>::WV;\n\tusing OV = typename IViewableMap<K, V>::OV;\n\tusing PA = typename std::allocator_traits<VA>::template rebind_alloc<std::pair<Wrapper<K>, Wrapper<V>>>;\n\n\tSignal<Event> change;\n\n\tusing data_t = ordered_map<Wrapper<K>, Wrapper<V>, wrapper::TransparentHash<K>, wrapper::TransparentKeyEqual<K>, PA>;\n\tmutable data_t map;\n\npublic:\n\t// region ctor/dtor\n\n\tViewableMap() = default;\n\n\tViewableMap(ViewableMap&&) = default;\n\n\tViewableMap& operator=(ViewableMap&&) = default;\n\n\tvirtual ~ViewableMap() = default;\n\t// endregion\n\n\t// region iterators\n\npublic:\n\tclass iterator\n\t{\n\t\tfriend class ViewableMap<K, V>;\n\n\t\tmutable typename data_t::iterator it_;\n\n\t\texplicit iterator(const typename data_t::iterator& it) : it_(it)\n\t\t{\n\t\t}\n\n\tpublic:\n\t\tusing iterator_category = typename data_t::iterator::iterator_category;\n\t\tusing key_type = K;\n\t\tusing value_type = V;\n\t\tusing difference_type = std::ptrdiff_t;\n\t\tusing reference = V const&;\n\t\tusing pointer = V const*;\n\n\t\titerator(const iterator& other) = default;\n\n\t\titerator(iterator&& other) noexcept = default;\n\n\t\titerator& operator=(const iterator& other) = default;\n\n\t\titerator& operator=(iterator&& other) noexcept = default;\n\n\t\titerator& operator++()\n\t\t{\n\t\t\t++it_;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator operator++(int)\n\t\t{\n\t\t\tauto it = *this;\n\t\t\t++*this;\n\t\t\treturn it;\n\t\t}\n\n\t\titerator& operator--()\n\t\t{\n\t\t\t--it_;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator operator--(int)\n\t\t{\n\t\t\tauto it = *this;\n\t\t\t--*this;\n\t\t\treturn it;\n\t\t}\n\n\t\titerator& operator+=(difference_type delta)\n\t\t{\n\t\t\tit_ += delta;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator& operator-=(difference_type delta)\n\t\t{\n\t\t\tit_ -= delta;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator operator+(difference_type delta) const\n\t\t{\n\t\t\tauto it = *this;\n\t\t\treturn it += delta;\n\t\t}\n\n\t\titerator operator-(difference_type delta) const\n\t\t{\n\t\t\tauto it = *this;\n\t\t\treturn it -= delta;\n\t\t}\n\n\t\tdifference_type operator-(iterator const& other) const\n\t\t{\n\t\t\treturn it_ - other.it_;\n\t\t}\n\n\t\tbool operator<(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn this->it_ < other.it_;\n\t\t}\n\n\t\tbool operator>(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn this->it_ > other.it_;\n\t\t}\n\n\t\tbool operator==(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn this->it_ == other.it_;\n\t\t}\n\n\t\tbool operator!=(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn !(*this == other);\n\t\t}\n\n\t\tbool operator<=(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn (this->it_ < other.it_) || (*this == other);\n\t\t}\n\n\t\tbool operator>=(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn (this->it_ > other.it_) || (*this == other);\n\t\t}\n\n\t\treference operator*() const noexcept\n\t\t{\n\t\t\treturn *it_.value();\n\t\t}\n\n\t\tpointer operator->() const noexcept\n\t\t{\n\t\t\treturn it_.value().get();\n\t\t}\n\n\t\tkey_type const& key() const\n\t\t{\n\t\t\treturn *it_.key();\n\t\t}\n\n\t\tvalue_type const& value() const\n\t\t{\n\t\t\treturn *it_.value();\n\t\t}\n\t};\n\n\tclass reverse_iterator : public std::reverse_iterator<iterator>\n\t{\n\t\tusing base_t = std::reverse_iterator<iterator>;\n\n\tpublic:\n\t\tusing iterator_category = typename iterator::iterator_category;\n\t\tusing key_type = typename iterator::key_type;\n\t\tusing value_type = typename iterator::value_type;\n\t\tusing difference_type = typename iterator::difference_type;\n\t\tusing reference = typename iterator::reference;\n\t\tusing pointer = typename iterator::pointer;\n\n\t\treverse_iterator(const reverse_iterator& other) = default;\n\n\t\treverse_iterator& operator=(const reverse_iterator& other) = default;\n\n\t\texplicit reverse_iterator(const iterator& other) : base_t(other){};\n\n\t\treverse_iterator& operator=(const iterator& other)\n\t\t{\n\t\t\tstatic_cast<base_t>(*this) = other;\n\t\t};\n\n\t\tkey_type const& key() const\n\t\t{\n\t\t\tauto it = base_t::current;\n\t\t\treturn (--(it)).key();\n\t\t}\n\n\t\tvalue_type const& value() const\n\t\t{\n\t\t\tauto it = base_t::current;\n\t\t\treturn (--it).value();\n\t\t}\n\t};\n\n\titerator begin() const\n\t{\n\t\treturn iterator(map.begin());\n\t}\n\n\titerator end() const\n\t{\n\t\treturn iterator(map.end());\n\t}\n\n\treverse_iterator rbegin() const\n\t{\n\t\treturn reverse_iterator(end());\n\t}\n\n\treverse_iterator rend() const\n\t{\n\t\treturn reverse_iterator(begin());\n\t}\n\n\t// endregion\n\n\tvoid advise(Lifetime lifetime, std::function<void(Event const&)> handler) const override\n\t{\n\t\tchange.advise(lifetime, handler);\n\t\t/*for (auto const &[key, value] : map) {*/\n\t\tfor (auto const& it : map)\n\t\t{\n\t\t\tauto& key = it.first;\n\t\t\tauto& value = it.second;\n\t\t\thandler(Event(typename Event::Add(&(*key), &(*value))));\n\t\t\t;\n\t\t}\n\t}\n\n\tconst V* get(K const& key) const override\n\t{\n\t\tauto it = map.find(key);\n\t\tif (it == map.end())\n\t\t{\n\t\t\treturn nullptr;\n\t\t}\n\t\treturn &(*it->second);\n\t}\n\n\tconst V* set(WK key, WV value) const override\n\t{\n\t\tif (map.count(key) == 0)\n\t\t{\n\t\t\t/*auto[it, success] = map.emplace(std::make_unique<K>(std::move(key)), std::make_unique<V>(std::move(value)));*/\n\t\t\tauto node = map.emplace(std::move(key), std::move(value));\n\t\t\tauto& it = node.first;\n\t\t\tauto const& key_ptr = it->first;\n\t\t\tauto const& value_ptr = it->second;\n\t\t\tchange.fire(typename Event::Add(&(*key_ptr), &(*value_ptr)));\n\t\t\treturn nullptr;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto it = map.find(key);\n\t\t\tauto const& key_ptr = it->first;\n\t\t\tauto const& value_ptr = it->second;\n\n\t\t\tif (*value_ptr != wrapper::get<V>(value))\n\t\t\t{\t // TO-DO more effective\n\t\t\t\tWrapper<V> old_value = std::move(map.at(key));\n\n\t\t\t\tmap.at(key_ptr) = Wrapper<V>(std::move(value));\n\t\t\t\tchange.fire(typename Event::Update(&(*key_ptr), &(*old_value), &(*value_ptr)));\n\t\t\t}\n\t\t\treturn &*(value_ptr);\n\t\t}\n\t}\n\n\tOV remove(K const& key) const override\n\t{\n\t\tif (map.count(key) > 0)\n\t\t{\n\t\t\tWrapper<V> old_value = std::move(map.at(key));\n\t\t\tchange.fire(typename Event::Remove(&key, &(*old_value)));\n\t\t\tmap.erase(key);\n\t\t\treturn wrapper::unwrap<V>(std::move(old_value));\n\t\t}\n\t\treturn nullopt;\n\t}\n\n\tvoid clear() const override\n\t{\n\t\tstd::vector<Event> changes;\n\t\t/*for (auto const &[key, value] : map) {*/\n\t\tfor (auto const& it : map)\n\t\t{\n\t\t\tchanges.push_back(typename Event::Remove(&(*it.first), &(*it.second)));\n\t\t}\n\t\tfor (auto const& it : changes)\n\t\t{\n\t\t\tchange.fire(it);\n\t\t}\n\t\tmap.clear();\n\t}\n\n\tsize_t size() const override\n\t{\n\t\treturn map.size();\n\t}\n\n\tbool empty() const override\n\t{\n\t\treturn map.empty();\n\t}\n};\n}\t // namespace rd\n\nstatic_assert(std::is_move_constructible<rd::ViewableMap<int, int>>::value, \"Is move constructible from ViewableMap<int, int>\");\n\n#endif\t  // RD_CPP_CORE_VIEWABLE_MAP_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/ViewableSet.h",
    "content": "#ifndef RD_CPP_CORE_VIEWABLESET_H\n#define RD_CPP_CORE_VIEWABLESET_H\n\n#include \"base/IViewableSet.h\"\n#include \"reactive/base/SignalX.h\"\n\n#include <std/allocator.h>\n#include <util/core_util.h>\n\nnamespace rd\n{\n/**\n * \\brief complete class which has @code IViewableSet<T>'s properties\n * \\tparam T\n */\ntemplate <typename T, typename A = allocator<T>>\nclass ViewableSet : public IViewableSet<T, A>\n{\npublic:\n\tusing Event = typename IViewableSet<T>::Event;\n\n\tusing IViewableSet<T, A>::advise;\n\nprivate:\n\tusing WT = typename IViewableSet<T, A>::WT;\n\tusing WA = typename std::allocator_traits<A>::template rebind_alloc<Wrapper<T>>;\n\n\tSignal<Event> change;\n\tusing data_t = ordered_set<Wrapper<T>, wrapper::TransparentHash<T>, wrapper::TransparentKeyEqual<T>, WA>;\n\tmutable data_t set;\n\npublic:\n\t// region ctor/dtor\n\n\tViewableSet() = default;\n\n\tViewableSet(ViewableSet&&) = default;\n\n\tViewableSet& operator=(ViewableSet&&) = default;\n\n\tvirtual ~ViewableSet() = default;\n\t// endregion\n\n\t// region iterators\npublic:\n\tclass iterator\n\t{\n\t\tfriend class ViewableSet<T>;\n\n\t\ttypename data_t::iterator it_;\n\n\t\texplicit iterator(const typename data_t::iterator& it) : it_(it)\n\t\t{\n\t\t}\n\n\tpublic:\n\t\tusing iterator_category = std::random_access_iterator_tag;\n\t\tusing value_type = T;\n\t\tusing difference_type = std::ptrdiff_t;\n\t\tusing pointer = T const*;\n\t\tusing reference = T const&;\n\n\t\titerator(const iterator& other) = default;\n\n\t\titerator(iterator&& other) noexcept = default;\n\n\t\titerator& operator=(const iterator& other) = default;\n\n\t\titerator& operator=(iterator&& other) noexcept = default;\n\n\t\titerator& operator++()\n\t\t{\n\t\t\t++it_;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator operator++(int)\n\t\t{\n\t\t\tauto it = *this;\n\t\t\t++*this;\n\t\t\treturn it;\n\t\t}\n\n\t\titerator& operator--()\n\t\t{\n\t\t\t--it_;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator operator--(int)\n\t\t{\n\t\t\tauto it = *this;\n\t\t\t--*this;\n\t\t\treturn it;\n\t\t}\n\n\t\titerator& operator+=(difference_type delta)\n\t\t{\n\t\t\tit_ += delta;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator& operator-=(difference_type delta)\n\t\t{\n\t\t\tit_ -= delta;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator operator+(difference_type delta) const\n\t\t{\n\t\t\tauto it = *this;\n\t\t\treturn it += delta;\n\t\t}\n\n\t\titerator operator-(difference_type delta) const\n\t\t{\n\t\t\tauto it = *this;\n\t\t\treturn it -= delta;\n\t\t}\n\n\t\tdifference_type operator-(iterator const& other) const\n\t\t{\n\t\t\treturn it_ - other.it_;\n\t\t}\n\n\t\tbool operator<(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn this->it_ < other.it_;\n\t\t}\n\n\t\tbool operator>(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn this->it_ > other.it_;\n\t\t}\n\n\t\tbool operator==(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn this->it_ == other.it_;\n\t\t}\n\n\t\tbool operator!=(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn !(*this == other);\n\t\t}\n\n\t\tbool operator<=(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn (this->it_ < other.it_) || (*this == other);\n\t\t}\n\n\t\tbool operator>=(iterator const& other) const noexcept\n\t\t{\n\t\t\treturn (this->it_ > other.it_) || (*this == other);\n\t\t}\n\n\t\treference operator*() const noexcept\n\t\t{\n\t\t\treturn **it_;\n\t\t}\n\n\t\tpointer operator->() const noexcept\n\t\t{\n\t\t\treturn (*it_).get();\n\t\t}\n\t};\n\n\tusing reverse_iterator = std::reverse_iterator<iterator>;\n\n\titerator begin() const\n\t{\n\t\treturn iterator(set.begin());\n\t}\n\n\titerator end() const\n\t{\n\t\treturn iterator(set.end());\n\t}\n\n\treverse_iterator rbegin() const\n\t{\n\t\treturn reverse_iterator(end());\n\t}\n\n\treverse_iterator rend() const\n\t{\n\t\treturn reverse_iterator(begin());\n\t}\n\n\t// endregion\n\n\tbool add(WT element) const override\n\t{\n\t\t/*auto const &[it, success] = set.emplace(std::make_unique<T>(std::move(element)));*/\n\t\tauto const& it = set.emplace(std::move(element));\n\t\tif (!it.second)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tchange.fire(Event(AddRemove::ADD, &(wrapper::get<T>(*it.first))));\n\t\treturn true;\n\t}\n\n\tbool addAll(std::vector<WT> elements) const override\n\t{\n\t\tfor (auto&& element : elements)\n\t\t{\n\t\t\tViewableSet::add(std::move(element));\n\t\t}\n\t\treturn true;\n\t}\n\n\tvoid clear() const override\n\t{\n\t\tstd::vector<Event> changes;\n\t\tfor (auto const& element : set)\n\t\t{\n\t\t\tchanges.push_back(Event(AddRemove::REMOVE, &(*element)));\n\t\t}\n\t\tfor (auto const& e : changes)\n\t\t{\n\t\t\tchange.fire(e);\n\t\t}\n\t\tset.clear();\n\t}\n\n\tbool remove(T const& element) const override\n\t{\n\t\tif (!ViewableSet::contains(element))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tauto it = set.find(element);\n\t\tchange.fire(Event(AddRemove::REMOVE, &(wrapper::get<T>(*it))));\n\t\tset.erase(it);\n\t\treturn true;\n\t}\n\n\tvoid advise(Lifetime lifetime, std::function<void(Event const&)> handler) const override\n\t{\n\t\tfor (auto const& x : set)\n\t\t{\n\t\t\thandler(Event(AddRemove::ADD, &(*x)));\n\t\t}\n\t\tchange.advise(lifetime, handler);\n\t}\n\n\tsize_t size() const override\n\t{\n\t\treturn set.size();\n\t}\n\n\tbool contains(T const& element) const override\n\t{\n\t\treturn set.count(element) > 0;\n\t}\n\n\tbool empty() const override\n\t{\n\t\treturn set.empty();\n\t}\n\n\ttemplate <typename... Args>\n\tbool emplace_add(Args&&... args) const\n\t{\n\t\treturn add(WT{std::forward<Args>(args)...});\n\t}\n};\n}\t // namespace rd\n\nstatic_assert(std::is_move_constructible<rd::ViewableSet<int>>::value, \"Is move constructible from ViewableSet<int>\");\n\n#endif\t  // RD_CPP_CORE_VIEWABLESET_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/IProperty.h",
    "content": "#ifndef RD_CPP_IPROPERTY_H\n#define RD_CPP_IPROPERTY_H\n\n#include \"SignalX.h\"\n#include \"IPropertyBase.h\"\n\n#include <lifetime/Lifetime.h>\n#include <types/wrapper.h>\n\n#include <functional>\n\nnamespace rd\n{\n/**\n * \\brief A mutable property.\n * \\tparam T type of stored value (may be abstract)\n */\ntemplate <typename T>\nclass IProperty : public IPropertyBase<T>\n{\nprotected:\n\tusing WT = typename IPropertyBase<T>::WT;\n\npublic:\n\t// region ctor/dtor\n\n\tIProperty() = default;\n\n\tIProperty(IProperty&& other) = default;\n\n\tIProperty& operator=(IProperty&& other) = default;\n\n\texplicit IProperty(T const& value) : IPropertyBase<T>(value)\n\t{\n\t}\n\n\ttemplate <typename F>\n\texplicit IProperty(F&& value) : IPropertyBase<T>(std::forward<F>(value))\n\t{\n\t}\n\n\tvirtual ~IProperty() = default;\n\t// endregion\n\n\tvirtual T const& get() const = 0;\n\nprivate:\n\tvoid advise0(Lifetime lifetime, std::function<void(T const&)> handler, Signal<T> const& signal) const\n\t{\n\t\tif (lifetime->is_terminated())\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tsignal.advise(lifetime, handler);\n\t\tif (this->has_value())\n\t\t{\n\t\t\thandler(this->get());\n\t\t}\n\t}\n\n\tvoid advise_before(Lifetime lifetime, std::function<void(T const&)> handler) const override\n\t{\n\t\tadvise0(lifetime, handler, this->before_change);\n\t}\n\npublic:\n\tvoid advise(Lifetime lifetime, std::function<void(T const&)> handler) const override\n\t{\n\t\tadvise0(lifetime, std::move(handler), this->change);\n\t}\n\n\t/**\n\t * \\brief set value of type T or derived type to it.\n\t */\n\tvirtual void set(value_or_wrapper<T>) const = 0;\n\n\t/**\n\t * \\brief construct value of type T and delegate call to set\n\t */\n\ttemplate <typename... Args>\n\tvoid emplace(Args&&... args) const\n\t{\n\t\tset(value_or_wrapper<T>{std::forward<Args>(args)...});\n\t}\n\n\tvoid set_if_empty(WT new_value) const\n\t{\n\t\tif (!this->has_value())\n\t\t{\n\t\t\tset(std::move(new_value));\n\t\t}\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_IPROPERTY_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/IPropertyBase.h",
    "content": "#ifndef RD_CPP_IPROPERTYBASE_H\n#define RD_CPP_IPROPERTYBASE_H\n\n#include \"interfaces.h\"\n#include \"SignalX.h\"\n\n#include <types/wrapper.h>\n#include <lifetime/SequentialLifetimes.h>\n\n#include \"thirdparty.hpp\"\n\nnamespace rd\n{\ntemplate <typename T>\nclass IPropertyBase : public ISource<T>, public IViewable<T>\n{\nprotected:\n\tmutable property_storage<T> value;\n\n\tSignal<T> change, before_change;\n\n\tusing WT = value_or_wrapper<T>;\n\npublic:\n\tbool has_value() const\n\t{\n\t\treturn (bool) (value);\n\t}\n\n\t// region ctor/dtor\n\n\tIPropertyBase() = default;\n\n\tIPropertyBase(IPropertyBase&& other) = default;\n\n\tIPropertyBase& operator=(IPropertyBase&& other) = default;\n\n\ttemplate <typename F>\n\texplicit IPropertyBase(F&& value) : value(std::forward<F>(value))\n\t{\n\t}\n\n\tvirtual ~IPropertyBase() = default;\n\t// endregion\n\n\tvirtual void advise_before(Lifetime lifetime, std::function<void(T const&)> handler) const = 0;\n\n\tvoid view(Lifetime lifetime, std::function<void(Lifetime, T const&)> handler) const override\n\t{\n\t\tif (lifetime->is_terminated())\n\t\t\treturn;\n\n\t\tLifetime lf = lifetime.create_nested();\n\t\tstd::shared_ptr<SequentialLifetimes> seq = std::make_shared<SequentialLifetimes>(lf);\n\n\t\tthis->advise_before(lf, [lf, seq](T const& /*v*/) {\n\t\t\tif (!lf->is_terminated())\n\t\t\t{\n\t\t\t\tseq->terminate_current();\n\t\t\t}\n\t\t});\n\n\t\tthis->advise(lf, [lf, seq, handler](T const& v) {\n\t\t\tif (!lf->is_terminated())\n\t\t\t{\n\t\t\t\thandler(seq->next(), v);\n\t\t\t}\n\t\t});\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_IPROPERTYBASE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/IViewableList.h",
    "content": "#ifndef RD_CPP_IVIEWABLELIST_H\n#define RD_CPP_IVIEWABLELIST_H\n\n#include \"interfaces.h\"\n#include \"viewable_collections.h\"\n\n#include <lifetime/LifetimeDefinition.h>\n#include <util/overloaded.h>\n#include <types/wrapper.h>\n\n#include <std/unordered_map.h>\n\n#include <vector>\n#include <utility>\n#include <algorithm>\n\n#include \"thirdparty.hpp\"\n\nnamespace rd\n{\nnamespace detail\n{\ntemplate <typename T>\nclass ListEvent\n{\npublic:\n\tclass Add\n\t{\n\tpublic:\n\t\tint32_t index;\n\t\tT const* new_value;\n\n\t\tAdd(int32_t index, T const* new_value) : index(index), new_value(new_value)\n\t\t{\n\t\t}\n\t};\n\n\tclass Update\n\t{\n\tpublic:\n\t\tint32_t index;\n\t\tT const* old_value;\n\t\tT const* new_value;\n\n\t\tUpdate(int32_t index, T const* old_value, T const* new_value) : index(index), old_value(old_value), new_value(new_value)\n\t\t{\n\t\t}\n\t};\n\n\tclass Remove\n\t{\n\tpublic:\n\t\tint32_t index;\n\t\tT const* old_value;\n\n\t\tRemove(int32_t index, T const* old_value) : index(index), old_value(old_value)\n\t\t{\n\t\t}\n\t};\n\n\tvariant<Add, Update, Remove> v;\n\n\tListEvent(Add x) : v(x)\n\t{\n\t}\n\n\tListEvent(Update x) : v(x)\n\t{\n\t}\n\n\tListEvent(Remove x) : v(x)\n\t{\n\t}\n\n\tint32_t get_index() const\n\t{\n\t\treturn visit(util::make_visitor([](Add const& e) { return e.index; }, [](Update const& e) { return e.index; },\n\t\t\t\t\t\t [](Remove const& e) { return e.index; }),\n\t\t\tv);\n\t}\n\n\tT const* get_new_value() const\n\t{\n\t\treturn visit(util::make_visitor([](Add const& e) { return e.new_value; }, [](Update const& e) { return e.new_value; },\n\t\t\t\t\t\t [](Remove const& /*e*/) { return static_cast<T const*>(nullptr); }),\n\t\t\tv);\n\t}\n\n\tfriend std::string to_string(ListEvent const& e)\n\t{\n\t\tstd::string res = visit(\n\t\t\tutil::make_visitor(\n\t\t\t\t[](typename ListEvent::Add const& e) { return \"Add \" + std::to_string(e.index) + \":\" + to_string(*e.new_value); },\n\t\t\t\t[](typename ListEvent::Update const& e) {\n\t\t\t\t\treturn \"Update \" + std::to_string(e.index) + \":\" +\n\t\t\t\t\t\t   //                       to_string(e.old_value) + \":\" +\n\t\t\t\t\t\t   to_string(*e.new_value);\n\t\t\t\t},\n\t\t\t\t[](typename ListEvent::Remove const& e) { return \"Remove \" + std::to_string(e.index); }),\n\t\t\te.v);\n\t\treturn res;\n\t}\n};\n}\t // namespace detail\n/**\n * \\brief A list allowing its contents to be observed.\n * \\tparam T type of stored values (may be abstract)\n */\ntemplate <typename T>\nclass IViewableList : public IViewable<std::pair<size_t, T const*>>, public ISource<detail::ListEvent<T>>\n{\nprotected:\n\tusing WT = value_or_wrapper<T>;\n\npublic:\n\t/**\n\t * \\brief Represents an addition, update or removal of an element in the list.\n\t */\n\tusing Event = typename detail::ListEvent<T>;\n\nprotected:\n\tmutable rd::unordered_map<Lifetime, std::vector<LifetimeDefinition>> lifetimes;\n\npublic:\n\t// region ctor/dtor\n\n\tIViewableList() = default;\n\n\tIViewableList(IViewableList&&) = default;\n\n\tIViewableList& operator=(IViewableList&&) = default;\n\n\tvirtual ~IViewableList() = default;\n\t// endregion\n\n\t/**\n\t * \\brief Adds a subscription to additions and removals of list elements. When a list element is updated,\n\t * the [handler] is called twice: to report the removal of the old element and the addition of the new one.\n\t * \\param lifetime lifetime of subscription.\n\t * \\param handler to be called.\n\t */\n\tvoid advise_add_remove(Lifetime lifetime, std::function<void(AddRemove, size_t, T const&)> handler) const\n\t{\n\t\tadvise(lifetime, [handler](Event e) {\n\t\t\tvisit(util::make_visitor([handler](typename Event::Add const& e) { handler(AddRemove::ADD, e.index, *e.new_value); },\n\t\t\t\t\t  [handler](typename Event::Update const& e) {\n\t\t\t\t\t\t  handler(AddRemove::REMOVE, e.index, *e.old_value);\n\t\t\t\t\t\t  handler(AddRemove::ADD, e.index, *e.new_value);\n\t\t\t\t\t  },\n\t\t\t\t\t  [handler](typename Event::Remove const& e) { handler(AddRemove::REMOVE, e.index, *e.old_value); }),\n\t\t\t\te.v);\n\t\t});\n\t}\n\n\t/**\n\t * \\brief Adds a subscription to changes of the contents of the list.\n\t * \\param lifetime lifetime of subscription.\n\t * \\param handler to be called.\n\t */\n\tvoid view(Lifetime lifetime, std::function<void(Lifetime lifetime, std::pair<size_t, T const*> const&)> handler) const override\n\t{\n\t\tview(lifetime, [handler](Lifetime lt, size_t idx, T const& v) { handler(lt, std::make_pair(idx, &v)); });\n\t}\n\n\t/**\n\t * \\brief @see view\tabove\n\t */\n\tvoid view(Lifetime lifetime, std::function<void(Lifetime, size_t, T const&)> handler) const\n\t{\n\t\tadvise_add_remove(lifetime, [this, lifetime, handler](AddRemove kind, size_t idx, T const& value) {\n\t\t\tswitch (kind)\n\t\t\t{\n\t\t\t\tcase AddRemove::ADD:\n\t\t\t\t{\n\t\t\t\t\tLifetimeDefinition def(lifetime);\n\t\t\t\t\tstd::vector<LifetimeDefinition>& v = lifetimes[lifetime];\n\t\t\t\t\tauto it = v.emplace(v.begin() + idx, std::move(def));\n\t\t\t\t\thandler(it->lifetime, idx, value);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase AddRemove::REMOVE:\n\t\t\t\t{\n\t\t\t\t\tLifetimeDefinition def = std::move(lifetimes.at(lifetime)[idx]);\n\t\t\t\t\tstd::vector<LifetimeDefinition>& v = lifetimes.at(lifetime);\n\t\t\t\t\tv.erase(v.begin() + idx);\n\t\t\t\t\tdef.terminate();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tvoid advise(Lifetime lifetime, std::function<void(Event const&)> handler) const override = 0;\n\n\tvirtual bool add(WT element) const = 0;\n\n\tvirtual bool add(size_t index, WT element) const = 0;\n\n\tvirtual WT removeAt(size_t index) const = 0;\n\n\tvirtual bool remove(T const& element) const = 0;\n\n\tvirtual T const& get(size_t index) const = 0;\n\n\tvirtual WT set(size_t index, WT element) const = 0;\n\n\tvirtual bool addAll(size_t index, std::vector<WT> elements) const = 0;\n\n\tvirtual bool addAll(std::vector<WT> elements) const = 0;\n\n\tvirtual void clear() const = 0;\n\n\tvirtual bool removeAll(std::vector<WT> elements) const = 0;\n\n\tvirtual size_t size() const = 0;\n\n\tvirtual bool empty() const = 0;\n\n\ttemplate <typename... Args>\n\tbool emplace_add(Args&&... args) const\n\t{\n\t\treturn add(WT{std::forward<Args>(args)...});\n\t}\n\n\ttemplate <typename... Args>\n\tbool emplace_add(size_t index, Args&&... args) const\n\t{\n\t\treturn add(index, WT{std::forward<Args>(args)...});\n\t}\n\n\ttemplate <typename... Args>\n\tWT emplace_set(size_t index, Args&&... args) const\n\t{\n\t\treturn set(index, WT{std::forward<Args>(args)...});\n\t}\n\n\ttemplate <typename U>\n\tfriend typename std::enable_if<(!std::is_abstract<U>::value), std::vector<U>>::type convert_to_list(\n\t\tIViewableList<U> const& list);\n\nprotected:\n\tvirtual const std::vector<Wrapper<T>>& getList() const = 0;\n};\n\ntemplate <typename T>\ntypename std::enable_if<(!std::is_abstract<T>::value), std::vector<T>>::type convert_to_list(IViewableList<T> const& list)\n{\n\tstd::vector<T> res(list.size());\n\tstd::transform(list.getList().begin(), list.getList().end(), res.begin(), [](Wrapper<T> const& ptr) { return *ptr; });\n\treturn res;\n}\n}\t // namespace rd\n\nstatic_assert(\n\tstd::is_move_constructible<rd::IViewableList<int>::Event>::value, \"Is move constructible from IViewableList<int>::Event\");\n\n#endif\t  // RD_CPP_IVIEWABLELIST_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/IViewableMap.h",
    "content": "#ifndef RD_CPP_IVIEWABLEMAP_H\n#define RD_CPP_IVIEWABLEMAP_H\n\n#include \"lifetime/LifetimeDefinition.h\"\n#include \"util/overloaded.h\"\n#include \"interfaces.h\"\n#include \"viewable_collections.h\"\n#include \"util/core_util.h\"\n\n#include \"std/unordered_map.h\"\n\n#include \"thirdparty.hpp\"\n\nnamespace rd\n{\nnamespace detail\n{\ntemplate <typename K, typename V>\nclass MapEvent\n{\npublic:\n\tclass Add\n\t{\n\tpublic:\n\t\tK const* key;\n\t\tV const* new_value;\n\n\t\tAdd(K const* key, V const* new_value) : key(key), new_value(new_value)\n\t\t{\n\t\t}\n\t};\n\n\tclass Update\n\t{\n\tpublic:\n\t\tK const* key;\n\t\tV const* old_value;\n\t\tV const* new_value;\n\n\t\tUpdate(K const* key, V const* old_value, V const* new_value) : key(key), old_value(old_value), new_value(new_value)\n\t\t{\n\t\t}\n\t};\n\n\tclass Remove\n\t{\n\tpublic:\n\t\tK const* key;\n\t\tV const* old_value;\n\n\t\tRemove(K const* key, V const* old_value) : key(key), old_value(old_value)\n\t\t{\n\t\t}\n\t};\n\n\tvariant<Add, Update, Remove> v;\n\n\tMapEvent(Add x) : v(x)\n\t{\n\t}\n\n\tMapEvent(Update x) : v(x)\n\t{\n\t}\n\n\tMapEvent(Remove x) : v(x)\n\t{\n\t}\n\n\tK const* get_key() const\n\t{\n\t\treturn visit(\n\t\t\tutil::make_visitor([](typename MapEvent::Add const& e) { return e.key; },\n\t\t\t\t[](typename MapEvent::Update const& e) { return e.key; }, [](typename MapEvent::Remove const& e) { return e.key; }),\n\t\t\tv);\n\t}\n\n\tV const* get_old_value() const\n\t{\n\t\treturn visit(util::make_visitor([](typename MapEvent::Add const&) { return static_cast<V const*>(nullptr); },\n\t\t\t\t\t\t [](typename MapEvent::Update const& e) { return e.old_value; },\n\t\t\t\t\t\t [](typename MapEvent::Remove const& e) { e.old_value; }),\n\t\t\tv);\n\t}\n\n\tV const* get_new_value() const\n\t{\n\t\treturn visit(util::make_visitor([](typename MapEvent::Add const& e) { return e.new_value; },\n\t\t\t\t\t\t [](typename MapEvent::Update const& e) { return e.new_value; },\n\t\t\t\t\t\t [](typename MapEvent::Remove const& /*e*/) { return static_cast<V const*>(nullptr); }),\n\t\t\tv);\n\t}\n\n\tfriend std::string to_string(MapEvent const& e)\n\t{\n\t\tstd::string res =\n\t\t\tvisit(util::make_visitor([](typename MapEvent::Add const& e)\n\t\t\t\t\t\t\t\t\t\t -> std::string { return \"Add \" + to_string(*e.key) + \":\" + to_string(*e.new_value); },\n\t\t\t\t\t  [](typename MapEvent::Update const& e) -> std::string {\n\t\t\t\t\t\t  return \"Update \" + to_string(*e.key) + \":\" +\n\t\t\t\t\t\t\t\t //                       to_string(e.old_value) + \":\" +\n\t\t\t\t\t\t\t\t to_string(*e.new_value);\n\t\t\t\t\t  },\n\t\t\t\t\t  [](typename MapEvent::Remove const& e) -> std::string { return \"Remove \" + to_string(*e.key); }),\n\t\t\t\te.v);\n\t\treturn res;\n\t}\n};\n}\t // namespace detail\n\n/**\n * \\brief A set allowing its contents to be observed.\n * \\tparam K type of stored keys (may be abstract)\n * \\tparam V type of stored values (may be abstract)\n */\ntemplate <typename K, typename V>\nclass IViewableMap : public IViewable<std::pair<K const*, V const*>>, public ISource<detail::MapEvent<K, V>>\n{\nprotected:\n\tusing WK = value_or_wrapper<K>;\n\tusing WV = value_or_wrapper<V>;\n\tusing OV = opt_or_wrapper<V>;\n\n\tmutable rd::unordered_map<Lifetime,\n\t\tordered_map<K const*, LifetimeDefinition, wrapper::TransparentHash<K>, wrapper::TransparentKeyEqual<K>>>\n\t\tlifetimes;\n\npublic:\n\t/**\n\t * \\brief Represents an addition, update or removal of an element in the map.\n\t */\n\tusing Event = typename detail::MapEvent<K, V>;\n\n\t// region ctor/dtor\n\n\tIViewableMap() = default;\n\n\tIViewableMap(IViewableMap&&) = default;\n\n\tIViewableMap& operator=(IViewableMap&&) = default;\n\n\tvirtual ~IViewableMap() = default;\n\t// endregion\n\n\tvoid view(Lifetime lifetime, std::function<void(Lifetime lifetime, std::pair<K const*, V const*> const&)\n\n\t\t\t\t\t\t\t\t\t >\n\t\t\t\t\t\t\t\t\t handler) const override\n\t{\n\t\tadvise_add_remove(lifetime, [this, lifetime, handler](AddRemove kind, K const& key, V const& value) {\n\t\t\tconst std::pair<K const*, V const*> entry = std::make_pair(&key, &value);\n\t\t\tswitch (kind)\n\t\t\t{\n\t\t\t\tcase AddRemove::ADD:\n\t\t\t\t{\n\t\t\t\t\tif (lifetimes[lifetime].count(key) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t/*auto const &[it, inserted] = lifetimes[lifetime].emplace(key, LifetimeDefinition(lifetime));*/\n\t\t\t\t\t\tauto const& pair = lifetimes[lifetime].emplace(&key, LifetimeDefinition(lifetime));\n\t\t\t\t\t\tauto& it = pair.first;\n\t\t\t\t\t\tauto& inserted = pair.second;\n\t\t\t\t\t\tRD_ASSERT_MSG(inserted, \"lifetime definition already exists in viewable map by key:\" + to_string(key));\n\t\t\t\t\t\thandler(it->second.lifetime, entry);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase AddRemove::REMOVE:\n\t\t\t\t{\n\t\t\t\t\tRD_ASSERT_MSG(lifetimes.at(lifetime).count(key) > 0,\n\t\t\t\t\t\t\"attempting to remove non-existing lifetime in viewable map by key:\" + to_string(key));\n\t\t\t\t\tLifetimeDefinition def = std::move(lifetimes.at(lifetime).at(key));\n\t\t\t\t\tlifetimes.at(lifetime).erase(key);\n\t\t\t\t\tdef.terminate();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * \\brief Adds a subscription to additions and removals of map elements. When a map element is updated, the [handler]\n\t * is called twice: to report the removal of the old element and the addition of the new one.\n\t * \\param lifetime lifetime of subscription.\n\t * \\param handler to be called.\n\t */\n\tvoid advise_add_remove(Lifetime lifetime, std::function<void(AddRemove, K const&, V const&)\n\n\t\t\t\t\t\t\t\t\t\t\t\t  >\n\t\t\t\t\t\t\t\t\t\t\t\t  handler) const\n\t{\n\t\tadvise(lifetime, [handler](Event e) {\n\t\t\tvisit(util::make_visitor([handler](typename Event::Add const& e) { handler(AddRemove::ADD, *e.key, *e.new_value); },\n\t\t\t\t\t  [handler](typename Event::Update const& e) {\n\t\t\t\t\t\t  handler(AddRemove::REMOVE, *e.key, *e.old_value);\n\t\t\t\t\t\t  handler(AddRemove::ADD, *e.key, *e.new_value);\n\t\t\t\t\t  },\n\t\t\t\t\t  [handler](typename Event::Remove const& e) { handler(AddRemove::REMOVE, *e.key, *e.old_value); }),\n\t\t\t\te.v);\n\t\t});\n\t}\n\n\t/**\n\t * \\brief Adds a subscription to changes of the contents of the map, with the handler receiving keys and values\n\t * as separate parameters.\n\t *\n\t * \\details When [handler] is initially added, it is called receiving all keys and values currently in the map.\n\t * Every time a key/value pair is added to the map, the [handler] is called receiving the new key and value.\n\t * The [Lifetime] instance passed to the handler expires when the key/value pair is removed from the map.\n\t *\n\t * \\param lifetime lifetime of subscription.\n\t * \\param handler to be called.\n\t */\n\tvoid view(Lifetime lifetime, std::function<void(Lifetime, K const&, V const&)\n\n\t\t\t\t\t\t\t\t\t >\n\t\t\t\t\t\t\t\t\t handler) const\n\t{\n\t\tview(lifetime,\n\t\t\t[handler](Lifetime lf, const std::pair<K const*, V const*> entry) { handler(lf, *entry.first, *entry.second); });\n\t}\n\n\tvoid advise(Lifetime lifetime, std::function<void(Event const&)> handler) const override = 0;\n\n\tvirtual const V* get(K const&) const = 0;\n\n\tvirtual const V* set(WK, WV) const = 0;\n\n\tvirtual OV remove(K const&) const = 0;\n\n\tvirtual void clear() const = 0;\n\n\tvirtual size_t size() const = 0;\n\n\tvirtual bool empty() const = 0;\n\n\ttemplate <typename... Args>\n\tconst V* emplace_set(WK wk, Args&&... args) const\n\t{\n\t\treturn set(std::move(wk), WV{std::forward<Args>(args)...});\n\t}\n};\n}\t // namespace rd\n\nstatic_assert(std::is_move_constructible<rd::IViewableMap<int, int>::Event>::value,\n\t\"Is move constructible from IViewableMap<int, int>::Event\");\n\n#endif\t  // RD_CPP_IVIEWABLEMAP_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/IViewableSet.h",
    "content": "#ifndef RD_CPP_IVIEWABLESET_H\n#define RD_CPP_IVIEWABLESET_H\n\n#include \"interfaces.h\"\n#include \"viewable_collections.h\"\n\n#include <lifetime/LifetimeDefinition.h>\n#include <util/core_util.h>\n\n#include <std/unordered_map.h>\n\n#include <thirdparty.hpp>\n\nnamespace rd\n{\nnamespace detail\n{\ntemplate <typename T>\nclass SetEvent\n{\npublic:\n\tSetEvent(AddRemove kind, T const* value) : kind(kind), value(value)\n\t{\n\t}\n\n\tAddRemove kind;\n\tT const* value;\n\n\tfriend std::string to_string(SetEvent const& e)\n\t{\n\t\treturn to_string(e.kind) + \":\" + to_string(*e.value);\n\t}\n};\n}\t // namespace detail\n\n/**\n * \\brief A set allowing its contents to be observed.\n * \\tparam T type of stored values (may be abstract)\n */\ntemplate <typename T, typename A = allocator<T>>\nclass IViewableSet : public IViewable<T>, public ISource<detail::SetEvent<T>>\n{\nprotected:\n\tusing WT = value_or_wrapper<T>;\n\tmutable rd::unordered_map<Lifetime,\n\t\tordered_map<T const*, LifetimeDefinition, wrapper::TransparentHash<T>, wrapper::TransparentKeyEqual<T>>>\n\t\tlifetimes;\n\npublic:\n\t// region ctor/dtor\n\n\tIViewableSet() = default;\n\n\tIViewableSet(IViewableSet&&) = default;\n\n\tIViewableSet& operator=(IViewableSet&&) = default;\n\n\tvirtual ~IViewableSet() = default;\n\t// endregion\n\n\t/**\n\t * \\brief Represents an addition or removal of an element in the set.\n\t */\n\tusing Event = typename detail::SetEvent<T>;\n\n\t/**\n\t * \\brief Adds a subscription for additions and removals of set elements. When the subscription is initially\n\t * added, [handler] is called with [AddRemove::Add] events for all elements currently in the set.\n\t *\n\t * \\param lifetime lifetime of subscription.\n\t * \\param handler to be called.\n\t */\n\tvoid advise(Lifetime lifetime, std::function<void(AddRemove, T const&)> handler) const\n\t{\n\t\tthis->advise(lifetime, [handler](Event e) { handler(e.kind, *e.value); });\n\t}\n\n\t/**\n\t * \\brief Adds a subscription to changes of the contents of the set.\n\t *\n\t * \\details When [handler] is initially added, it is called receiving all elements currently in the set.\n\t * Every time an object is added to the set, the [handler] is called receiving the new element.\n\t * The [Lifetime] instance passed to the handler expires when the element is removed from the set.\n\t *\n\t * \\param lifetime\n\t * \\param handler\n\t */\n\tvoid view(Lifetime lifetime, std::function<void(Lifetime, T const&)> handler) const override\n\t{\n\t\tadvise(lifetime, [this, lifetime, handler](AddRemove kind, T const& key) {\n\t\t\tswitch (kind)\n\t\t\t{\n\t\t\t\tcase AddRemove::ADD:\n\t\t\t\t{\n\t\t\t\t\t/*auto const &[it, inserted] = lifetimes[lifetime].emplace(key, LifetimeDefinition(lifetime));*/\n\t\t\t\t\tauto const& it = lifetimes[lifetime].emplace(&key, lifetime);\n\t\t\t\t\tRD_ASSERT_MSG(it.second, \"lifetime definition already exists in viewable set by key:\" + to_string(key));\n\t\t\t\t\thandler(it.first->second.lifetime, key);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase AddRemove::REMOVE:\n\t\t\t\t{\n\t\t\t\t\tRD_ASSERT_MSG(lifetimes.at(lifetime).count(key) > 0,\n\t\t\t\t\t\t\"attempting to remove non-existing lifetime in viewable set by key:\" + to_string(key));\n\t\t\t\t\tLifetimeDefinition def = std::move(lifetimes.at(lifetime).at(key));\n\t\t\t\t\tlifetimes.at(lifetime).erase(key);\n\t\t\t\t\tdef.terminate();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * \\brief Adds a subscription for additions and removals of set elements. When the subscription is initially\n\t * added, [handler] is called with [AddRemove.Add] events for all elements currently in the set.\n\t *\n\t * \\param lifetime lifetime of subscription.\n\t * \\param handler to be called.\n\t */\n\tvoid advise(Lifetime lifetime, std::function<void(Event const&)> handler) const override = 0;\n\n\tvirtual bool add(WT) const = 0;\n\n\tvirtual bool addAll(std::vector<WT> elements) const = 0;\n\n\tvirtual void clear() const = 0;\n\n\tvirtual bool remove(T const&) const = 0;\n\n\tvirtual size_t size() const = 0;\n\n\tvirtual bool contains(T const&) const = 0;\n\n\tvirtual bool empty() const = 0;\n\n\ttemplate <typename... Args>\n\tbool emplace_add(Args&&... args) const\n\t{\n\t\treturn add(WT{std::forward<Args>(args)...});\n\t}\n};\n}\t // namespace rd\n\nstatic_assert(\n\tstd::is_move_constructible<rd::IViewableSet<int>::Event>::value, \"Is move constructible from IViewableSet<int>::Event\");\n\n#endif\t  // RD_CPP_IVIEWABLESET_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/SignalCookie.cpp",
    "content": "#include \"SignalCookie.h\"\n\n#include <atomic>\n\nnamespace\n{\nstd::atomic<int32_t> cookie;\n}\n\nvoid rd_signal_cookie_inc()\n{\n\t++cookie;\n}\n\nvoid rd_signal_cookie_dec()\n{\n\t--cookie;\n}\n\nint32_t rd_signal_cookie_get()\n{\n\treturn cookie;\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/SignalCookie.h",
    "content": "#ifndef RD_CPP_SIGNALCOOKIE_H\n#define RD_CPP_SIGNALCOOKIE_H\n\n#include <cstdint>\n#include <rd_core_export.h>\n\nextern \"C\" void RD_CORE_API rd_signal_cookie_inc();\nextern \"C\" void RD_CORE_API rd_signal_cookie_dec();\nextern \"C\" int32_t RD_CORE_API rd_signal_cookie_get();\n\n#endif\t  // RD_CPP_SIGNALCOOKIE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/SignalX.h",
    "content": "#ifndef RD_CPP_CORE_SIGNAL_H\n#define RD_CPP_CORE_SIGNAL_H\n\n#include \"interfaces.h\"\n#include \"SignalCookie.h\"\n\n#include <lifetime/Lifetime.h>\n#include <util/core_util.h>\n\n#include <utility>\n#include <functional>\n#include <atomic>\n\nnamespace rd\n{\n/**\n * \\brief complete class which has \\a Signal<T> 's properties\n */\ntemplate <typename T>\nclass Signal final : public ISignal<T>\n{\nprivate:\n\tusing WT = typename ISignal<T>::WT;\n\n\tclass Event\n\t{\n\tprivate:\n\t\tstd::function<void(T const&)> action;\n\t\tLifetime lifetime;\n\n\tpublic:\n\t\t// region ctor/dtor\n\t\tEvent() = delete;\n\n\t\ttemplate <typename F>\n\t\tEvent(F&& action, Lifetime lifetime) : action(std::forward<F>(action)), lifetime(lifetime)\n\t\t{\n\t\t}\n\n\t\tEvent(Event&&) = default;\n\t\t// endregion\n\n\t\tbool is_alive() const\n\t\t{\n\t\t\treturn !lifetime->is_terminated();\n\t\t}\n\n\t\tvoid execute_if_alive(T const& value) const\n\t\t{\n\t\t\tif (is_alive())\n\t\t\t{\n\t\t\t\taction(value);\n\t\t\t}\n\t\t}\n\t};\n\n\tusing counter_t = int32_t;\n\tusing listeners_t = std::map<counter_t, Event>;\n\n\tmutable counter_t advise_id = 0;\n\tmutable listeners_t listeners, priority_listeners;\n\n\tstatic void cleanup(listeners_t& queue)\n\t{\n\t\tutil::erase_if(queue, [](Event const& e) -> bool { return !e.is_alive(); });\n\t}\n\n\tvoid fire_impl(T const& value, listeners_t& queue) const\n\t{\n\t\tfor (auto const& p : queue)\n\t\t{\n\t\t\tauto const& event = p.second;\n\t\t\tevent.execute_if_alive(value);\n\t\t}\n\t\tcleanup(queue);\n\t}\n\n\ttemplate <typename F>\n\tvoid advise0(const Lifetime& lifetime, F&& handler, listeners_t& queue) const\n\t{\n\t\tif (lifetime->is_terminated())\n\t\t\treturn;\n\t\tcounter_t id = advise_id /*.load()*/;\n\t\tqueue.emplace(id, Event(std::forward<F>(handler), lifetime));\n\t\t++advise_id;\n\t}\n\npublic:\n\t// region ctor/dtor\n\n\tSignal() = default;\n\n\tSignal(Signal const& other) = delete;\n\n\tSignal& operator=(Signal const& other) = delete;\n\n\tSignal(Signal&&) = default;\n\n\tSignal& operator=(Signal&&) = default;\n\n\tvirtual ~Signal() = default;\n\n\t// endregion\n\n\tusing ISignal<T>::fire;\n\n\tvoid fire(T const& value) const override\n\t{\n\t\tfire_impl(value, priority_listeners);\n\t\tfire_impl(value, listeners);\n\t}\n\n\tusing ISignal<T>::advise;\n\n\tvoid advise(Lifetime lifetime, std::function<void(T const&)> handler) const override\n\t{\n\t\tadvise0(lifetime, std::move(handler), isPriorityAdvise() ? priority_listeners : listeners);\n\t}\n\n\tstatic bool isPriorityAdvise()\n\t{\n\t\treturn rd_signal_cookie_get() > 0;\n\t}\n};\n\ntemplate <typename F>\nvoid priorityAdviseSection(F&& block)\n{\n\trd_signal_cookie_inc();\n\tblock();\n\trd_signal_cookie_dec();\n}\n}\t // namespace rd\n\nstatic_assert(std::is_move_constructible<rd::Signal<int>>::value, \"Is not move constructible from Signal<int>\");\nstatic_assert(std::is_move_constructible<rd::Signal<rd::Void>>::value, \"Is not move constructible from Signal<Void>\");\n\n#endif\t  // RD_CPP_CORE_SIGNAL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/interfaces.h",
    "content": "#ifndef RD_CPP_CORE_INTERFACES_H\n#define RD_CPP_CORE_INTERFACES_H\n\n#include <lifetime/Lifetime.h>\n#include <types/wrapper.h>\n#include <util/core_traits.h>\n\n#include <functional>\n#include <type_traits>\n\nnamespace rd\n{\n/**\n * \\brief An object that allows to subscribe to events.\n * \\tparam T type of events\n */\ntemplate <typename T>\nclass ISource\n{\npublic:\n\tvirtual ~ISource() = default;\n\n\t/**\n\t * \\brief Adds an event subscription.\n\t * \\param lifetime lifetime of subscription.\n\t * \\param handler to be called, every time an event occurs.\n\t */\n\tvirtual void advise(Lifetime lifetime, std::function<void(T const&)> handler) const = 0;\n\n\t/**\n\t * \\brief @code advise with Eternal lifetime\n\t */\n\ttemplate <typename F>\n\tvoid advise_eternal(F&& handler) const\n\t{\n\t\tadvise(Lifetime::Eternal(), std::forward<F>(handler));\n\t}\n\n\t/**\n\t * \\brief @code Void specialisation of @code advise method, at @tparam T=Void\n\t */\n\tvoid advise(Lifetime lifetime, std::function<void()> handler) const\n\t{\n\t\tadvise(lifetime, [handler = std::move(handler)](Void) { handler(); });\n\t}\n};\n\n/**\n * \\brief An object that allows to subscribe to changes of its contents.\n * \\tparam T type of content\n */\ntemplate <typename T>\nclass IViewable\n{\npublic:\n\tvirtual ~IViewable() = default;\n\n\tvirtual void view(Lifetime lifetime, std::function<void(Lifetime, T const&)\n\n\t\t\t\t\t\t\t\t\t\t\t >\n\t\t\t\t\t\t\t\t\t\t\t handler) const = 0;\n};\n\n/**\n * \\brief An object which has a collection of event listeners and can broadcast an event to the listeners.\n * \\tparam T type of events\n */\ntemplate <typename T>\nclass ISignal : public ISource<T>\n{\nprotected:\n\tusing WT = value_or_wrapper<T>;\n\npublic:\n\tvirtual ~ISignal() = default;\n\n\tvirtual void fire(T const& value) const = 0;\n\n\t/**\n\t * \\brief @code fire specialisation at T=Void\n\t */\n\ttemplate <typename U = T>\n\ttypename std::enable_if_t<util::is_void<U>> fire() const\n\t{\n\t\tfire(Void{});\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_CORE_INTERFACES_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/reactive/base/viewable_collections.h",
    "content": "#ifndef RD_CPP_VIEWABLE_COLLECTIONS_H\n#define RD_CPP_VIEWABLE_COLLECTIONS_H\n\n#include <string>\n\nnamespace rd\n{\nenum class AddRemove\n{\n\tADD,\n\tREMOVE\n};\n\ninline std::string to_string(AddRemove kind)\n{\n\tswitch (kind)\n\t{\n\t\tcase AddRemove::ADD:\n\t\t\treturn \"Add\";\n\t\tcase AddRemove::REMOVE:\n\t\t\treturn \"Remove\";\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n\nenum class Op\n{\n\tADD,\n\tUPDATE,\n\tREMOVE,\n\tACK\n};\n\ninline std::string to_string(Op op)\n{\n\tswitch (op)\n\t{\n\t\tcase Op::ADD:\n\t\t\treturn \"Add\";\n\t\tcase Op::UPDATE:\n\t\t\treturn \"Update\";\n\t\tcase Op::REMOVE:\n\t\t\treturn \"Remove\";\n\t\tcase Op::ACK:\n\t\t\treturn \"Ack\";\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n}\t // namespace rd\n\n#endif\t  // RD_CPP_VIEWABLE_COLLECTIONS_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/std/allocator.h",
    "content": "#ifndef RD_CPP_ALLOCATOR_H\n#define RD_CPP_ALLOCATOR_H\n\n#include <memory>\n\nnamespace rd\n{\ntemplate <typename T>\nusing allocator = std::allocator<T>;\n}\n\n#endif\t  // RD_CPP_ALLOCATOR_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/std/hash.h",
    "content": "#ifndef RD_CPP_HASH_H\n#define RD_CPP_HASH_H\n\n#include <cstddef>\n#include <functional>\n\nnamespace rd\n{\ntemplate <typename T>\nstruct hash\n{\n\tsize_t operator()(const T& value) const noexcept\n\t{\n\t\treturn std::hash<T>()(value);\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_HASH_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/std/list.h",
    "content": "#ifndef RD_CPP_LIST_H\n#define RD_CPP_LIST_H\n\n#include <vector>\n#include <cstdint>\n\nnamespace rd\n{\ntemplate <typename T>\nint32_t size(T const& value) = delete;\n\n// c++17 has std::size for std::vector\n#if __cplusplus < 201703L\n\ntemplate <typename T, typename A>\nint32_t size(std::vector<T, A> const& value)\n{\n\treturn static_cast<int32_t>(value.size());\n}\n#else\t\ntemplate <typename T, typename A>\nint32_t size(std::vector<T, A> const& value)\n{\n\treturn std::size(value);\n}\n#endif\n\ntemplate <typename T, typename A>\nvoid resize(std::vector<T, A>& value, int32_t size)\n{\n\tvalue.resize(size);\n}\n}\t // namespace rd\n\n#endif\t  // RD_CPP_LIST_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/std/to_string.h",
    "content": "// ReSharper disable CppUE4CodingStandardNamingViolationWarning\n#ifndef RD_CPP_TO_STRING_H\n#define RD_CPP_TO_STRING_H\n\n#include <string>\n#include <thread>\n#include <sstream>\n#include <atomic>\n#include <future>\n#include <locale>\n\n#include \"ww898/utf_converters.hpp\"\n\n#include <thirdparty.hpp>\n\nnamespace rd\n{\nnamespace detail\n{\nusing std::to_string;\n\ninline std::string to_string(std::string const& val)\n{\n\treturn val;\n}\n\ninline std::string to_string(const char* val)\n{\n\treturn val;\n}\n\ninline std::string to_string(std::wstring const& val)\n{\n\treturn ww898::utf::conv<std::string::value_type>(val);\n}\n\ninline std::string to_string(std::thread::id const& id)\n{\n\tstd::ostringstream ss;\n\tss << id;\n\treturn ss.str();\n}\n\ninline std::string to_string(std::exception const& e)\n{\n\treturn std::string(e.what());\n}\n\ninline std::string to_string(std::future_status const& status)\n{\n\tswitch (status)\n\t{\n\t\tcase std::future_status::ready:\n\t\t\treturn \"ready\";\n\t\tcase std::future_status::timeout:\n\t\t\treturn \"timeout\";\n\t\tcase std::future_status::deferred:\n\t\t\treturn \"deferred\";\n\t\tdefault:\n\t\t\treturn \"unknown\";\n\t}\n}\n\ntemplate <typename Rep, typename Period>\ninline std::string to_string(std::chrono::duration<Rep, Period> const& time)\n{\n\treturn std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(time).count()) + \"ms\";\n}\n\ntemplate <typename T>\ninline std::string to_string(T const* val)\n{\n\treturn val ? to_string(*val) : \"nullptr\";\n}\n\ntemplate <typename T>\ninline std::string to_string(std::atomic<T> const& value)\n{\n\treturn to_string(value.load());\n}\n\ntemplate <typename T>\ninline std::string to_string(optional<T> const& val)\n{\n\tif (val.has_value())\n\t{\n\t\treturn to_string(*val);\n\t}\n\telse\n\t{\n\t\treturn \"nullopt\";\n\t}\n}\n\ntemplate <typename F, typename S>\ninline std::string to_string(const std::pair<F, S> p)\n{\n\treturn \"(\" + to_string(p.first) + \", \" + to_string(p.second) + \")\";\n}\n\ntemplate <template <class, class> class C, typename T, typename A>\nstd::string to_string(C<T, A> const& v)\n{\n\tstd::string res = \"[\";\n\tfor (const auto& item : v)\n\t{\n\t\tres += to_string(item);\n\t\tres += \",\";\n\t}\n\tres += \"]\";\n\treturn res;\n}\n\ntemplate <class T>\nstd::string as_string(T const& t)\n{\n\treturn to_string(t);\n}\n\nusing std::to_wstring;\n\ninline std::wstring to_wstring(std::string const& s)\n{\n\treturn ww898::utf::conv<std::wstring::value_type>(s);\n}\n\ntemplate <class T>\nstd::wstring as_wstring(T const& t)\n{\n\treturn to_wstring(t);\n}\n}\t // namespace detail\n\ntemplate <typename T>\nstd::string to_string(T const& val)\n{\n\treturn detail::as_string(val);\n}\n\ntemplate <typename T>\nstd::wstring to_wstring(T const& val)\n{\n\treturn detail::as_wstring(val);\n}\n}\t // namespace rd\n\n#endif\t  // RD_CPP_TO_STRING_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/std/unordered_map.h",
    "content": "#ifndef RD_CPP_UNORDERED_MAP_H\n#define RD_CPP_UNORDERED_MAP_H\n\n#include \"hash.h\"\n\n#include <unordered_map>\n\nnamespace rd\n{\ntemplate <class _Key, class _Tp, class _Hash = hash<_Key>, class _Pred = std::equal_to<_Key>,\n\tclass _Alloc = std::allocator<std::pair<const _Key, _Tp> > >\nusing unordered_map = std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>;\n}\n\n#endif\t  // RD_CPP_UNORDERED_MAP_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/std/unordered_set.h",
    "content": "#ifndef RD_CPP_UNORDERED_SET_H\n#define RD_CPP_UNORDERED_SET_H\n\n#include \"hash.h\"\n\n#include <unordered_set>\n\nnamespace rd\n{\ntemplate <class _Value, class _Hash = hash<_Value>, class _Pred = std::equal_to<_Value>, class _Alloc = std::allocator<_Value> >\nusing unordered_set = std::unordered_set<_Value, _Hash, _Pred, _Alloc>;\n}\n\n#endif\t  // RD_CPP_UNORDERED_SET_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/types/DateTime.cpp",
    "content": "#include \"DateTime.h\"\n\n#include <sstream>\n#include <iomanip>\n\nnamespace rd\n{\nDateTime::DateTime(time_t seconds) : seconds(seconds)\n{\n}\n\nbool operator<(const DateTime& lhs, const DateTime& rhs)\n{\n\treturn lhs.seconds < rhs.seconds;\n}\n\nbool operator>(const DateTime& lhs, const DateTime& rhs)\n{\n\treturn rhs < lhs;\n}\n\nbool operator<=(const DateTime& lhs, const DateTime& rhs)\n{\n\treturn !(rhs < lhs);\n}\n\nbool operator>=(const DateTime& lhs, const DateTime& rhs)\n{\n\treturn !(lhs < rhs);\n}\n\nstd::string to_string(DateTime const& time)\n{\n\tstd::stringstream ss;\n\tss << std::put_time(std::localtime(&time.seconds), \"%F %T\");\n\treturn ss.str();\n}\n\nbool operator==(const DateTime& lhs, const DateTime& rhs)\n{\n\treturn lhs.seconds == rhs.seconds;\n}\n\nbool operator!=(const DateTime& lhs, const DateTime& rhs)\n{\n\treturn !(rhs == lhs);\n}\n\nsize_t hash<rd::DateTime>::operator()(const rd::DateTime& value) const noexcept\n{\n\treturn rd::hash<decltype(value.seconds)>()(value.seconds);\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/types/DateTime.h",
    "content": "#ifndef RD_CPP_DATETIME_H\n#define RD_CPP_DATETIME_H\n\n#include <std/hash.h>\n\n#include <ctime>\n#include <string>\n\n#include <rd_core_export.h>\n\nnamespace rd\n{\n/**\n * \\brief Wrapper around time_t to be synchronized with \"Date\" in Kt and \"DateTime\" in C#.\n */\nclass RD_CORE_API DateTime\n{\npublic:\n\tstd::time_t seconds;\n\n\texplicit DateTime(time_t seconds);\n\n\tfriend bool RD_CORE_API operator<(const DateTime& lhs, const DateTime& rhs);\n\n\tfriend bool RD_CORE_API operator>(const DateTime& lhs, const DateTime& rhs);\n\n\tfriend bool RD_CORE_API operator<=(const DateTime& lhs, const DateTime& rhs);\n\n\tfriend bool RD_CORE_API operator>=(const DateTime& lhs, const DateTime& rhs);\n\n\tfriend bool RD_CORE_API operator==(const DateTime& lhs, const DateTime& rhs);\n\n\tfriend bool RD_CORE_API operator!=(const DateTime& lhs, const DateTime& rhs);\n\n\t//\"1970-01-01 03:01:38\" for example\n\tfriend std::string RD_CORE_API to_string(DateTime const& time);\n};\n}\t // namespace rd\nnamespace rd\n{\ntemplate <>\nstruct RD_CORE_API hash<rd::DateTime>\n{\n\tsize_t operator()(const rd::DateTime& value) const noexcept;\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_DATETIME_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/types/Void.h",
    "content": "#ifndef RD_CPP_VOID_H\n#define RD_CPP_VOID_H\n\n#include <functional>\n#include <string>\n\nnamespace rd\n{\n/**\n * \\brief For using in idle events\n */\nclass Void\n{\n\tfriend inline bool operator==(const Void&, const Void&)\n\t{\n\t\treturn true;\n\t}\n\n\tfriend inline bool operator!=(const Void&, const Void&)\n\t{\n\t\treturn false;\n\t}\n};\n\ninline std::string to_string(Void const&)\n{\n\treturn \"void\";\n}\n}\t // namespace rd\n\nnamespace std\n{\ntemplate <>\nstruct hash<rd::Void>\n{\n\tsize_t operator()(const rd::Void&) const noexcept\n\t{\n\t\treturn 0;\n\t}\n};\n}\t // namespace std\n\n#endif\t  // RD_CPP_VOID_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/types/wrapper.h",
    "content": "#ifndef RD_CPP_WRAPPER_H\n#define RD_CPP_WRAPPER_H\n\n#include <util/core_traits.h>\n#include <std/allocator.h>\n#include <std/hash.h>\n#include <std/to_string.h>\n\n#include <thirdparty.hpp>\n\n#include <type_traits>\n#include <memory>\n#include <utility>\n\nnamespace rd\n{\ntemplate <typename T, typename A = std::allocator<T>>\nclass Wrapper;\n\ntemplate <typename T, typename R = void>\nstruct helper\n{\n\tusing value_or_wrapper_type = T;\n\tusing opt_or_wrapper_type = optional<T>;\n\tusing property_storage = optional<T>;\n\tusing raw_type = T;\n};\n\ntemplate <typename T>\nstruct helper<T, typename std::enable_if_t<util::in_heap_v<T>>>\n{\n\tusing value_or_wrapper_type = Wrapper<T>;\n\tusing opt_or_wrapper_type = Wrapper<T>;\n\tusing property_storage = Wrapper<T>;\n\tusing raw_type = T;\n};\n\n/*template<typename T>\nstruct helper<optional<T>> {\n\tusing value_or_wrapper_type = Wrapper<T>;\n\tusing opt_or_wrapper_type = Wrapper<T>;\n\tusing property_storage = optional<optional<T>>;\n\tusing raw_type = T;\n};*/\n\ntemplate <typename T>\nstruct helper<Wrapper<T>>\n{\n\tusing value_or_wrapper_type = Wrapper<T>;\n\tusing opt_or_wrapper_type = Wrapper<T>;\n\tusing property_storage = Wrapper<Wrapper<T>>;\n\tusing raw_type = T;\n};\n\ntemplate <typename T>\nusing value_or_wrapper = typename helper<T>::value_or_wrapper_type;\n\ntemplate <typename T>\nusing opt_or_wrapper = typename helper<T>::opt_or_wrapper_type;\n\ntemplate <typename T>\nusing property_storage = typename helper<T>::property_storage;\n\ntemplate <typename T>\nusing raw_type = typename helper<T>::raw_type;\n\ntemplate <typename>\nstruct is_wrapper : std::false_type\n{\n};\n\ntemplate <typename T>\nstruct is_wrapper<Wrapper<T>> : std::true_type\n{\n};\n\ntemplate <typename T>\nconstexpr bool is_wrapper_v = is_wrapper<T>::value;\n\n/**\n * \\brief wrapper over value of any type. It supports semantic of shared ownership due to shared_ptr as storage.\n * \\tparam T type of value\n */\ntemplate <typename T, typename A>\nclass Wrapper final : public std::shared_ptr<T>\n{\nprivate:\n\ttemplate <typename, typename>\n\tfriend class Wrapper;\n\n\tusing Base = std::shared_ptr<T>;\n\n\tA alloc;\n\npublic:\n\tusing type = T;\n\n\t// region ctor/dtor\n\n\tWrapper() = default;\n\n\tWrapper(Wrapper const&) = default;\n\n\tWrapper& operator=(Wrapper const&) = default;\n\n\tWrapper(Wrapper&&) = default;\n\n\tWrapper& operator=(Wrapper&&) = default;\n\n\tconstexpr explicit Wrapper(std::nullptr_t) noexcept\n\t{\n\t}\n\n\tconstexpr Wrapper(nullopt_t) noexcept\n\t{\n\t}\n\n\ttemplate <typename R, typename = typename std::enable_if_t<util::is_base_of_v<T, R>>>\n\tWrapper(Wrapper<R> const& other) : Base(std::static_pointer_cast<T>(static_cast<std::shared_ptr<R>>(other)))\n\t{\n\t}\n\n\ttemplate <typename R, typename = typename std::enable_if_t<util::is_base_of_v<T, R>>>\n\tWrapper(Wrapper<R>&& other) : Base(std::static_pointer_cast<T>(static_cast<std::shared_ptr<R>>(std::move(other))))\n\t{\n\t}\n\n\ttemplate <typename F, typename G = typename util::not_string_literal<F&&>::type,\n\t\ttypename = typename std::enable_if_t<\n\t\t\t/*util::negation<\n\t\t\t\tutil::disjunction<\n\t\t\t\t\tstd::is_null_pointer<std::decay_t<F>>,\n\t\t\t\t\tstd::is_same<Wrapper<T>, std::decay_t<F>>,\n\t\t\t\t\tdetail::is_optional<std::decay_t<F>>\n\t\t\t\t>\n\t\t\t>::value*/\n\t\t\tutil::conjunction<std::is_constructible<std::shared_ptr<T>, std::shared_ptr<G>>,\n\t\t\t\tutil::negation<std::is_abstract<G>>>::value>>\n\tWrapper(F&& value) : Base(std::allocate_shared<G>(alloc, std::forward<F>(value)))\n\t{\n\t}\n\n\ttemplate <typename F>\n\tWrapper(std::shared_ptr<F> const& ptr) noexcept : Base(std::static_pointer_cast<T>(ptr))\n\t{\n\t}\n\n\ttemplate <typename F>\n\tWrapper(std::shared_ptr<F>&& ptr) noexcept : Base(std::static_pointer_cast<T>(std::move(ptr)))\n\t{\n\t}\n\n\ttemplate <typename U = T, typename R = typename std::enable_if_t<!std::is_abstract<std::decay_t<U>>::value>>\n\tWrapper(optional<U>&& opt)\n\t{\n\t\tif (opt)\n\t\t{\n\t\t\t*this = std::allocate_shared<U>(alloc, *std::move(opt));\n\t\t}\n\t}\n\n\ttemplate <typename R>\n\tstatic Wrapper<T> dynamic(Wrapper<R> const& w)\n\t{\n\t\treturn Wrapper<T>(std::dynamic_pointer_cast<T>(w));\n\t}\n\n\ttemplate <typename R>\n\tstatic Wrapper<T> dynamic(Wrapper<R>&& w)\n\t{\n\t\treturn Wrapper<T>(std::dynamic_pointer_cast<T>(std::move(w)));\n\t}\n\n\t~Wrapper() = default;\n\t// endregion\n\n\tconstexpr bool has_value() const\n\t{\n\t\treturn operator bool();\n\t}\n\n\tconstexpr T& operator*() &\n\t{\n\t\treturn *static_cast<Base&>(*this);\n\t};\n\n\tconstexpr T const& operator*() const&\n\t{\n\t\treturn *static_cast<Base const&>(*this);\n\t};\n\n\t/*constexpr T &&operator*() &&{\n\t\treturn *ptr.get();\n\t};*/\n\n\tT const* operator->() const\n\t{\n\t\treturn Base::operator->();\n\t}\n\n\tT* operator->()\n\t{\n\t\treturn Base::operator->();\n\t}\n\n\texplicit operator bool() const noexcept\n\t{\n\t\treturn Base::operator bool();\n\t}\n\n\tfriend bool operator==(const Wrapper& lhs, const Wrapper& rhs)\n\t{\n\t\tbool is_lhs = (bool) lhs;\n\t\tbool is_rhs = (bool) rhs;\n\t\tif (is_lhs != is_rhs)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (!is_lhs && !is_rhs)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\treturn *lhs.get() == *rhs.get();\n\t}\n\n\tfriend bool operator!=(const Wrapper& lhs, const Wrapper& rhs)\n\t{\n\t\treturn !(rhs == lhs);\n\t}\n\n\tfriend std::string to_string(Wrapper const& value)\n\t{\n\t\treturn value.has_value() ? to_string(*value) : \"nullptr\"s;\n\t}\n};\n\nnamespace wrapper\n{\ntemplate <typename T>\ndecltype(auto) get(T&& w)\n{\n\treturn std::forward<T>(w);\n}\n\ntemplate <typename T>\ndecltype(auto) get(T const& w)\n{\n\treturn w;\n}\n\ntemplate <typename T>\nT& get(Wrapper<T>& w)\n{\n\treturn *w;\n}\n\ntemplate <typename T>\nT const& get(Wrapper<T> const& w)\n{\n\treturn *w;\n}\n\ntemplate <typename T>\nT&& get(Wrapper<T>&& w)\n{\n\treturn *std::move(std::move(w));\n}\n\n/*template<typename T>\nWrapper<T> make_wrapper(std::unique_ptr<T> &&value) {\n\treturn Wrapper<T>(std::move(value));\n}*/\n\ntemplate <typename T>\ntypename std::enable_if_t<!util::in_heap_v<T>, T> unwrap(Wrapper<T>&& ptr)\n{\n\treturn std::move(*ptr);\n}\n\ntemplate <typename T>\ntypename std::enable_if_t<util::in_heap_v<T>, Wrapper<T>> unwrap(Wrapper<T>&& ptr)\n{\n\treturn Wrapper<T>(std::move(ptr));\n}\n\ntemplate <typename T, typename... Args>\nWrapper<T> make_wrapper(Args&&... args)\n{\n\treturn Wrapper<T>(std::make_shared<T>(std::forward<Args>(args)...));\n}\n\ntemplate <typename T, typename A, typename... Args>\nWrapper<T> allocate_wrapper(const A& alloc, Args&&... args)\n{\n\treturn Wrapper<T>(std::allocate_shared<T, A>(alloc, std::forward<Args>(args)...));\n}\n/*template<typename T>\nconstexpr Wrapper<T> null_wrapper = Wrapper<T>(nullptr);*/\n}\t // namespace wrapper\n\ntemplate <typename T>\nstruct hash<rd::Wrapper<T>>\n{\n\tsize_t operator()(const rd::Wrapper<T>& value) const noexcept\n\t{\n\t\treturn rd::hash<T>()(*value);\n\t}\n};\n}\t // namespace rd\n\nstatic_assert(rd::is_wrapper<rd::Wrapper<std::wstring>>::value, \"is wrapper doesn't work\");\n\n#endif\t  // RD_CPP_WRAPPER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/util/core_traits.h",
    "content": "#ifndef RD_CORE_CPP_TRAITS_H\n#define RD_CORE_CPP_TRAITS_H\n\n#include <types/Void.h>\n\n#include <type_traits>\n#include <string>\n\nnamespace rd\n{\nclass IPolymorphicSerializable;\n\nnamespace util\n{\n// region non_std\n\ntemplate <typename T, typename U>\nconstexpr bool is_same_v = std::is_same<T, U>::value;\n\ntemplate <typename Base, typename Derived>\nconstexpr bool is_base_of_v = std::is_base_of<Base, Derived>::value;\n\ntemplate <bool B>\nusing bool_constant = std::integral_constant<bool, B>;\n\ntemplate <class B>\nstruct negation : bool_constant<!bool(B::value)>\n{\n};\n\ntemplate <class...>\nstruct disjunction : std::false_type\n{\n};\ntemplate <class B1>\nstruct disjunction<B1> : B1\n{\n};\ntemplate <class B1, class... Bn>\nstruct disjunction<B1, Bn...> : std::conditional_t<bool(B1::value), B1, disjunction<Bn...>>\n{\n};\n\ntemplate <class...>\nstruct conjunction : std::true_type\n{\n};\ntemplate <class B1>\nstruct conjunction<B1> : B1\n{\n};\ntemplate <class B1, class... Bn>\nstruct conjunction<B1, Bn...> : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1>\n{\n};\n\ntemplate <class...>\nusing void_t = void;\n\ntemplate <typename F, typename... Args>\nstruct is_invocable\n\t: std::is_constructible<std::function<void(Args...)>, std::reference_wrapper<typename std::remove_reference<F>::type>>\n{\n};\n\ntemplate <typename R, typename F, typename... Args>\nstruct is_invocable_r\n\t: std::is_constructible<std::function<R(Args...)>, std::reference_wrapper<typename std::remove_reference<F>::type>>\n{\n};\n\ntemplate <class F, class... Ts>\nconstexpr bool is_invocable_v = is_invocable<F, Ts...>::value;\n\n#ifdef __cpp_lib_is_invocable\ntemplate <class> struct result_of;\n\ntemplate <class F, class... TN>\nstruct result_of<F(TN...)>\n{\n\tusing type = std::invoke_result_t<F, TN...>;\n};\n#else\ntemplate<class... TN> using result_of = std::result_of<TN...>;\n#endif\ntemplate<class... TN> using result_of_t = typename result_of<TN...>::type;\n\ntemplate <typename T>\nconstexpr bool is_enum_v = std::is_enum<T>::value;\n\n// TO-DO: is is_pod actually required for memcpy-like serialization?\ntemplate <class T>\nconstexpr bool is_pod_v = std::is_trivial<T>::value && std::is_standard_layout<T>::value;\n// endregion\n\ntemplate <typename T>\n/*inline */ constexpr bool is_void = std::is_same<T, Void>::value;\n\n// region in_heap\n\ntemplate <typename T>\n//\t\tusing in_heap = disjunction<std::is_abstract<T>, std::is_same<T, std::wstring>>;\nusing in_heap = disjunction<std::is_base_of<IPolymorphicSerializable, T>, std::is_same<T, std::wstring>>;\n\ntemplate <typename T>\n/*inline */ constexpr bool in_heap_v = in_heap<T>::value;\n\nstatic_assert(in_heap_v<std::wstring>, \"std::wstring should be placed in shared memory\");\nstatic_assert(!in_heap_v<int>, \"int shouldn't be placed in shared memory\");\n\n// endregion\n\n// region literal\n\ntemplate <typename T>\nstruct is_wstring_literal :\n\t/*std::is_same<\n\t\t\tT,\n\t\t\tstd::add_lvalue_reference_t<const wchar_t[std::extent<std::remove_reference_t<T>>::value]>*/\n\tstd::is_convertible<T, std::wstring>\n{\n};\n\ntemplate <typename T, bool = is_wstring_literal<T>::value>\nstruct not_string_literal\n{\n\tusing type = std::wstring;\n};\n\ntemplate <>\nstruct not_string_literal<std::wstring, true>\n{\n\tusing type = std::wstring;\n};\n\ntemplate <typename T>\nstruct not_string_literal<T, false>\n{\n\tusing type = std::decay_t<T>;\n};\n\nstatic_assert(is_wstring_literal<decltype(L\" \")>::value, \"is_wstring trait doesn't work\");\nstatic_assert(is_wstring_literal<decltype(L\" \")&&>::value, \"is_wstring trait doesn't work\");\nstatic_assert(is_wstring_literal<decltype(L\" \")&>::value, \"is_wstring trait doesn't work\");\nstatic_assert(is_wstring_literal<wchar_t const (&)[1]>::value, \"is_wstring trait doesn't work\");\nstatic_assert(!is_wstring_literal<int>::value, \"is_wstring trait doesn't work\");\n//\t\tstatic_assert(is_wstring_literal<std::wstring>::value, \"is_wstring trait doesn't work\");\n\n// endregion\n}\t // namespace util\n}\t // namespace rd\n\n#endif\t  // RD_CORE_CPP_TRAITS_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/util/core_util.h",
    "content": "#ifndef RD_CPP_CORE_CPP_UTIL_H\n#define RD_CPP_CORE_CPP_UTIL_H\n\n#include \"erase_if.h\"\n#include \"gen_util.h\"\n#include \"overloaded.h\"\n#include \"shared_function.h\"\n\n#include <std/hash.h>\n#include <std/to_string.h>\n#include <types/wrapper.h>\n\n#include <thirdparty.hpp>\n#include <spdlog/spdlog.h>\n\n#include <memory>\n#include <string>\n#include <thread>\n#include <atomic>\n#include <iostream>\n#include <sstream>\n#include <cassert>\n\n#define RD_ASSERT_MSG(expr, msg)    \\\n\tif (!(expr))                    \\\n\t{                               \\\n\t\tspdlog::error(\"{}\\n\", msg); \\\n\t\tassert(expr);               \\\n\t}\n#define RD_ASSERT_THROW_MSG(expr, msg) \\\n\tif (!(expr))                       \\\n\t{                                  \\\n\t\tspdlog::error(\"{}\\n\", msg);    \\\n\t\tthrow std::runtime_error(msg); \\\n\t}\n\nnamespace rd\n{\nnamespace util\n{\ntemplate <typename T0, typename... T>\nconstexpr std::vector<T0> arrayListOf(T0&& arg, T&&... args)\n{\n\treturn std::vector<T0>{std::forward<T0>(arg), std::forward<T>(args)...};\n}\n}\t // namespace util\n\nnamespace wrapper\n{\ntemplate <typename T>\nstruct TransparentKeyEqual\n{\n\tusing is_transparent = void;\n\n\tbool operator()(T const& val_l, T const& val_r) const\n\t{\n\t\treturn val_l == val_r;\n\t}\n\n\tbool operator()(Wrapper<T> const& ptr_l, Wrapper<T> const& ptr_r) const\n\t{\n\t\treturn ptr_l == ptr_r;\n\t}\n\n\tbool operator()(T const* val_l, T const* val_r) const\n\t{\n\t\treturn *val_l == *val_r;\n\t}\n\n\tbool operator()(T const& val_r, Wrapper<T> const& ptr_l) const\n\t{\n\t\treturn *ptr_l == val_r;\n\t}\n\n\tbool operator()(T const& val_l, T const* ptr_r) const\n\t{\n\t\treturn val_l == *ptr_r;\n\t}\n\n\tbool operator()(Wrapper<T> const& val_l, T const* ptr_r) const\n\t{\n\t\treturn *val_l == *ptr_r;\n\t}\n};\n\ntemplate <typename T>\nstruct TransparentHash\n{\n\tusing is_transparent = void;\n\tusing transparent_key_equal = std::equal_to<>;\n\n\tsize_t operator()(T const& val) const noexcept\n\t{\n\t\treturn rd::hash<T>()(val);\n\t}\n\n\tsize_t operator()(Wrapper<T> const& ptr) const noexcept\n\t{\n\t\treturn rd::hash<Wrapper<T>>()(ptr);\n\t}\n\n\tsize_t operator()(T const* val) const noexcept\n\t{\n\t\treturn rd::hash<T>()(*val);\n\t}\n};\n}\t // namespace wrapper\n}\t // namespace rd\n\n#endif\t  // RD_CPP_CORE_CPP_UTIL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/util/enum.h",
    "content": "#ifndef RD_CPP_ENUM_H\n#define RD_CPP_ENUM_H\n\n#include <type_traits>\n\n#define RD_DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE)                                                                     \\\n\textern \"C++\"                                                                                                    \\\n\t{                                                                                                               \\\n\t\tinline ENUMTYPE operator|(ENUMTYPE a, ENUMTYPE b)                                                           \\\n\t\t{                                                                                                           \\\n\t\t\treturn ENUMTYPE(((std::underlying_type_t<ENUMTYPE>) a) | ((std::underlying_type_t<ENUMTYPE>) b));       \\\n\t\t}                                                                                                           \\\n\t\tinline ENUMTYPE& operator|=(ENUMTYPE& a, ENUMTYPE b)                                                        \\\n\t\t{                                                                                                           \\\n\t\t\treturn (ENUMTYPE&) (((std::underlying_type_t<ENUMTYPE>&) a) |= ((std::underlying_type_t<ENUMTYPE>) b)); \\\n\t\t}                                                                                                           \\\n\t\tinline ENUMTYPE operator&(ENUMTYPE a, ENUMTYPE b)                                                           \\\n\t\t{                                                                                                           \\\n\t\t\treturn ENUMTYPE(((std::underlying_type_t<ENUMTYPE>) a) & ((std::underlying_type_t<ENUMTYPE>) b));       \\\n\t\t}                                                                                                           \\\n\t\tinline ENUMTYPE& operator&=(ENUMTYPE& a, ENUMTYPE b)                                                        \\\n\t\t{                                                                                                           \\\n\t\t\treturn (ENUMTYPE&) (((std::underlying_type_t<ENUMTYPE>&) a) &= ((std::underlying_type_t<ENUMTYPE>) b)); \\\n\t\t}                                                                                                           \\\n\t\tinline ENUMTYPE operator~(ENUMTYPE a)                                                                       \\\n\t\t{                                                                                                           \\\n\t\t\treturn ENUMTYPE(~((std::underlying_type_t<ENUMTYPE>) a));                                               \\\n\t\t}                                                                                                           \\\n\t\tinline ENUMTYPE operator^(ENUMTYPE a, ENUMTYPE b)                                                           \\\n\t\t{                                                                                                           \\\n\t\t\treturn ENUMTYPE(((std::underlying_type_t<ENUMTYPE>) a) ^ ((std::underlying_type_t<ENUMTYPE>) b));       \\\n\t\t}                                                                                                           \\\n\t\tinline ENUMTYPE& operator^=(ENUMTYPE& a, ENUMTYPE b)                                                        \\\n\t\t{                                                                                                           \\\n\t\t\treturn (ENUMTYPE&) (((std::underlying_type_t<ENUMTYPE>&) a) ^= ((std::underlying_type_t<ENUMTYPE>) b)); \\\n\t\t}                                                                                                           \\\n\t}\n\n#endif\t  // RD_CPP_ENUM_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/util/erase_if.h",
    "content": "#ifndef RD_CPP_ERASE_IF_H\n#define RD_CPP_ERASE_IF_H\n\nnamespace rd\n{\nnamespace util\n{\ntemplate <typename ContainerT, class _Pr>\nvoid erase_if(ContainerT& items, _Pr _Pred)\n{\n\tfor (auto it = items.begin(); it != items.end();)\n\t{\n\t\tif (_Pred(it->second))\n\t\t\tit = items.erase(it);\n\t\telse\n\t\t\t++it;\n\t}\n}\n}\t // namespace util\n}\t // namespace rd\n\n#endif\t  // RD_CPP_ERASE_IF_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/util/gen_util.h",
    "content": "#ifndef RD_CPP_GEN_UTIL_H\n#define RD_CPP_GEN_UTIL_H\n\n#include <std/hash.h>\n#include <std/allocator.h>\n\n#include <cstdlib>\n\nnamespace rd\n{\n\ntemplate <template <class, class> class C, typename T, typename A = allocator<T>>\nsize_t contentHashCode(C<T, A> const& list) noexcept\n{\n\tsize_t __r = 0;\n\tfor (auto const& e : list)\n\t{\n\t\t__r = __r * 31 + hash<T>()(e);\n\t}\n\treturn __r;\n\t// TO-DO faster for integrals\n}\n\ntemplate <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>\nsize_t contentDeepHashCode(T const& value) noexcept\n{\n\treturn rd::hash<T>()(value);\n}\n\ntemplate<class T>\nusing remove_all_t = std::remove_reference_t<std::remove_cv_t<T>>;\n\n// optional and rd::Wrapper\ntemplate <class T, typename = std::enable_if_t<!std::is_integral<T>::value>>\ntypename std::enable_if_t<std::is_same<decltype(T{}.has_value()), bool>::value, size_t> contentDeepHashCode(T const& value) noexcept\n{\n\treturn rd::hash<remove_all_t<T>>()(value);\n}\n\n// containers\ntemplate <class T, typename = std::enable_if_t<!std::is_integral<T>::value>>\ntypename std::enable_if_t<std::is_integral<remove_all_t<decltype(*begin(T{}))>>::value, size_t> contentDeepHashCode(T const& value) noexcept\n{\n\treturn contentHashCode(value);\n}\n\n// containers of non-integral types\ntemplate <class T, typename = std::enable_if_t<!std::is_integral<T>::value>>\ntypename std::enable_if_t<!std::is_integral<remove_all_t<decltype(*begin(T{}))>>::value, size_t> contentDeepHashCode(T const& value) noexcept\n{\n\tsize_t result = 1;\n\tfor (auto const& x : value)\n\t{\n\t\tresult = 31 * result + contentDeepHashCode<remove_all_t<decltype(x)>>(x);\n\t}\n\treturn result;\n}\n\n}\t // namespace rd\n\n#endif\t  // RD_CPP_GEN_UTIL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/util/overloaded.h",
    "content": "#ifndef RD_CPP_OVERLOADED_H\n#define RD_CPP_OVERLOADED_H\n\nnamespace rd\n{\nnamespace util\n{\ntemplate <typename... Ts>\nstruct overloaded;\n\ntemplate <typename T>\nstruct overloaded<T> : T\n{\n\toverloaded(T t) : T(t)\n\t{\n\t}\n\n\tusing T::operator();\n};\n\ntemplate <typename T, class... Ts>\nstruct overloaded<T, Ts...> : T, overloaded<Ts...>\n{\n\toverloaded(T t, Ts... rest) : T(t), overloaded<Ts...>(rest...)\n\t{\n\t}\n\n\tusing T::operator();\n\tusing overloaded<Ts...>::operator();\n};\n\ntemplate <typename... Ts>\noverloaded<Ts...> make_visitor(Ts... lambdas)\n{\n\treturn overloaded<Ts...>(lambdas...);\n}\n}\t // namespace util\n}\t // namespace rd\n\n#endif\t  // RD_CPP_OVERLOADED_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_core_cpp/src/main/util/shared_function.h",
    "content": "#ifndef RD_CPP_SHARED_FUNCTION_H\n#define RD_CPP_SHARED_FUNCTION_H\n\n#include <memory>\n\nnamespace rd\n{\nnamespace util\n{\ntemplate <class F>\nstruct shared_function\n{\n\tstd::shared_ptr<F> f;\n\n\tshared_function() = delete;\t   // = default works, but I don't use it\n\tshared_function(F&& f_) : f(std::make_shared<F>(std::move(f_)))\n\t{\n\t}\n\n\tshared_function(shared_function const&) = default;\n\n\tshared_function(shared_function&&) = default;\n\n\tshared_function& operator=(shared_function const&) = default;\n\n\tshared_function& operator=(shared_function&&) = default;\n\n\ttemplate <class... As>\n\tauto operator()(As&&... as) const\n\t{\n\t\treturn (*f)(std::forward<As>(as)...);\n\t}\n};\n\ntemplate <class F>\nshared_function<std::decay_t<F> > make_shared_function(F&& f)\n{\n\treturn {std::forward<F>(f)};\n}\n}\t // namespace util\n}\t // namespace rd\n\n#endif\t  // RD_CPP_SHARED_FUNCTION_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/rd_framework_export.h",
    "content": "\n#ifndef RD_FRAMEWORK_API_H\n#define RD_FRAMEWORK_API_H\n\n#if defined(_WIN32)\n# ifdef RD_FRAMEWORK_STATIC_DEFINE\n#  define RD_FRAMEWORK_API\n#  define RD_FRAMEWORK_NO_EXPORT\n# else\n#  ifndef RD_FRAMEWORK_API\n#    ifdef rd_framework_cpp_EXPORTS\n        /* We are building this library */\n#      define RD_FRAMEWORK_API __declspec(dllexport)\n#    else\n        /* We are using this library */\n#      define RD_FRAMEWORK_API __declspec(dllimport)\n#    endif\n#  endif\n\n#  ifndef RD_FRAMEWORK_NO_EXPORT\n#    define RD_FRAMEWORK_NO_EXPORT\n#  endif\n# endif\n\n# ifndef RD_FRAMEWORK_DEPRECATED\n#  define RD_FRAMEWORK_DEPRECATED __declspec(deprecated)\n# endif\n\n# ifndef RD_FRAMEWORK_DEPRECATED_EXPORT\n#  define RD_FRAMEWORK_DEPRECATED_EXPORT RD_FRAMEWORK_API RD_FRAMEWORK_DEPRECATED\n# endif\n\n# ifndef RD_FRAMEWORK_DEPRECATED_NO_EXPORT\n#  define RD_FRAMEWORK_DEPRECATED_NO_EXPORT RD_FRAMEWORK_NO_EXPORT RD_FRAMEWORK_DEPRECATED\n# endif\n\n# if 0 /* DEFINE_NO_DEPRECATED */\n#  ifndef RD_FRAMEWORK_NO_DEPRECATED\n#    define RD_FRAMEWORK_NO_DEPRECATED\n#  endif\n# endif\n#endif\n\n#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__)\n# ifdef RD_FRAMEWORK_STATIC_DEFINE\n#  define RD_FRAMEWORK_API\n#  define RD_FRAMEWORK_NO_EXPORT\n# else\n#  ifndef RD_FRAMEWORK_API\n#    ifdef rd_framework_cpp_EXPORTS\n        /* We are building this library */\n#      define RD_FRAMEWORK_API __attribute__((visibility(\"default\")))\n#    else\n        /* We are using this library */\n#      define RD_FRAMEWORK_API __attribute__((visibility(\"default\")))\n#    endif\n#  endif\n\n#  ifndef RD_FRAMEWORK_NO_EXPORT\n#    define RD_FRAMEWORK_NO_EXPORT __attribute__((visibility(\"hidden\")))\n#  endif\n# endif\n\n# ifndef RD_FRAMEWORK_DEPRECATED\n#  define RD_FRAMEWORK_DEPRECATED __attribute__ ((__deprecated__))\n# endif\n\n# ifndef RD_FRAMEWORK_DEPRECATED_EXPORT\n#  define RD_FRAMEWORK_DEPRECATED_EXPORT RD_FRAMEWORK_API RD_FRAMEWORK_DEPRECATED\n# endif\n\n# ifndef RD_FRAMEWORK_DEPRECATED_NO_EXPORT\n#  define RD_FRAMEWORK_DEPRECATED_NO_EXPORT RD_FRAMEWORK_NO_EXPORT RD_FRAMEWORK_DEPRECATED\n# endif\n\n# if 0 /* DEFINE_NO_DEPRECATED */\n#  ifndef RD_FRAMEWORK_NO_DEPRECATED\n#    define RD_FRAMEWORK_NO_DEPRECATED\n#  endif\n# endif\n#endif\n\n#endif /* RD_FRAMEWORK_API_H */\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IProtocol.cpp",
    "content": "#include \"IProtocol.h\"\n\n#include \"scheduler/base/IScheduler.h\"\n#include \"protocol/Identities.h\"\n#include \"base/IWire.h\"\n#include \"base/IProtocol.h\"\n//#include \"serialization/SerializationCtx.h\"\n\n#include <utility>\n\nnamespace rd\n{\nIProtocol::IProtocol()\n{\n}\n\nIProtocol::IProtocol(std::shared_ptr<Identities> identity, IScheduler* scheduler, std::shared_ptr<IWire> wire)\n\t: identity(std::move(identity)), scheduler(scheduler), wire(std::move(wire))\n{\n}\n\nconst IProtocol* IProtocol::get_protocol() const\n{\n\treturn this;\n}\n\nIScheduler* IProtocol::get_scheduler() const\n{\n\treturn scheduler;\n}\n\nconst IWire* IProtocol::get_wire() const\n{\n\treturn wire.get();\n}\n\nconst Serializers& IProtocol::get_serializers() const\n{\n\treturn *serializers;\n}\n\nconst Identities* IProtocol::get_identity() const\n{\n\treturn identity.get();\n}\n\nconst RName& IProtocol::get_location() const\n{\n\treturn location;\n}\n\nIProtocol::~IProtocol() = default;\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IProtocol.h",
    "content": "#ifndef RD_CPP_IPROTOCOL_H\n#define RD_CPP_IPROTOCOL_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"IRdDynamic.h\"\n#include \"serialization/Serializers.h\"\n#include \"protocol/Identities.h\"\n#include \"scheduler/base/IScheduler.h\"\n#include \"base/IWire.h\"\n\n#include <memory>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n// region predeclared\n\nclass SerializationCtx;\n// endregion\n\n/**\n * \\brief A root node in an object graph which can be synchronized with its remote copy over a network or a similar connection.\n */\nclass RD_FRAMEWORK_API IProtocol : public IRdDynamic\n{\n\tfriend class RdExtBase;\n\npublic:\n\tstd::unique_ptr<Serializers> serializers = std::make_unique<Serializers>();\n\nprotected:\n\tmutable RName location;\n\n\tstd::shared_ptr<Identities> identity;\n\tIScheduler* scheduler = nullptr;\n\npublic:\n\tstd::shared_ptr<IWire> wire;\n\t// region ctor/dtor\n\n\tIProtocol();\n\n\tIProtocol(std::shared_ptr<Identities> identity, IScheduler* scheduler, std::shared_ptr<IWire> wire);\n\n\tIProtocol(IProtocol&& other) noexcept = default;\n\n\tIProtocol& operator=(IProtocol&& other) noexcept = default;\n\n\tvirtual ~IProtocol();\n\t// endregion\n\n\tconst Identities* get_identity() const;\n\n\tconst IProtocol* get_protocol() const override;\n\n\tIScheduler* get_scheduler() const;\n\n\tconst IWire* get_wire() const;\n\n\tconst Serializers& get_serializers() const;\n\n\tconst RName& get_location() const override;\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_IPROTOCOL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IRdBindable.h",
    "content": "#ifndef RD_CPP_FRAMEWORK_IRDBINDABLE_H\n#define RD_CPP_FRAMEWORK_IRDBINDABLE_H\n\n#include \"IRdDynamic.h\"\n#include \"lifetime/Lifetime.h\"\n#include \"protocol/RdId.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass Identities;\n}\n\nnamespace rd\n{\n/**\n * \\brief A non-root node in an object graph which can be synchronized with its remote copy over a network or\n * a similar connection.\n */\nclass RD_FRAMEWORK_API IRdBindable : public IRdDynamic\n{\npublic:\n\t// region ctor/dtor\n\n\tIRdBindable() = default;\n\n\tIRdBindable(IRdBindable&& other) = default;\n\n\tIRdBindable& operator=(IRdBindable&& other) = default;\n\n\tvirtual ~IRdBindable() = default;\n\t// endregion\n\n\tvirtual void set_id(RdId id) const = 0;\n\tvirtual RdId get_id() const = 0;\n\n\t/**\n\t * \\brief Inserts the node into the object graph under the given [parent] and assigns the specified [name] to it.\n\t * The node will be removed from the graph when the specified [lf] lifetime is terminated.\n\t *\n\t * \\param lf lifetime of node.\n\t * \\param parent to whom bind.\n\t * \\param name specified name of node.\n\t */\n\tvirtual void bind(Lifetime lf, IRdDynamic const* parent, string_view name) const = 0;\n\n\t/**\n\t * \\brief Assigns IDs to this node and its child nodes in the graph.\n\t *\n\t * \\param identities to generate unique identifiers for children.\n\t * \\param id which is assigned to this node.\n\t */\n\tvirtual void identify(Identities const& identities, RdId const& id) const = 0;\n};\n\ntemplate <typename T>\ntypename std::enable_if_t<!util::is_base_of_v<IRdBindable, typename std::decay_t<T>>> inline identifyPolymorphic(\n\tT&&, Identities const& /*identities*/, RdId const& /*id*/)\n{\n}\n\n// template <>\ninline void identifyPolymorphic(const IRdBindable& that, Identities const& identities, RdId const& id)\n{\n\tthat.identify(identities, id);\n}\n\ntemplate <typename T>\ntypename std::enable_if_t<util::is_base_of_v<IRdBindable, T>> inline identifyPolymorphic(\n\tstd::vector<T> const& that, Identities const& identities, RdId const& id)\n{\n\tfor (size_t i = 0; i < that.size(); ++i)\n\t{\n\t\tthat[i].identify(identities, id.mix(static_cast<int32_t>(i)));\n\t}\n}\n\ntemplate <typename T>\ntypename std::enable_if_t<!util::is_base_of_v<IRdBindable, typename std::decay_t<T>>> inline bindPolymorphic(\n\tT&&, Lifetime /*lf*/, const IRdDynamic* /*parent*/, string_view /*name*/)\n{\n}\n\ninline void bindPolymorphic(IRdBindable const& that, Lifetime lf, const IRdDynamic* parent, string_view name)\n{\n\tthat.bind(lf, parent, name);\n}\n\ntemplate <typename T>\ntypename std::enable_if_t<util::is_base_of_v<IRdBindable, T>> inline bindPolymorphic(\n\tstd::vector<T> const& that, Lifetime lf, IRdDynamic const* parent, string_view name)\n{\n\tfor (auto& obj : that)\n\t{\n\t\tobj.bind(lf, parent, name);\n\t}\n}\n}\t // namespace rd\n\n#endif\t  // RD_CPP_FRAMEWORK_IRDBINDABLE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IRdDynamic.h",
    "content": "#ifndef RD_CPP_IRDDYNAMIC_H\n#define RD_CPP_IRDDYNAMIC_H\n\n#include \"impl/RName.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n// region predeclared\n\nclass IProtocol;\n\nclass SerializationCtx;\n// endregion\n\n/**\n * \\brief A node in a graph of entities that can be synchronized with its remote copy over a network or\n * a similar connection.\n */\nclass RD_FRAMEWORK_API IRdDynamic\n{\npublic:\n\t// region ctor/dtor\n\n\tIRdDynamic() = default;\n\n\tIRdDynamic(IRdDynamic&& other) = default;\n\n\tIRdDynamic& operator=(IRdDynamic&& other) = default;\n\n\tvirtual ~IRdDynamic() = default;\n\t// endregion\n\n\tvirtual const IProtocol* get_protocol() const = 0;\n\n\tvirtual SerializationCtx& get_serialization_context() const = 0;\n\n\tvirtual const RName& get_location() const = 0;\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_IRDDYNAMIC_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IRdReactive.h",
    "content": "#ifndef RD_CPP_FRAMEWORK_IRDREACTIVE_H\n#define RD_CPP_FRAMEWORK_IRDREACTIVE_H\n\n#include \"IRdBindable.h\"\n#include \"scheduler/base/IScheduler.h\"\n#include \"IRdWireable.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n/**\n * \\brief A non-root node in an object graph which can be synchronized with its remote copy over a network or\n * a similar connection, and which allows to subscribe to its changes.\n */\nclass RD_FRAMEWORK_API IRdReactive\n{\npublic:\n\t/**\n\t * \\brief If set to true, local changes to this object can be performed on any thread.\n\t * Otherwise, local changes can be performed only on the UI thread.\n\t */\n\tbool async = false;\n\t// region ctor/dtor\n\n\tIRdReactive() = default;\n\n\tvirtual ~IRdReactive() = default;\n\t// endregion\n\n\t/**\n\t * \\brief Scheduler on which wire invokes callback [onWireReceived]. Default is the same as [protocol]'s one.\n\t * \\return scheduler\n\t */\n\tvirtual IScheduler* get_wire_scheduler() const = 0;\n\n\t/**\n\t * \\brief Callback that wire triggers when it receives messaged\n\t * \\param buffer where serialised info is stored\n\t */\n\tvirtual void on_wire_received(Buffer buffer) const = 0;\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_FRAMEWORK_IRDREACTIVE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IRdWireable.cpp",
    "content": "#include \"IRdWireable.h\"\n\nnamespace rd\n{\n}"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IRdWireable.h",
    "content": "#ifndef RD_CPP_IRDWIREABLE_H\n#define RD_CPP_IRDWIREABLE_H\n\n#include \"protocol/RdId.h\"\n#include \"scheduler/base/IScheduler.h\"\n#include \"protocol/Buffer.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API IRdWireable\n{\npublic:\n\tmutable RdId rdid = RdId::Null();\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_IRDWIREABLE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/ISerializersOwner.cpp",
    "content": "#include \"ISerializersOwner.h\"\n\nnamespace rd\n{\nvoid ISerializersOwner::registry(Serializers const& serializers) const\n{\n\tauto it = used.insert(&serializers);\n\tif (!it.second)\n\t{\n\t\treturn;\n\t}\n\n\tregisterSerializersCore(serializers);\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/ISerializersOwner.h",
    "content": "#ifndef RD_CPP_ISERIALIZERSOWNER_H\n#define RD_CPP_ISERIALIZERSOWNER_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <unordered_set>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n// region predeclared\n\nclass Serializers;\n// endregion\n\nclass RD_FRAMEWORK_API ISerializersOwner\n{\n\tmutable std::unordered_set<Serializers const*> used;\n\npublic:\n\t// region ctor/dtor\n\n\tvirtual ~ISerializersOwner() = default;\n\t// endregion\n\n\tvoid registry(Serializers const& serializers) const;\n\n\tvirtual void registerSerializersCore(Serializers const& serializers) const = 0;\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_ISERIALIZERSOWNER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IUnknownInstance.cpp",
    "content": "#include \"IUnknownInstance.h\"\n\nnamespace rd\n{\nIUnknownInstance::IUnknownInstance()\n{\n}\n\nIUnknownInstance::IUnknownInstance(const RdId& unknownId) : unknownId(unknownId)\n{\n}\n\nIUnknownInstance::IUnknownInstance(RdId&& unknownId) : unknownId(std::move(unknownId))\n{\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IUnknownInstance.h",
    "content": "#ifndef RD_CPP_IUNKNOWNINSTANCE_H\n#define RD_CPP_IUNKNOWNINSTANCE_H\n\n#include \"protocol/RdId.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API IUnknownInstance\n{\npublic:\n\tRdId unknownId{0};\n\n\tIUnknownInstance();\n\n\texplicit IUnknownInstance(const RdId& unknownId);\n\n\texplicit IUnknownInstance(RdId&& unknownId);\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_IUNKNOWNINSTANCE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/IWire.h",
    "content": "#ifndef RD_CPP_IWIRE_H\n#define RD_CPP_IWIRE_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"reactive/base/interfaces.h\"\n#include \"base/IRdReactive.h\"\n#include \"reactive/Property.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RdReactiveBase;\n/**\n * \\brief Sends and receives serialized object data over a network or a similar connection.\n */\nclass RD_FRAMEWORK_API IWire\n{\npublic:\n\tProperty<bool> connected{false};\n\tProperty<bool> heartbeatAlive{false};\n\n\t// region ctor/dtor\n\n\tIWire() = default;\n\n\tIWire(IWire&&) = default;\n\n\tvirtual ~IWire() = default;\n\t// endregion\n\n\t/**\n\t * \\brief Sends a data block with the given [id] and the given [writer] function that can write the data.\n\t * \\param id of recipient.\n\t * \\param writer is used to serialise data before send.\n\t */\n\tvirtual void send(RdId const& id, std::function<void(Buffer& buffer)> writer) const = 0;\n\n\t/**\n\t * \\brief Adds a [handler] for receiving updated values of the object with the given [id]. The handler is removed\n\t * when the given [lifetime] is terminated.\n\t * \\param lifetime lifetime of subscription.\n\t * \\param entity to be subscripted\n\t */\n\tvirtual void advise(Lifetime lifetime, RdReactiveBase const* entity) const = 0;\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_IWIRE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/RdBindableBase.cpp",
    "content": "#include \"RdBindableBase.h\"\n\n#include \"reactive/base/SignalX.h\"\n\nnamespace rd\n{\nstd::string RdBindableBase::toString() const\n{\n\treturn \"location=\" + to_string(location) + \",rdid=\" + to_string(rdid);\n}\n\nbool RdBindableBase::is_bound() const\n{\n\treturn parent != nullptr;\n}\n\nvoid RdBindableBase::bind(Lifetime lf, IRdDynamic const* parent, string_view name) const\n{\n\tRD_ASSERT_MSG(!is_bound(), (\"Trying to bind already bound this to \" + to_string(parent->get_location())));\n\tlf->bracket(\n\t\t[this, lf, parent, &name] {\n\t\t\tthis->parent = parent;\n\t\t\tlocation = parent->get_location().sub(name, \".\");\n\t\t\tthis->bind_lifetime = lf;\n\t\t},\n\t\t[this, lf]() {\n\t\t\tthis->bind_lifetime = lf;\n\t\t\tlocation = location.sub(\"<<unbound>>\", \"::\");\n\t\t\tthis->parent = nullptr;\n\t\t\trdid = RdId::Null();\n\t\t});\n\n\tget_protocol()->get_scheduler()->assert_thread();\n\n\tpriorityAdviseSection([this, lf]() { init(lf); });\n}\n\n// must be overriden if derived class have bindable members\nvoid RdBindableBase::identify(const Identities& identities, RdId const& id) const\n{\n\tRD_ASSERT_MSG(rdid.isNull(), \"Already has RdId: \" + to_string(rdid) + \", entities: $this\");\n\tRD_ASSERT_MSG(!id.isNull(), \"Assigned RdId mustn't be null, entities: $this\");\n\n\tthis->rdid = id;\n\tfor (const auto& it : bindable_extensions)\n\t{\n\t\tidentifyPolymorphic(*(it.second), identities, id.mix(\".\").mix(it.first));\n\t}\n}\n\nconst IProtocol* RdBindableBase::get_protocol() const\n{\n\tif (is_bound())\n\t{\n\t\tauto protocol = parent->get_protocol();\n\t\tif (protocol != nullptr)\n\t\t{\n\t\t\treturn protocol;\n\t\t}\n\t}\n\tthrow std::invalid_argument(\"Not bound: \" + to_string(location));\n}\n\nconst RName& RdBindableBase::get_location() const\n{\n\treturn location;\n}\n\nRdId RdBindableBase::get_id() const\n{\n\treturn rdid;\n}\n\nvoid RdBindableBase::set_id(RdId id) const\n{\n\trdid = id;\n}\n\nSerializationCtx& RdBindableBase::get_serialization_context() const\n{\n\tif (is_bound())\n\t{\n\t\treturn parent->get_serialization_context();\n\t}\n\telse\n\t{\n\t\tthrow std::invalid_argument(\"Not bound: \" + to_string(location));\n\t}\n}\n\nvoid RdBindableBase::init(Lifetime lifetime) const\n{\n\tfor (const auto& it : bindable_extensions)\n\t{\n\t\tif (it.second != nullptr)\n\t\t{\n\t\t\tbindPolymorphic(*(it.second), lifetime, this, it.first);\n\t\t}\n\t}\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/RdBindableBase.h",
    "content": "#ifndef RD_CPP_RDBINDABLEBASE_H\n#define RD_CPP_RDBINDABLEBASE_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"IRdBindable.h\"\n#include \"base/IProtocol.h\"\n\n#include \"thirdparty.hpp\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API RdBindableBase : public virtual IRdBindable /*, IPrintable*/\n{\nprotected:\n\tmutable RName location;\n\tmutable IRdDynamic const* parent = nullptr;\n\tmutable RdId rdid = RdId::Null();\n\n\tmutable optional<Lifetime> bind_lifetime;\n\n\tbool is_bound() const;\n\n\tconst IProtocol* get_protocol() const override;\n\n\tvirtual std::string toString() const;\n\npublic:\n\t// region ctor/dtor\n\n\tRdBindableBase() : location(\"<<not bound>>\")\n\t{\n\t}\n\n\tRdBindableBase(RdBindableBase&& other) = default;\n\n\tRdBindableBase& operator=(RdBindableBase&& other) = default;\n\n\t~RdBindableBase() override = default;\n\t// endregion\n\n\t// need to implement in subclasses\n\tvirtual void init(Lifetime lifetime) const;\n\n\tconst RName& get_location() const override;\n\n\tRdId get_id() const override;\n\n\tvoid set_id(RdId id) const override;\n\n\tvoid bind(Lifetime lf, IRdDynamic const* parent, string_view name) const override;\n\n\tvoid identify(const Identities& identities, RdId const& id) const override;\n\n\tSerializationCtx& get_serialization_context() const override;\n\n\tmutable ordered_map<std::string, std::shared_ptr<IRdBindable>> bindable_extensions;\t   // TO-DO concurrency\n\t// mutable std::map<std::string, std::any> non_bindable_extensions;//TO-DO concurrency\n\n\ttemplate <typename T, typename... Args>\n\tauto getOrCreateExtension(std::string name, Args&&... args) const ->\n\t\ttypename std::enable_if_t<util::is_base_of_v<IRdBindable, T>, T> const&\n\t{\n\t\tauto it = bindable_extensions.find(name);\n\t\tif (it != bindable_extensions.end())\n\t\t{\n\t\t\treturn *dynamic_cast<T const*>(it->second.get());\n\t\t}\n\t\tstd::shared_ptr<T> new_extension = std::make_shared<T>(std::forward<Args>(args)...);\n\t\tT const& res = *new_extension.get();\n\t\tif (bind_lifetime.has_value())\n\t\t{\n\t\t\tauto protocol = get_protocol();\n\t\t\tnew_extension->identify(*protocol->get_identity(), rdid.mix(\".\").mix(name));\n\t\t\tnew_extension->bind(*bind_lifetime, this, name);\n\t\t}\n\t\tbindable_extensions.emplace(name, std::move(new_extension));\n\t\treturn res;\n\t}\n\n\t/* template<typename T>\n std::enable_if_t<!util::is_base_of_v<IRdBindable, T>, T> const &\n getOrCreateExtension(std::string const &name, std::function<T()> create) const {\n\t if (non_bindable_extensions.count(name) == 0) {\n\t\t return std::any_cast<T const &>(non_bindable_extensions[name] = create());\n\t }\n\t return std::any_cast<T const &>(non_bindable_extensions.at(name));\n }*/\n};\n\n// T : RdBindableBase\ntemplate <typename T>\nT& withId(T& that, RdId const& id)\n{\n\tRD_ASSERT_MSG(that.get_id() == RdId::Null(), \"this.id != RdId.NULL_ID, but \" + to_string(that.get_id()));\n\tRD_ASSERT_MSG(id != RdId::Null(), \"id != RdId.NULL_ID\");\n\n\tthat.set_id(id);\n\treturn that;\n}\n\ntemplate <typename T>\nT& statics(T& that, int64_t id)\n{\n\tRD_ASSERT_MSG((id > 0 && id < RdId::MAX_STATIC_ID), (\"Expected id > 0 && id < RdId.MaxStaticId, got \" + std::to_string(id)));\n\treturn withId(that, RdId(static_cast<int64_t>(id)));\n}\n\ntemplate <typename T>\nT& withIdFromName(T& that, std::string const& name)\n{\n\treturn withId(that, RdId::Null().mix(name));\n}\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n#endif\t  // RD_CPP_RDBINDABLEBASE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/RdPropertyBase.h",
    "content": "#ifndef RD_CPP_RDPROPERTYBASE_H\n#define RD_CPP_RDPROPERTYBASE_H\n\n#include \"base/RdReactiveBase.h\"\n#include \"serialization/Polymorphic.h\"\n#include \"reactive/Property.h\"\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#endif\n\nnamespace rd\n{\ntemplate <typename T, typename S = Polymorphic<T>>\nclass RdPropertyBase : public RdReactiveBase, public Property<T>\n{\nprotected:\n\tusing WT = typename IProperty<T>::WT;\n\t// mastering\n\tmutable int32_t master_version = 0;\n\tmutable bool default_value_changed = false;\n\n\t// init\npublic:\n\tmutable bool optimize_nested = false;\n\n\tbool is_master = false;\n\n\t// region ctor/dtor\n\n\tRdPropertyBase() = default;\n\n\tRdPropertyBase(RdPropertyBase const&) = delete;\n\n\tRdPropertyBase(RdPropertyBase&& other) = default;\n\n\tRdPropertyBase& operator=(RdPropertyBase&& other) = default;\n\n\ttemplate <typename F>\n\texplicit RdPropertyBase(F&& value) : Property<T>(std::forward<F>(value))\n\t{\n\t}\n\n\tvirtual ~RdPropertyBase() = default;\n\t// endregion\n\n\tbool is_default_value_changed() const\n\t{\n\t\treturn default_value_changed;\n\t}\n\n\tvoid init(Lifetime lifetime) const override\n\t{\n\t\tRdReactiveBase::init(lifetime);\n\n\t\tif (!optimize_nested)\n\t\t{\n\t\t\tthis->change.advise(lifetime, [this](T const& v) {\n\t\t\t\tif (is_local_change)\n\t\t\t\t{\n\t\t\t\t\tif (this->has_value())\n\t\t\t\t\t{\n\t\t\t\t\t\tconst IProtocol* iProtocol = get_protocol();\n\t\t\t\t\t\tconst Identities* identity = iProtocol->get_identity();\n\t\t\t\t\t\tidentifyPolymorphic(v, *identity, identity->next(rdid));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tadvise(lifetime, [this](T const& v) {\n\t\t\tif (!is_local_change)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (is_master)\n\t\t\t{\n\t\t\t\tmaster_version++;\n\t\t\t}\n\t\t\tget_wire()->send(rdid, [this, &v](Buffer& buffer) {\n\t\t\t\tbuffer.write_integral<int32_t>(master_version);\n\t\t\t\tS::write(this->get_serialization_context(), buffer, v);\n\t\t\t\tspdlog::get(\"logSend\")->trace(\"SEND property {} + {}:: ver = {}, value = {}\", to_string(location), to_string(rdid),\n\t\t\t\t\tstd::to_string(master_version), to_string(v));\n\t\t\t});\n\t\t});\n\n\t\tget_wire()->advise(lifetime, this);\n\n\t\tif (!optimize_nested)\n\t\t{\n\t\t\tthis->view(lifetime, [this](Lifetime lf, T const& v) {\n\t\t\t\tif (this->has_value())\n\t\t\t\t{\n\t\t\t\t\tbindPolymorphic(v, lf, this, \"$\");\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tvoid on_wire_received(Buffer buffer) const override\n\t{\n\t\tint32_t version = buffer.read_integral<int32_t>();\n\t\tWT v = S::read(this->get_serialization_context(), buffer);\n\n\t\tbool rejected = is_master && version < master_version;\n\t\tspdlog::get(\"logSend\")->trace(\"RECV property {} {}:: oldver={}, ver={}, value = {}{}\", to_string(location), to_string(rdid),\n\t\t\tmaster_version, version, to_string(v), (rejected ? \">> REJECTED\" : \"\"));\n\t\tif (rejected)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tmaster_version = version;\n\n\t\tProperty<T>::set(std::move(v));\n\t}\n\n\tvoid advise(Lifetime lifetime, std::function<void(T const&)> handler) const override\n\t{\n\t\tif (is_bound())\n\t\t{\n\t\t\tassert_threading();\n\t\t}\n\t\tProperty<T>::advise(lifetime, handler);\n\t}\n\n\tvoid set(value_or_wrapper<T> new_value) const override\n\t{\n\t\tthis->local_change([this, new_value = std::move(new_value)]() mutable {\n\t\t\tthis->default_value_changed = true;\n\t\t\tProperty<T>::set(std::move(new_value));\n\t\t});\n\t}\n\n\tfriend bool operator==(const RdPropertyBase& lhs, const RdPropertyBase& rhs)\n\t{\n\t\treturn &lhs == &rhs;\n\t}\n\n\tfriend bool operator!=(const RdPropertyBase& lhs, const RdPropertyBase& rhs)\n\t{\n\t\treturn !(rhs == lhs);\n\t}\n};\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\nstatic_assert(std::is_move_constructible<rd::RdPropertyBase<int>>::value, \"Is move constructible from RdPropertyBase<int>\");\n\n#endif\t  // RD_CPP_RDPROPERTYBASE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/RdReactiveBase.cpp",
    "content": "#include \"RdReactiveBase.h\"\n\n#include \"spdlog/sinks/stdout_color_sinks.h\"\n\nnamespace rd\n{\nstatic std::shared_ptr<spdlog::logger> logReceived =\n\tspdlog::stderr_color_mt<spdlog::synchronous_factory>(\"logReceived\", spdlog::color_mode::automatic);\nstd::shared_ptr<spdlog::logger> logSend =\n\tspdlog::stderr_color_mt<spdlog::synchronous_factory>(\"logSend\", spdlog::color_mode::automatic);\n\nRdReactiveBase::RdReactiveBase(RdReactiveBase&& other) : RdBindableBase(std::move(other)) /*, async(other.async)*/\n{\n\tasync = other.async;\n}\n\nRdReactiveBase& RdReactiveBase::operator=(RdReactiveBase&& other)\n{\n\tasync = other.async;\n\tstatic_cast<RdBindableBase&>(*this) = std::move(other);\n\treturn *this;\n}\n\nconst IWire* RdReactiveBase::get_wire() const\n{\n\treturn get_protocol()->get_wire();\n}\n\nvoid RdReactiveBase::assert_threading() const\n{\n\tif (!async)\n\t{\n\t\tget_default_scheduler()->assert_thread();\n\t}\n}\n\nvoid RdReactiveBase::assert_bound() const\n{\n\tif (!is_bound())\n\t{\n\t\tthrow std::invalid_argument(\"Not bound\");\n\t}\n}\n\nconst Serializers& RdReactiveBase::get_serializers() const\n{\n\treturn *get_protocol()->serializers.get();\n}\n\nIScheduler* RdReactiveBase::get_default_scheduler() const\n{\n\treturn get_protocol()->get_scheduler();\n}\n\nIScheduler* RdReactiveBase::get_wire_scheduler() const\n{\n\treturn get_default_scheduler();\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/RdReactiveBase.h",
    "content": "#ifndef RD_CPP_RDREACTIVEBASE_H\n#define RD_CPP_RDREACTIVEBASE_H\n\n#include \"base/RdBindableBase.h\"\n#include \"base/IRdReactive.h\"\n#include \"guards.h\"\n\n#include \"spdlog/spdlog.h\"\n\n#include <rd_framework_export.h>\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#endif\n\nnamespace rd\n{\n// region predeclared\n\nclass IWire;\n\nclass IProtocol;\n\nclass Serializers;\n// endregion\n\nclass RD_FRAMEWORK_API RdReactiveBase : public RdBindableBase, public IRdReactive\n{\npublic:\n\t// region ctor/dtor\n\n\tRdReactiveBase() = default;\n\n\tRdReactiveBase(RdReactiveBase&& other);\n\n\tRdReactiveBase& operator=(RdReactiveBase&& other);\n\n\tvirtual ~RdReactiveBase() = default;\n\t// endregion\n\n\tconst IWire* get_wire() const;\n\n\tmutable bool is_local_change = false;\n\n\t// delegated\n\n\tconst Serializers& get_serializers() const;\n\n\tIScheduler* get_default_scheduler() const;\n\n\tIScheduler* get_wire_scheduler() const override;\n\n\tvoid assert_threading() const;\n\n\tvoid assert_bound() const;\n\n\ttemplate <typename F>\n\tauto local_change(F&& action) const -> typename util::result_of_t<F()>\n\t{\n\t\tif (is_bound() && !async)\n\t\t{\n\t\t\tassert_threading();\n\t\t}\n\n\t\tRD_ASSERT_MSG(!is_local_change, \"!isLocalChange for RdReactiveBase with id:\" + to_string(rdid));\n\n\t\tutil::bool_guard bool_guard(is_local_change);\n\t\treturn action();\n\t}\n};\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n#endif\t  // RD_CPP_RDREACTIVEBASE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/WireBase.cpp",
    "content": "#include \"WireBase.h\"\n\nnamespace rd\n{\nvoid WireBase::advise(Lifetime lifetime, const RdReactiveBase* entity) const\n{\n\tmessage_broker.advise_on(lifetime, entity);\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/base/WireBase.h",
    "content": "#ifndef RD_CPP_WIREBASE_H\n#define RD_CPP_WIREBASE_H\n\n#include \"reactive/Property.h\"\n#include \"base/IWire.h\"\n#include \"protocol/MessageBroker.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API WireBase : public IWire\n{\nprotected:\n\tIScheduler* scheduler = nullptr;\n\n\tMessageBroker message_broker;\n\npublic:\n\t// region ctor/dtor\n\texplicit WireBase(IScheduler* scheduler) : scheduler(scheduler), message_broker(scheduler)\n\t{\n\t}\n\n\tvirtual ~WireBase() = default;\n\t// endregion\n\n\tvirtual void advise(Lifetime lifetime, RdReactiveBase const* entity) const override;\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_WIREBASE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/ext/ExtWire.cpp",
    "content": "#include \"ExtWire.h\"\n\n#include \"protocol/Buffer.h\"\n\nnamespace rd\n{\nExtWire::ExtWire()\n{\n\tconnected.advise(Lifetime::Eternal(), [this](bool b) {\n\t\tif (b)\n\t\t{\n\t\t\t{\n\t\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\t\t\twhile (true)\n\t\t\t\t{\n\t\t\t\t\tif (sendQ.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// auto[id, payload] = std::move(sendQ.front());\n\t\t\t\t\tauto it = std::move(sendQ.front());\n\t\t\t\t\tsendQ.pop();\n\t\t\t\t\trealWire->send(\n\t\t\t\t\t\tit.first, [payload = std::move(it.second)](Buffer& buffer) { buffer.write_byte_array_raw(payload); });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n}\n\nvoid ExtWire::advise(Lifetime lifetime, RdReactiveBase const* entity) const\n{\n\trealWire->advise(lifetime, entity);\n}\n\nvoid ExtWire::send(RdId const& id, std::function<void(Buffer& buffer)> writer) const\n{\n\t{\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\tif (!sendQ.empty() || !connected.get())\n\t\t{\n\t\t\tBuffer buffer;\n\t\t\twriter(buffer);\n\t\t\tsendQ.emplace(id, buffer.getRealArray());\n\t\t\treturn;\n\t\t}\n\t}\n\trealWire->send(id, std::move(writer));\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/ext/ExtWire.h",
    "content": "#ifndef RD_CPP_EXTWIRE_H\n#define RD_CPP_EXTWIRE_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"base/IWire.h\"\n#include \"protocol/RdId.h\"\n#include \"protocol/Buffer.h\"\n\n#include <queue>\n#include <mutex>\n#include <functional>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API ExtWire final : public IWire\n{\n\tmutable std::mutex lock;\n\n\tmutable std::queue<std::pair<RdId, Buffer::ByteArray> > sendQ;\n\npublic:\n\tExtWire();\n\n\tmutable IWire const* realWire = nullptr;\n\n\tvoid advise(Lifetime lifetime, RdReactiveBase const* entity) const override;\n\n\tvoid send(RdId const& id, std::function<void(Buffer& buffer)> writer) const override;\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_EXTWIRE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/ext/RdExtBase.cpp",
    "content": "#include \"RdExtBase.h\"\n\n#include \"lifetime/Lifetime.h\"\n#include \"base/RdPropertyBase.h\"\n#include \"protocol/Protocol.h\"\n#include \"scheduler/SynchronousScheduler.h\"\n\nnamespace rd\n{\nconst IProtocol* RdExtBase::get_protocol() const\n{\n\treturn extProtocol ? extProtocol.get() : RdReactiveBase::get_protocol();\n}\n\n// must be overriden if derived ext have bindable members\nvoid RdExtBase::init(Lifetime lifetime) const\n{\n\t//    Protocol.initializationLogger.traceMe { \"binding\" }\n\n\tauto parentProtocol = RdReactiveBase::get_protocol();\n\tstd::shared_ptr<IWire> parentWire = parentProtocol->wire;\n\n\t//    serializersOwner.registry(parentProtocol.serializers);\n\n\tIScheduler* sc = parentProtocol->get_scheduler();\n\textWire->realWire = parentWire.get();\n\tlifetime->bracket(\n\t\t[&] {\n\t\t\textProtocol =\n\t\t\t\tstd::make_shared<Protocol>(parentProtocol->identity, sc, std::static_pointer_cast<IWire>(extWire), lifetime);\n\t\t},\n\t\t[this] { extProtocol = nullptr; });\n\n\tparentWire->advise(lifetime, this);\n\n\t// it's critical to advise before 'Ready' is sent because we advise on SynchronousScheduler\n\n\tlifetime->bracket([this, parentWire] { sendState(*parentWire, ExtState::Ready); },\n\t\t[this, parentWire] { sendState(*parentWire, ExtState::Disconnected); });\n\n\tfor (auto const& it : bindable_extensions)\n\t{\n\t\tbindPolymorphic(*(it.second), lifetime, this, it.first);\n\t}\n\ttraceMe(Protocol::initializationLogger, \"created and bound\");\n}\n\nvoid RdExtBase::on_wire_received(Buffer buffer) const\n{\n\tExtState remoteState = buffer.read_enum<ExtState>();\n\ttraceMe(spdlog::get(\"logReceived\"), \"remote: \" + to_string(remoteState));\n\n\tswitch (remoteState)\n\t{\n\t\tcase ExtState::Ready:\n\t\t{\n\t\t\tsendState(*extWire->realWire, ExtState::ReceivedCounterpart);\n\t\t\textWire->connected.set(true);\n\t\t\tbreak;\n\t\t}\n\t\tcase ExtState::ReceivedCounterpart:\n\t\t{\n\t\t\textWire->connected.set(true);\t // don't set anything if already set\n\t\t\tbreak;\n\t\t}\n\t\tcase ExtState::Disconnected:\n\t\t{\n\t\t\textWire->connected.set(false);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tint64_t counterpartSerializationHash = buffer.read_integral<int64_t>();\n\tif (serializationHash != counterpartSerializationHash)\n\t{\n\t\tRD_ASSERT_MSG(false, \"serializationHash of ext \" + to_string(location) +\n\t\t\t\t\t\t\t\t \" doesn't match to counterpart: maybe you forgot to generate models?\\n\"\n\t\t\t\t\t\t\t\t \"our: \" +\n\t\t\t\t\t\t\t\t to_string(serializationHash) + \", counterpart:\" + to_string(counterpartSerializationHash))\n\t}\n}\n\nvoid RdExtBase::sendState(IWire const& wire, ExtState state) const\n{\n\twire.send(rdid, [&](Buffer& buffer) {\n\t\tbuffer.write_enum<ExtState>(state);\n\t\tbuffer.write_integral<int64_t>(serializationHash);\n\t});\n}\n\nvoid RdExtBase::traceMe(std::shared_ptr<spdlog::logger> logger, string_view message) const\n{\n\tlogger->trace(\"ext {} {}:: {}\", to_string(location), to_string(rdid), std::string(message));\n}\n\nIScheduler* RdExtBase::get_wire_scheduler() const\n{\n\treturn &SynchronousScheduler::Instance();\n}\n\nstd::string to_string(RdExtBase::ExtState state)\n{\n\tswitch (state)\n\t{\n\t\tcase RdExtBase::ExtState::Ready:\n\t\t\treturn \"Ready\";\n\t\tcase RdExtBase::ExtState::ReceivedCounterpart:\n\t\t\treturn \"ReceivedCounterpart\";\n\t\tcase RdExtBase::ExtState::Disconnected:\n\t\t\treturn \"Disconnected\";\n\t}\n\treturn {};\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/ext/RdExtBase.h",
    "content": "#ifndef RD_CPP_RDEXTBASE_H\n#define RD_CPP_RDEXTBASE_H\n\n#include \"base/RdReactiveBase.h\"\n#include \"ExtWire.h\"\n\n#include \"spdlog/spdlog.h\"\n\n#include <rd_framework_export.h>\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#pragma warning(disable : 4251)\n#endif\n\nnamespace rd\n{\n/**\n * \\brief Base class for creating extension node according to bottom-up design.\n */\nclass RD_FRAMEWORK_API RdExtBase : public RdReactiveBase\n{\n\tstd::shared_ptr<ExtWire> extWire = std::make_shared<ExtWire>();\n\tmutable std::shared_ptr<IProtocol> extProtocol /* = nullptr*/;\n\npublic:\n\tenum class ExtState\n\t{\n\t\tReady,\n\t\tReceivedCounterpart,\n\t\tDisconnected\n\t};\n\n\t// region ctor/dtor\n\n\tRdExtBase() = default;\n\n\tRdExtBase(RdExtBase&&) = default;\n\n\tRdExtBase& operator=(RdExtBase&&) = default;\n\n\tvirtual ~RdExtBase() = default;\n\t// endregion\n\n\tmutable int64_t serializationHash = 0;\n\n\tconst IProtocol* get_protocol() const override;\n\n\tIScheduler* get_wire_scheduler() const override;\n\n\tvoid init(Lifetime lifetime) const override;\n\n\tvoid on_wire_received(Buffer buffer) const override;\n\n\tvoid sendState(IWire const& wire, ExtState state) const;\n\n\tvoid traceMe(std::shared_ptr<spdlog::logger> logger, string_view message) const;\n};\n\nstd::string to_string(RdExtBase::ExtState state);\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_RDEXTBASE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/impl/RName.cpp",
    "content": "#include \"RName.h\"\n\n#include \"thirdparty.hpp\"\n\nnamespace rd\n{\nclass RNameImpl\n{\npublic:\n\t// region ctor/dtor\n\tRNameImpl(RName parent, string_view localName, string_view separator);\n\n\tRNameImpl(const RName& other) = delete;\n\tRNameImpl(RName&& other) noexcept = delete;\n\tRNameImpl& operator=(const RNameImpl& other) = delete;\n\tRNameImpl& operator=(RNameImpl&& other) noexcept = delete;\n\t// endregion\n\n\tfriend std::string to_string(RNameImpl const& value);\n\nprivate:\n\tRName parent;\n\tstd::string local_name, separator;\n};\n\nRNameImpl::RNameImpl(RName parent, string_view localName, string_view separator)\n\t: parent(parent), local_name(localName), separator(separator)\n{\n}\n\nRName::RName(RName parent, string_view localName, string_view separator)\n\t: impl(std::make_shared<RNameImpl>(std::move(parent), localName, separator))\n{\n}\n\nRName RName::sub(string_view localName, string_view separator) const\n{\n\treturn RName(*this, localName, separator);\n}\n\nstd::string to_string(RName const& value)\n{\n\tstd::string res;\n\tif (value.impl)\n\t{\n\t\tres = to_string(*value.impl);\n\t}\n\treturn res;\n}\n\nstd::string to_string(RNameImpl const& value)\n{\n\tif (value.parent)\n\t{\n\t\tstd::string res;\n\t\tres = to_string(value.parent);\n\t\tres += value.separator;\n\t\tres += value.local_name;\n\t\treturn res;\n\t}\n\treturn value.local_name;\n}\n\nRName::RName(string_view local_name) : RName(RName(), local_name, \"\")\n{\n}\n\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/impl/RName.h",
    "content": "#ifndef RD_CPP_FRAMEWORK_RNAME_H\n#define RD_CPP_FRAMEWORK_RNAME_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"thirdparty.hpp\"\n\n#include <string>\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RNameImpl;\n\n/**\n * \\brief Recursive name. For constructs like Aaaa.Bbb::CCC\n */\nclass RD_FRAMEWORK_API RName\n{\npublic:\n\t// region ctor/dtor\n\n\tRName() = default;\n\n\tRName(const RName& other) = default;\n\n\tRName(RName&& other) noexcept = default;\n\n\tRName& operator=(const RName& other) = default;\n\n\tRName& operator=(RName&& other) noexcept = default;\n\n\tRName(RName parent, string_view localName, string_view separator);\n\n\texplicit RName(string_view local_name);\n\t// endregion\n\n\tRName sub(string_view localName, string_view separator) const;\n\n\texplicit operator bool() const\n\t{\n\t\treturn impl != nullptr;\n\t}\n\n\tfriend std::string RD_FRAMEWORK_API to_string(RName const& value);\n\nprivate:\n\tstd::shared_ptr<RNameImpl> impl;\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_FRAMEWORK_RNAME_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/impl/RdList.h",
    "content": "#ifndef RD_CPP_RDLIST_H\n#define RD_CPP_RDLIST_H\n\n#include \"reactive/ViewableList.h\"\n#include \"base/RdReactiveBase.h\"\n#include \"serialization/Polymorphic.h\"\n#include \"std/allocator.h\"\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#endif\n\nnamespace rd\n{\n/**\n * \\brief Reactive list for connection through wire.\n *\n * \\tparam T type of stored values\n * \\tparam S \"SerDes\" for values\n * \\tparam A allocator for values\n */\ntemplate <typename T, typename S = Polymorphic<T>, typename A = allocator<T>>\nclass RdList final : public RdReactiveBase, public ViewableList<T, A>, public ISerializable\n{\nprivate:\n\tusing WT = typename IViewableList<T>::WT;\n\n\t//\t\tmutable ViewableList<T> list;\n\tusing list = ViewableList<T>;\n\tmutable int64_t next_version = 1;\n\n\tstd::string logmsg(Op op, int64_t version, int32_t key, T const* value = nullptr) const\n\t{\n\t\treturn \"list \" + to_string(location) + \" \" + to_string(rdid) + \":: \" + to_string(op) + \":: key = \" + std::to_string(key) +\n\t\t\t   ((version > 0) ? \" :: version = \" + std::to_string(version) : \"\") +\n\t\t\t   \" :: value = \" + (value ? to_string(*value) : \"\");\n\t}\n\npublic:\n\tusing Event = typename IViewableList<T>::Event;\n\n\tusing value_t = T;\n\t// region ctor/dtor\n\n\tRdList() = default;\n\n\tRdList(RdList&&) = default;\n\n\tRdList& operator=(RdList&&) = default;\n\n\tvirtual ~RdList() = default;\n\t// endregion\n\n\tstatic RdList<T, S> read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\tRdList<T, S> result;\n\t\tint64_t next_version = buffer.read_integral<int64_t>();\n\t\tRdId id = RdId::read(buffer);\n\n\t\tresult.next_version = next_version;\n\t\twithId(result, std::move(id));\n\t\treturn result;\n\t}\n\n\tvoid write(SerializationCtx& /*ctx*/, Buffer& buffer) const override\n\t{\n\t\tbuffer.write_integral<int64_t>(next_version);\n\t\trdid.write(buffer);\n\t}\n\n\tstatic const int32_t versionedFlagShift = 2;\t// update when changing Op\n\n\tbool optimize_nested = false;\n\n\tvoid init(Lifetime lifetime) const override\n\t{\n\t\tRdBindableBase::init(lifetime);\n\n\t\tlocal_change([this, lifetime] {\n\t\t\tadvise(lifetime, [this, lifetime](typename IViewableList<T>::Event e) {\n\t\t\t\tif (!is_local_change)\n\t\t\t\t\treturn;\n\n\t\t\t\tif (!optimize_nested)\n\t\t\t\t{\n\t\t\t\t\tT const* new_value = e.get_new_value();\n\t\t\t\t\tif (new_value)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst IProtocol* iProtocol = get_protocol();\n\t\t\t\t\t\tconst Identities* identity = iProtocol->get_identity();\n\t\t\t\t\t\tidentifyPolymorphic(*new_value, *identity, identity->next(rdid));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tget_wire()->send(rdid, [this, e](Buffer& buffer) {\n\t\t\t\t\tOp op = static_cast<Op>(e.v.index());\n\n\t\t\t\t\tbuffer.write_integral<int64_t>(static_cast<int64_t>(op) | (next_version++ << versionedFlagShift));\n\t\t\t\t\tbuffer.write_integral<int32_t>(static_cast<const int32_t>(e.get_index()));\n\n\t\t\t\t\tT const* new_value = e.get_new_value();\n\t\t\t\t\tif (new_value)\n\t\t\t\t\t{\n\t\t\t\t\t\tS::write(this->get_serialization_context(), buffer, *new_value);\n\t\t\t\t\t}\n\t\t\t\t\tspdlog::get(\"logSend\")->trace(logmsg(op, next_version - 1, e.get_index(), new_value));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\n\t\tget_wire()->advise(lifetime, this);\n\n\t\tif (!optimize_nested)\n\t\t{\n\t\t\tthis->view(lifetime, [this](Lifetime lf, size_t index, T const& value) {\n\t\t\t\tbindPolymorphic(value, lf, this, \"[\" + std::to_string(index) + \"]\");\n\t\t\t});\n\t\t}\n\t}\n\n\tvoid on_wire_received(Buffer buffer) const override\n\t{\n\t\tint64_t header = (buffer.read_integral<int64_t>());\n\t\tint64_t version = header >> versionedFlagShift;\n\t\tOp op = static_cast<Op>((header & ((1 << versionedFlagShift) - 1L)));\n\t\tint32_t index = (buffer.read_integral<int32_t>());\n\n\t\tRD_ASSERT_MSG(version == next_version,\n\t\t\t(\"Version conflict for \" + to_string(location) + \"}. Expected version \" + std::to_string(next_version) + \", received \" +\n\t\t\t\tstd::to_string(version) + \". Are you modifying a list from two sides?\"));\n\n\t\tnext_version++;\n\n\t\tswitch (op)\n\t\t{\n\t\t\tcase Op::ADD:\n\t\t\t{\n\t\t\t\tauto value = S::read(this->get_serialization_context(), buffer);\n\n\t\t\t\tspdlog::get(\"logReceived\")->trace(logmsg(op, version, index, &(wrapper::get<T>(value))));\n\n\t\t\t\t(index < 0) ? list::add(std::move(value)) : list::add(static_cast<size_t>(index), std::move(value));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase Op::UPDATE:\n\t\t\t{\n\t\t\t\tauto value = S::read(this->get_serialization_context(), buffer);\n\n\t\t\t\tspdlog::get(\"logReceived\")->trace(logmsg(op, version, index, &(wrapper::get<T>(value))));\n\n\t\t\t\tlist::set(static_cast<size_t>(index), std::move(value));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase Op::REMOVE:\n\t\t\t{\n\t\t\t\tspdlog::get(\"logReceived\")->trace(logmsg(op, version, index));\n\n\t\t\t\tlist::removeAt(static_cast<size_t>(index));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase Op::ACK:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tvoid advise(Lifetime lifetime, std::function<void(Event const&)> handler) const override\n\t{\n\t\tif (is_bound())\n\t\t{\n\t\t\tassert_threading();\n\t\t}\n\t\tlist::advise(lifetime, handler);\n\t}\n\n\tbool add(WT element) const override\n\t{\n\t\treturn local_change([this, element = std::move(element)]() mutable { return list::add(std::move(element)); });\n\t}\n\n\tbool add(size_t index, WT element) const override\n\t{\n\t\treturn local_change([this, index, element = std::move(element)]() mutable { return list::add(index, std::move(element)); });\n\t}\n\n\tbool remove(T const& element) const override\n\t{\n\t\treturn local_change([&] { return list::remove(element); });\n\t}\n\n\tWT removeAt(size_t index) const override\n\t{\n\t\treturn local_change([&] { return list::removeAt(index); });\n\t}\n\n\tT const& get(size_t index) const override\n\t{\n\t\treturn list::get(index);\n\t};\n\n\tWT set(size_t index, WT element) const override\n\t{\n\t\treturn local_change([&] { return list::set(index, std::move(element)); });\n\t}\n\n\tvoid clear() const override\n\t{\n\t\treturn local_change([&] { list::clear(); });\n\t}\n\n\tsize_t size() const override\n\t{\n\t\treturn list::size();\n\t}\n\n\tbool empty() const override\n\t{\n\t\treturn list::empty();\n\t}\n\n\tstd::vector<Wrapper<T>> const& getList() const override\n\t{\n\t\treturn list::getList();\n\t}\n\n\tbool addAll(size_t index, std::vector<WT> elements) const override\n\t{\n\t\treturn local_change([&] { return list::addAll(index, std::move(elements)); });\n\t}\n\n\tbool addAll(std::vector<WT> elements) const override\n\t{\n\t\treturn local_change([&] { return list::addAll(std::move(elements)); });\n\t}\n\n\tbool removeAll(std::vector<WT> elements) const override\n\t{\n\t\treturn local_change([&] { return list::removeAll(std::move(elements)); });\n\t}\n\n\tfriend std::string to_string(RdList const& value)\n\t{\n\t\tstd::string res = \"[\";\n\t\tfor (auto const& p : value)\n\t\t{\n\t\t\tres += to_string(p) + \",\";\n\t\t}\n\t\treturn res + \"]\";\n\t}\n\t// region iterators\n\n\tusing iterator = typename ViewableList<T>::iterator;\n\n\tusing reverse_iterator = typename ViewableList<T>::reverse_iterator;\n\t// endregion\n};\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\nstatic_assert(std::is_move_constructible<rd::RdList<int>>::value, \"Is move constructible RdList<int>\");\n\n#endif\t  // RD_CPP_RDLIST_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/impl/RdMap.h",
    "content": "#ifndef RD_CPP_RDMAP_H\n#define RD_CPP_RDMAP_H\n\n#include \"reactive/ViewableMap.h\"\n#include \"base/RdReactiveBase.h\"\n#include \"serialization/Polymorphic.h\"\n#include \"util/shared_function.h\"\n\n#include <cstdint>\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#endif\n\nnamespace rd\n{\n/**\n * \\brief Reactive map for connection through wire.\n *\n * \\tparam K type of stored keys\n * \\tparam V type of stored values\n * \\tparam KS \"SerDes\" for keys\n * \\tparam VS \"SerDes\" for values\n * \\tparam KA allocator for keys\n * \\tparam VA allocator for values\n */\ntemplate <typename K, typename V, typename KS = Polymorphic<K>, typename VS = Polymorphic<V>, typename KA = std::allocator<K>,\n\ttypename VA = std::allocator<V>>\nclass RdMap final : public RdReactiveBase, public ViewableMap<K, V, KA, VA>, public ISerializable\n{\nprivate:\n\tusing WK = typename IViewableMap<K, V>::WK;\n\tusing WV = typename IViewableMap<K, V>::WV;\n\tusing OV = typename IViewableMap<K, V>::OV;\n\n\tusing map = ViewableMap<K, V>;\n\tmutable int64_t next_version = 0;\n\tmutable ordered_map<K const*, int64_t, wrapper::TransparentHash<K>, wrapper::TransparentKeyEqual<K>> pendingForAck;\n\n\tstd::string logmsg(Op op, int64_t version, K const* key, V const* value = nullptr) const\n\t{\n\t\treturn \"map \" + to_string(location) + \" \" + to_string(rdid) + \":: \" + to_string(op) + \":: key = \" + to_string(*key) +\n\t\t\t   ((version > 0) ? \" :: version = \" + std::to_string(version) : \"\") +\n\t\t\t   \" :: value = \" + (value ? to_string(*value) : \"\");\n\t}\n\n\tstd::string logmsg(Op op, int64_t version, K const* key, optional<WV> const& value) const\n\t{\n\t\treturn logmsg(op, version, key, value ? &(wrapper::get(*value)) : nullptr);\n\t}\n\npublic:\n\tbool is_master = false;\n\n\tbool optimize_nested = false;\n\n\tusing Event = typename IViewableMap<K, V>::Event;\n\n\tusing key_type = K;\n\tusing value_type = V;\n\n\t// region ctor/dtor\n\n\tRdMap() = default;\n\n\tRdMap(RdMap&&) = default;\n\n\tRdMap& operator=(RdMap&&) = default;\n\n\tvirtual ~RdMap() = default;\n\t// endregion\n\n\tstatic RdMap<K, V, KS, VS> read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\tRdMap<K, V, KS, VS> res;\n\t\tRdId id = RdId::read(buffer);\n\t\twithId(res, id);\n\t\treturn res;\n\t}\n\n\tvoid write(SerializationCtx& /*ctx*/, Buffer& buffer) const override\n\t{\n\t\trdid.write(buffer);\n\t}\n\n\tstatic const int32_t versionedFlagShift = 8;\n\n\tvoid init(Lifetime lifetime) const override\n\t{\n\t\tRdBindableBase::init(lifetime);\n\n\t\tlocal_change([this, lifetime]() {\n\t\t\tadvise(lifetime, [this, lifetime](Event e) {\n\t\t\t\tif (!is_local_change)\n\t\t\t\t\treturn;\n\n\t\t\t\tV const* new_value = e.get_new_value();\n\t\t\t\tif (new_value)\n\t\t\t\t{\n\t\t\t\t\tconst IProtocol* iProtocol = get_protocol();\n\t\t\t\t\tconst Identities* identity = iProtocol->get_identity();\n\t\t\t\t\tidentifyPolymorphic(*new_value, *identity, identity->next(rdid));\n\t\t\t\t}\n\n\t\t\t\tget_wire()->send(rdid, [this, e](Buffer& buffer) {\n\t\t\t\t\tint32_t versionedFlag = ((is_master ? 1 : 0)) << versionedFlagShift;\n\t\t\t\t\tOp op = static_cast<Op>(e.v.index());\n\n\t\t\t\t\tbuffer.write_integral<int32_t>(static_cast<int32_t>(op) | versionedFlag);\n\n\t\t\t\t\tint64_t version = is_master ? ++next_version : 0L;\n\n\t\t\t\t\tif (is_master)\n\t\t\t\t\t{\n\t\t\t\t\t\tpendingForAck.emplace(e.get_key(), version);\n\t\t\t\t\t\tbuffer.write_integral(version);\n\t\t\t\t\t}\n\n\t\t\t\t\tKS::write(this->get_serialization_context(), buffer, *e.get_key());\n\n\t\t\t\t\tV const* new_value = e.get_new_value();\n\t\t\t\t\tif (new_value)\n\t\t\t\t\t{\n\t\t\t\t\t\tVS::write(this->get_serialization_context(), buffer, *new_value);\n\t\t\t\t\t}\n\n\t\t\t\t\tspdlog::get(\"logSend\")->trace(\"SEND{}\", logmsg(op, next_version - 1, e.get_key(), new_value));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\n\t\tget_wire()->advise(lifetime, this);\n\n\t\tif (!optimize_nested)\n\t\t\tthis->view(lifetime, [this](Lifetime lf, std::pair<K const*, V const*> entry) {\n\t\t\t\tbindPolymorphic(entry.second, lf, this, \"[\" + to_string(*entry.first) + \"]\");\n\t\t\t});\n\t}\n\n\tvoid on_wire_received(Buffer buffer) const override\n\t{\n\t\tint32_t header = buffer.read_integral<int32_t>();\n\t\tbool msg_versioned = (header >> versionedFlagShift) != 0;\n\t\tOp op = static_cast<Op>(header & ((1 << versionedFlagShift) - 1));\n\n\t\tint64_t version = msg_versioned ? buffer.read_integral<int64_t>() : 0;\n\n\t\tWK key = KS::read(this->get_serialization_context(), buffer);\n\n\t\tif (op == Op::ACK)\n\t\t{\n\t\t\tstd::string errmsg;\n\t\t\tif (!msg_versioned)\n\t\t\t{\n\t\t\t\terrmsg = \"Received \" + to_string(Op::ACK) + \" while msg hasn't versioned flag set\";\n\t\t\t}\n\t\t\telse if (!is_master)\n\t\t\t{\n\t\t\t\terrmsg = \"Received \" + to_string(Op::ACK) + \" when not a Master\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (pendingForAck.count(key) > 0)\n\t\t\t\t{\n\t\t\t\t\tint64_t pendingVersion = pendingForAck.at(key);\n\t\t\t\t\tif (pendingVersion < version)\n\t\t\t\t\t{\n\t\t\t\t\t\terrmsg = \"Pending version \" + std::to_string(pendingVersion) + \" < \" + to_string(Op::ACK) + \" version `\" +\n\t\t\t\t\t\t\t\t std::to_string(version);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// side effect\n\t\t\t\t\t\tif (pendingVersion == version)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpendingForAck.erase(key);\t // else we don't need to remove, silently drop\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// return good result\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terrmsg = \"No pending for \" + to_string(Op::ACK);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (errmsg.empty())\n\t\t\t{\n\t\t\t\tspdlog::get(\"logReceived\")->trace(logmsg(Op::ACK, version, &(wrapper::get<K>(key))));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tspdlog::get(\"logReceived\")->error(logmsg(Op::ACK, version, &(wrapper::get<K>(key))) + \" >> \" + errmsg);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tBuffer serialized_key;\n\t\t\tKS::write(this->get_serialization_context(), serialized_key, wrapper::get<K>(key));\n\n\t\t\tbool is_put = (op == Op::ADD || op == Op::UPDATE);\n\t\t\toptional<WV> value;\n\t\t\tif (is_put)\n\t\t\t{\n\t\t\t\tvalue = VS::read(this->get_serialization_context(), buffer);\n\t\t\t}\n\n\t\t\tif (msg_versioned || !is_master || pendingForAck.count(key) == 0)\n\t\t\t{\n\t\t\t\tspdlog::get(\"logReceived\")->trace(\"RECV{}\", logmsg(op, version, &(wrapper::get<K>(key)), value));\n\t\t\t\tif (value.has_value())\n\t\t\t\t{\n\t\t\t\t\tmap::set(std::move(key), *std::move(value));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tmap::remove(wrapper::get<K>(key));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tspdlog::get(\"logReceived\")->trace(\"{} >> REJECTED\", logmsg(op, version, &(wrapper::get<K>(key)), value));\n\t\t\t}\n\n\t\t\tif (msg_versioned)\n\t\t\t{\n\t\t\t\tauto writer =\n\t\t\t\t\tutil::make_shared_function([version, serialized_key = std::move(serialized_key)](Buffer& innerBuffer) mutable {\n\t\t\t\t\t\tinnerBuffer.write_integral<int32_t>((1u << versionedFlagShift) | static_cast<int32_t>(Op::ACK));\n\t\t\t\t\t\tinnerBuffer.write_integral<int64_t>(version);\n\t\t\t\t\t\t// KS::write(this->get_serialization_context(), innerBuffer, wrapper::get<K>(key));\n\t\t\t\t\t\tinnerBuffer.write_byte_array_raw(serialized_key.getArray());\n\t\t\t\t\t\t// logSend.trace(logmsg(Op::ACK, version, serialized_key));\n\t\t\t\t\t});\n\t\t\t\tget_wire()->send(rdid, std::move(writer));\n\t\t\t\tif (is_master)\n\t\t\t\t{\n\t\t\t\t\tspdlog::get(\"logReceived\")->error(\"Both ends are masters: {}\", to_string(location));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid advise(Lifetime lifetime, std::function<void(Event const&)> handler) const override\n\t{\n\t\tif (is_bound())\n\t\t{\n\t\t\tassert_threading();\n\t\t}\n\t\tmap::advise(lifetime, handler);\n\t}\n\n\tV const* get(K const& key) const override\n\t{\n\t\treturn local_change([&] { return map::get(key); });\n\t}\n\n\tV const* set(WK key, WV value) const override\n\t{\n\t\treturn local_change([&]() mutable { return map::set(std::move(key), std::move(value)); });\n\t}\n\n\tOV remove(K const& key) const override\n\t{\n\t\treturn local_change([&] { return map::remove(key); });\n\t}\n\n\tvoid clear() const override\n\t{\n\t\treturn local_change([&] { return map::clear(); });\n\t}\n\n\tsize_t size() const override\n\t{\n\t\treturn map::size();\n\t}\n\n\tbool empty() const override\n\t{\n\t\treturn map::empty();\n\t}\n\n\tfriend std::string to_string(RdMap const& value)\n\t{\n\t\tstd::string res = \"[\";\n\t\tfor (auto it = value.begin(); it != value.end(); ++it)\n\t\t{\n\t\t\tres += to_string(it.key()) + \"=>\" + to_string(it.value()) + \",\";\n\t\t}\n\t\treturn res + \"]\";\n\t}\n};\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\nstatic_assert(std::is_move_constructible<rd::RdMap<int, int>>::value, \"Is move constructible RdMap<int, int>\");\nstatic_assert(std::is_move_assignable<rd::RdMap<int, int>>::value, \"Is move constructible RdMap<int, int>\");\nstatic_assert(std::is_default_constructible<rd::RdMap<int, int>>::value, \"Is default constructible RdMap<int, int>\");\n\n#endif\t  // RD_CPP_RDMAP_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/impl/RdProperty.h",
    "content": "#ifndef RD_CPP_RDPROPERTY_H\n#define RD_CPP_RDPROPERTY_H\n\n#include \"base/RdPropertyBase.h\"\n#include \"serialization/Polymorphic.h\"\n#include \"serialization/ISerializable.h\"\n#include \"std/allocator.h\"\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#endif\n\nnamespace rd\n{\n/**\n * \\brief Reactive property for connection through wire.\n\n * \\tparam T type of stored value\n * \\tparam S \"SerDes\" for value\n */\ntemplate <typename T, typename S = Polymorphic<T>, typename A = allocator<T>>\nclass RdProperty final : public RdPropertyBase<T, S>, public ISerializable\n{\npublic:\n\tusing value_type = T;\n\n\t// region ctor/dtor\n\n\tRdProperty() = default;\n\n\tRdProperty(RdProperty const&) = delete;\n\n\tRdProperty& operator=(RdProperty const&) = delete;\n\n\tRdProperty(RdProperty&&) = default;\n\n\tRdProperty& operator=(RdProperty&&) = default;\n\n\ttemplate <typename F>\n\texplicit RdProperty(F&& value) : RdPropertyBase<T, S>(std::forward<F>(value))\n\t{\n\t}\n\n\tvirtual ~RdProperty() = default;\n\t// endregion\n\n\tstatic RdProperty<T, S> read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\tRdId id = RdId::read(buffer);\n\t\tbool not_null = buffer.read_bool();\t   // not null/\n\t\t(void) not_null;\n\t\tauto value = S::read(ctx, buffer);\n\t\tRdProperty<T, S> property;\n\t\tproperty.value = std::move(value);\n\t\twithId(property, id);\n\t\treturn property;\n\t}\n\n\tvoid write(SerializationCtx& ctx, Buffer& buffer) const override\n\t{\n\t\tthis->rdid.write(buffer);\n\t\tbuffer.write_bool(true);\n\t\tS::write(ctx, buffer, this->get());\n\t}\n\n\tvoid advise(Lifetime lifetime, std::function<void(T const&)> handler) const override\n\t{\n\t\tRdPropertyBase<T, S>::advise(lifetime, std::move(handler));\n\t}\n\n\tRdProperty<T, S>& slave()\n\t{\n\t\tthis->is_master = false;\n\t\treturn *this;\n\t}\n\n\tvoid identify(Identities const& identities, RdId const& id) const override\n\t{\n\t\tRdBindableBase::identify(identities, id);\n\t\tif (!this->optimize_nested && this->has_value())\n\t\t{\n\t\t\tidentifyPolymorphic(this->get(), identities, identities.next(id));\n\t\t}\n\t}\n\n\tfriend bool operator==(const RdProperty& lhs, const RdProperty& rhs)\n\t{\n\t\treturn &lhs == &rhs;\n\t}\n\n\tfriend bool operator!=(const RdProperty& lhs, const RdProperty& rhs)\n\t{\n\t\treturn !(rhs == lhs);\n\t}\n\n\tfriend std::string to_string(RdProperty const& value)\n\t{\n\t\treturn to_string(static_cast<Property<T> const&>(value));\n\t}\n};\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\nstatic_assert(std::is_move_constructible<rd::RdProperty<int>>::value, \"Is move constructible from RdProperty<int>\");\n\n#endif\t  // RD_CPP_RDPROPERTY_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/impl/RdSet.h",
    "content": "#ifndef RD_CPP_RDSET_H\n#define RD_CPP_RDSET_H\n\n#include \"reactive/ViewableSet.h\"\n#include \"base/RdReactiveBase.h\"\n#include \"serialization/Polymorphic.h\"\n#include \"std/allocator.h\"\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#endif\n\nnamespace rd\n{\n/**\n * \\brief Reactive set for connection through wire.\n *\n * \\tparam T type of stored values\n * \\tparam S \"SerDes\" for values\n */\ntemplate <typename T, typename S = Polymorphic<T>, typename A = allocator<T>>\nclass RdSet final : public RdReactiveBase, public ViewableSet<T, A>, public ISerializable\n{\nprivate:\n\tusing WT = typename IViewableSet<T>::WT;\n\nprotected:\n\tusing set = ViewableSet<T>;\n\npublic:\n\tusing Event = typename IViewableSet<T>::Event;\n\n\tusing value_type = T;\n\n\t// region ctor/dtor\n\n\tRdSet() = default;\n\n\tRdSet(RdSet&&) = default;\n\n\tRdSet& operator=(RdSet&&) = default;\n\n\tvirtual ~RdSet() = default;\n\n\t// endregion\n\n\tstatic RdSet<T, S> read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\tRdSet<T, S> result;\n\t\tRdId id = RdId::read(buffer);\n\t\twithId(result, std::move(id));\n\t\treturn result;\n\t}\n\n\tvoid write(SerializationCtx& /*ctx*/, Buffer& buffer) const override\n\t{\n\t\trdid.write(buffer);\n\t}\n\n\tbool optimize_nested = false;\n\n\tvoid init(Lifetime lifetime) const override\n\t{\n\t\tRdBindableBase::init(lifetime);\n\n\t\tlocal_change([this, lifetime] {\n\t\t\tadvise(lifetime, [this](AddRemove kind, T const& v) {\n\t\t\t\tif (!is_local_change)\n\t\t\t\t\treturn;\n\n\t\t\t\tget_wire()->send(rdid, [this, kind, &v](Buffer& buffer) {\n\t\t\t\t\tbuffer.write_enum<AddRemove>(kind);\n\t\t\t\t\tS::write(this->get_serialization_context(), buffer, v);\n\n\t\t\t\t\tspdlog::get(\"logSend\")->trace(\"SENDset {} {}:: {}:: {}\", to_string(location), to_string(rdid), to_string(kind), to_string(v));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\n\t\tget_wire()->advise(lifetime, this);\n\t}\n\n\tvoid on_wire_received(Buffer buffer) const override\n\t{\n\t\tAddRemove kind = buffer.read_enum<AddRemove>();\n\t\tauto value = S::read(this->get_serialization_context(), buffer);\n\n\t\tswitch (kind)\n\t\t{\n\t\t\tcase AddRemove::ADD:\n\t\t\t{\n\t\t\t\tset::add(std::move(value));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase AddRemove::REMOVE:\n\t\t\t{\n\t\t\t\tset::remove(wrapper::get<T>(value));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tbool add(WT value) const override\n\t{\n\t\treturn local_change([this, value = std::move(value)]() mutable { return set::add(std::move(value)); });\n\t}\n\n\tvoid clear() const override\n\t{\n\t\treturn local_change([&] { return set::clear(); });\n\t}\n\n\tbool remove(T const& value) const override\n\t{\n\t\treturn local_change([&] { return set::remove(value); });\n\t}\n\n\tsize_t size() const override\n\t{\n\t\treturn local_change([&] { return set::size(); });\n\t}\n\n\tbool contains(T const& value) const override\n\t{\n\t\treturn local_change([&] { return set::contains(value); });\n\t}\n\n\tbool empty() const override\n\t{\n\t\treturn local_change([&] { return set::empty(); });\n\t}\n\n\tvoid advise(Lifetime lifetime, std::function<void(Event const&)> handler) const override\n\t{\n\t\tif (is_bound())\n\t\t{\n\t\t\tassert_threading();\n\t\t}\n\t\tset::advise(lifetime, std::move(handler));\n\t}\n\n\tbool addAll(std::vector<WT> elements) const override\n\t{\n\t\treturn local_change([this, elements = std::move(elements)]() mutable { return set::addAll(elements); });\n\t}\n\n\tfriend std::string to_string(RdSet const& value)\n\t{\n\t\tstd::string res = \"[\";\n\t\tfor (auto const& p : value)\n\t\t{\n\t\t\tres += to_string(p) + \",\";\n\t\t}\n\t\treturn res + \"]\";\n\t}\n\n\tusing IViewableSet<T>::advise;\n};\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\nstatic_assert(std::is_move_constructible<rd::RdSet<int>>::value, \"Is move constructible RdSet<int>\");\n\n#endif\t  // RD_CPP_RDSET_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/impl/RdSignal.h",
    "content": "#ifndef RD_CPP_RDSIGNAL_H\n#define RD_CPP_RDSIGNAL_H\n\n#include \"lifetime/Lifetime.h\"\n#include \"reactive/base/interfaces.h\"\n#include \"scheduler/base/IScheduler.h\"\n#include \"reactive/base/SignalX.h\"\n#include \"base/RdReactiveBase.h\"\n#include \"serialization/Polymorphic.h\"\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#endif\n\nnamespace rd\n{\n/**\n * \\brief Reactive signal for connection through wire.\n *\n * \\tparam T type of events\n * \\tparam S \"SerDes\" for events\n */\ntemplate <typename T, typename S = Polymorphic<T>>\nclass RdSignal final : public RdReactiveBase, public ISignal<T>, public ISerializable\n{\nprivate:\n\tusing WT = typename ISignal<T>::WT;\n\n\tstd::string logmsg(T const& value) const\n\t{\n\t\treturn \"signal \" + to_string(location) + \" \" + to_string(rdid) + \":: value = \" + to_string(value);\n\t}\n\n\tmutable IScheduler* wire_scheduler{};\n\nprivate:\n\tvoid set_wire_scheduler(IScheduler* scheduler) const\n\t{\n\t\twire_scheduler = scheduler;\n\t}\n\nprotected:\n\tSignal<T> signal;\n\npublic:\n\t// region ctor/dtor\n\n\tRdSignal(RdSignal const&) = delete;\n\n\tRdSignal& operator=(RdSignal const&) = delete;\n\n\tRdSignal() = default;\n\n\tRdSignal(RdSignal&&) = default;\n\n\tRdSignal& operator=(RdSignal&&) = default;\n\n\tvirtual ~RdSignal() = default;\n\t// endregion\n\n\tstatic RdSignal<T, S> read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\tRdSignal<T, S> res;\n\t\tconst RdId& id = RdId::read(buffer);\n\t\twithId(res, id);\n\t\treturn res;\n\t}\n\n\tvoid write(SerializationCtx& /*ctx*/, Buffer& buffer) const override\n\t{\n\t\trdid.write(buffer);\n\t}\n\n\tvoid init(Lifetime lifetime) const override\n\t{\n\t\tRdReactiveBase::init(lifetime);\n\t\tset_wire_scheduler(get_default_scheduler());\n\t\tget_wire()->advise(lifetime, this);\n\t}\n\n\tvoid on_wire_received(Buffer buffer) const override\n\t{\n\t\tauto value = S::read(this->get_serialization_context(), buffer);\n\t\tspdlog::get(\"logReceived\")->trace(\"RECV{}\", logmsg(wrapper::get<T>(value)));\n\n\t\tsignal.fire(wrapper::get<T>(value));\n\t}\n\n\tusing ISignal<T>::fire;\n\n\tvoid fire(T const& value) const override\n\t{\n\t    // Disabling checking for bounding, to fix async signal being called unbound on another thread.\n\t\t// Copying hack from rd-net\n\t\t// https://github.com/JetBrains/rd/blob/d00d07c38784af5743c75ceca4bbceb92f6f8149/rd-net/RdFramework/Impl/RdSignal.cs#L72-L95\n\t\t// assert_bound();\n\t\tif (!async)\n\t\t{\n\t\t\tassert_threading();\n\t\t}\n\n\t\tif (async && !is_bound()) return;\n\n\t\tget_wire()->send(rdid, [this, &value](Buffer& buffer) {\n\t\t\tspdlog::get(\"logSend\")->trace(\"SEND{}\", logmsg(value));\n\t\t\tS::write(get_serialization_context(), buffer, value);\n\t\t});\n\t\tsignal.fire(value);\n\t}\n\n\tusing ISource<T>::advise;\n\n\tvoid advise(Lifetime lifetime, std::function<void(T const&)> handler) const override\n\t{\n\t\tif (is_bound())\n\t\t{\n\t\t\tassert_threading();\n\t\t}\n\t\tsignal.advise(lifetime, handler);\n\t}\n\n\ttemplate <typename F>\n\tvoid advise_on(Lifetime lifetime, IScheduler* scheduler, F&& handler)\n\t{\n\t\tif (is_bound())\n\t\t{\n\t\t\tassert_threading();\n\t\t}\n\t\tset_wire_scheduler(scheduler);\n\t\tsignal.advise(lifetime, std::forward<F>(handler));\n\t}\n\n\tIScheduler* get_wire_scheduler() const override\n\t{\n\t\treturn wire_scheduler;\n\t}\n\n\tfriend std::string to_string(RdSignal const&)\n\t{\n\t\treturn \"\";\n\t}\n};\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\nstatic_assert(std::is_move_constructible<rd::RdSignal<int>>::value, \"Is not move constructible from RdSignal<int>\");\n\n#endif\t  // RD_CPP_RDSIGNAL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/intern/InternRoot.cpp",
    "content": "#include \"InternRoot.h\"\n\n#include \"serialization/AbstractPolymorphic.h\"\n#include \"serialization/InternedAnySerializer.h\"\n\nnamespace rd\n{\nInternRoot::InternRoot()\n{\n\tasync = true;\n}\n\nIScheduler* InternRoot::get_wire_scheduler() const\n{\n\treturn &intern_scheduler;\n}\n\nvoid InternRoot::on_wire_received(Buffer buffer) const\n{\n\toptional<InternedAny> value = InternedAnySerializer::read(get_serialization_context(), buffer);\n\tif (!value)\n\t{\n\t\treturn;\n\t}\n\tconst int32_t remote_id = buffer.read_integral<int32_t>();\n\tset_interned_correspondence(remote_id ^ 1, *std::move(value));\n\tRD_ASSERT_MSG(((remote_id & 1) == 0), \"Remote sent ID marked as our own, bug?\");\n}\n\nvoid InternRoot::bind(Lifetime lf, IRdDynamic const* parent, string_view name) const\n{\n\tRD_ASSERT_MSG(!is_bound(), \"Trying to bound already bound \"s + to_string(this->location) + \" to \" + to_string(parent->get_location()))\n\n\tlf->bracket(\n\t\t[this, parent, &name] {\n\t\t\tthis->parent = parent;\n\t\t\tlocation = parent->get_location().sub(name, \".\");\n\t\t},\n\t\t[this] {\n\t\t\tlocation = location.sub(\"<<unbound>>\", \"::\");\n\t\t\tthis->parent = nullptr;\n\t\t\trdid = RdId::Null();\n\t\t});\n\n\t{\n\t\t// if something's interned before bind\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\tmy_items_lis.clear();\n\t\tother_items_list.clear();\n\t\tinverse_map.clear();\n\t}\n\tget_protocol()->get_wire()->advise(lf, this);\n}\n\nvoid InternRoot::identify(const Identities& /*identities*/, RdId const& id) const\n{\n\tRD_ASSERT_MSG(rdid.isNull(), \"Already has RdId: \" + to_string(rdid) + \", entities: $this\");\n\tRD_ASSERT_MSG(!id.isNull(), \"Assigned RdId mustn't be null, entities: $this\");\n\n\trdid = id;\n}\n\nvoid InternRoot::set_interned_correspondence(int32_t id, InternedAny&& value) const\n{\n\tRD_ASSERT_MSG(!is_index_owned(id), \"Setting interned correspondence for object that we should have written, bug?\")\n\n\tstd::lock_guard<decltype(lock)> guard(lock);\n\tother_items_list[id / 2] = value;\n\tinverse_map[value] = id;\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/intern/InternRoot.h",
    "content": "#ifndef RD_CPP_INTERNROOT_H\n#define RD_CPP_INTERNROOT_H\n\n#include \"base/RdReactiveBase.h\"\n#include \"InternScheduler.h\"\n#include \"lifetime/Lifetime.h\"\n#include \"types/wrapper.h\"\n#include \"serialization/RdAny.h\"\n#include \"util/core_traits.h\"\n\n#include \"tsl/ordered_map.h\"\n\n#include <vector>\n#include <string>\n#include <mutex>\n\n#include <rd_framework_export.h>\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#pragma warning(disable : 4251)\n#endif\n\nnamespace rd\n{\n// region predeclared\n\nclass Identities;\n\n// endregion\n\n/**\n * \\brief Node in graph for storing interned objects.\n */\nclass RD_FRAMEWORK_API InternRoot final : public RdReactiveBase\n{\nprivate:\n\t// template<typename T>\n\tmutable std::vector<InternedAny> my_items_lis;\n\n\t// template<typename T>\n\tmutable ordered_map<int32_t, InternedAny> other_items_list;\n\t// template<typename T>\n\tmutable ordered_map<InternedAny, int32_t, any::TransparentHash, any::TransparentKeyEqual> inverse_map;\n\n\tmutable InternScheduler intern_scheduler;\n\n\tmutable std::recursive_mutex lock;\n\n\tvoid set_interned_correspondence(int32_t id, InternedAny&& value) const;\n\n\tstatic constexpr bool is_index_owned(int32_t id);\n\npublic:\n\t// region ctor/dtor\n\n\tInternRoot();\n\t// endregion\n\n\ttemplate <typename T>\n\tint32_t intern_value(Wrapper<T> value) const;\n\n\ttemplate <typename T>\n\tWrapper<T> un_intern_value(int32_t id) const;\n\n\tIScheduler* get_wire_scheduler() const override;\n\n\tvoid bind(Lifetime lf, IRdDynamic const* parent, string_view name) const override;\n\n\tvoid identify(const Identities& identities, RdId const& id) const override;\n\n\tvoid on_wire_received(Buffer buffer) const override;\n};\n}\t // namespace rd\n\n#include \"serialization/InternedAnySerializer.h\"\n\nnamespace rd\n{\n/*template<typename T>\nstd::vector<value_or_wrapper<T>> InternRoot::myItemsList = {};\n\ntemplate<typename T>\nordered_map<int32_t, value_or_wrapper<T>> InternRoot::otherItemsList = {};\n\ntemplate<typename T>\nordered_map<value_or_wrapper<T>, int32_t> InternRoot::inverseMap = {};*/\n\nconstexpr bool InternRoot::is_index_owned(int32_t id)\n{\n\treturn !static_cast<bool>(id & 1);\n}\n\ntemplate <typename T>\nWrapper<T> InternRoot::un_intern_value(int32_t id) const\n{\n\t// don't need lock because value's already exists and never removes\n\treturn any::get<T>(is_index_owned(id) ? my_items_lis[id / 2] : other_items_list[id / 2]);\n}\n\ntemplate <typename T>\nint32_t InternRoot::intern_value(Wrapper<T> value) const\n{\n\tInternedAny any = any::make_interned_any<T>(value);\n\n\tstd::lock_guard<decltype(lock)> guard(lock);\n\n\tauto it = inverse_map.find(any);\n\tint32_t index = 0;\n\tif (it == inverse_map.end())\n\t{\n\t\tget_protocol()->get_wire()->send(this->rdid, [this, &index, value, any](Buffer& buffer) {\n\t\t\tInternedAnySerializer::write<T>(get_serialization_context(), buffer, wrapper::get<T>(value));\n\t\t\t{\n\t\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\t\t\tindex = static_cast<int32_t>(my_items_lis.size()) * 2;\n\t\t\t\tmy_items_lis.emplace_back(any);\n\t\t\t}\n\t\t\tbuffer.write_integral<int32_t>(index);\n\t\t});\n\t}\n\telse\n\t{\n\t\tindex = it->second;\n\t}\n\tif (inverse_map.count(any) == 0)\n\t{\n\t\tinverse_map[any] = index;\n\t}\n\treturn index;\n}\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_INTERNROOT_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/intern/InternScheduler.cpp",
    "content": "#include \"InternScheduler.h\"\n\n#include \"guards.h\"\n\nnamespace rd\n{\nthread_local int32_t InternScheduler::active_counts = 0;\n\nInternScheduler::InternScheduler()\n{\n\tout_of_order_execution = true;\n}\n\nvoid InternScheduler::queue(std::function<void()> action)\n{\n\tutil::increment_guard<int32_t> guard(active_counts);\n\taction();\n}\n\nvoid InternScheduler::flush()\n{\n}\n\nbool InternScheduler::is_active() const\n{\n\treturn active_counts > 0;\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/intern/InternScheduler.h",
    "content": "#ifndef RD_CPP_INTERNSCHEDULER_H\n#define RD_CPP_INTERNSCHEDULER_H\n\n#include \"scheduler/base/IScheduler.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n/**\n * \\brief Scheduler for interning object. Maintains out of order execution.\n */\nclass InternScheduler : public IScheduler\n{\n\tstatic thread_local int32_t active_counts;\n\npublic:\n\t// region ctor/dtor\n\n\tInternScheduler();\n\t// endregion\n\n\tvoid queue(std::function<void()> action) override;\n\n\tvoid flush() override;\n\n\tbool is_active() const override;\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_INTERNSCHEDULER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/Buffer.cpp",
    "content": "#include <utility>\n\n#include \"protocol/Buffer.h\"\n\n#include <string>\n#include <algorithm>\n\nnamespace rd\n{\nBuffer::Buffer() : Buffer(16)\n{\n}\n\nBuffer::Buffer(size_t initialSize) : data_(initialSize)\n{\n}\n\nBuffer::Buffer(ByteArray array, size_t offset) : data_(std::move(array)), offset(offset)\n{\n}\n\nsize_t Buffer::get_position() const\n{\n\treturn offset;\n}\n\nvoid Buffer::set_position(size_t value)\n{\n\toffset = value;\n}\n\nvoid Buffer::check_available(size_t moreSize) const\n{\n\tif (offset + moreSize > size())\n\t{\n\t\tthrow std::out_of_range(\n\t\t\t\"Expected \" + std::to_string(moreSize) + \" bytes in buffer, only\" + std::to_string(size() - offset) + \"available\");\n\t}\n}\n\nvoid Buffer::read(word_t* dst, size_t size)\n{\n\tif (size == 0)\n\t\treturn;\n\tcheck_available(size);\n\tstd::copy(&data_[offset], &data_[offset] + size, dst);\n\toffset += size;\n}\n\nvoid Buffer::write(const word_t* src, size_t size)\n{\n\tif (size == 0)\n\t\treturn;\n\trequire_available(size);\n\tstd::copy(src, src + size, &data_[offset]);\n\toffset += size;\n}\n\nvoid Buffer::require_available(size_t moreSize)\n{\n\tif (offset + moreSize >= size())\n\t{\n\t\tconst size_t new_size = (std::max)(size() * 2, offset + moreSize);\n\t\tdata_.resize(new_size);\n\t}\n}\n\nvoid Buffer::rewind()\n{\n\tset_position(0);\n}\n\nBuffer::ByteArray Buffer::getArray() const&\n{\n\treturn data_;\n}\n\nBuffer::ByteArray Buffer::getArray() &&\n{\n\trewind();\n\treturn std::move(data_);\n}\n\nBuffer::ByteArray Buffer::getRealArray() const&\n{\n\tauto res = getArray();\n\tres.resize(offset);\n\treturn res;\n}\n\nBuffer::ByteArray Buffer::getRealArray() &&\n{\n\tauto res = std::move(data_);\n\tres.resize(offset);\n\trewind();\n\treturn res;\n}\n\nBuffer::word_t const* Buffer::data() const\n{\n\treturn data_.data();\n}\n\nBuffer::word_t* Buffer::data()\n{\n\treturn data_.data();\n}\n\nBuffer::word_t const* Buffer::current_pointer() const\n{\n\treturn data() + offset;\n}\n\nBuffer::word_t* Buffer::current_pointer()\n{\n\treturn data() + offset;\n}\n\nsize_t Buffer::size() const\n{\n\treturn data_.size();\n}\n\n/*std::string Buffer::readString() const {\nauto v = readArray<uint8_t>();\nreturn std::string(v.begin(), v.end());\n}\n\nvoid Buffer::writeString(std::string const &value) const {\nstd::vector<uint8_t> v(value.begin(), value.end());\nwriteArray<uint8_t>(v);\n}*/\n\ntemplate <int>\nstd::wstring read_wstring_spec(Buffer& buffer)\n{\n\tauto v = buffer.read_array<std::vector, uint16_t>();\n\treturn std::wstring(v.begin(), v.end());\n}\n\ntemplate <>\nstd::wstring read_wstring_spec<2>(Buffer& buffer)\n{\n\tconst int32_t len = buffer.read_integral<int32_t>();\n\tRD_ASSERT_MSG(len >= 0, \"read null string(length =\" + std::to_string(len) + \")\");\n\tstd::wstring result;\n\tresult.resize(len);\n\tbuffer.read(reinterpret_cast<Buffer::word_t*>(&result[0]), sizeof(wchar_t) * len);\n\treturn result;\n}\n\nstd::wstring Buffer::read_wstring()\n{\n\treturn read_wstring_spec<sizeof(wchar_t)>(*this);\n}\n\ntemplate <int>\nvoid write_wstring_spec(Buffer& buffer, wstring_view value)\n{\n\tconst std::vector<uint16_t> v(value.begin(), value.end());\n\tbuffer.write_array<std::vector, uint16_t>(v);\n}\n\ntemplate <>\nvoid write_wstring_spec<2>(Buffer& buffer, wstring_view value)\n{\n\tbuffer.write_integral<int32_t>(static_cast<int32_t>(value.size()));\n\tbuffer.write(reinterpret_cast<Buffer::word_t const*>(value.data()), sizeof(wchar_t) * value.size());\n}\n\nvoid Buffer::write_wstring(std::wstring const& value)\n{\n\twrite_wstring(wstring_view(value));\n}\n\nvoid Buffer::write_char16_string(const uint16_t* data, size_t len)\n{\n\twrite_integral<int32_t>(static_cast<int32_t>(len));\n\twrite(reinterpret_cast<word_t const*>(data), sizeof(uint16_t) * len);\n}\n\nuint16_t* Buffer::read_char16_string()\n{\t\n\tconst int32_t len = read_integral<int32_t>();\n\tRD_ASSERT_MSG(len >= 0, \"read null string(length =\" + std::to_string(len) + \")\");\n\tuint16_t * result = new uint16_t[len+1];\n\tread(reinterpret_cast<Buffer::word_t*>(&result[0]), sizeof(uint16_t) * len);\n\tresult[len] = 0;\n\treturn result;\n}\n\nvoid Buffer::write_wstring(wstring_view value)\n{\n\twrite_wstring_spec<sizeof(wchar_t)>(*this, value);\n}\n\nvoid Buffer::write_wstring(Wrapper<std::wstring> const& value)\n{\n\twrite_wstring(*value);\n}\n\nint64_t TICKS_AT_EPOCH = 621355968000000000L;\nint64_t TICKS_PER_MILLISECOND = 10000000;\n\nDateTime Buffer::read_date_time()\n{\n\tint64_t time_in_ticks = read_integral<int64_t>();\n\ttime_t t = static_cast<time_t>(time_in_ticks / TICKS_PER_MILLISECOND - TICKS_AT_EPOCH / TICKS_PER_MILLISECOND);\n\treturn DateTime{t};\n}\n\nvoid Buffer::write_date_time(DateTime const& date_time)\n{\n\tuint64_t t = date_time.seconds * TICKS_PER_MILLISECOND + TICKS_AT_EPOCH;\n\twrite_integral<int64_t>(t);\n}\n\nbool Buffer::read_bool()\n{\n\tconst auto res = read_integral<uint8_t>();\n\tRD_ASSERT_MSG(res == 0 || res == 1, \"get byte:\" + std::to_string(res) + \" instead of 0 or 1\");\n\treturn res == 1;\n}\n\nvoid Buffer::write_bool(bool value)\n{\n\twrite_integral<word_t>(value ? 1 : 0);\n}\n\nwchar_t Buffer::read_char()\n{\n\treturn static_cast<wchar_t>(read_integral<uint16_t>());\n}\n\nvoid Buffer::write_char(wchar_t value)\n{\n\twrite_integral<uint16_t>(value);\n}\n\nvoid Buffer::read_byte_array(ByteArray& array)\n{\n\tconst int32_t length = read_integral<int32_t>();\n\tarray.resize(length);\n\tread_byte_array_raw(array);\n}\n\nvoid Buffer::read_byte_array_raw(ByteArray& array)\n{\n\tread(array.data(), array.size());\n}\n\nvoid Buffer::write_byte_array_raw(const ByteArray& array)\n{\n\twrite(array.data(), array.size());\n}\n\nBuffer::ByteArray& Buffer::get_data()\n{\n\treturn data_;\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/Buffer.h",
    "content": "#ifndef RD_CPP_UNSAFEBUFFER_H\n#define RD_CPP_UNSAFEBUFFER_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"types/DateTime.h\"\n#include \"util/core_util.h\"\n#include \"types/wrapper.h\"\n#include \"std/allocator.h\"\n#include \"std/list.h\"\n\n#include <vector>\n#include <type_traits>\n#include <functional>\n#include <memory>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n/**\n * \\brief Simple data buffer. Allows to \"SerDes\" plenty of types, such as integrals, arrays, etc.\n */\nclass RD_FRAMEWORK_API Buffer final\n{\npublic:\n\tfriend class PkgInputStream;\n\n\tusing word_t = uint8_t;\n\n\tusing Allocator = std::allocator<word_t>;\n\n\tusing ByteArray = std::vector<word_t, Allocator>;\n\nprivate:\n\ttemplate <int>\n\tfriend std::wstring read_wstring_spec(Buffer&);\n\n\ttemplate <int>\n\tfriend void write_wstring_spec(Buffer&, wstring_view);\n\n\tByteArray data_;\n\n\tsize_t offset = 0;\n\n\t// read\n\tvoid read(word_t* dst, size_t size);\n\n\t// write\n\tvoid write(const word_t* src, size_t size);\n\n\tsize_t size() const;\n\npublic:\n\t// region ctor/dtor\n\n\tBuffer();\n\n\texplicit Buffer(size_t initial_size);\n\n\texplicit Buffer(ByteArray array, size_t offset = 0);\n\n\tBuffer(Buffer const&) = delete;\n\n\tBuffer& operator=(Buffer const&) = delete;\n\n\tBuffer(Buffer&&) noexcept = default;\n\n\tBuffer& operator=(Buffer&&) noexcept = default;\n\n\t// endregion\n\n\tsize_t get_position() const;\n\n\tvoid set_position(size_t value);\n\n\tvoid require_available(size_t size);\n\n\tvoid check_available(size_t moreSize) const;\n\n\tvoid rewind();\n\n\ttemplate <typename T, typename = typename std::enable_if_t<std::is_integral<T>::value, T>>\n\tT read_integral()\n\t{\n\t\tT result;\n\t\tread(reinterpret_cast<word_t*>(&result), sizeof(T));\n\t\treturn result;\n\t}\n\n\ttemplate <typename T, typename = typename std::enable_if_t<std::is_integral<T>::value>>\n\tvoid write_integral(T const& value)\n\t{\n\t\twrite(reinterpret_cast<word_t const*>(&value), sizeof(T));\n\t}\n\n\ttemplate <typename T, typename = typename std::enable_if_t<std::is_floating_point<T>::value, T>>\n\tT read_floating_point()\n\t{\n\t\tT result;\n\t\tread(reinterpret_cast<word_t*>(&result), sizeof(T));\n\t\treturn result;\n\t}\n\n\ttemplate <typename T, typename = typename std::enable_if_t<std::is_floating_point<T>::value>>\n\tvoid write_floating_point(T const& value)\n\t{\n\t\twrite(reinterpret_cast<word_t const*>(&value), sizeof(T));\n\t}\n\n\ttemplate <template <class, class> class C, typename T, typename A = allocator<T>,\n\t\ttypename = typename std::enable_if_t<util::is_pod_v<T>>>\n\tC<T, A> read_array()\n\t{\n\t\tint32_t len = read_integral<int32_t>();\n\t\tRD_ASSERT_MSG(len >= 0, \"read null array(length = \" + std::to_string(len) + \")\");\n\t\tC<T, A> result;\n\t\tusing rd::resize;\n\t\tresize(result, len);\n\t\tif (len > 0)\n\t\t{\n\t\t\tread(reinterpret_cast<word_t*>(&result[0]), sizeof(T) * len);\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate <template <class, class> class C, typename T, typename A = allocator<value_or_wrapper<T>>>\n\tC<value_or_wrapper<T>, A> read_array(std::function<value_or_wrapper<T>()> reader)\n\t{\n\t\tint32_t len = read_integral<int32_t>();\n\t\tC<value_or_wrapper<T>, A> result;\n\t\tusing rd::resize;\n\t\tresize(result, len);\n\t\tfor (int32_t i = 0; i < len; ++i)\n\t\t{\n\t\t\tresult[i] = std::move(reader());\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate <template <class, class> class C, typename T, typename A = allocator<T>,\n\t\ttypename = typename std::enable_if_t<util::is_pod_v<T>>>\n\tvoid write_array(C<T, A> const& container)\n\t{\n\t\tusing rd::size;\n\t\tconst int32_t& len = rd::size(container);\n\t\twrite_integral<int32_t>(static_cast<int32_t>(len));\n\t\tif (len > 0)\n\t\t{\n\t\t\twrite(reinterpret_cast<word_t const*>(&container[0]), sizeof(T) * len);\n\t\t}\n\t}\n\n\ttemplate <template <class, class> class C, typename T, typename A = allocator<T>,\n\t\ttypename = typename std::enable_if_t<!rd::util::in_heap_v<T>>>\n\tvoid write_array(C<T, A> const& container, std::function<void(T const&)> writer)\n\t{\n\t\tusing rd::size;\n\t\twrite_integral<int32_t>(size(container));\n\t\tfor (auto const& e : container)\n\t\t{\n\t\t\twriter(e);\n\t\t}\n\t}\n\n\ttemplate <template <class, class> class C, typename T, typename A = allocator<Wrapper<T>>>\n\tvoid write_array(C<Wrapper<T>, A> const& container, std::function<void(T const&)> writer)\n\t{\n\t\tusing rd::size;\n\t\twrite_integral<int32_t>(size(container));\n\t\tfor (auto const& e : container)\n\t\t{\n\t\t\twriter(*e);\n\t\t}\n\t}\n\n\tvoid read_byte_array(ByteArray& array);\n\n\tvoid read_byte_array_raw(ByteArray& array);\n\n\tvoid write_byte_array_raw(ByteArray const& array);\n\n\t//    std::string readString() const;\n\n\t//    void writeString(std::string const &value) const;\n\n\tbool read_bool();\n\n\tvoid write_bool(bool value);\n\n\twchar_t read_char();\n\n\tvoid write_char(wchar_t value);\n\n\tvoid write_char16_string(const uint16_t* data, size_t len);\n\n\tuint16_t * read_char16_string();\n\n\tstd::wstring read_wstring();\n\n\tvoid write_wstring(std::wstring const& value);\n\n\tvoid write_wstring(wstring_view value);\n\n\tvoid write_wstring(Wrapper<std::wstring> const& value);\n\n\tDateTime read_date_time();\n\n\tvoid write_date_time(DateTime const& date_time);\n\n\ttemplate <typename T, typename = typename std::enable_if_t<util::is_enum_v<T>>>\n\tT read_enum()\n\t{\n\t\tint32_t x = read_integral<int32_t>();\n\t\treturn static_cast<T>(x);\n\t}\n\n\ttemplate <typename T, typename = typename std::enable_if_t<util::is_enum_v<T>>>\n\tvoid write_enum(T const& x)\n\t{\n\t\twrite_integral<int32_t>(static_cast<int32_t>(x));\n\t}\n\n\ttemplate <typename T, typename = typename std::enable_if_t<util::is_enum_v<T>>>\n\tT read_enum_set()\n\t{\n\t\tint32_t x = read_integral<int32_t>();\n\t\treturn static_cast<T>(x);\n\t}\n\n\ttemplate <typename T, typename = typename std::enable_if_t<util::is_enum_v<T>>>\n\tvoid write_enum_set(T const& x)\n\t{\n\t\twrite_integral<int32_t>(static_cast<int32_t>(x));\n\t}\n\n\ttemplate <typename T, typename F, typename = typename std::enable_if_t<util::is_same_v<typename util::result_of_t<F()>, T>>>\n\topt_or_wrapper<T> read_nullable(F&& reader)\n\t{\n\t\tbool nullable = !read_bool();\n\t\tif (nullable)\n\t\t{\n\t\t\treturn {};\n\t\t}\n\t\treturn {reader()};\n\t}\n\n\ttemplate <typename T, typename F,\n\t\ttypename = typename std::enable_if_t<util::is_same_v<typename util::result_of_t<F()>, Wrapper<T>>>>\n\tWrapper<T> read_nullable(F&& reader)\n\t{\n\t\tbool nullable = !read_bool();\n\t\tif (nullable)\n\t\t{\n\t\t\treturn {};\n\t\t}\n\t\treturn reader();\n\t}\n\n\ttemplate <typename T>\n\ttypename std::enable_if_t<!std::is_abstract<T>::value> write_nullable(\n\t\toptional<T> const& value, std::function<void(T const&)> writer)\n\t{\n\t\tif (!value)\n\t\t{\n\t\t\twrite_bool(false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\twrite_bool(true);\n\t\t\twriter(*value);\n\t\t}\n\t}\n\n\ttemplate <typename T, typename F>\n\ttypename std::enable_if_t<!util::is_invocable_v<F, Wrapper<T>>> write_nullable(Wrapper<T> const& value, F&& writer)\n\t{\n\t\tif (!value)\n\t\t{\n\t\t\twrite_bool(false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\twrite_bool(true);\n\t\t\twriter(*value);\n\t\t}\n\t}\n\n\ttemplate <typename T, typename F>\n\ttypename std::enable_if_t<util::is_invocable_v<F, Wrapper<T>>> write_nullable(Wrapper<T> const& value, F&& writer)\n\t{\n\t\tif (!value)\n\t\t{\n\t\t\twrite_bool(false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\twrite_bool(true);\n\t\t\twriter(value);\n\t\t}\n\t}\n\n\tByteArray getArray() const&;\n\n\tByteArray getArray() &&;\n\n\tByteArray getRealArray() const&;\n\n\tByteArray getRealArray() &&;\n\n\tword_t const* data() const;\n\n\tword_t* data();\n\n\tword_t const* current_pointer() const;\n\n\tword_t* current_pointer();\n\n\tByteArray& get_data();\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_UNSAFEBUFFER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/Identities.cpp",
    "content": "#include \"protocol/Identities.h\"\n\nnamespace rd\n{\nconstexpr Identities::IdKind Identities::SERVER;\nconstexpr Identities::IdKind Identities::CLIENT;\n\nIdentities::Identities(IdKind dynamicKind) : id_acc(dynamicKind == IdKind::Client ? BASE_CLIENT_ID : BASE_SERVER_ID)\n{\n}\n\nRdId Identities::next(const RdId& parent) const\n{\n\tRdId result = parent.mix(id_acc.fetch_add(2));\n\treturn result;\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/Identities.h",
    "content": "#ifndef RD_CPP_FRAMEWORK_IDENTITIES_H\n#define RD_CPP_FRAMEWORK_IDENTITIES_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"protocol/RdId.h\"\n\n#include <atomic>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n/**\n * \\brief Generates unique identifiers for objects in an object graph.\n */\nclass RD_FRAMEWORK_API Identities\n{\nprivate:\n\tmutable std::atomic_int32_t id_acc;\n\npublic:\n\tenum class IdKind\n\t{\n\t\tClient,\n\t\tServer\n\t};\n\n\tconstexpr static IdKind SERVER = IdKind::Server;\n\tconstexpr static IdKind CLIENT = IdKind::Client;\n\n\tconstexpr static int32_t BASE_CLIENT_ID = RdId::MAX_STATIC_ID;\n\n\tconstexpr static int32_t BASE_SERVER_ID = RdId::MAX_STATIC_ID + 1;\n\n\t// region ctor/dtor\n\n\texplicit Identities(IdKind dynamicKind);\n\n\tvirtual ~Identities() = default;\n\t// endregion\n\n\t/**\n\t * \\brief Generates the next unique identifier.\n\t * \\param parent previous id which is used for generating.\n\t * \\return unique identifier.\n\t */\n\tRdId next(const RdId& parent) const;\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_FRAMEWORK_IDENTITIES_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/MessageBroker.cpp",
    "content": "#include \"protocol/MessageBroker.h\"\n\n#include \"base/RdReactiveBase.h\"\n#include \"spdlog/sinks/stdout_color_sinks.h\"\n\nnamespace rd\n{\nstd::shared_ptr<spdlog::logger> MessageBroker::logger =\n\tspdlog::stderr_color_mt<spdlog::synchronous_factory>(\"logger\", spdlog::color_mode::automatic);\n\nstatic void execute(const IRdReactive* that, Buffer msg)\n{\n\tmsg.read_integral<int16_t>();\t   // skip context\n\tthat->on_wire_received(std::move(msg));\n}\n\nvoid MessageBroker::invoke(const RdReactiveBase* that, Buffer msg, bool sync) const\n{\n\tif (sync)\n\t{\n\t\texecute(that, std::move(msg));\n\t}\n\telse\n\t{\n\t\tauto action = [this, that, message = std::move(msg)]() mutable {\n\t\t\tbool exists_id = false;\n\t\t\t{\n\t\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\t\t\texists_id = subscriptions.count(that->get_id()) > 0;\n\t\t\t}\n\t\t\tif (exists_id)\n\t\t\t{\n\t\t\t\texecute(that, std::move(message));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlogger->trace(\"Disappeared Handler for Reactive entities with id: {}\", to_string(that->get_id()));\n\t\t\t}\n\t\t};\n\t\tstd::function<void()> function = util::make_shared_function(std::move(action));\n\t\tthat->get_wire_scheduler()->queue(std::move(function));\n\t}\n}\n\nMessageBroker::MessageBroker(IScheduler* defaultScheduler) : default_scheduler(defaultScheduler)\n{\n}\n\nvoid MessageBroker::dispatch(RdId id, Buffer message) const\n{\n\tRD_ASSERT_MSG(!id.isNull(), \"id mustn't be null\")\n\n\t{\t // synchronized recursively\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\tRdReactiveBase const* s = subscriptions[id];\n\t\tif (s == nullptr)\n\t\t{\n\t\t\tauto it = broker.find(id);\n\t\t\tif (it == broker.end())\n\t\t\t{\n\t\t\t\tit = broker.emplace(id, Mq{}).first;\n\t\t\t}\n\n\t\t\tbroker[id].default_scheduler_messages.emplace(std::move(message));\n\n\t\t\tauto action = [this, it, id]() mutable {\n\t\t\t\tauto& current = it->second;\n\t\t\t\tRdReactiveBase const* subscription = subscriptions[id];\n\n\t\t\t\toptional<Buffer> message;\n\t\t\t\t{\n\t\t\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\t\t\t\tif (!current.default_scheduler_messages.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tmessage = make_optional<Buffer>(std::move(current.default_scheduler_messages.front()));\n\t\t\t\t\t\tcurrent.default_scheduler_messages.pop();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (subscription != nullptr)\n\t\t\t\t{\n\t\t\t\t\tif (message)\n\t\t\t\t\t{\n\t\t\t\t\t\tinvoke(subscription, *std::move(message), subscription->get_wire_scheduler() == default_scheduler);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlogger->trace(\"No handler for id: {}\", to_string(id));\n\t\t\t\t}\n\n\t\t\t\tif (current.default_scheduler_messages.empty())\n\t\t\t\t{\n\t\t\t\t\tauto t = std::move(broker[id]);\n\t\t\t\t\tbroker.erase(id);\n\t\t\t\t\tfor (auto& it : t.custom_scheduler_messages)\n\t\t\t\t\t{\n\t\t\t\t\t\tRD_ASSERT_MSG(subscription->get_wire_scheduler() != default_scheduler,\n\t\t\t\t\t\t\t\"require equals of wire and default schedulers\")\n\t\t\t\t\t\tinvoke(subscription, std::move(it));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t\tstd::function<void()> function = util::make_shared_function(std::move(action));\n\t\t\tdefault_scheduler->queue(std::move(function));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (s->get_wire_scheduler() == default_scheduler || s->get_wire_scheduler()->out_of_order_execution)\n\t\t\t{\n\t\t\t\tinvoke(s, std::move(message));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto it = broker.find(id);\n\t\t\t\tif (it == broker.end())\n\t\t\t\t{\n\t\t\t\t\tinvoke(s, std::move(message));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tMq& mq = it->second;\n\t\t\t\t\tmq.custom_scheduler_messages.push_back(std::move(message));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//        }\n}\n\nvoid MessageBroker::advise_on(Lifetime lifetime, RdReactiveBase const* entity) const\n{\n\tRD_ASSERT_MSG(!entity->get_id().isNull(), (\"id is null for entities: \" + std::string(typeid(*entity).name())))\n\n\t// advise MUST happen under default scheduler, not custom\n\tdefault_scheduler->assert_thread();\n\n\tstd::lock_guard<decltype(lock)> guard(lock);\n\tif (!lifetime->is_terminated())\n\t{\n\t\tauto key = entity->get_id();\n\t\tsubscriptions[key] = entity;\n\t\tlifetime->add_action([this, key]() { subscriptions.erase(key); });\n\t}\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/MessageBroker.h",
    "content": "#ifndef RD_CPP_MESSAGEBROKER_H\n#define RD_CPP_MESSAGEBROKER_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"base/IRdReactive.h\"\n\n#include \"std/unordered_map.h\"\n\n#include \"spdlog/spdlog.h\"\n\n#include <queue>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RdReactiveBase;\n\nclass RD_FRAMEWORK_API Mq\n{\npublic:\n\t// region ctor/dtor\n\n\tMq() = default;\n\n\tMq(Mq const&) = delete;\n\n\tMq& operator=(Mq const&) = delete;\n\n\tMq(Mq&&) = default;\n\n\tMq& operator=(Mq&&) = default;\n\t// endregion\n\n\tmutable std::queue<Buffer> default_scheduler_messages;\n\tstd::vector<Buffer> custom_scheduler_messages;\n};\n\nclass RD_FRAMEWORK_API MessageBroker final\n{\nprivate:\n\tIScheduler* default_scheduler = nullptr;\n\tmutable rd::unordered_map<RdId, RdReactiveBase const*> subscriptions;\n\tmutable rd::unordered_map<RdId, Mq> broker;\n\n\tmutable std::recursive_mutex lock;\n\n\tstatic std::shared_ptr<spdlog::logger> logger;\n\n\tvoid invoke(const RdReactiveBase* that, Buffer msg, bool sync = false) const;\n\npublic:\n\t// region ctor/dtor\n\n\texplicit MessageBroker(IScheduler* defaultScheduler);\n\t// endregion\n\n\tvoid dispatch(RdId id, Buffer message) const;\n\n\tvoid advise_on(Lifetime lifetime, RdReactiveBase const* entity) const;\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_MESSAGEBROKER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/Protocol.cpp",
    "content": "#include \"protocol/Protocol.h\"\n\n#include \"serialization/SerializationCtx.h\"\n#include \"intern/InternRoot.h\"\n\n#include \"spdlog/sinks/stdout_color_sinks.h\"\n\n#include <utility>\n\nnamespace rd\n{\nstd::shared_ptr<spdlog::logger> Protocol::initializationLogger =\n\tspdlog::stderr_color_mt<spdlog::synchronous_factory>(\"initializationLogger\", spdlog::color_mode::automatic);\n\nconstexpr string_view Protocol::InternRootName;\n\nvoid Protocol::initialize() const\n{\n\tinternRoot = std::make_unique<InternRoot>();\n\n\tcontext = std::make_unique<SerializationCtx>(\n\t\tserializers.get(), SerializationCtx::roots_t{{util::getPlatformIndependentHash(\"Protocol\"), internRoot.get()}});\n\n\tinternRoot->set_id(RdId::Null().mix(InternRootName));\n\tscheduler->queue([this] { internRoot->bind(lifetime, this, InternRootName); });\n}\n\nProtocol::Protocol(std::shared_ptr<Identities> identity, IScheduler* scheduler, std::shared_ptr<IWire> wire, Lifetime lifetime)\n\t: IProtocol(std::move(identity), scheduler, std::move(wire)), lifetime(lifetime)\n{\n\t// initialize();\n}\n\nProtocol::Protocol(Identities::IdKind kind, IScheduler* scheduler, std::shared_ptr<IWire> wire, Lifetime lifetime)\n\t: IProtocol(std::make_shared<Identities>(kind), scheduler, std::move(wire)), lifetime(lifetime)\n{\n\t// initialize();\n}\n\nProtocol::~Protocol() = default;\n\nSerializationCtx& Protocol::get_serialization_context() const\n{\n\tif (!context)\n\t{\n\t\tinitialize();\n\t}\n\treturn *context;\n}\n\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/Protocol.h",
    "content": "#ifndef RD_CPP_PROTOCOL_H\n#define RD_CPP_PROTOCOL_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"base/IProtocol.h\"\n#include \"protocol/Identities.h\"\n#include \"serialization/SerializationCtx.h\"\n\n#include <memory>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n// region predeclared\n\nclass SerializationCtx;\n\nclass InternRoot;\n// endregion\n\n/**\n * \\brief Top level node in the object graph. It stores [SerializationCtx] for polymorphic \"SerDes\"\n */\nclass RD_FRAMEWORK_API Protocol : /*IRdDynamic, */ public IProtocol\n{\n\tconstexpr static string_view InternRootName{\"ProtocolInternRoot\"};\n\n\tLifetime lifetime;\n\n\tmutable std::unique_ptr<SerializationCtx> context;\n\n\tmutable std::unique_ptr<InternRoot> internRoot;\n\n\t// region ctor/dtor\nprivate:\n\tvoid initialize() const;\n\npublic:\n\tProtocol(std::shared_ptr<Identities> identity, IScheduler* scheduler, std::shared_ptr<IWire> wire, Lifetime lifetime);\n\n\tProtocol(Identities::IdKind, IScheduler* scheduler, std::shared_ptr<IWire> wire, Lifetime lifetime);\n\n\tProtocol(Protocol const&) = delete;\n\n\tProtocol(Protocol&&) noexcept = default;\n\n\tProtocol& operator=(Protocol&&) noexcept = default;\n\n\tvirtual ~Protocol();\n\t// endregion\n\n\tSerializationCtx& get_serialization_context() const override;\n\n\tstatic std::shared_ptr<spdlog::logger> initializationLogger;\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_PROTOCOL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/RdId.cpp",
    "content": "#include \"protocol/RdId.h\"\n\n#include \"protocol/Identities.h\"\n\nnamespace rd\n{\nRdId RdId::read(Buffer& buffer)\n{\n\tconst auto number = buffer.read_integral<hash_t>();\n\treturn RdId(number);\n}\n\nvoid RdId::write(Buffer& buffer) const\n{\n\tbuffer.write_integral(hash);\n}\n\nstd::string to_string(RdId const& id)\n{\n\treturn std::to_string(id.hash);\n}\n\nbool operator==(RdId const& left, RdId const& right)\n{\n\treturn left.hash == right.hash;\n}\n\nbool operator!=(const RdId& lhs, const RdId& rhs)\n{\n\treturn !(rhs == lhs);\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/protocol/RdId.h",
    "content": "#ifndef RD_CPP_FRAMEWORK_RDID_H\n#define RD_CPP_FRAMEWORK_RDID_H\n\n#include \"protocol/Buffer.h\"\n#include \"hashing.h\"\n#include \"std/hash.h\"\n\n#include \"thirdparty.hpp\"\n\n#include <cstdint>\n#include <string>\n\n#include <memory>\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RdId;\n\ntemplate <>\nstruct RD_FRAMEWORK_API hash<RdId>\n{\n\tsize_t operator()(const RdId& value) const noexcept;\n};\n\n/**\n * \\brief An identifier of the object that participates in the object graph.\n */\nclass RD_FRAMEWORK_API RdId\n{\npublic:\n\tusing hash_t = util::hash_t;\n\nprivate:\n\tfriend struct hash<RdId>;\n\n\tconstexpr static hash_t NULL_ID = 0;\n\n\thash_t hash{NULL_ID};\n\npublic:\n\tfriend bool RD_FRAMEWORK_API operator==(RdId const& left, RdId const& right);\n\n\tfriend bool RD_FRAMEWORK_API operator!=(const RdId& lhs, const RdId& rhs);\n\n\t// region ctor/dtor\n\tconstexpr RdId() = default;\n\n\tconstexpr RdId(const RdId& other) = default;\n\n\tconstexpr RdId& operator=(const RdId& other) = default;\n\n\tconstexpr RdId(RdId&& other) noexcept = default;\n\n\tconstexpr RdId& operator=(RdId&& other) noexcept = default;\n\n\texplicit constexpr RdId(hash_t hash) : hash(hash)\n\t{\n\t}\n\t// endregion\n\n\t//\t\tstatic const RdId NULL_ID;\n\n\tstatic constexpr RdId Null()\n\t{\n\t\treturn RdId{NULL_ID};\n\t}\n\n\tstatic constexpr int32_t MAX_STATIC_ID = 1'000'000;\n\n\tstatic RdId read(Buffer& buffer);\n\n\tvoid write(Buffer& buffer) const;\n\n\tconstexpr hash_t get_hash() const\n\t{\n\t\treturn hash;\n\t}\n\n\tconstexpr bool isNull() const\n\t{\n\t\treturn get_hash() == NULL_ID;\n\t}\n\n\tRdId notNull()\n\t{\n\t\tRD_ASSERT_MSG(!isNull(), \"id is null\");\n\t\treturn *this;\n\t}\n\n\t/*template<size_t N>\n\tconstexpr RdId mix(char const (&tail)[N]) const {\n\t\treturn RdId(util::getPlatformIndependentHash<N>(tail, static_cast<util::constexpr_hash_t>(hash)));\n\t}*/\n\n\tconstexpr RdId mix(string_view tail) const\n\t{\n\t\treturn RdId(util::getPlatformIndependentHash(tail, static_cast<util::constexpr_hash_t>(hash)));\n\t}\n\n\t/*constexpr RdId mix(int32_t tail) const {\n\t\treturn RdId(util::getPlatformIndependentHash(tail, static_cast<util::constexpr_hash_t>(hash)));\n\t}\n\n\t*/\n\tconstexpr RdId mix(int64_t tail) const\n\t{\n\t\treturn RdId(util::getPlatformIndependentHash(tail, static_cast<util::constexpr_hash_t>(hash)));\n\t}\n\n\tfriend std::string RD_FRAMEWORK_API to_string(RdId const& id);\n};\n\ninline size_t hash<RdId>::operator()(const RdId& value) const noexcept\n{\n\treturn hash<RdId::hash_t>()(value.hash);\n}\n}\t // namespace rd\n\n#endif\t  // RD_CPP_FRAMEWORK_RDID_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/SimpleScheduler.cpp",
    "content": "#include \"SimpleScheduler.h\"\n\nnamespace rd\n{\nvoid SimpleScheduler::flush()\n{\n}\n\nvoid SimpleScheduler::queue(std::function<void()> action)\n{\n\taction();\n}\n\nbool SimpleScheduler::is_active() const\n{\n\treturn true;\n}\n}\t // namespace rd"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/SimpleScheduler.h",
    "content": "#ifndef RD_CPP_TESTSCHEDULER_H\n#define RD_CPP_TESTSCHEDULER_H\n\n#include \"scheduler/base/IScheduler.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n/**\n * \\brief simple scheduler, which immediately invoke action on queue, and is always active.\n */\nclass RD_FRAMEWORK_API SimpleScheduler : public IScheduler\n{\npublic:\n\t// region ctor/dtor\n\tSimpleScheduler() = default;\n\n\tvirtual ~SimpleScheduler() = default;\n\t// endregion\n\n\tvoid flush() override;\n\n\tvoid queue(std::function<void()> action) override;\n\n\tbool is_active() const override;\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_TESTSCHEDULER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/SingleThreadScheduler.cpp",
    "content": "#include \"SingleThreadScheduler.h\"\n\n#include <utility>\n\n#include \"ctpl_stl.h\"\n\nnamespace rd\n{\nSingleThreadScheduler::SingleThreadScheduler(Lifetime lifetime, std::string name)\n\t: SingleThreadSchedulerBase(std::move(name)), lifetime(lifetime)\n{\n\tlifetime->add_action([this]() {\n\t\ttry\n\t\t{\n\t\t\tpool->stop(true);\n\t\t}\n\t\tcatch (std::exception const& e)\n\t\t{\n\t\t\t(void)e;\n\t\t\tlog->error(\"Failed to terminate {}\", this->name);\n\t\t}\n\t});\n}\n}\t // namespace rd"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/SingleThreadScheduler.h",
    "content": "#ifndef RD_CPP_SINGLETHREADSCHEDULER_H\n#define RD_CPP_SINGLETHREADSCHEDULER_H\n\n#include \"base/SingleThreadSchedulerBase.h\"\n\n#include \"lifetime/Lifetime.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API SingleThreadScheduler : public SingleThreadSchedulerBase\n{\npublic:\n\tLifetime lifetime;\n\n\tSingleThreadScheduler(Lifetime lifetime, std::string name);\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_SINGLETHREADSCHEDULER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/SynchronousScheduler.cpp",
    "content": "#include \"SynchronousScheduler.h\"\n\n#include \"guards.h\"\n\nnamespace rd\n{\nstatic thread_local int32_t SynchronousScheduler_active_count = 0;\n\nvoid SynchronousScheduler::queue(std::function<void()> action)\n{\n\tutil::increment_guard<int32_t> guard(SynchronousScheduler_active_count);\n\taction();\n}\n\nvoid SynchronousScheduler::flush()\n{\n}\n\nbool SynchronousScheduler::is_active() const\n{\n\treturn SynchronousScheduler_active_count > 0;\n}\n\nSynchronousScheduler& SynchronousScheduler::Instance()\n{\n\tstatic SynchronousScheduler globalSynchronousScheduler;\n\treturn globalSynchronousScheduler;\n}\n}\t // namespace rd"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/SynchronousScheduler.h",
    "content": "#ifndef RD_CPP_SYNCHRONOUSSCHEDULER_H\n#define RD_CPP_SYNCHRONOUSSCHEDULER_H\n\n#include \"scheduler/base/IScheduler.h\"\n\n#include \"guards.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API SynchronousScheduler : public IScheduler\n{\npublic:\n\t// region ctor/dtor\n\n\tSynchronousScheduler() = default;\n\n\tSynchronousScheduler(SynchronousScheduler const&) = delete;\n\n\tSynchronousScheduler(SynchronousScheduler&&) = delete;\n\n\tvirtual ~SynchronousScheduler() = default;\n\t// endregion\n\n\tvoid queue(std::function<void()> action) override;\n\n\tvoid flush() override;\n\n\tbool is_active() const override;\n\n\t/**\n\t * \\brief global synchronous scheduler for whole application.\n\t */\n\tstatic SynchronousScheduler& Instance();\n};\n\n}\t // namespace rd\n\n#endif\t  // RD_CPP_SYNCHRONOUSSCHEDULER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/base/IScheduler.cpp",
    "content": "#include \"IScheduler.h\"\n\n#include \"spdlog/spdlog.h\"\n\n#include <functional>\n#include <sstream>\n\nnamespace rd\n{\nvoid IScheduler::assert_thread() const\n{\n\tif (!is_active())\n\t{\n\t\tstd::ostringstream msg;\n\t\tmsg << \"Illegal scheduler for current action. Must be \" << thread_id << \", was \" << std::this_thread::get_id();\n\t\tspdlog::error(msg.str());\n\t}\n}\n\nvoid IScheduler::invoke_or_queue(std::function<void()> action)\n{\n\tif (is_active())\n\t{\n\t\taction();\n\t}\n\telse\n\t{\n\t\tqueue(action);\n\t}\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/base/IScheduler.h",
    "content": "#ifndef RD_CPP_ISCHEDULER_H\n#define RD_CPP_ISCHEDULER_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <functional>\n#include <thread>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n/**\n * \\brief Allows to queue the execution of actions on a different thread.\n */\nclass RD_FRAMEWORK_API IScheduler\n{\nprotected:\n\tstd::thread::id thread_id;\n\npublic:\n\t// region ctor/dtor\n\n\tIScheduler() = default;\n\n\tvirtual ~IScheduler() = default;\n\t// endregion\n\n\t/**\n\t * \\brief Queues the execution of the given [action].\n\t *\n\t * \\param action to be queued.\n\t */\n\tvirtual void queue(std::function<void()> action) = 0;\n\n\t// TO-DO\n\tbool out_of_order_execution = false;\n\n\tvirtual void assert_thread() const;\n\n\t/**\n\t * \\brief invoke action immediately if scheduler is active, queue it otherwise.\n\t * \\param action to be invoked\n\t */\n\tvirtual void invoke_or_queue(std::function<void()> action);\n\n\tvirtual void flush() = 0;\n\n\tvirtual bool is_active() const = 0;\n\n\tstd::thread::id get_thread_id() const\n\t{\n\t\treturn thread_id;\n\t}\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_ISCHEDULER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/base/SingleThreadSchedulerBase.cpp",
    "content": "#include \"SingleThreadSchedulerBase.h\"\n\n#include \"util/core_util.h\"\n\n#include \"ctpl_stl.h\"\n#include \"spdlog/include/spdlog/sinks/stdout_color_sinks.h\"\n\nnamespace rd\n{\nSingleThreadSchedulerBase::PoolTask::PoolTask(std::function<void()> f, SingleThreadSchedulerBase* scheduler)\n\t: f(std::move(f)), scheduler(scheduler)\n{\n}\n\nvoid SingleThreadSchedulerBase::PoolTask::operator()(int id) const\n{\n\ttry\n\t{\n\t\tf();\n\t\t--scheduler->tasks_executing;\n\t}\n\tcatch (std::exception const& e)\n\t{\n\t\tscheduler->log->error(\"Background task failed, scheduler={}, thread_id={} | {}\", scheduler->name, id, e.what());\n\t\t--scheduler->tasks_executing;\n\t}\n}\n\nSingleThreadSchedulerBase::SingleThreadSchedulerBase(std::string name)\n\t: log(spdlog::stderr_color_mt<spdlog::synchronous_factory>(name, spdlog::color_mode::automatic))\n\t, name(std::move(name))\n\t, pool(std::make_unique<ctpl::thread_pool>(1))\n{\n\tRD_ASSERT_THROW_MSG(pool->size() == 1, \"Thread pool wasn't properly initalized\");\n\tthread_id = pool->get_thread(0).get_id();\n}\n\nvoid SingleThreadSchedulerBase::flush()\n{\n\tRD_ASSERT_MSG(!is_active(), \"Can't flush this scheduler in a reentrant way: we are inside queued item's execution\");\n\n\twhile (tasks_executing != 0)\n\t{\n\t\tstd::this_thread::yield();\n\t}\n}\n\nvoid SingleThreadSchedulerBase::queue(std::function<void()> action)\n{\n\t++tasks_executing;\n\tPoolTask task(action, this);\n\tpool->push(std::move(task));\n}\n\nbool SingleThreadSchedulerBase::is_active() const\n{\n\treturn thread_id == std::this_thread::get_id();\n}\n\nSingleThreadSchedulerBase::~SingleThreadSchedulerBase() = default;\n}\t // namespace rd"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/scheduler/base/SingleThreadSchedulerBase.h",
    "content": "#ifndef RD_CPP_SINGLETHREADSCHEDULERBASE_H\n#define RD_CPP_SINGLETHREADSCHEDULERBASE_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"scheduler/base/IScheduler.h\"\n#include \"lifetime/Lifetime.h\"\n#include \"spdlog/spdlog.h\"\n\n#include <utility>\n\n#include <rd_framework_export.h>\n\nnamespace ctpl\n{\nclass thread_pool;\n}\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API SingleThreadSchedulerBase : public IScheduler\n{\nprotected:\n\tstd::shared_ptr<spdlog::logger> log;\n\tstd::string name;\n\n\tstd::atomic_uint32_t tasks_executing{0};\n\tstd::atomic_uint32_t active{0};\n\tstd::unique_ptr<ctpl::thread_pool> pool;\n\n\tclass PoolTask\n\t{\n\t\tstd::function<void()> f;\n\t\tSingleThreadSchedulerBase* scheduler;\n\n\tpublic:\n\t\texplicit PoolTask(std::function<void()> f, SingleThreadSchedulerBase* scheduler);\n\n\t\tvoid operator()(int id) const;\n\t};\n\npublic:\n\t// region ctor/dtor\n\tSingleThreadSchedulerBase(std::string name);\n\n\tvirtual ~SingleThreadSchedulerBase();\n\t// endregion\n\n\tvoid flush() override;\n\n\tvoid queue(std::function<void()> action) override;\n\n\tbool is_active() const override;\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_SINGLETHREADSCHEDULERBASE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/AbstractPolymorphic.h",
    "content": "#ifndef RD_CPP_ABSTRACTPOLYMORPHIC_H\n#define RD_CPP_ABSTRACTPOLYMORPHIC_H\n\n#include \"types/wrapper.h\"\n#include \"serialization/Polymorphic.h\"\n#include \"serialization/SerializationCtx.h\"\n\nnamespace rd\n{\ntemplate <typename T>\nclass AbstractPolymorphic\n{\npublic:\n\tstatic value_or_wrapper<T> read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\treturn ctx.get_serializers().readPolymorphicNullable<T>(ctx, buffer);\n\t}\n\n\tstatic void write(SerializationCtx& ctx, Buffer& buffer, T const& value)\n\t{\n\t\tctx.get_serializers().writePolymorphicNullable(ctx, buffer, value);\n\t}\n\n\tstatic void write(SerializationCtx& ctx, Buffer& buffer, Wrapper<T> const& value)\n\t{\n\t\tctx.get_serializers().writePolymorphicNullable(ctx, buffer, *value);\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_ABSTRACTPOLYMORPHIC_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/ArraySerializer.h",
    "content": "#ifndef RD_CPP_ARRAYSERIALIZER_H\n#define RD_CPP_ARRAYSERIALIZER_H\n\n#include \"serialization/SerializationCtx.h\"\n#include \"framework_traits.h\"\n\n#include <vector>\n\nnamespace rd\n{\ntemplate <typename S, template <class, class> class C, typename T = typename util::read_t<S>,\n\ttypename A = allocator<value_or_wrapper<T>>>\nclass ArraySerializer\n{\npublic:\n\tstatic C<value_or_wrapper<T>, A> read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\treturn buffer.read_array<C, T, A>([&] { return S::read(ctx, buffer); });\n\t}\n\n\tstatic void write(SerializationCtx& ctx, Buffer& buffer, C<value_or_wrapper<T>, A> const& value)\n\t{\n\t\tbuffer.write_array<C, T, A>(value, [&](T const& inner_value) { S::write(ctx, buffer, inner_value); });\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_ARRAYSERIALIZER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/DefaultAbstractDeclaration.cpp",
    "content": "#include \"DefaultAbstractDeclaration.h\"\n\nnamespace rd\n{\nconst std::string DefaultAbstractDeclaration::not_registered_error_message =\n\t\"Maybe you forgot to invoke 'register()' method of corresponding Toplevel. \"\n\t\"Usually it should be done automatically during 'bind()' invocation but in complex cases you should do it manually.\";\n\nWrapper<DefaultAbstractDeclaration> DefaultAbstractDeclaration::readUnknownInstance(\n\tSerializationCtx& /*ctx*/, Buffer& /*buffer*/, RdId const& unknownId, int32_t /*size*/)\n{\n\tthrow std::invalid_argument(\"Can't find reader by id: \" + to_string(unknownId) + not_registered_error_message);\n}\n\nstd::string DefaultAbstractDeclaration::type_name() const\n{\n\treturn \"DefaultAbstractDeclaration\";\n}\n\nbool DefaultAbstractDeclaration::equals(ISerializable const& /*serializable*/) const\n{\n\treturn false;\n}\n\nvoid DefaultAbstractDeclaration::write(SerializationCtx& /*ctx*/, Buffer& /*buffer*/) const\n{\n\tthrow std::invalid_argument(\"DefaultAbstractDeclaration couldn't be written\");\n}\n}\t // namespace rd"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/DefaultAbstractDeclaration.h",
    "content": "#ifndef RD_CPP_DEFAULTABSTRACTDECLARATION_H\n#define RD_CPP_DEFAULTABSTRACTDECLARATION_H\n\n#include \"types/wrapper.h\"\n#include \"protocol/RdId.h\"\n#include \"serialization/ISerializable.h\"\n#include \"base/IUnknownInstance.h\"\n\nnamespace rd\n{\n// region predeclared\n\nclass SerializationCtx;\n\nclass Buffer;\n// endregion\n\nclass DefaultAbstractDeclaration : public IPolymorphicSerializable, public IUnknownInstance\n{\n\tconst static std::string not_registered_error_message;\n\npublic:\n\tstatic Wrapper<DefaultAbstractDeclaration> readUnknownInstance(\n\t\tSerializationCtx& ctx, Buffer& buffer, RdId const& unknownId, int32_t size);\n\n\tstd::string type_name() const override;\n\n\tbool equals(ISerializable const& serializable) const override;\n\n\tvoid write(SerializationCtx& ctx, Buffer& buffer) const override;\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_DEFAULTABSTRACTDECLARATION_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/ISerializable.cpp",
    "content": "#include \"serialization/ISerializable.h\"\n\n#include \"std/hash.h\"\n\nnamespace rd\n{\nsize_t IPolymorphicSerializable::hashCode() const noexcept\n{\n\treturn rd::hash<void const*>()(static_cast<void const*>(this));\n}\n\nbool operator==(const IPolymorphicSerializable& lhs, const IPolymorphicSerializable& rhs)\n{\n\treturn lhs.equals(rhs);\n}\n\nbool operator!=(const IPolymorphicSerializable& lhs, const IPolymorphicSerializable& rhs)\n{\n\treturn !(lhs == rhs);\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/ISerializable.h",
    "content": "#ifndef RD_CPP_ISERIALIZABLE_H\n#define RD_CPP_ISERIALIZABLE_H\n\n#include <string>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n// region predeclared\n\nclass Buffer;\n\nclass SerializationCtx;\n// endregion\n\n/**\n * \\brief Provides \\ref write for serialization to be overriden. For deserialization derived class must have static\n * method read. See examples for more information.\n */\nclass RD_FRAMEWORK_API ISerializable\n{\npublic:\n\tvirtual ~ISerializable() = default;\n\n\tvirtual void write(SerializationCtx& ctx, Buffer& buffer) const = 0;\n};\n\n/**\n * \\brief Dynamically polymorhic node.\n */\nclass RD_FRAMEWORK_API IPolymorphicSerializable : public ISerializable\n{\npublic:\n\t/**\n\t * \\return actual class's name as written in source code.\n\t */\n\tvirtual std::string type_name()\n\t\tconst = 0 /*{ throw std::invalid_argument(\"type doesn't support polymorphic serialization\"); }*/;\n\n\t//\t\tvirtual bool equals(IPolymorphicSerializable const& object) const = 0;\n\n\tvirtual size_t hashCode() const noexcept;\n\n\tvirtual std::string toString() const = 0;\n\n\tvirtual bool equals(ISerializable const&) const = 0;\n\n\tfriend bool RD_FRAMEWORK_API operator==(const IPolymorphicSerializable& lhs, const IPolymorphicSerializable& rhs);\n\n\tfriend bool RD_FRAMEWORK_API operator!=(const IPolymorphicSerializable& lhs, const IPolymorphicSerializable& rhs);\n};\n}\t // namespace rd\n\nnamespace std\n{\ntemplate <>\nstruct RD_FRAMEWORK_API hash<rd::IPolymorphicSerializable>\n{\n\tsize_t operator()(const rd::IPolymorphicSerializable& value) const noexcept\n\t{\n\t\treturn value.hashCode();\n\t}\n};\n}\t // namespace std\n\n#endif\t  // RD_CPP_ISERIALIZABLE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/InternedAnySerializer.h",
    "content": "#ifndef RD_CPP_ANYSERIALIZER_H\n#define RD_CPP_ANYSERIALIZER_H\n\n#include \"serialization/SerializationCtx.h\"\n#include \"serialization/RdAny.h\"\n\n#include \"thirdparty.hpp\"\n\nnamespace rd\n{\n// region predeclared\n\nclass Buffer;\n// endregion\n\nclass InternedAnySerializer\n{\npublic:\n\tstatic optional<InternedAny> read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\treturn ctx.get_serializers().readAny(ctx, buffer);\n\t}\n\n\ttemplate <typename T>\n\tstatic void write(SerializationCtx& ctx, Buffer& buffer, T const& value)\n\t{\n\t\tctx.get_serializers().writePolymorphicNullable(ctx, buffer, value);\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_ANYSERIALIZER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/InternedSerializer.h",
    "content": "#ifndef RD_CPP_INTERNEDSERIALIZER_H\n#define RD_CPP_INTERNEDSERIALIZER_H\n\n#include \"serialization/SerializationCtx.h\"\n#include \"serialization/Polymorphic.h\"\n#include \"framework_traits.h\"\n\nnamespace rd\n{\ntemplate <typename S, util::hash_t InternKey, typename T = typename util::read_t<S>>\nclass InternedSerializer\n{\npublic:\n\tstatic Wrapper<T> read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\treturn ctx.readInterned<T, InternKey>(buffer, [&](SerializationCtx&, Buffer&) { return S::read(ctx, buffer); });\n\t}\n\n\tstatic void write(SerializationCtx& ctx, Buffer& buffer, Wrapper<T> const& value)\n\t{\n\t\tctx.writeInterned<T, InternKey>(buffer, value,\n\t\t\t[&](SerializationCtx&, Buffer&, T const& inner_value) mutable -> void { S::write(ctx, buffer, inner_value); });\n\t}\n};\n}\t // namespace rd\n#endif\t  // RD_CPP_INTERNEDSERIALIZER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/NullableSerializer.h",
    "content": "#ifndef RD_CPP_NULLABLESERIALIZER_H\n#define RD_CPP_NULLABLESERIALIZER_H\n\n#include \"serialization/Polymorphic.h\"\n#include \"serialization/AbstractPolymorphic.h\"\n#include \"types/wrapper.h\"\n#include \"framework_traits.h\"\n\n#include <type_traits>\n\nnamespace rd\n{\ntemplate <typename S, typename R = void>\nclass NullableSerializer\n{\n\tusing T = typename util::read_t<S>;\n\npublic:\n\tstatic opt_or_wrapper<T> read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\treturn buffer.read_nullable<T>([&]() -> T { return S::read(ctx, buffer); });\n\t}\n\n\tstatic void write(SerializationCtx& ctx, Buffer& buffer, optional<T> const& value)\n\t{\n\t\tbuffer.write_nullable<T>(value, [&](T const& inner_value) { S::write(ctx, buffer, inner_value); });\n\t}\n\n\tstatic void write(SerializationCtx& ctx, Buffer& buffer, Wrapper<T> const& value)\n\t{\n\t\tbuffer.write_nullable<T>(value, [&](T const& inner_value) { S::write(ctx, buffer, inner_value); });\n\t}\n};\n\ntemplate <typename S>\nclass NullableSerializer<S, std::enable_if_t<is_wrapper_v<util::read_t<S>>>>\n{\n\tusing W = typename util::read_t<S>;\n\tusing T = typename W::type;\n\npublic:\n\tstatic Wrapper<T> read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\treturn buffer.read_nullable<T>([&]() -> Wrapper<T> { return S::read(ctx, buffer); });\n\t}\n\n\tstatic void write(SerializationCtx& ctx, Buffer& buffer, Wrapper<T> const& value)\n\t{\n\t\tbuffer.write_nullable<T>(value, [&](T const& inner_value) { S::write(ctx, buffer, inner_value); });\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_NULLABLESERIALIZER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/Polymorphic.cpp",
    "content": "#include \"Polymorphic.h\"\n\nnamespace rd\n{\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/Polymorphic.h",
    "content": "#ifndef RD_CPP_POLYMORPHIC_H\n#define RD_CPP_POLYMORPHIC_H\n\n#include \"protocol/Buffer.h\"\n#include \"base/RdReactiveBase.h\"\n\n#include <type_traits>\n\nnamespace rd\n{\n// region predeclared\n\nclass SerializationCtx;\n// endregion\n\n/**\n * \\brief Maintains \"SerDes\" for statically polymorphic type [T].\n * Requires static \"read\" and \"write\" methods as in common case below.\n * \\tparam T type to \"SerDes\"\n * \\tparam R trait specialisation (void by default)\n */\ntemplate <typename T, typename R = void>\nclass Polymorphic\n{\npublic:\n\tinline static T read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\treturn T::read(ctx, buffer);\n\t}\n\n\tinline static void write(SerializationCtx& ctx, Buffer& buffer, T const& value)\n\t{\n\t\tvalue.write(ctx, buffer);\n\t}\n\n\tinline static void write(SerializationCtx& ctx, Buffer& buffer, Wrapper<T> const& value)\n\t{\n\t\tvalue->write(ctx, buffer);\n\t}\n};\n\ntemplate <typename T>\nclass Polymorphic<T, typename std::enable_if_t<std::is_integral<T>::value>>\n{\npublic:\n\tinline static T read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\treturn buffer.read_integral<T>();\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& buffer, T const& value)\n\t{\n\t\tbuffer.write_integral<T>(value);\n\t}\n};\n\ntemplate <typename T>\nclass Polymorphic<T, typename std::enable_if_t<std::is_floating_point<T>::value>>\n{\npublic:\n\tinline static T read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\treturn buffer.read_floating_point<T>();\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& buffer, T const& value)\n\t{\n\t\tbuffer.write_floating_point<T>(value);\n\t}\n};\n\n// class Polymorphic<int, void>;\n\ntemplate <template <class, class> class C, typename T, typename A>\nclass Polymorphic<C<T, A>, typename std::enable_if_t<!util::is_base_of_v<RdReactiveBase, T> &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t !util::is_same_v<Wrapper<T, A>, C<T, A>>>>\n{\npublic:\n\tinline static C<T, A> read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\treturn buffer.read_array<C, T, A>();\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& buffer, C<T, A> const& value)\n\t{\n\t\tbuffer.write_array<C, T, A>(value);\n\t}\n};\n\ntemplate <>\nclass Polymorphic<bool>\n{\npublic:\n\tinline static bool read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\treturn buffer.read_bool();\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& buffer, bool const& value)\n\t{\n\t\tbuffer.write_bool(value);\n\t}\n};\n\ntemplate <>\nclass Polymorphic<wchar_t>\n{\npublic:\n\tinline static wchar_t read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\treturn buffer.read_char();\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& buffer, bool const& value)\n\t{\n\t\tbuffer.write_char(value);\n\t}\n};\n\ntemplate <>\nclass Polymorphic<std::wstring>\n{\npublic:\n\tinline static std::wstring read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\treturn buffer.read_wstring();\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& buffer, std::wstring const& value)\n\t{\n\t\tbuffer.write_wstring(value);\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& buffer, Wrapper<std::wstring> const& value)\n\t{\n\t\tbuffer.write_wstring(*value);\n\t}\n};\n\ntemplate <>\nclass Polymorphic<DateTime>\n{\npublic:\n\tinline static DateTime read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\treturn buffer.read_date_time();\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& buffer, DateTime const& value)\n\t{\n\t\tbuffer.write_date_time(value);\n\t}\n};\n\ntemplate <>\nclass Polymorphic<Void>\n{\npublic:\n\tinline static Void read(SerializationCtx& /*ctx*/, Buffer& /*buffer*/)\n\t{\n\t\treturn {};\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& /*buffer*/, Void const& /*value*/)\n\t{\n\t}\n};\n\ntemplate <typename T>\nclass Polymorphic<T, typename std::enable_if_t<util::is_base_of_v<RdReactiveBase, T>>>\n{\npublic:\n\tinline static T read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\treturn T::read(ctx, buffer);\n\t}\n\n\tinline static void write(SerializationCtx& ctx, Buffer& buffer, T const& value)\n\t{\n\t\tvalue.write(ctx, buffer);\n\t}\n};\n\ntemplate <typename T>\nclass Polymorphic<T, typename std::enable_if_t<util::is_enum_v<T>>>\n{\npublic:\n\tinline static T read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\treturn buffer.read_enum<T>();\n\t}\n\n\tinline static void write(SerializationCtx& /*ctx*/, Buffer& buffer, T const& value)\n\t{\n\t\tbuffer.write_enum<T>(value);\n\t}\n};\n\ntemplate <typename T>\nclass Polymorphic<optional<T>>\n{\npublic:\n\tinline static optional<T> read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\treturn buffer.read_nullable<T>([&ctx, &buffer]() { return Polymorphic<T>::read(ctx, buffer); });\n\t}\n\n\tinline static void write(SerializationCtx& ctx, Buffer& buffer, optional<T> const& value)\n\t{\n\t\tbuffer.write_nullable<T>(value, [&ctx, &buffer](T const& v) { Polymorphic<T>::write(ctx, buffer, v); });\n\t}\n};\n\ntemplate <typename T, typename A>\nclass Polymorphic<Wrapper<T, A>>\n{\npublic:\n\tinline static void write(SerializationCtx& ctx, Buffer& buffer, Wrapper<T, A> const& value)\n\t{\n\t\tvalue->write(ctx, buffer);\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_POLYMORPHIC_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/RdAny.cpp",
    "content": "#include \"RdAny.h\"\n\nnamespace rd\n{\nnamespace any\n{\n}\n}\t // namespace rd"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/RdAny.h",
    "content": "#ifndef RD_CPP_ANY_H\n#define RD_CPP_ANY_H\n\n#include \"util/core_util.h\"\n#include \"types/wrapper.h\"\n#include \"serialization/ISerializable.h\"\n\n#include \"thirdparty.hpp\"\n\n#include <memory>\n#include <string>\n#include <cstring>\n\nnamespace rd\n{\nnamespace any\n{\nusing super_t = IPolymorphicSerializable;\nusing wrapped_super_t = Wrapper<super_t>;\nusing string = Wrapper<std::wstring>;\n}\t // namespace any\n/**\n * \\brief Presents union type to be interned. It may be either \\link std::wstring,\n * either \\link rd::IPolymorphicSerializable.\n */\nusing InternedAny = variant<any::wrapped_super_t, any::string>;\n\nnamespace any\n{\ntemplate <typename T>\nInternedAny make_interned_any(Wrapper<T> wrapper)\n{\n\treturn {wrapped_super_t(wrapper)};\n}\n\ntemplate <>\ninline InternedAny make_interned_any<std::wstring>(Wrapper<std::wstring> wrapper)\n{\n\treturn {wrapper};\n}\n\ntemplate <typename T, typename Any>\ntypename std::enable_if_t<!util::is_base_of_v<IPolymorphicSerializable, T>, any::string> get(Any const& any)\n{\n\treturn get<string>(any);\n}\n\ntemplate <typename T, typename Any>\ntypename std::enable_if_t<util::is_base_of_v<IPolymorphicSerializable, T>, Wrapper<T>> get(Any&& any)\n{\n\treturn Wrapper<T>::dynamic(get<wrapped_super_t>(std::forward<Any>(any)));\n}\n\nstruct TransparentKeyEqual\n{\n\tusing is_transparent = void;\n\n\tbool operator()(InternedAny const& val_l, InternedAny const& val_r) const\n\t{\n\t\treturn val_l == val_r;\n\t}\n\n\tbool operator()(InternedAny const& val_l, wrapped_super_t const& val_r) const\n\t{\n\t\treturn visit(util::make_visitor(\n\t\t\t\t\t\t [&](wrapped_super_t const& value) { return *value == *val_r; }, [](any::string const&) { return false; }),\n\t\t\tval_l);\n\t}\n\n\tbool operator()(super_t const& val_l, InternedAny const& val_r) const\n\t{\n\t\treturn operator()(val_r, val_l);\n\t}\n\n\tbool operator()(InternedAny const& val_l, super_t const& val_r) const\n\t{\n\t\treturn visit(util::make_visitor(\n\t\t\t\t\t\t [&](wrapped_super_t const& value) { return *value == val_r; }, [](any::string const&) { return false; }),\n\t\t\tval_l);\n\t}\n\n\tbool operator()(wrapped_super_t const& val_l, InternedAny const& val_r) const\n\t{\n\t\treturn operator()(val_r, val_l);\n\t}\n\n\tbool operator()(InternedAny const& val_l, any::string const& val_r) const\n\t{\n\t\treturn visit(util::make_visitor(\n\t\t\t\t\t\t [](wrapped_super_t const& /*value*/) { return false; }, [&](any::string const& s) { return s == val_r; }),\n\t\t\tval_l);\n\t}\n\n\tbool operator()(any::string const& val_l, InternedAny const& val_r) const\n\t{\n\t\treturn operator()(val_r, val_l);\n\t}\n};\n\nstruct TransparentHash\n{\n\tusing is_transparent = void;\n\tusing transparent_key_equal = std::equal_to<>;\n\n\tsize_t operator()(InternedAny const& value) const noexcept\n\t{\n\t\treturn visit(util::make_visitor([](wrapped_super_t const& value) { return rd::hash<wrapped_super_t>()(value); },\n\t\t\t\t\t\t [](any::string const& value) { return rd::hash<any::string>()(value); }),\n\t\t\tvalue);\n\t}\n\n\tsize_t operator()(wrapped_super_t const& value) const noexcept\n\t{\n\t\treturn rd::hash<wrapped_super_t>()(value);\n\t}\n\n\tsize_t operator()(super_t const& value) const noexcept\n\t{\n\t\treturn rd::hash<super_t>()(value);\n\t}\n\n\tsize_t operator()(any::string const& value) const noexcept\n\t{\n\t\treturn rd::hash<any::string>()(value);\n\t}\n};\n}\t // namespace any\n}\t // namespace rd\n\nstatic_assert(!std::is_trivially_copy_constructible<rd::Wrapper<rd::IPolymorphicSerializable>>::value,\n\t\"wrapper mustn't be trivially_copy_constructible\");\n\n#endif\t  // RD_CPP_ANY_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/SerializationCtx.cpp",
    "content": "#include \"SerializationCtx.h\"\n\nnamespace rd\n{\n//\tSerializationCtx::SerializationCtx(const IProtocol &protocol) : serializers(protocol.serializers.get()) {}\n\n//\tSerializationCtx::SerializationCtx(const Serializers *const serializers) : serializers(serializers) {}\n\nSerializationCtx::SerializationCtx(const Serializers* serializers, roots_t intern_roots)\n\t: serializers(serializers), intern_roots(std::move(intern_roots))\n{\n}\n\nSerializationCtx SerializationCtx::withInternRootsHere(\n\tRdBindableBase const& owner, std::initializer_list<std::string> new_roots) const\n{\n\troots_t next_roots = intern_roots;\n\tfor (const auto& item : new_roots)\n\t{\n\t\tauto const& name = \"InternRoot-\" + item;\n\t\tInternRoot const& root = owner.getOrCreateExtension<InternRoot>(name);\n\t\twithId(root, owner.get_id().mix(\".\").mix(name));\n\t\tnext_roots.emplace(util::getPlatformIndependentHash(item), &root);\n\t}\n\treturn SerializationCtx(serializers, std::move(next_roots));\n}\n\nSerializers const& SerializationCtx::get_serializers() const\n{\n\treturn *serializers;\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/SerializationCtx.h",
    "content": "#ifndef RD_CPP_FRAMEWORK_SERIALIZATIONCTX_H\n#define RD_CPP_FRAMEWORK_SERIALIZATIONCTX_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"protocol/Buffer.h\"\n#include \"protocol/RdId.h\"\n\n#include \"std/unordered_map.h\"\n\n#include <functional>\n#include <string>\n#include <utility>\n#include <regex>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n// region predeclared\n\nclass IProtocol;\n\nclass Serializers;\n\nclass InternRoot;\n\nclass RdBindableBase;\n// endregion\n\nclass RD_FRAMEWORK_API SerializationCtx\n{\n\tSerializers const* serializers = nullptr;\n\npublic:\n\tusing roots_t = rd::unordered_map<util::hash_t, InternRoot const*>;\n\n\troots_t intern_roots{};\n\n\t// region ctor/dtor\n\n\t//    SerializationCtx() = delete;\n\n\tSerializationCtx(SerializationCtx const& other) = delete;\n\n\tSerializationCtx& operator=(SerializationCtx const& other) = delete;\n\n\tSerializationCtx(SerializationCtx&& other) = default;\n\n\tSerializationCtx& operator=(SerializationCtx&& other) = default;\n\n\t//\t\texplicit SerializationCtx(const Serializers *serializers = nullptr);\n\n\texplicit SerializationCtx(const Serializers* serializers, roots_t intern_roots = {});\n\n\tSerializationCtx withInternRootsHere(RdBindableBase const& owner, std::initializer_list<std::string> new_roots) const;\n\n\t// endregion\n\n\ttemplate <typename T, util::hash_t InternKey>\n\tWrapper<T> readInterned(Buffer& buffer, std::function<T(SerializationCtx&, Buffer&)> readValueDelegate);\n\n\ttemplate <typename T, util::hash_t InternKey, typename F,\n\t\ttypename = typename std::enable_if_t<util::is_invocable<F, SerializationCtx&, Buffer&, T>::value> >\n\tvoid writeInterned(Buffer& buffer, Wrapper<T> const& value, F&& writeValueDelegate);\n\n\tSerializers const& get_serializers() const;\n};\n}\t // namespace rd\n\n#include \"intern/InternRoot.h\"\n\nnamespace rd\n{\ntemplate <typename T, util::hash_t InternKey>\nWrapper<T> SerializationCtx::readInterned(Buffer& buffer, std::function<T(SerializationCtx&, Buffer&)> readValueDelegate)\n{\n\tauto it = intern_roots.find(InternKey);\n\tif (it != intern_roots.end())\n\t{\n\t\tint32_t index = buffer.read_integral<int32_t>() ^ 1;\n\t\treturn it->second->un_intern_value<T>(index);\n\t}\n\telse\n\t{\n\t\treturn wrapper::make_wrapper<T>(readValueDelegate(*this, buffer));\n\t}\n}\n\ntemplate <typename T, util::hash_t InternKey, typename F, typename>\nvoid SerializationCtx::writeInterned(Buffer& buffer, const Wrapper<T>& value, F&& writeValueDelegate)\n{\n\tauto it = intern_roots.find(InternKey);\n\tif (it != intern_roots.end())\n\t{\n\t\tint32_t index = it->second->intern_value<T>(value);\n\t\tbuffer.write_integral<int32_t>(index);\n\t}\n\telse\n\t{\n\t\twriteValueDelegate(const_cast<SerializationCtx&>(*this), buffer, *value);\n\t}\n}\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n#endif\t  // RD_CPP_FRAMEWORK_SERIALIZATIONCTX_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/Serializers.cpp",
    "content": "#include \"Serializers.h\"\n\n#include \"serialization/AbstractPolymorphic.h\"\n\nnamespace rd\n{\nconstexpr RdId STRING_PREDEFINED_ID = RdId(10);\n\nRdId Serializers::real_rd_id(const IUnknownInstance& value)\n{\n\treturn value.unknownId;\n}\n\nRdId Serializers::real_rd_id(const IPolymorphicSerializable& value)\n{\n\treturn RdId(util::getPlatformIndependentHash(value.type_name()));\n}\n\nRdId Serializers::real_rd_id(const std::wstring& /*value*/)\n{\n\treturn STRING_PREDEFINED_ID;\n}\n\nvoid Serializers::real_write(SerializationCtx& /*ctx*/, Buffer& buffer, IUnknownInstance const& value)\n{\n\tvalue.unknownId.write(buffer);\n}\n\nvoid Serializers::real_write(SerializationCtx& ctx, Buffer& buffer, IPolymorphicSerializable const& value)\n{\n\tvalue.write(ctx, buffer);\n}\n\nvoid Serializers::real_write(SerializationCtx& ctx, Buffer& buffer, std::wstring const& value)\n{\n\tPolymorphic<std::wstring>::write(ctx, buffer, value);\n}\n\nvoid Serializers::register_in()\n{\n\treaders[STRING_PREDEFINED_ID] = [](SerializationCtx& ctx, Buffer& buffer) -> InternedAny {\n\t\treturn {wrapper::make_wrapper<std::wstring>(Polymorphic<std::wstring>::read(ctx, buffer))};\n\t};\n}\n\nSerializers::Serializers()\n{\n\tregister_in();\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/serialization/Serializers.h",
    "content": "#ifndef RD_CPP_SERIALIZERS_H\n#define RD_CPP_SERIALIZERS_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"protocol/RdId.h\"\n#include \"serialization/ISerializable.h\"\n#include \"protocol/Identities.h\"\n#include \"base/IUnknownInstance.h\"\n#include \"hashing.h\"\n#include \"serialization/RdAny.h\"\n#include \"DefaultAbstractDeclaration.h\"\n\n#include \"std/unordered_map.h\"\n\n#include <utility>\n#include <iostream>\n#include <unordered_set>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\n// region predeclared\n\nclass SerializationCtx;\n// endregion\n\nclass RD_FRAMEWORK_API Serializers\n{\nprivate:\n\tstatic RdId real_rd_id(IUnknownInstance const& value);\n\n\tstatic RdId real_rd_id(IPolymorphicSerializable const& value);\n\n\tstatic RdId real_rd_id(std::wstring const& value);\n\n\tstatic void real_write(SerializationCtx& ctx, Buffer& buffer, IUnknownInstance const& value);\n\n\tstatic void real_write(SerializationCtx& ctx, Buffer& buffer, IPolymorphicSerializable const& value);\n\n\tstatic void real_write(SerializationCtx& ctx, Buffer& buffer, std::wstring const& value);\n\n\tvoid register_in();\n\n\tmutable rd::unordered_map<RdId, std::function<InternedAny(SerializationCtx&, Buffer&)>> readers;\n\npublic:\n\tSerializers();\n\n\ttemplate <typename T, typename = typename std::enable_if_t<util::is_base_of_v<IPolymorphicSerializable, T>>>\n\tvoid registry() const;\n\n\ttemplate <typename T = DefaultAbstractDeclaration>\n\toptional<InternedAny> readAny(SerializationCtx& ctx, Buffer& buffer) const;\n\n\ttemplate <typename T>\n\tvalue_or_wrapper<T> readPolymorphicNullable(SerializationCtx& ctx, Buffer& buffer) const;\n\n\ttemplate <typename T /*, typename = typename std::enable_if<std::is_base_of<IPolymorphicSerializable, T>::value>::type*/>\n\tvoid writePolymorphicNullable(SerializationCtx& ctx, Buffer& buffer, const T& value) const;\n\n\ttemplate <typename T>\n\tvalue_or_wrapper<T> readPolymorphic(SerializationCtx& ctx, Buffer& buffer) const;\n\n\ttemplate <typename T>\n\tvoid writePolymorphic(SerializationCtx& ctx, Buffer& stream, const Wrapper<T>& value) const;\n\n\ttemplate <typename T>\n\tvoid writePolymorphic(SerializationCtx& ctx, Buffer& stream, T const& value) const;\n};\n}\t // namespace rd\n\nnamespace rd\n{\ntemplate <typename T, typename>\nvoid Serializers::registry() const\n{\n\tstd::string type_name = T::static_type_name();\n\tutil::hash_t h = util::getPlatformIndependentHash(type_name);\n\tRdId id(h);\n\n\tRD_ASSERT_MSG(readers.count(id) == 0, \"Can't register \" + type_name + \" with id: \" + to_string(id));\n\n\treaders[id] = [](SerializationCtx& ctx, Buffer& buffer) -> Wrapper<IPolymorphicSerializable> {\n\t\treturn wrapper::make_wrapper<T>(T::read(ctx, buffer));\n\t};\n}\n\ntemplate <typename T>\noptional<InternedAny> Serializers::readAny(SerializationCtx& ctx, Buffer& buffer) const\n{\n\tRdId id = RdId::read(buffer);\n\tif (id.isNull())\n\t{\n\t\treturn nullopt;\n\t}\n\tint32_t size = buffer.read_integral<int32_t>();\n\tbuffer.check_available(static_cast<size_t>(size));\n\n\tif (readers.count(id) == 0)\n\t{\n\t\treturn any::make_interned_any<T>(T::readUnknownInstance(ctx, buffer, id, size));\n\t}\n\tauto const& reader = readers.at(id);\n\treturn reader(ctx, buffer);\n}\n\ntemplate <typename T>\nvalue_or_wrapper<T> Serializers::readPolymorphicNullable(SerializationCtx& ctx, Buffer& buffer) const\n{\n\toptional<InternedAny> any = readAny<T>(ctx, buffer);\n\treturn any::get<T>(*(std::move(any)));\n}\n\ntemplate <typename T /*, typename*/>\nvoid Serializers::writePolymorphicNullable(SerializationCtx& ctx, Buffer& buffer, const T& value) const\n{\n\treal_rd_id(value).write(buffer);\n\n\tint32_t length_tag_position = static_cast<int32_t>(buffer.get_position());\n\tbuffer.write_integral<int32_t>(0);\n\tint32_t object_start_position = static_cast<int32_t>(buffer.get_position());\n\treal_write(ctx, buffer, value);\n\t//\t\tvalue.write(ctx, buffer);\n\tint32_t object_end_position = static_cast<int32_t>(buffer.get_position());\n\tbuffer.set_position(static_cast<size_t>(length_tag_position));\n\tbuffer.write_integral<int32_t>(object_end_position - object_start_position);\n\tbuffer.set_position(static_cast<size_t>(object_end_position));\n}\n\ntemplate <typename T>\nvalue_or_wrapper<T> Serializers::readPolymorphic(SerializationCtx& ctx, Buffer& buffer) const\n{\n\treturn readPolymorphicNullable<T>(ctx, buffer);\n}\n\ntemplate <typename T>\nvoid Serializers::writePolymorphic(SerializationCtx& ctx, Buffer& stream, const Wrapper<T>& value) const\n{\n\twritePolymorphicNullable(ctx, stream, *value);\n}\n\ntemplate <typename T>\nvoid Serializers::writePolymorphic(SerializationCtx& ctx, Buffer& stream, T const& value) const\n{\n\twritePolymorphicNullable(ctx, stream, value);\n}\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_SERIALIZERS_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/task/RdCall.h",
    "content": "#ifndef RD_CPP_RDCALL_H\n#define RD_CPP_RDCALL_H\n\n#include \"serialization/Polymorphic.h\"\n#include \"RdTask.h\"\n#include \"RdTaskResult.h\"\n#include \"scheduler/SynchronousScheduler.h\"\n#include \"WiredRdTask.h\"\n\n#include <thread>\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#endif\n\nnamespace rd\n{\n/**\n * \\brief Represents an API provided by the remote process which can be invoked through the protocol.\n *\n * \\tparam TReq type of request\n * \\tparam TRes type of response\n * \\tparam ReqSer \"SerDes\" for request\n * \\tparam ResSer \"SerDes\" for response\n */\ntemplate <typename TReq, typename TRes, typename ReqSer = Polymorphic<TReq>, typename ResSer = Polymorphic<TRes> >\nclass RdCall : public virtual RdReactiveBase, public ISerializable\n{\n\tusing WTReq = value_or_wrapper<TReq>;\n\tusing WTRes = value_or_wrapper<TRes>;\n\n\tmutable optional<RdId> sync_task_id;\n\npublic:\n\t// region ctor/dtor\n\tRdCall() = default;\n\n\tRdCall(RdCall&&) = default;\n\n\tRdCall& operator=(RdCall&&) = default;\n\n\tvirtual ~RdCall() = default;\n\t// endregion\n\n\tstatic RdCall<TReq, TRes, ReqSer, ResSer> read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\tRdCall<TReq, TRes, ReqSer, ResSer> res;\n\t\tconst RdId& id = RdId::read(buffer);\n\t\twithId(res, id);\n\t\treturn res;\n\t}\n\n\tvoid write(SerializationCtx& /*ctx*/, Buffer& buffer) const override\n\t{\n\t\trdid.write(buffer);\n\t}\n\n\tvoid init(Lifetime lifetime) const override\n\t{\n\t\tRdBindableBase::init(lifetime);\n\t\tbind_lifetime = lifetime;\n\t\tget_wire()->advise(lifetime, this);\n\t}\n\n\t/**\n\t * \\brief Invokes the API with the parameters given as [request] and waits for the result.\n\t *\n\t * \\param request value to deliver\n\t * \\return result of remote invoking\n\t */\n\tWiredRdTask<TRes, ResSer> sync(TReq const& request, std::chrono::milliseconds timeout = std::chrono::milliseconds(200)) const\n\t{\n\t\tauto task = start_internal(request, true, &SynchronousScheduler::Instance());\n\t\tauto time_at_start = std::chrono::system_clock::now();\n\t\twhile (!task.has_value() && !(*bind_lifetime)->is_terminated() &&\n\t\t\t   ((std::chrono::system_clock::now() - time_at_start) < timeout))\n\t\t{\n\t\t\tstd::this_thread::yield();\n\t\t}\n\t\tspdlog::debug(\"Time elapsed: {}, has_value={}\", to_string(std::chrono::system_clock::now() - time_at_start),\n\t\t\tto_string(task.has_value()));\n\t\ttask.value_or_throw().unwrap();\t   // check for existing value\n\t\tsync_task_id = nullopt;\n\t\treturn task;\n\t}\n\n\tIScheduler* get_wire_scheduler() const override\n\t{\n\t\treturn &SynchronousScheduler::Instance();\n\t}\n\n\t/**\n\t * \\brief Asynchronously invokes the API with the parameters given as [request] and waits for the result.\n\t *\n\t * \\param request value of request\n\t * \\param responseScheduler to assign value\n\t * \\return task which will have its result value.\n\t */\n\tWiredRdTask<TRes, ResSer> start(TReq const& request, IScheduler* responseScheduler = nullptr) const\n\t{\n\t\treturn start_internal(request, false, responseScheduler ? responseScheduler : get_default_scheduler());\n\t}\n\n\tvoid on_wire_received(Buffer) const override\n\t{\n\t\tRD_ASSERT_MSG(false, \"RdCall.on_wire_received called\")\n\t}\n\nprivate:\n\tWiredRdTask<TRes, ResSer> start_internal(TReq const& request, bool sync, IScheduler* scheduler) const\n\t{\n\t\tassert_bound();\n\t\tif (!async)\n\t\t{\n\t\t\tassert_threading();\n\t\t}\n\n\t\tRdId task_id = get_protocol()->get_identity()->next(rdid);\n\t\tWiredRdTask<TRes, ResSer> task{*bind_lifetime, *this, task_id, scheduler};\n\n\t\tif (sync)\n\t\t{\n\t\t\tif (sync_task_id.has_value())\n\t\t\t{\n\t\t\t\tthrow std::invalid_argument(\n\t\t\t\t\t\"Already exists sync task for call \" + to_string(location) + \", taskId = \" + rd::to_string(*sync_task_id));\n\t\t\t}\n\t\t\tsync_task_id = task_id;\n\t\t}\n\n\t\tget_wire()->send(rdid, [&](Buffer& buffer) {\n\t\t\tspdlog::get(\"logSend\")->trace(\"call {}::{} send {} request {} : {}\", to_string(location), to_string(rdid), (sync ? \"SYNC\" : \"ASYNC\"),\n\t\t\t\tto_string(task_id), to_string(request));\n\t\t\ttask_id.write(buffer);\n\t\t\tReqSer::write(get_serialization_context(), buffer, request);\n\t\t});\n\n\t\treturn task;\n\t}\n\npublic:\n\tfriend bool operator==(const RdCall& lhs, const RdCall& rhs)\n\t{\n\t\treturn &lhs == &rhs;\n\t}\n\n\tfriend bool operator!=(const RdCall& lhs, const RdCall& rhs)\n\t{\n\t\treturn !(rhs == lhs);\n\t}\n\n\tfriend std::string to_string(RdCall const& /*value*/)\n\t{\n\t\treturn \"RdCall\";\n\t}\n};\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n#endif\t  // RD_CPP_RDCALL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/task/RdEndpoint.h",
    "content": "#ifndef RD_CPP_RDENDPOINT_H\n#define RD_CPP_RDENDPOINT_H\n\n#include \"serialization/Polymorphic.h\"\n#include \"RdTask.h\"\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4250)\n#endif\n\nnamespace rd\n{\n/**\n * \\brief An API that is exposed to the remote process and can be invoked over the protocol.\n *\n * \\tparam TReq type of request\n * \\tparam TRes type of response\n * \\tparam ReqSer \"SerDes\" for request\n * \\tparam ResSer \"SerDes\" for response\n */\ntemplate <typename TReq, typename TRes, typename ReqSer = Polymorphic<TReq>, typename ResSer = Polymorphic<TRes>>\nclass RdEndpoint : public virtual RdReactiveBase, public ISerializable\n{\n\tusing WTReq = value_or_wrapper<TReq>;\n\tusing WTRes = value_or_wrapper<TRes>;\n\n\tusing handler_t = std::function<RdTask<TRes, ResSer>(Lifetime, TReq const&)>;\n\tmutable handler_t local_handler;\n\n\tmutable tsl::ordered_map<RdId, RdTask<TRes, ResSer>, rd::hash<RdId>> awaiting_tasks;\t// TO-DO get rid of it\npublic:\n\t// region ctor/dtor\n\n\tRdEndpoint() = default;\n\n\texplicit RdEndpoint(handler_t handler)\n\t{\n\t\tset(std::move(handler));\n\t}\n\n\texplicit RdEndpoint(std::function<WTRes(TReq const&)> handler)\n\t{\n\t\tset(std::move(handler));\n\t}\n\n\tRdEndpoint(RdEndpoint&&) = default;\n\n\tRdEndpoint& operator=(RdEndpoint&&) = default;\n\n\tvirtual ~RdEndpoint() = default;\n\t// endregion\n\n\tstatic RdEndpoint<TReq, TRes, ReqSer, ResSer> read(SerializationCtx& /*ctx*/, Buffer& buffer)\n\t{\n\t\tRdEndpoint<TReq, TRes, ReqSer, ResSer> res;\n\t\tconst RdId& id = RdId::read(buffer);\n\t\twithId(res, id);\n\t\treturn res;\n\t}\n\n\tvoid write(SerializationCtx& /*ctx*/, Buffer& buffer) const override\n\t{\n\t\trdid.write(buffer);\n\t}\n\n\t/**\n\t * \\brief Assigns a handler that executes the API asynchronously.\n\t * \\param handler to assign\n\t */\n\tvoid set(handler_t handler) const\n\t{\n\t\tRD_ASSERT_MSG(handler, \"handler is set already\");\n\t\tlocal_handler = std::move(handler);\n\t}\n\n\t/**\n\t * \\brief @see set above\n\t */\n\tvoid set(std::function<WTRes(TReq const&)> functor) const\n\t{\n\t\tlocal_handler = [handler = std::move(functor)](Lifetime _, TReq const& req) -> RdTask<TRes, ResSer>\n\t\t{ return RdTask<TRes, ResSer>::from_result(handler(req)); };\n\t}\n\n\tvoid init(Lifetime lifetime) const override\n\t{\n\t\tRdReactiveBase::init(lifetime);\n\t\tbind_lifetime = lifetime;\n\t\tget_wire()->advise(lifetime, this);\n\t}\n\n\tvoid on_wire_received(Buffer buffer) const override\n\t{\n\t\tauto task_id = RdId::read(buffer);\n\t\tauto value = ReqSer::read(get_serialization_context(), buffer);\n\t\tspdlog::get(\"logReceived\")->trace(\"endpoint {}::{} request = {}\", to_string(location), to_string(rdid), to_string(value));\n\t\tif (!local_handler)\n\t\t{\n\t\t\tthrow std::invalid_argument(\"handler is empty for RdEndPoint\");\n\t\t}\n\t\tauto task = awaiting_tasks[task_id] = {};\n\t\ttry\n\t\t{\n\t\t\ttask = local_handler(*bind_lifetime, wrapper::get<TReq>(value));\n\t\t}\n\t\tcatch (std::exception const& e)\n\t\t{\n\t\t\ttask.fault(e);\n\t\t}\n\t\ttask.advise(*bind_lifetime,\n\t\t\t[this, task_id, &task](RdTaskResult<TRes, ResSer> const& task_result)\n\t\t\t{\n\t\t\t\tspdlog::get(\"logSend\")->trace(\n\t\t\t\t\t\"endpoint {}::{} response = {}\", to_string(location), to_string(rdid), to_string(*task.result));\n\t\t\t\tget_wire()->send(\n\t\t\t\t\ttask_id, [&](Buffer& inner_buffer) { task_result.write(get_serialization_context(), inner_buffer); });\n\t\t\t\t// TO-DO remove from awaiting_tasks\n\t\t\t});\n\t}\n\n\tfriend bool operator==(const RdEndpoint& lhs, const RdEndpoint& rhs)\n\t{\n\t\treturn &lhs == &rhs;\n\t}\n\n\tfriend bool operator!=(const RdEndpoint& lhs, const RdEndpoint& rhs)\n\t{\n\t\treturn !(rhs == lhs);\n\t}\n\n\tfriend std::string to_string(RdEndpoint const& /*value*/)\n\t{\n\t\treturn \"RdEndpoint\";\n\t}\n};\n}\t // namespace rd\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n#endif\t  // RD_CPP_RDENDPOINT_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/task/RdSymmetricCall.h",
    "content": "#ifndef RD_CPP_RDSYMMETRICCALL_H\n#define RD_CPP_RDSYMMETRICCALL_H\n\n#include \"task/RdCall.h\"\n#include \"task/RdEndpoint.h\"\n\nnamespace rd\n{\ntemplate <typename TReq, typename TRes, typename ReqSer = Polymorphic<TReq>, typename ResSer = Polymorphic<TRes> >\nclass RdSymmetricCall : public RdCall<TReq, TRes, ReqSer, ResSer>, public RdEndpoint<TReq, TRes, ReqSer, ResSer>\n{\npublic:\n\tvoid init(Lifetime lifetime) const override\n\t{\n\t\tRdCall<TReq, TRes, ReqSer, ResSer>::init(lifetime);\n\t}\n\n\tvoid on_wire_received(Buffer buffer) const override\n\t{\n\t\tRdEndpoint<TReq, TRes, ReqSer, ResSer>::on_wire_received(std::move(buffer));\n\t}\n\n\tfriend bool operator==(const RdSymmetricCall& lhs, const RdSymmetricCall& rhs)\n\t{\n\t\treturn &lhs == &rhs;\n\t}\n\n\tfriend bool operator!=(const RdSymmetricCall& lhs, const RdSymmetricCall& rhs)\n\t{\n\t\treturn !(rhs == lhs);\n\t}\n\n\tfriend std::string to_string(RdSymmetricCall const&)\n\t{\n\t\treturn \"RdSymmetricCall\";\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_RDSYMMETRICCALL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/task/RdTask.h",
    "content": "#ifndef RD_CPP_RDTASK_H\n#define RD_CPP_RDTASK_H\n\n#include \"RdTaskImpl.h\"\n#include \"serialization/Polymorphic.h\"\n\n#include <functional>\n\nnamespace rd\n{\n/**\n * \\brief Represents a task that can be asynchronously executed.\n *\n * \\tparam T type of stored value\n * \\tparam S \"SerDes\" for value\n */\ntemplate <typename T, typename S = Polymorphic<T>>\nclass RdTask\n{\nprotected:\n\tusing WT = value_or_wrapper<T>;\n\n\tusing TRes = RdTaskResult<T, S>;\n\n\tmutable std::shared_ptr<detail::RdTaskImpl<T, S>> impl{std::make_shared<detail::RdTaskImpl<T, S>>()};\n\n\tProperty<RdTaskResult<T, S>>* result{&impl->result};\n\npublic:\n\tusing result_type = RdTaskResult<T, S>;\n\n\ttemplate <typename, typename, typename, typename>\n\tfriend class RdEndpoint;\n\t// region ctor/dtor\n\n\tRdTask() = default;\n\n\tRdTask(RdTask const& other) = default;\n\n\tRdTask& operator=(RdTask const& other) = default;\n\n\tRdTask(RdTask&& other) = default;\n\n\tRdTask& operator=(RdTask&& other) = default;\n\n\tvirtual ~RdTask() = default;\n\t// endregion\n\n\tstatic RdTask from_result(WT value)\n\t{\n\t\tRdTask<T, S> res;\n\t\tres.set(std::move(value));\n\t\treturn res;\n\t}\n\n\tvoid set(WT value) const\n\t{\n\t\ttypename TRes::Success t(std::move(value));\n\t\timpl->result.set(std::move(t));\n\t}\n\n\tvoid set_result(TRes value) const\n\t{\n\t\timpl->result.set(std::move(value));\n\t}\n\n\tvoid set_result_if_empty(TRes value) const\n\t{\n\t\timpl->result.set_if_empty(std::move(value));\n\t}\n\n\tvoid cancel() const\n\t{\n\t\timpl->result.set(typename TRes::Cancelled());\n\t}\n\n\tvoid fault(std::exception const& e) const\n\t{\n\t\timpl->result.set(typename TRes::Fault(e));\n\t}\n\n\tbool has_value() const\n\t{\n\t\treturn impl->result.has_value();\n\t}\n\n\tconst TRes& value_or_throw() const\n\t{\n\t\tif (impl->result.has_value())\n\t\t{\n\t\t\treturn impl->result.get();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow std::invalid_argument(\"task is empty\");\n\t\t}\n\t}\n\n\tbool is_succeeded() const\n\t{\n\t\treturn has_value() && value_or_throw().is_succeeded();\n\t};\n\n\tbool is_canceled() const\n\t{\n\t\treturn has_value() && value_or_throw().is_canceled();\n\t};\n\n\tbool is_faulted() const\n\t{\n\t\treturn has_value() && value_or_throw().is_faulted();\t// TO-DO atomic\n\t}\n\n\tvoid advise(Lifetime lifetime, std::function<void(TRes const&)> handler) const\n\t{\n\t\timpl->result.advise(lifetime, [handler = std::move(handler)](optional<TRes> const& opt_value) {\n\t\t\tif (opt_value)\n\t\t\t{\n\t\t\t\thandler(*opt_value);\n\t\t\t}\n\t\t});\n\t}\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_RDTASK_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/task/RdTaskImpl.h",
    "content": "#ifndef RD_CPP_RDTASKIMPL_H\n#define RD_CPP_RDTASKIMPL_H\n\n#include \"serialization/Polymorphic.h\"\n#include \"RdTaskResult.h\"\n\n#include \"thirdparty.hpp\"\n\nnamespace rd\n{\ntemplate <typename, typename>\nclass RdTask;\n\nnamespace detail\n{\ntemplate <typename T, typename S = Polymorphic<T>>\nclass RdTaskImpl\n{\nprivate:\n\tmutable Property<RdTaskResult<T, S>> result;\n\npublic:\n\ttemplate <typename, typename>\n\tfriend class ::rd::RdTask;\n};\n}\t // namespace detail\n}\t // namespace rd\n\n#endif\t  // RD_CPP_RDTASKIMPL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/task/RdTaskResult.h",
    "content": "#ifndef RD_CPP_RDTASKRESULT_H\n#define RD_CPP_RDTASKRESULT_H\n\n#include \"serialization/Polymorphic.h\"\n#include \"util/overloaded.h\"\n#include \"types/wrapper.h\"\n#include \"util/core_util.h\"\n\n#include \"thirdparty.hpp\"\n\n#include <exception>\n#include <functional>\n\nnamespace rd\n{\n/**\n * \\brief Advanced monad result. It is in of following states: Success, Cancelled, Fault;\n * Success -  Execution completed. Result stores in it.\n * Cancelled - Task was cancelled on callee side.\n * Fault - Something went wrong and reason stores in it.\n * \\tparam T type of result\n * \\tparam S \"SerDes\" for T\n */\ntemplate <typename T, typename S = Polymorphic<T> >\nclass RdTaskResult final : public ISerializable\n{\n\tusing WT = value_or_wrapper<T>;\n\npublic:\n\tclass Success\n\t{\n\tpublic:\n\t\tmutable WT value;\n\n\t\texplicit Success(WT&& value) : value(std::move(value))\n\t\t{\n\t\t}\n\t};\n\n\tclass Cancelled\n\t{\n\t};\n\n\tclass Fault\n\t{\n\tpublic:\n\t\tstd::wstring reason_type_fqn;\n\t\tstd::wstring reason_message;\n\t\tstd::wstring reason_as_text;\n\n\t\tFault(std::wstring reason_type_fqn, std::wstring reason_message, std::wstring reason_as_text)\n\t\t\t: reason_type_fqn(std::move(reason_type_fqn))\n\t\t\t, reason_message(std::move(reason_message))\n\t\t\t, reason_as_text(std::move(reason_as_text))\n\t\t{\n\t\t}\n\n\t\texplicit Fault(const std::exception& e)\n\t\t{\n\t\t\treason_message = to_wstring(to_string(e));\n\t\t}\n\t};\n\n\t// region ctor/dtor\n\n\ttemplate <typename F>\n\tRdTaskResult(F&& v) : v(std::forward<F>(v))\n\t{\n\t}\n\n\tRdTaskResult(RdTaskResult const&) = default;\n\n\tRdTaskResult(RdTaskResult&&) = default;\n\n\tRdTaskResult& operator=(RdTaskResult&&) = default;\n\n\tvirtual ~RdTaskResult() = default;\n\t// endregion\n\n\tstatic RdTaskResult<T, S> read(SerializationCtx& ctx, Buffer& buffer)\n\t{\n\t\tconst int32_t kind = buffer.read_integral<int32_t>();\n\t\tswitch (kind)\n\t\t{\n\t\t\tcase 0:\n\t\t\t{\n\t\t\t\treturn Success(std::move(S::read(ctx, buffer)));\n\t\t\t}\n\t\t\tcase 1:\n\t\t\t{\n\t\t\t\treturn Cancelled();\n\t\t\t}\n\t\t\tcase 2:\n\t\t\t{\n\t\t\t\tauto reason_type_fqn = buffer.read_wstring();\n\t\t\t\tauto reason_message = buffer.read_wstring();\n\t\t\t\tauto reason_as_text = buffer.read_wstring();\n\t\t\t\treturn Fault(std::move(reason_type_fqn), std::move(reason_message), std::move(reason_as_text));\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow std::invalid_argument(\"Fail on RdTaskResult reading with kind: \" + std::to_string(kind));\n\t\t}\n\t}\n\n\tvoid write(SerializationCtx& ctx, Buffer& buffer) const override\n\t{\n\t\tvisit(util::make_visitor(\n\t\t\t\t  [&ctx, &buffer](Success const& value) {\n\t\t\t\t\t  buffer.write_integral<int32_t>(0);\n\t\t\t\t\t  S::write(ctx, buffer, value.value);\n\t\t\t\t  },\n\t\t\t\t  [&buffer](Cancelled const&) { buffer.write_integral<int32_t>(1); },\n\t\t\t\t  [&buffer](Fault const& value) {\n\t\t\t\t\t  buffer.write_integral<int32_t>(2);\n\t\t\t\t\t  buffer.write_wstring(value.reason_type_fqn);\n\t\t\t\t\t  buffer.write_wstring(value.reason_message);\n\t\t\t\t\t  buffer.write_wstring(value.reason_as_text);\n\t\t\t\t  }),\n\t\t\tv);\n\t}\n\n\tT const& unwrap() const\n\t{\n\t\treturn visit(util::make_visitor([](Success const& value) -> T const& { return wrapper::get<T>(value.value); },\n\t\t\t\t\t\t [](Cancelled const&) -> T const& { throw std::invalid_argument(\"Task finished in Cancelled state\"); },\n\t\t\t\t\t\t [](Fault const& value) -> T const& { throw std::runtime_error(to_string(value.reason_message)); }),\n\t\t\tv);\n\t}\n\n\tbool is_succeeded() const\n\t{\n\t\treturn v.index() == 0;\n\t}\n\n\tbool is_canceled() const\n\t{\n\t\treturn v.index() == 1;\n\t}\n\n\tvoid as_canceled(std::function<void(Cancelled const&)> f) const\n\t{\n\t\tf(rd::get<Cancelled>(v));\n\t}\n\n\tbool is_faulted() const\n\t{\n\t\treturn v.index() == 2;\n\t}\n\n\tvoid as_faulted(std::function<void(Fault const&)> f)\n\t{\n\t\tf(rd::get<Fault>(v));\n\t}\n\n\tfriend bool operator==(const RdTaskResult& lhs, const RdTaskResult& rhs)\n\t{\n\t\treturn &lhs == &rhs;\n\t}\n\n\tfriend bool operator!=(const RdTaskResult& lhs, const RdTaskResult& rhs)\n\t{\n\t\treturn !(rhs == lhs);\n\t}\n\n\tfriend std::string to_string(RdTaskResult const& taskResult)\n\t{\n\t\treturn visit(util::make_visitor([](Success const& value) -> std::string { return to_string(value.value); },\n\t\t\t\t\t\t [](Cancelled const&) -> std::string { return \"Cancelled state\"; },\n\t\t\t\t\t\t [](Fault const& value) -> std::string { return to_string(value.reason_message); }),\n\t\t\ttaskResult.v);\n\t}\n\nprivate:\n\tmutable variant<Success, Cancelled, Fault> v;\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_RDTASKRESULT_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/task/WiredRdTask.h",
    "content": "#ifndef RD_CPP_WIREDRDTASK_H\n#define RD_CPP_WIREDRDTASK_H\n\n#include \"RdTask.h\"\n#include \"WiredRdTaskImpl.h\"\n#include \"base/RdReactiveBase.h\"\n#include \"scheduler/base/IScheduler.h\"\n\nnamespace rd\n{\ntemplate <typename T, typename S = Polymorphic<T>>\nclass WiredRdTask final : public RdTask<T, S>\n{\n\tmutable std::shared_ptr<detail::WiredRdTaskImpl<T, S>> impl{};\n\npublic:\n\t// region ctor/dtor\n\tWiredRdTask() = delete;\n\n\tWiredRdTask(Lifetime lifetime, RdReactiveBase const& call, RdId rdid, IScheduler* scheduler)\n\t\t: impl(std::make_shared<detail::WiredRdTaskImpl<T, S>>(lifetime, call, rdid, scheduler, RdTask<T, S>::result))\n\t{\n\t}\n\n\tWiredRdTask(WiredRdTask const& other) = default;\n\n\tWiredRdTask& operator=(WiredRdTask const& other) = default;\n\n\tWiredRdTask(WiredRdTask&& other) = default;\n\n\tWiredRdTask& operator=(WiredRdTask&& other) = default;\n\n\tvirtual ~WiredRdTask() = default;\n\t// endregion\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_WIREDRDTASK_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/task/WiredRdTaskImpl.h",
    "content": "#ifndef RD_CPP_WIREDRDTASKIMPL_H\n#define RD_CPP_WIREDRDTASKIMPL_H\n\n#include \"serialization/Polymorphic.h\"\n#include \"RdTaskResult.h\"\n\nnamespace rd\n{\ntemplate <typename, typename>\nclass WiredRdTask;\n\nnamespace detail\n{\ntemplate <typename T, typename S = Polymorphic<T>>\nclass WiredRdTaskImpl : public RdReactiveBase\n{\nprivate:\n\tLifetime lifetime;\n\tRdReactiveBase const* cutpoint{};\n\tIScheduler* scheduler{};\n\tProperty<RdTaskResult<T, S>>* result{};\n\n\tLifetimeImpl::counter_t termination_lifetime_id{};\n\npublic:\n\ttemplate <typename, typename>\n\tfriend class ::rd::WiredRdTask;\n\n\tWiredRdTaskImpl(\n\t\tLifetime lifetime, RdReactiveBase const& cutpoint, RdId rdid, IScheduler* scheduler, Property<RdTaskResult<T, S>>* result)\n\t\t: lifetime(lifetime), cutpoint(&cutpoint), scheduler(scheduler), result(result)\n\t{\n\t\tthis->rdid = std::move(rdid);\n\t\tcutpoint.get_wire()->advise(lifetime, this);\n\t\ttermination_lifetime_id =\n\t\t\tlifetime->add_action([this]() { this->result->set_if_empty(typename RdTaskResult<T, S>::Cancelled{}); });\n\t}\n\n\tvirtual ~WiredRdTaskImpl()\n\t{\n\t\tlifetime->remove_action(termination_lifetime_id);\n\t}\n\n\tvoid on_wire_received(Buffer buffer) const override\n\t{\n\t\tauto read_result = RdTaskResult<T, S>::read(cutpoint->get_serialization_context(), buffer);\n\t\tspdlog::get(\"logReceived\")\n\t\t\t->trace(\"call {} {} received response {} : {}\", to_string(cutpoint->get_location()), to_string(rdid), to_string(rdid),\n\t\t\t\tto_string(read_result));\n\t\tscheduler->queue([&, moved_result = std::move(read_result)]() mutable {\n\t\t\tif (this->result->has_value())\n\t\t\t{\n\t\t\t\tspdlog::get(\"logReceived\")->trace(\"call {} {} response was dropped, task result is: {}\", to_string(location), to_string(rdid),\n\t\t\t\t\tto_string(moved_result.unwrap()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis->result->set_if_empty(std::move(moved_result));\n\t\t\t}\n\t\t});\n\t}\n\n\tIScheduler* get_wire_scheduler() const override\n\t{\n\t\treturn &SynchronousScheduler::Instance();\n\t}\n};\n}\t // namespace detail\n}\t // namespace rd\n\n#endif\t  // RD_CPP_WIREDRDTASKIMPL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/util/framework_traits.h",
    "content": "#ifndef RD_CPP_FRAMEWORK_TRAITS_H\n#define RD_CPP_FRAMEWORK_TRAITS_H\n\n#include \"serialization/Polymorphic.h\"\n\n#include <utility>\n#include <type_traits>\n\nnamespace rd\n{\nnamespace util\n{\ntemplate <typename S, typename T = decltype((S::read(std::declval<rd::SerializationCtx&>(), std::declval<rd::Buffer&>())))>\nusing read_t = T;\n\nstatic_assert(util::is_same_v<std::wstring, read_t<Polymorphic<std::wstring>>>, \" \");\n}\t // namespace util\n}\t // namespace rd\n\n#endif\t  // RD_CPP_FRAMEWORK_TRAITS_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/util/guards.h",
    "content": "#ifndef RD_CPP_GUARDS_H\n#define RD_CPP_GUARDS_H\n\nnamespace rd\n{\nnamespace util\n{\ntemplate <typename T>\nclass increment_guard\n{\n\tT& x;\n\npublic:\n\texplicit increment_guard(T& new_x) : x(new_x)\n\t{\n\t\t++x;\n\t}\n\n\t~increment_guard()\n\t{\n\t\t--x;\n\t}\n};\n\nclass bool_guard\n{\n\tbool& x;\n\npublic:\n\texplicit bool_guard(bool& new_x) : x(new_x)\n\t{\n\t\tx = true;\n\t}\n\n\t~bool_guard()\n\t{\n\t\tx = false;\n\t}\n};\n}\t // namespace util\n}\t // namespace rd\n\n#endif\t  // RD_CPP_GUARDS_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/util/hashing.cpp",
    "content": ""
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/util/hashing.h",
    "content": "#ifndef RD_CPP_HASHING_H\n#define RD_CPP_HASHING_H\n\n#include \"nonstd/string_view.hpp\"\n\n#include <cstdint>\n#include <cstdlib>\n#include <string>\n\nnamespace rd\n{\nnamespace util\n{\nusing hash_t = int64_t;\nusing constexpr_hash_t = uint64_t;\t  // hash_t;\n\nconstexpr constexpr_hash_t DEFAULT_HASH = 19;\nconstexpr constexpr_hash_t HASH_FACTOR = 31;\n\n// PLEASE DO NOT CHANGE IT!!! IT'S EXACTLY THE SAME ON C# SIDE\nconstexpr hash_t hashImpl(constexpr_hash_t initial, char const* begin, char const* end)\n{\n\treturn (begin == end) ? initial : hashImpl(initial * HASH_FACTOR + *begin, begin + 1, end);\n}\n\n/*template<size_t N>\nconstexpr hash_t getPlatformIndependentHash(char const (&that)[N], constexpr_hash_t initial = DEFAULT_HASH) {\n\treturn static_cast<hash_t>(hashImpl(initial, &that[0], &that[N - 1]));\n}*/\n\nconstexpr hash_t getPlatformIndependentHash(string_view that, constexpr_hash_t initial = DEFAULT_HASH)\n{\n\treturn static_cast<hash_t>(hashImpl(initial, &that[0], &that[that.length() - 1] + 1));\n}\n\nconstexpr hash_t getPlatformIndependentHash(int32_t const& that, constexpr_hash_t initial = DEFAULT_HASH)\n{\n\treturn static_cast<hash_t>(initial * HASH_FACTOR + static_cast<constexpr_hash_t>(that + 1));\n}\n\nconstexpr hash_t getPlatformIndependentHash(int64_t const& that, constexpr_hash_t initial = DEFAULT_HASH)\n{\n\treturn static_cast<hash_t>(initial * HASH_FACTOR + static_cast<constexpr_hash_t>(that + 1));\n}\n}\t // namespace util\n}\t // namespace rd\n#endif\t  // RD_CPP_HASHING_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/util/thread_util.cpp",
    "content": "#include \"thread_util.h\"\n\n#ifdef _WIN32\n\n#include <windows.h>\nconst DWORD MS_VC_EXCEPTION = 0x406D1388;\n\n#pragma pack(push, 8)\ntypedef struct tagTHREADNAME_INFO\n{\n\tDWORD dwType;\t\t // Must be 0x1000.\n\tLPCSTR szName;\t\t // Pointer to name (in user addr space).\n\tDWORD dwThreadID;\t // Thread ID (-1=caller thread).\n\tDWORD dwFlags;\t\t // Reserved for future use, must be zero.\n} THREADNAME_INFO;\n#pragma pack(pop)\n\nvoid SetThreadName(uint32_t dwThreadID, const char* threadName)\n{\n\tTHREADNAME_INFO info;\n\tinfo.dwType = 0x1000;\n\tinfo.szName = threadName;\n\tinfo.dwThreadID = dwThreadID;\n\tinfo.dwFlags = 0;\n\n\t__try\n\t{\n\t\tRaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*) &info);\n\t}\n\t__except (EXCEPTION_EXECUTE_HANDLER)\n\t{\n\t}\n}\n\nvoid SetThreadName(const char* threadName)\n{\n\tSetThreadName(GetCurrentThreadId(), threadName);\n}\n\n#elif defined(__APPLE__)\n\n#include <pthread.h>\n\nvoid SetThreadName(const char* threadName)\n{\n\tpthread_setname_np(threadName);\n}\n\n#else\n\n#include <pthread.h>\n\nvoid SetThreadName(const char* threadName)\n{\n\tpthread_setname_np(pthread_self(), threadName);\n}\n\n#endif\n\nnamespace rd\n{\nnamespace util\n{\nvoid set_thread_name(const char* name)\n{\n\tSetThreadName(name);\n}\n\n}\t // namespace util\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/util/thread_util.h",
    "content": "#ifndef RD_CPP_THREAD_UTIL_H\n#define RD_CPP_THREAD_UTIL_H\n\n#include <thread>\n\nnamespace rd\n{\nnamespace util\n{\nvoid set_thread_name(const char* name);\n\n}\n\n}\t // namespace rd\n\n#endif\t  // RD_CPP_THREAD_UTIL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/ByteBufferAsyncProcessor.cpp",
    "content": "#include \"ByteBufferAsyncProcessor.h\"\n\n#include \"util/guards.h\"\n#include <util/thread_util.h>\n\n#include \"spdlog/sinks/stdout_color_sinks.h\"\n\nnamespace rd\n{\nsize_t ByteBufferAsyncProcessor::INITIAL_CAPACITY = 1024 * 1024;\n\nstd::shared_ptr<spdlog::logger> ByteBufferAsyncProcessor::logger =\n\tspdlog::stderr_color_mt<spdlog::synchronous_factory>(\"byteBufferLog\", spdlog::color_mode::automatic);\n\nByteBufferAsyncProcessor::ByteBufferAsyncProcessor(\n\tstd::string id, std::function<bool(Buffer::ByteArray const&, sequence_number_t)> processor)\n\t: id(std::move(id)), processor(std::move(processor))\n{\n\tdata.reserve(INITIAL_CAPACITY);\n}\n\nvoid ByteBufferAsyncProcessor::cleanup0()\n{\n\t{\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\n\t\tstate = StateKind::Terminated;\n\t}\n\t// TO-DO clean data\n\n\tcv.notify_all();\n}\n\nbool ByteBufferAsyncProcessor::terminate0(time_t timeout, StateKind state_to_set, string_view action)\n{\n\t{\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\tif (state == StateKind::Initialized)\n\t\t{\n\t\t\tlogger->debug(\"Can't {} \\'{}\\', because it hasn't been started yet\", std::string(action), id);\n\t\t\tcleanup0();\n\t\t\treturn true;\n\t\t}\n\n\t\tif (state >= state_to_set)\n\t\t{\n\t\t\tlogger->debug(\"Trying to {} async processor \\'{}' but it's in state {}\", std::string(action), id, to_string(state));\n\t\t\treturn true;\n\t\t}\n\n\t\tstate = state_to_set;\n\t}\n\tcv.notify_all();\n\n\tstd::future_status status = async_future.wait_for(timeout);\n\n\tbool success = true;\n\n\tif (status == std::future_status::timeout)\n\t{\n\t\tlogger->error(\"Couldn't wait async thread during time: {}\", to_string(timeout));\n\t\tsuccess = false;\n\t}\n\n\tcleanup0();\n\n\treturn success;\n}\n\nvoid ByteBufferAsyncProcessor::add_data(std::vector<Buffer::ByteArray>&& new_data)\n{\n\tstd::lock_guard<decltype(queue_lock)> guard(queue_lock);\n\tstd::move(new_data.begin(), new_data.end(), std::back_inserter(queue));\n\t//\t\tfor (auto &&item : new_data) {\n\t//\t\t\tqueue.emplace(std::move(item));\n\t//\t\t}\n}\n\n/**\n * @brief Cleanup pending queue. Should be called under queue_lock.\n */\nvoid ByteBufferAsyncProcessor::cleanup_pending_queue()\n{\n\twhile (current_seqn <= acknowledged_seqn)\n\t{\n\t\tpending_queue.pop_front();\n\t\t++current_seqn;\n\t}\n}\n\nbool ByteBufferAsyncProcessor::reprocess()\n{\n\t{\n\t\tstd::lock_guard<decltype(queue_lock)> guard(queue_lock);\n\n\t\tlogger->debug(\"{}: reprocessing started\", id);\n\n\t\tstd::unique_lock<decltype(processing_lock)> ul(processing_lock);\n\t\tprocessing_cv.wait(ul, [this]() -> bool { return !in_processing; });\n\n\t\tlogger->debug(\"{}: reprocessing waited for main processing\", id);\n\n\t\tcleanup_pending_queue();\n\t\tfor (int i = 0; i < pending_queue.size(); ++i)\n\t\t{\n\t\t\tauto const& item = pending_queue[i];\n\t\t\tif (!processor(item, current_seqn + i))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\nvoid ByteBufferAsyncProcessor::process()\n{\n\t{\n\t\tstd::lock_guard<decltype(queue_lock)> guard(queue_lock);\n\t\tstd::unique_lock<decltype(processing_lock)> ul(processing_lock);\n\t\tutil::bool_guard bool_guard(in_processing);\n\n\t\tlogger->debug(\"{}: processing started\", id);\n\n\t\twhile (!queue.empty() && processor(queue.front(), max_sent_seqn + 1))\n\t\t{\n\t\t\t++max_sent_seqn;\n\t\t\tpending_queue.push_back(std::move(queue.front()));\n\t\t\tqueue.pop_front();\n\t\t}\n\t}\n\tprocessing_cv.notify_all();\n\n\tcv.notify_all();\n}\n\nvoid ByteBufferAsyncProcessor::ThreadProc()\n{\n\trd::util::set_thread_name(id.empty() ? \"ByteBufferAsyncProcessor Thread\" : id.c_str());\n\tasync_thread_id = std::this_thread::get_id();\n\n\twhile (true)\n\t{\n\t\t{\n\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\n\t\t\tif (state >= StateKind::Terminated)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twhile (data.empty() || interrupt_balance != 0)\n\t\t\t{\n\t\t\t\tif (state >= StateKind::Stopping)\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcv.wait(lock);\n\n\t\t\t\tlogger->debug(\"{}'s ThreadProc waited for notify\", id);\n\n\t\t\t\tif (state >= StateKind::Terminating)\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tadd_data(std::move(data));\n\t\t\tdata.clear();\n\t\t}\n\n\t\ttry\n\t\t{\n\t\t\tprocess();\n\t\t}\n\t\tcatch (std::exception const& e)\n\t\t{\n\t\t\tlogger->error(\"Exception while processing byte queue | {}\", e.what());\n\t\t}\n\t}\n}\n\nvoid ByteBufferAsyncProcessor::start()\n{\n\t{\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\n\t\tif (state != StateKind::Initialized)\n\t\t{\n\t\t\tlogger->debug(\"Trying to START async processor {} but it's in state {}\", id, to_string(state));\n\t\t\treturn;\n\t\t}\n\n\t\tstate = StateKind::AsyncProcessing;\n\n\t\tasync_future = std::async(std::launch::async, &ByteBufferAsyncProcessor::ThreadProc, this);\n\t}\n}\n\nbool ByteBufferAsyncProcessor::stop(time_t timeout)\n{\n\treturn terminate0(timeout, StateKind::Stopping, \"STOP\");\n}\n\nbool ByteBufferAsyncProcessor::terminate(time_t timeout)\n{\n\treturn terminate0(timeout, StateKind::Terminating, \"TERMINATE\");\n}\n\nvoid ByteBufferAsyncProcessor::put(Buffer::ByteArray new_data)\n{\n\t{\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\n\t\tif (state >= StateKind::Stopping)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tdata.emplace_back(std::move(new_data));\n\t}\n\tcv.notify_all();\n}\n\nvoid ByteBufferAsyncProcessor::pause(const std::string& reason)\n{\n\tstd::lock_guard<decltype(lock)> guard(lock);\n\n\t++interrupt_balance;\n\n\tlogger->debug(\"{} paused with reason={},state={}\", id, reason, to_string(state));\n\n\tauto current_thread_id = std::this_thread::get_id();\n\tif (current_thread_id != async_thread_id)\n\t{\n\t\tlogger->debug(\"{} paused from another thread : {}\", id, to_string(current_thread_id));\n\t\tstd::unique_lock<decltype(processing_lock)> ul(processing_lock);\n\t\tprocessing_cv.wait(ul, [this]() -> bool { return !in_processing; });\n\t\tlogger->debug(\"{}: pausing waited for main processing\", id);\n\t}\n}\n\nvoid ByteBufferAsyncProcessor::resume()\n{\n\t{\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\n\t\treprocess();\n\n\t\t--interrupt_balance;\n\n\t\tlogger->debug(\"{} resumed\", id);\n\t}\n\n\tcv.notify_all();\n}\n\nvoid ByteBufferAsyncProcessor::acknowledge(sequence_number_t seqn)\n{\n\tstd::lock_guard<decltype(lock)> guard(lock);\n\n\tif (seqn > acknowledged_seqn)\n\t{\n\t\tlogger->trace(\"{}: new acknowledged seqn: {}\", this->id, seqn);\n\t\tacknowledged_seqn = seqn;\n\n\t\tstd::lock_guard<decltype(queue_lock)> queue_guard(queue_lock);\n\t\tcleanup_pending_queue();\n\t}\n\telse\n\t{\n\t\tlogger->error(\"Acknowledge {} called, while next seqn MUST BE greater than {}\", seqn, acknowledged_seqn);\n\t}\n}\n\nstd::string to_string(ByteBufferAsyncProcessor::StateKind state)\n{\n\tswitch (state)\n\t{\n\t\tcase ByteBufferAsyncProcessor::StateKind::Initialized:\n\t\t\treturn \"Initialized\";\n\t\tcase ByteBufferAsyncProcessor::StateKind::AsyncProcessing:\n\t\t\treturn \"AsyncProcessing\";\n\t\tcase ByteBufferAsyncProcessor::StateKind::Stopping:\n\t\t\treturn \"Stopping\";\n\t\tcase ByteBufferAsyncProcessor::StateKind::Terminating:\n\t\t\treturn \"Terminating\";\n\t\tcase ByteBufferAsyncProcessor::StateKind::Terminated:\n\t\t\treturn \"Terminated\";\n\t}\n\treturn {};\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/ByteBufferAsyncProcessor.h",
    "content": "#ifndef RD_CPP_BYTEBUFFERASYNCPROCESSOR_H\n#define RD_CPP_BYTEBUFFERASYNCPROCESSOR_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"protocol/Buffer.h\"\n#include \"spdlog/spdlog.h\"\n\n#include <chrono>\n#include <string>\n#include <mutex>\n#include <condition_variable>\n#include <future>\n#include <list>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nusing sequence_number_t = int64_t;\n\nclass RD_FRAMEWORK_API ByteBufferAsyncProcessor\n{\npublic:\n\tenum class StateKind\n\t{\n\t\tInitialized,\n\t\tAsyncProcessing,\n\t\tStopping,\n\t\tTerminating,\n\t\tTerminated\n\t};\n\nprivate:\n\tusing time_t = std::chrono::milliseconds;\n\n\tstatic size_t INITIAL_CAPACITY;\n\n\tstd::recursive_mutex lock;\n\tstd::condition_variable_any cv;\n\n\tstd::string id;\n\n\tstd::function<bool(Buffer::ByteArray const&, sequence_number_t seqn)> processor;\n\n\tStateKind state{StateKind::Initialized};\n\tstatic std::shared_ptr<spdlog::logger> logger;\n\n\tstd::thread::id async_thread_id;\n\tstd::future<void> async_future;\n\n\tstd::vector<Buffer::ByteArray> data;\n\tstd::mutex queue_lock;\n\tstd::deque<Buffer::ByteArray> queue{};\n\tstd::deque<Buffer::ByteArray> pending_queue{};\n\n\tsequence_number_t max_sent_seqn = 0;\n\tsequence_number_t current_seqn = 1;\n\tsequence_number_t acknowledged_seqn = 0;\n\n\tint32_t interrupt_balance = 0;\n\tbool in_processing = false;\n\tstd::mutex processing_lock;\n\tstd::condition_variable processing_cv;\n\npublic:\n\t// region ctor/dtor\n\n\texplicit ByteBufferAsyncProcessor(std::string id, std::function<bool(Buffer::ByteArray const&, sequence_number_t)> processor);\n\n\t// endregion\nprivate:\n\tvoid cleanup0();\n\n\tbool terminate0(time_t timeout, StateKind state_to_set, string_view action);\n\n\tvoid add_data(std::vector<Buffer::ByteArray>&& new_data);\n\n\tvoid cleanup_pending_queue();\n\n\tbool reprocess();\n\n\tvoid process();\n\n\tvoid ThreadProc();\n\npublic:\n\tvoid start();\n\n\tbool stop(time_t timeout = time_t(0));\n\n\tbool terminate(time_t timeout = time_t(0) /*InfiniteDuration*/);\n\n\tvoid put(Buffer::ByteArray new_data);\n\n\tvoid pause(const std::string& reason);\n\n\tvoid resume();\n\n\tvoid acknowledge(int64_t seqn);\n};\n\nstd::string to_string(ByteBufferAsyncProcessor::StateKind state);\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_BYTEBUFFERASYNCPROCESSOR_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/PkgInputStream.cpp",
    "content": "#define NOMINMAX\n\n#include \"PkgInputStream.h\"\n\n#include <algorithm>\n\nnamespace rd\n{\nvoid PkgInputStream::rewind()\n{\n\tbuffer.rewind();\n}\n\nvoid PkgInputStream::require_available(int size)\n{\n\tbuffer.require_available(size);\n}\n\nsize_t PkgInputStream::get_position() const\n{\n\treturn buffer.get_position();\n}\n\nBuffer::word_t* PkgInputStream::data()\n{\n\treturn buffer.data();\n}\n\nBuffer& PkgInputStream::get_buffer()\n{\n\treturn buffer;\n}\n\nint32_t PkgInputStream::try_read(Buffer::word_t* res, size_t size)\n{\n\tif (memory == -1 || buffer.get_position() == memory)\n\t{\n\t\tmemory = request_data();\n\t\tif (memory == -1)\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\t}\n\tconst int32_t n = static_cast<int32_t>((std::min)(size, memory - buffer.get_position()));\n\tBuffer::word_t* start = buffer.current_pointer();\n\tstd::copy(start, start + n, res);\n\tbuffer.set_position(buffer.get_position() + n);\n\treturn n;\n}\n\nbool PkgInputStream::read(Buffer::word_t* res, size_t size)\n{\n\t//\t\tspdlog::trace(\"PkgInputStream call: size={}, pos={}, memory={}\", size, buffer.get_position(), memory);\n\n\tint32_t summary_size = 0;\n\twhile (summary_size < size)\n\t{\n\t\tconst int32_t bytes_read = try_read(res + summary_size, size - summary_size);\n\t\tif (bytes_read == -1)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tsummary_size += bytes_read;\n\t}\n\treturn true;\n}\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/PkgInputStream.h",
    "content": "#ifndef RD_CPP_PKGINPUTSTREAM_H\n#define RD_CPP_PKGINPUTSTREAM_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"protocol/Buffer.h\"\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API PkgInputStream\n{\nprivate:\n\tBuffer buffer;\n\n\tstd::function<int32_t()> request_data;\n\n\tsize_t memory = 0;\n\npublic:\n\ttemplate <typename F>\n\texplicit PkgInputStream(F&& f) : request_data(std::forward<F>(f))\n\t{\n\t}\n\n\tvoid rewind();\n\n\tvoid require_available(int size);\n\n\tsize_t get_position() const;\n\n\tBuffer::word_t* data();\n\n\tBuffer& get_buffer();\n\n\tint32_t try_read(Buffer::word_t* res, size_t size);\n\n\tbool read(Buffer::word_t* res, size_t size);\n\n\ttemplate <typename T>\n\tT read_integral()\n\t{\n\t\tT x{};\n\t\tif (!read(reinterpret_cast<Buffer::word_t*>(&x), sizeof(T)))\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\t\treturn x;\n\t}\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_PKGINPUTSTREAM_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/PumpScheduler.cpp",
    "content": "#include \"wire/PumpScheduler.h\"\n\n#include \"util/core_util.h\"\n\nnamespace rd\n{\nnamespace test\n{\nnamespace util\n{\nPumpScheduler::PumpScheduler() : created_thread_id(std::this_thread::get_id())\n{\n}\n\nvoid PumpScheduler::flush()\n{\n\tassert_thread();\n\tauto action = std::move(messages.front());\n\tmessages.pop();\n\taction();\n}\n\nvoid PumpScheduler::queue(std::function<void()> action)\n{\n\t{\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\tmessages.push(std::move(action));\n\t}\n\tcv.notify_all();\n}\n\nbool PumpScheduler::is_active() const\n{\n\treturn true;\n}\n\nvoid PumpScheduler::assert_thread() const\n{\n\tRD_ASSERT_MSG(created_thread_id == std::this_thread::get_id(),\n\t\t\"Illegal thread for current action, must be: \" + to_string(created_thread_id) +\n\t\t\t\", current thread: \" + to_string(std::this_thread::get_id()))\n}\n\nvoid PumpScheduler::pump_one_message()\n{\n\t{\n\t\tstd::unique_lock<decltype(lock)> ul(lock);\n\t\tcv.wait(ul, [this]() -> bool { return !messages.empty(); });\n\t}\n\tflush();\n}\n\nPumpScheduler::PumpScheduler(std::string const& name) : PumpScheduler()\n{\n\tthis->name = name;\n}\n}\t // namespace util\n}\t // namespace test\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/PumpScheduler.h",
    "content": "#ifndef RD_CPP_PUMPSCHEDULER_H\n#define RD_CPP_PUMPSCHEDULER_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"scheduler/base/IScheduler.h\"\n\n#include <condition_variable>\n#include <thread>\n#include <queue>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nnamespace test\n{\nnamespace util\n{\nclass RD_FRAMEWORK_API PumpScheduler : public IScheduler\n{\npublic:\n\tstd::string name;\n\n\tmutable std::condition_variable cv;\n\tmutable std::mutex lock;\n\n\tstd::thread::id created_thread_id;\n\tmutable std::queue<std::function<void()> > messages;\n\n\t// region ctor/dtor\n\n\tPumpScheduler();\n\n\texplicit PumpScheduler(std::string const& name);\n\n\tvirtual ~PumpScheduler() = default;\n\t// endregion\n\n\tvoid flush() override;\n\n\tvoid queue(std::function<void()> action) override;\n\n\tbool is_active() const override;\n\n\tvoid assert_thread() const override;\n\n\tvoid pump_one_message();\n};\n}\t // namespace util\n}\t // namespace test\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_PUMPSCHEDULER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/SocketWire.cpp",
    "content": "#include \"wire/SocketWire.h\"\n\n#include <util/thread_util.h>\n\n#include \"spdlog/sinks/stdout_color_sinks.h\"\n\n#include <SimpleSocket.h>\n#include <ActiveSocket.h>\n#include <PassiveSocket.h>\n\n#include <utility>\n#include <thread>\n#include <csignal>\n\nnamespace rd\n{\nstd::shared_ptr<spdlog::logger> SocketWire::Base::logger =\n\tspdlog::stderr_color_mt<spdlog::synchronous_factory>(\"wireLog\", spdlog::color_mode::automatic);\n\nstd::chrono::milliseconds SocketWire::timeout = std::chrono::milliseconds(500);\n\nconstexpr int32_t SocketWire::Base::ACK_MESSAGE_LENGTH;\nconstexpr int32_t SocketWire::Base::PING_MESSAGE_LENGTH;\nconstexpr int32_t SocketWire::Base::PACKAGE_HEADER_LENGTH;\n\nSocketWire::Base::Base(std::string id, Lifetime parentLifetime, IScheduler* scheduler)\n\t: WireBase(scheduler), id(std::move(id)), scheduler(scheduler), lifetimeDef(parentLifetime)\n{\n\tasync_send_buffer.pause(\"initial\");\n\tasync_send_buffer.start();\n\tping_pkg_header.write_integral(PING_MESSAGE_LENGTH);\n}\n\nSocketWire::Base::~Base()\n{\n\tif (!lifetimeDef.is_terminated())\n\t{\n\t\tlifetimeDef.terminate();\n\t}\n}\n\nvoid SocketWire::Base::receiverProc() const\n{\n\twhile (!lifetimeDef.lifetime->is_terminated())\n\t{\n\t\ttry\n\t\t{\n\t\t\tif (!socket_provider->IsSocketValid())\n\t\t\t{\n\t\t\t\tlogger->debug(\"{}: stop receive messages because socket disconnected\", this->id);\n\t\t\t\t//\t\t\t\t\tasync_send_buffer.terminate();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (!read_and_dispatch_message())\n\t\t\t{\n\t\t\t\tlogger->debug(\"{}: connection was gracefully shutdown\", id);\n\t\t\t\t//\t\t\t\t\tasync_send_buffer.terminate();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tcatch (std::exception const& ex)\n\t\t{\n\t\t\tlogger->error(\"{} caught processing | {}\", this->id, ex.what());\n\t\t\t//\t\t\t\tasync_send_buffer.terminate();\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nbool SocketWire::Base::send0(Buffer::ByteArray const& msg, sequence_number_t seqn) const\n{\n\ttry\n\t{\n\t\tstd::lock_guard<decltype(socket_send_lock)> guard(socket_send_lock);\n\n\t\tint32_t msglen = static_cast<int32_t>(msg.size());\n\n\t\tsend_package_header.rewind();\n\t\tsend_package_header.write_integral(msglen);\n\t\tsend_package_header.write_integral(seqn);\n\n\t\tRD_ASSERT_THROW_MSG(\n\t\t\tsocket_provider->Send(send_package_header.data(), send_package_header.get_position()) == PACKAGE_HEADER_LENGTH,\n\t\t\tthis->id +\n\t\t\t\t\": failed to send header over the network\"\n\t\t\t\t\", reason: \" +\n\t\t\t\tsocket_provider->DescribeError())\n\n\t\tRD_ASSERT_THROW_MSG(socket_provider->Send(msg.data(), msglen) == msglen, this->id +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \": failed to send package over the network\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \", reason: \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t socket_provider->DescribeError());\n\t\tlogger->info(\"{}: were sent {} bytes\", this->id, msglen);\n\t\t//        RD_ASSERT_MSG(socketProvider->Flush(), \"{}: failed to flush\");\n\t\treturn true;\n\t}\n\tcatch (std::exception const& e)\n\t{\n\t\t//\t\t\tasync_send_buffer.pause(\"send0\");\n\t\tlogger->warn(\"Send0 failed due to: | {}\", e.what());\n\t\treturn false;\n\t}\n}\n\nvoid SocketWire::Base::send(RdId const& rd_id, std::function<void(Buffer& buffer)> writer) const\n{\n\tRD_ASSERT_MSG(!rd_id.isNull(), \"{}: id mustn't be null\");\n\n\tBuffer local_send_buffer;\n\tlocal_send_buffer.write_integral<int32_t>(0);\t // placeholder for length\n\trd_id.write(local_send_buffer);\t\t\t\t\t // write id\n\tlocal_send_buffer.write_integral<int16_t>(0);\t // placeholder for context\n\twriter(local_send_buffer);\t\t\t\t\t\t // write rest\n\n\tint32_t len = static_cast<int32_t>(local_send_buffer.get_position());\n\n\tlocal_send_buffer.rewind();\n\tlocal_send_buffer.write_integral<int32_t>(len - 4);\n\tlocal_send_buffer.set_position(len);\n\tasync_send_buffer.put(std::move(local_send_buffer).getRealArray());\n}\n\nvoid SocketWire::Base::set_socket_provider(std::shared_ptr<CActiveSocket> new_socket)\n{\n\t{\n\t\tstd::lock_guard<decltype(socket_send_lock)> guard(socket_send_lock);\n\t\tsocket_provider = std::move(new_socket);\n\t\tsocket_send_var.notify_all();\n\t}\n\t{\n\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\tif (lifetimeDef.lifetime->is_terminated())\n\t\t{\n\t\t\treturn;\n\t\t}\n\t}\n\n\tauto heartbeat = LifetimeDefinition::use([this](Lifetime heartbeatLifetime) {\n\t\tconst auto heartbeat = start_heartbeat(heartbeatLifetime).share();\n\n\t\tasync_send_buffer.resume();\n\n\t\tconnected.set(true);\n\n\t\treceiverProc();\n\n\t\tconnected.set(false);\n\n\t\tasync_send_buffer.pause(\"Disconnected\");\n\n\t\treturn heartbeat;\n\t});\n\tconst auto status = heartbeat.wait_for(timeout);\n\n\tlogger->debug(\"{}: waited for heartbeat to stop with status: {}\", this->id, static_cast<uint32_t>(status));\n\n\tif (!socket_provider->IsSocketValid())\n\t{\n\t\tlogger->debug(\"{}: socket was already shut down\", this->id);\n\t}\n\telse if (!socket_provider->Shutdown(CSimpleSocket::Both))\n\t{\n\t\t// double close?\n\t\tlogger->warn(\"{}: possibly double close after disconnect\", this->id);\n\t}\n}\n\nbool SocketWire::Base::connection_established(int32_t timestamp, int32_t notion_timestamp)\n{\n\treturn timestamp - notion_timestamp <= MaximumHeartbeatDelay;\n}\n\nstd::future<void> SocketWire::Base::start_heartbeat(Lifetime lifetime)\n{\n\treturn std::async([this, lifetime] {\n\t\twhile (!lifetime->is_terminated())\n\t\t{\n\t\t\tstd::this_thread::sleep_for(heartBeatInterval);\n\t\t\tping();\n\t\t}\n\t});\n}\n\nbool SocketWire::Base::read_from_socket(Buffer::word_t* res, int32_t msglen) const\n{\n\tint32_t ptr = 0;\n\twhile (ptr < msglen)\n\t{\n\t\tRD_ASSERT_MSG(hi >= lo, \"hi >= lo\")\n\n\t\tint32_t rest = msglen - ptr;\n\t\tint32_t available = static_cast<int32_t>(hi - lo);\n\n\t\tif (available > 0)\n\t\t{\n\t\t\tint32_t copylen = (std::min)(rest, available);\n\t\t\tstd::copy(lo, lo + copylen, res + ptr);\n\t\t\tlo += copylen;\n\t\t\tptr += copylen;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (hi == receiver_buffer.end())\n\t\t\t{\n\t\t\t\thi = lo = receiver_buffer.begin();\n\t\t\t}\n\t\t\tlogger->info(\"{}: receive started\", this->id);\n\t\t\tint32_t read = socket_provider->Receive(static_cast<int32_t>(receiver_buffer.end() - hi), &*hi);\n\t\t\tif (read == -1)\n\t\t\t{\n\t\t\t\tauto err = socket_provider->GetSocketError();\n\t\t\t\tif (err == CSimpleSocket::SocketInvalidSocket)\n\t\t\t\t{\n\t\t\t\t\tlogger->info(\"{}: socket was shut down for receiving\", this->id);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tlogger->error(\"{}: error has occurred while receiving\", this->id);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (read == 0)\n\t\t\t{\n\t\t\t\tlogger->info(\"{}: socket was shut down for receiving\", this->id);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\thi += read;\n\t\t\tif (read > 0)\n\t\t\t{\n\t\t\t\tlogger->info(\"{}: receive finished: {} bytes read\", this->id, read);\n\t\t\t}\n\t\t}\n\t}\n\tif (ptr != msglen)\n\t{\n\t\tlogger->error(\"read invalid number of bytes from socket, expected: {}, actual: {}\", msglen, ptr);\n\t\tassert(false);\n\t}\n\treturn true;\n}\n\nstatic constexpr std::pair<int, sequence_number_t> INVALID_HEADER = std::make_pair(-1, -1);\n\nstd::pair<int, sequence_number_t> SocketWire::Base::read_header() const\n{\n\tint32_t len = 0;\n\tsequence_number_t seqn = 0;\n\twhile (true)\n\t{\n\t\tif (!read_integral_from_socket(len))\n\t\t{\n\t\t\treturn INVALID_HEADER;\n\t\t}\n\t\tif (len == PING_MESSAGE_LENGTH)\n\t\t{\n\t\t\tint32_t received_timestamp = 0;\n\t\t\tint32_t received_counterpart_timestamp = 0;\n\t\t\tif (!read_integral_from_socket(received_timestamp))\n\t\t\t{\n\t\t\t\treturn INVALID_HEADER;\n\t\t\t}\n\t\t\tif (!read_integral_from_socket(received_counterpart_timestamp))\n\t\t\t{\n\t\t\t\treturn INVALID_HEADER;\n\t\t\t}\n\n\t\t\tcounterpart_timestamp = received_timestamp;\n\t\t\tcounterpart_acknowledge_timestamp = received_counterpart_timestamp;\n\n\t\t\tif ((connection_established(current_timestamp, counterpart_acknowledge_timestamp)))\n\t\t\t{\n\t\t\t\tif (!heartbeatAlive.get())\n\t\t\t\t{\t // only on change\n\t\t\t\t\tlogger->trace(\n\t\t\t\t\t\t\"Connection is alive after receiving PING {}: \"\n\t\t\t\t\t\t\"received_timestamp: {}, \"\n\t\t\t\t\t\t\"received_counterpart_timestamp: {}, \"\n\t\t\t\t\t\t\"current_timestamp: {}, \"\n\t\t\t\t\t\t\"counterpart_timestamp: {}, \"\n\t\t\t\t\t\t\"counterpart_acknowledge_timestamp: {}, \",\n\t\t\t\t\t\tid, received_timestamp, received_counterpart_timestamp, current_timestamp, counterpart_timestamp,\n\t\t\t\t\t\tcounterpart_acknowledge_timestamp);\n\t\t\t\t}\n\t\t\t\theartbeatAlive.set(true);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (!read_integral_from_socket(seqn))\n\t\t{\n\t\t\treturn INVALID_HEADER;\n\t\t}\n\n\t\tif (len == ACK_MESSAGE_LENGTH)\n\t\t{\n\t\t\tasync_send_buffer.acknowledge(seqn);\n\t\t\tcontinue;\n\t\t}\n\t\treturn std::make_pair(len, seqn);\n\t}\n}\n\nint32_t SocketWire::Base::read_package() const\n{\n\treceive_pkg.rewind();\n\n\tconst auto pair = read_header();\n\tif (pair == INVALID_HEADER)\n\t{\n\t\tlogger->debug(\"{}: failed to read header\", this->id);\n\t\treturn -1;\n\t}\n\tconst auto len = pair.first;\n\tconst auto seqn = pair.second;\n\n\tlogger->debug(\"{}: read len={}, seqn={}, max_received_seqn={}\", this->id, len, seqn, max_received_seqn);\n\n\treceive_pkg.require_available(len);\n\tif (!read_data_from_socket(receive_pkg.data(), len))\n\t{\n\t\tlogger->debug(\"{}: failed to read package\", this->id);\n\t\treturn -1;\n\t}\n\tsend_ack(seqn);\n\tif (seqn <= max_received_seqn && seqn != 1)\n\t{\n\t\treturn true;\n\t}\n\tmax_received_seqn = seqn;\n\n\tlogger->info(\"{}: was received package, bytes={}, seqn={}\", this->id, len, seqn);\n\treturn len;\n}\n\nbool SocketWire::Base::read_and_dispatch_message() const\n{\n\tsz = (sz == -1 ? receive_pkg.read_integral<int32_t>() : sz);\n\tif (sz == -1)\n\t{\n\t\tlogger->debug(\"{}: sz == -1\", this->id);\n\t\treturn false;\n\t}\n\tid_ = (id_ == -1 ? receive_pkg.read_integral<RdId::hash_t>() : id_);\n\tif (id_ == -1)\n\t{\n\t\tlogger->error(\"id == -1\");\n\t\treturn false;\n\t}\n\tlogger->trace(\"{}: message info: sz={}, id={}\", this->id, sz, id_);\n\tconst RdId rd_id{id_};\n\tsz -= 8;\t// RdId\n\tmessage.require_available(sz);\n\n\tif (!receive_pkg.read(message.data() + message.get_position(), sz - message.get_position()))\n\t{\n\t\tlogger->error(\"{}: constructing message failed\", this->id);\n\t\treturn false;\n\t}\n\n\tlogger->debug(\"{}: message received\", this->id);\n\tmessage_broker.dispatch(rd_id, std::move(message));\n\tlogger->debug(\"{}: message dispatched\", this->id);\n\n\tsz = -1;\n\tid_ = -1;\n\tmessage.rewind();\n\treturn true;\n\t//\t\tRD_ASSERT_MSG(summary_size == sz, \"Broken message, read:%d bytes, expected:%d bytes\", summary_size, sz)\n}\n\nCSimpleSocket* SocketWire::Base::get_socket_provider() const\n{\n\treturn socket_provider.get();\n}\n\nvoid SocketWire::Base::ping() const\n{\n\tif (!connection_established(current_timestamp, counterpart_acknowledge_timestamp))\n\t{\n\t\tif (heartbeatAlive.get())\n\t\t{\t // only on change\n\t\t\tlogger->trace(\n\t\t\t\t\"Disconnect detected while sending PING {}: \"\n\t\t\t\t\"current_timestamp: {}, \"\n\t\t\t\t\"counterpart_timestamp: {}, \"\n\t\t\t\t\"counterpart_acknowledge_timestamp: {}\",\n\t\t\t\tthis->id, current_timestamp, counterpart_timestamp, counterpart_acknowledge_timestamp);\n\t\t}\n\t\theartbeatAlive.set(false);\n\t}\n\ttry\n\t{\n\t\tping_pkg_header.set_position(sizeof(PING_MESSAGE_LENGTH));\n\t\tping_pkg_header.write_integral(current_timestamp);\n\t\tping_pkg_header.write_integral(counterpart_timestamp);\n\t\t{\n\t\t\tstd::lock_guard<decltype(socket_send_lock)> guard(socket_send_lock);\n\t\t\tint32_t sent = socket_provider->Send(ping_pkg_header.data(), ping_pkg_header.get_position());\n\t\t\tif (sent == 0 && !socket_provider->IsSocketValid())\n\t\t\t{\n\t\t\t\tlogger->debug(\"{}: failed to send ping over the network, reason: socket was shut down for sending\", this->id);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tRD_ASSERT_THROW_MSG(sent == PACKAGE_HEADER_LENGTH,\n\t\t\t\tfmt::format(\"{}: failed to send ping over the network, reason: {}\", this->id, socket_provider->DescribeError()))\n\t\t}\n\n\t\t++current_timestamp;\n\t}\n\tcatch (std::exception const& e)\n\t{\n\t\tlogger->debug(\"{}: exception raised during PING | {}\", this->id, e.what());\n\t}\n}\n\nbool SocketWire::Base::send_ack(sequence_number_t seqn) const\n{\n\tlogger->trace(\"{} send ack {}\", id, seqn);\n\ttry\n\t{\n\t\tack_buffer.rewind();\n\t\tack_buffer.write_integral(ACK_MESSAGE_LENGTH);\n\t\tack_buffer.write_integral(seqn);\n\t\t{\n\t\t\tstd::lock_guard<decltype(socket_send_lock)> guard(socket_send_lock);\n\t\t\tRD_ASSERT_THROW_MSG(socket_provider->Send(ack_buffer.data(), ack_buffer.get_position()) == PACKAGE_HEADER_LENGTH,\n\t\t\t\tthis->id +\n\t\t\t\t\t\": failed to send ack over the network\"\n\t\t\t\t\t\", reason: \" +\n\t\t\t\t\tsocket_provider->DescribeError())\n\t\t}\n\t\treturn true;\n\t}\n\tcatch (std::exception const& e)\n\t{\n\t\tlogger->warn(\"{}: exception raised during ACK, seqn = {} | {}\", id, seqn, e.what());\n\t\treturn false;\n\t}\n}\n\nbool SocketWire::Base::try_shutdown_connection() const\n{\n\tauto s = get_socket_provider();\n\tif (s == nullptr)\n\t\treturn false;\n\n\treturn s->Shutdown(CSimpleSocket::Both);\n}\n\nSocketWire::Client::Client(Lifetime parentLifetime, IScheduler* scheduler, uint16_t port, const std::string& id)\n\t: Base(id, parentLifetime, scheduler), port(port), clientLifetimeDefinition(parentLifetime)\n{\n\tLifetime lifetime = clientLifetimeDefinition.lifetime;\n\tthread = std::thread([this, lifetime]() mutable {\n\t\trd::util::set_thread_name(this->id.empty() ? \"SocketWire::Client Thread\" : this->id.c_str());\n\n\t\ttry\n\t\t{\n\t\t\tlogger->info(\"{}: started, port: {}.\", this->id, this->port);\n\n\t\t\twhile (!lifetime->is_terminated())\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tsocket = std::make_shared<CActiveSocket>();\n\t\t\t\t\tRD_ASSERT_THROW_MSG(socket->Initialize(),\n\t\t\t\t\t\tfmt::format(\"{}: failed to init ActiveSocket, reason: {}\", this->id, socket->DescribeError()));\n\t\t\t\t\tRD_ASSERT_THROW_MSG(socket->DisableNagleAlgoritm(),\n\t\t\t\t\t\tfmt::format(\"{}: failed to DisableNagleAlgoritm, reason: {}\", this->id, socket->DescribeError()));\n\n\t\t\t\t\t// On windows connect will try to send SYN 3 times with interval of 500ms (total time is 1second)\n\t\t\t\t\t// Connect timeout doesn't work if it's more than 1 second. But we don't need it because we can close socket any\n\t\t\t\t\t// moment.\n\n\t\t\t\t\t// https://stackoverflow.com/questions/22417228/prevent-tcp-socket-connection-retries\n\t\t\t\t\t// HKLM\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\TcpMaxConnectRetransmissions\n\t\t\t\t\tlogger->info(\"{}: connecting 127.0.0.1: {}\", this->id, this->port);\n\t\t\t\t\tRD_ASSERT_THROW_MSG(socket->Open(\"127.0.0.1\", this->port),\n\t\t\t\t\t\tfmt::format(\"{}: failed to open ActiveSocket, reason: {}\", this->id, socket->DescribeError()));\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\t\t\t\t\tif (lifetime->is_terminated())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!socket->Close())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlogger->error(\"{} failed to close socket, reason: {}\", this->id, socket->DescribeError());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tset_socket_provider(socket);\n\t\t\t\t}\n\t\t\t\tcatch (std::exception const& e)\n\t\t\t\t{\n\t\t\t\t\tlogger->debug(\"{}: connection error for port {} ({}).\", this->id, this->port, e.what());\n\n\t\t\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\t\t\t\tbool should_reconnect = false;\n\t\t\t\t\tif (!lifetime->is_terminated())\n\t\t\t\t\t{\n\t\t\t\t\t\tcv.wait_for(lock, timeout);\n\t\t\t\t\t\tshould_reconnect = !lifetime->is_terminated();\n\t\t\t\t\t}\n\t\t\t\t\tif (should_reconnect)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (std::exception const& e)\n\t\t{\n\t\t\tlogger->info(\"{}: closed with exception: {}\", this->id, e.what());\n\t\t}\n\t\tlogger->info(\"{}: terminated, port: {}.\", this->id, this->port);\n\t});\n\n\tlifetime->add_action([this]() {\n\t\tlogger->info(\"{}: starts terminating lifetime\", this->id);\n\n\t\tconst bool send_buffer_stopped = async_send_buffer.stop(timeout);\n\t\tlogger->debug(\"{}: send buffer stopped, success: {}\", this->id, send_buffer_stopped);\n\n\t\t{\n\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\t\tlogger->debug(\"{}: closing socket\", this->id);\n\n\t\t\tif (socket != nullptr)\n\t\t\t{\n\t\t\t\tif (!socket->Close())\n\t\t\t\t{\n\t\t\t\t\tlogger->error(\"{}: failed to close socket\", this->id);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcv.notify_all();\n\n\t\tlogger->debug(\"{}: waiting for receiver thread\", this->id);\n\t\tlogger->debug(\"{}: is thread joinable? {}\", this->id, thread.joinable());\n\t\tthread.join();\n\t\tlogger->info(\"{}: termination finished\", this->id);\n\t});\n}\n\nSocketWire::Client::~Client()\n{\n\tif (!clientLifetimeDefinition.is_terminated())\n\t{\n\t\tclientLifetimeDefinition.terminate();\n\t}\n}\n\nSocketWire::Server::Server(Lifetime parentLifetime, IScheduler* scheduler, uint16_t port, const std::string& id)\n\t: Base(id, parentLifetime, scheduler), ss(std::make_unique<CPassiveSocket>()), serverLifetimeDefinition(parentLifetime)\n{\n#ifdef SIGPIPE\n\tsignal(SIGPIPE, SIG_IGN);\n#endif\n\tRD_ASSERT_MSG(ss->Initialize(), fmt::format(\"{}: failed to initialize socket, reason: {}\", this->id, socket->DescribeError()));\n\tRD_ASSERT_MSG(ss->Listen(\"127.0.0.1\", port),\n\t\tfmt::format(\"{}: failed to listen socket on port: {}, reason: {}\", this->id, std::to_string(port), ss->DescribeError()));\n\n\tthis->port = ss->GetServerPort();\n\tRD_ASSERT_MSG(this->port != 0, fmt::format(\"{}: port wasn't chosen\", this->id));\n\n\tlogger->info(\"{}: listening 127.0.0.1/{}\", this->id, this->port);\n\tLifetime lifetime = serverLifetimeDefinition.lifetime;\n\n\tthread = std::thread([this, lifetime]() mutable {\n\t\trd::util::set_thread_name(this->id.empty() ? \"SocketWire::Server Thread\" : this->id.c_str());\n\n\t\tlogger->info(\"{}: started, port: {}.\", this->id, this->port);\n\n\t\ttry\n\t\t{\n\t\t\twhile (!lifetime->is_terminated())\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tlogger->info(\"{}: accepting started\", this->id);\n\n\t\t\t\t\t// [HACK]: Fix RIDER-51111.\n\t\t\t\t\t// winsock blocking accept hangs after creating new process with createprocess with inheritHandles=true\n\t\t\t\t\t// property. Unreal Engine uses the same logic for handling sockets where they wait for timeout on select\n\t\t\t\t\t// before trying to accept connection.\n\t\t\t\t\twhile(ss->IsSocketValid() && !ss->Select(0, 300)){}\n\n\t\t\t\t\tCActiveSocket* accepted = ss->Accept();\n\t\t\t\t\tRD_ASSERT_THROW_MSG(\n\t\t\t\t\t\taccepted != nullptr, fmt::format(\"{}: accepting failed, reason: {}\", this->id, ss->DescribeError()));\n\t\t\t\t\tsocket.reset(accepted);\n\t\t\t\t\tlogger->info(\"{}: accepted passive socket {}/{}\", this->id, socket->GetClientAddr(), socket->GetClientPort());\n\t\t\t\t\tRD_ASSERT_THROW_MSG(socket->DisableNagleAlgoritm(),\n\t\t\t\t\t\tfmt::format(\"{}: tcpNoDelay failed, reason: {}\", this->id, socket->DescribeError()));\n\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\t\t\t\t\tif (lifetime->is_terminated())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlogger->debug(\"{}: closing passive socket\", this->id);\n\t\t\t\t\t\t\tif (!socket->Close())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlogger->error(\"{}: failed to close socket\", this->id);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlogger->info(\"{}: close passive socket\", this->id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger->debug(\"{}: setting socket provider\", this->id);\n\t\t\t\t\tset_socket_provider(socket);\n\t\t\t\t}\n\t\t\t\tcatch (std::exception const& e)\n\t\t\t\t{\n\t\t\t\t\tlogger->info(\"{}: closed with exception: {}\", this->id, e.what());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (std::exception const& e)\n\t\t{\n\t\t\tlogger->error(\"{}: terminal socket error ({}).\", this->id, e.what());\n\t\t}\n\n\t\tlogger->info(\"{}: terminated, port: {}.\", this->id, this->port);\n\t});\n\n\tlifetime->add_action([this] {\n\t\tlogger->info(\"{}: start terminating lifetime\", this->id);\n\n\t\tconst bool send_buffer_stopped = async_send_buffer.stop(timeout);\n\t\tlogger->debug(\"{}: send buffer stopped, success: {}\", this->id, send_buffer_stopped);\n\n\t\tlogger->debug(\"{}: closing server socket\", this->id);\n\t\tif (!ss->Close())\n\t\t{\n\t\t\tlogger->error(\"{}: failed to close server socket\", this->id);\n\t\t}\n\n\t\t{\n\t\t\tstd::lock_guard<decltype(lock)> guard(lock);\n\t\t\tlogger->debug(\"{}: closing socket\", this->id);\n\t\t\tif (socket != nullptr)\n\t\t\t{\n\t\t\t\tif (!socket->Close())\n\t\t\t\t{\n\t\t\t\t\tlogger->error(\"{}: failed to close socket\", this->id);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlogger->debug(\"{}: waiting for receiver thread\", this->id);\n\t\tlogger->debug(\"{}: is thread joinable? {}\", this->id, thread.joinable());\n\t\tthread.join();\n\t\tlogger->info(\"{}: termination finished\", this->id);\n\t});\n}\n\nSocketWire::Server::~Server()\n{\n\tif (!serverLifetimeDefinition.is_terminated())\n\t{\n\t\tserverLifetimeDefinition.terminate();\n\t}\n}\n\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/SocketWire.h",
    "content": "#ifndef RD_CPP_SOCKETWIRE_H\n#define RD_CPP_SOCKETWIRE_H\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include \"scheduler/base/IScheduler.h\"\n#include \"base/WireBase.h\"\n#include \"ByteBufferAsyncProcessor.h\"\n#include \"PkgInputStream.h\"\n\n#include <string>\n#include <array>\n#include <condition_variable>\n\n#include <rd_framework_export.h>\n\nclass CSimpleSocket;\nclass CActiveSocket;\nclass CPassiveSocket;\n\nnamespace rd\n{\nclass RD_FRAMEWORK_API SocketWire\n{\n\tstatic std::chrono::milliseconds timeout;\n\npublic:\n\tclass RD_FRAMEWORK_API Base : public WireBase\n\t{\n\tprotected:\n\t\tstatic std::shared_ptr<spdlog::logger> logger;\n\n\t\tstd::timed_mutex lock;\n\t\tmutable std::mutex socket_send_lock;\n\t\tmutable std::mutex wire_send_lock;\n\n\t\tstd::thread thread{};\n\n\t\tstd::string id;\n\t\tIScheduler* scheduler = nullptr;\n\t\tstd::shared_ptr<CSimpleSocket> socket_provider;\n\n\t\tstd::shared_ptr<CActiveSocket> socket;\n\n\t\tmutable std::condition_variable socket_send_var;\n\t\tmutable ByteBufferAsyncProcessor async_send_buffer{id + \"-AsyncSendProcessor\",\n\t\t\t[this](Buffer::ByteArray const& it, sequence_number_t seqn) -> bool { return this->send0(it, seqn); }};\n\n\t\tstatic constexpr size_t RECEIVE_BUFFER_SIZE = 1u << 16;\n\t\tmutable std::array<Buffer::word_t, RECEIVE_BUFFER_SIZE> receiver_buffer{};\n\t\tmutable decltype(receiver_buffer)::iterator lo = receiver_buffer.begin(), hi = receiver_buffer.begin();\n\n\t\tstatic constexpr int32_t ACK_MESSAGE_LENGTH = -1;\n\t\tstatic constexpr int32_t PING_MESSAGE_LENGTH = -2;\n\t\tstatic constexpr int32_t PACKAGE_HEADER_LENGTH = sizeof(ACK_MESSAGE_LENGTH) + sizeof(sequence_number_t);\n\t\tmutable Buffer ack_buffer{PACKAGE_HEADER_LENGTH};\n\n\t\t/**\n\t\t * \\brief Timestamp of this wire which increases at intervals of [heartBeatInterval].\n\t\t */\n\t\tmutable int32_t current_timestamp = 0;\n\n\t\t/**\n\t\t * \\brief Actual knowledge about counterpart's [currentTimeStamp].\n\t\t */\n\t\tmutable int32_t counterpart_timestamp = 0;\n\n\t\t/**\n\t\t * \\brief The latest received counterpart's acknowledge of this wire's [currentTimeStamp].\n\t\t */\n\t\tmutable int32_t counterpart_acknowledge_timestamp = 0;\n\n\t\tmutable Buffer ping_pkg_header{PACKAGE_HEADER_LENGTH};\n\n\t\tmutable sequence_number_t max_received_seqn = 0;\n\t\tmutable Buffer send_package_header{PACKAGE_HEADER_LENGTH};\n\n\t\tstatic constexpr int32_t CHUNK_SIZE = 16370;\n\t\tmutable int32_t sz = -1;\n\t\tmutable RdId::hash_t id_ = -1;\n\t\tmutable PkgInputStream receive_pkg{[this]() -> int32_t { return this->read_package(); }};\n\n\t\tmutable Buffer message{CHUNK_SIZE};\n\n\t\tbool read_from_socket(Buffer::word_t* res, int32_t msglen) const;\n\n\t\ttemplate <typename T>\n\t\tbool read_integral_from_socket(T& x) const\n\t\t{\n\t\t\treturn read_from_socket(reinterpret_cast<Buffer::word_t*>(&x), sizeof(T));\n\t\t}\n\n\t\tbool read_data_from_socket(Buffer::word_t* data, size_t len) const\n\t\t{\n\t\t\treturn read_from_socket(reinterpret_cast<Buffer::word_t*>(data), static_cast<int32_t>(len));\n\t\t}\n\n\t\tvoid set_socket_provider(std::shared_ptr<CActiveSocket> new_socket);\n\n\t\tCSimpleSocket* get_socket_provider() const;\n\n\tpublic:\n\t\tstatic constexpr int32_t MaximumHeartbeatDelay = 3;\n\t\tstd::chrono::milliseconds heartBeatInterval = std::chrono::milliseconds(500);\n\n\t\t// region ctor/dtor\n\n\t\tBase(std::string id, Lifetime lifetime, IScheduler* scheduler);\n\n\t\tvirtual ~Base() override;\n\n\t\t// endregion\n\n\t\tstd::pair<int, sequence_number_t> read_header() const;\n\n\t\tint32_t read_package() const;\n\n\t\tbool read_and_dispatch_message() const;\n\n\t\tvoid receiverProc() const;\n\n\t\tbool send0(Buffer::ByteArray const& msg, sequence_number_t seqn) const;\n\n\t\tvoid send(RdId const& rd_id, std::function<void(Buffer& buffer)> writer) const override;\n\n\t\tstatic bool connection_established(int32_t timestamp, int32_t acknowledged_timestamp);\n\n\t\tstd::future<void> start_heartbeat(Lifetime lifetime);\n\n\t\tvoid ping() const;\n\n\t\tbool send_ack(sequence_number_t seqn) const;\n\n\t\tbool try_shutdown_connection() const;\n\t\t\n\tprivate:\t\t\n\t\tLifetimeDefinition lifetimeDef;\n\t};\n\n\tclass RD_FRAMEWORK_API Client : public Base\n\t{\n\tpublic:\n\t\tuint16_t port = 0;\n\n\t\t// region ctor/dtor\n\n\t\tClient(Lifetime parentLifetime, IScheduler* scheduler, uint16_t port = 0, const std::string& id = \"ClientSocket\");\n\n\t\tvirtual ~Client() override;\n\t\t// endregion\n\n\t\tstd::condition_variable_any cv;\n\tprivate:\t\t\n\t\tLifetimeDefinition clientLifetimeDefinition;\n\t};\n\n\tclass RD_FRAMEWORK_API Server : public Base\n\t{\n\tpublic:\n\t\tuint16_t port = 0;\n\n\t\tstd::unique_ptr<CPassiveSocket> ss;\n\n\t\t// region ctor/dtor\n\n\t\tServer(Lifetime lifetime, IScheduler* scheduler, uint16_t port = 0, const std::string& id = \"ServerSocket\");\n\n\t\tvirtual ~Server() override;\n\t\t// endregion\n\tprivate:\n\t\tLifetimeDefinition serverLifetimeDefinition;\n\t};\n};\n}\t // namespace rd\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n\n#endif\t  // RD_CPP_SOCKETWIRE_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/WireUtil.cpp",
    "content": "#include \"wire/WireUtil.h\"\n\n#include \"util/core_util.h\"\n\n#include \"PassiveSocket.h\"\n#include \"Host.h\"\n\n#include <utility>\n#include <thread>\n\nnamespace rd\n{\nnamespace util\n{\nuint16_t find_free_port()\n{\n\tCPassiveSocket fake_server;\n\tfake_server.Initialize();\n\tfake_server.Listen(\"127.0.0.1\", 0);\n\tuint16_t port = fake_server.GetServerPort();\n\tRD_ASSERT_MSG(port != 0, \"no free port\");\n\treturn port;\n}\n\nvoid sleep_this_thread(int64_t ms)\n{\n\tstd::this_thread::sleep_for(std::chrono::milliseconds(ms));\n}\n}\t // namespace util\n}\t // namespace rd\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_framework_cpp/src/main/wire/WireUtil.h",
    "content": "#ifndef RD_CPP_WIREUTIL_H\n#define RD_CPP_WIREUTIL_H\n\n#include <cstdint>\n\n#include <rd_framework_export.h>\n\nnamespace rd\n{\nnamespace util\n{\nuint16_t RD_FRAMEWORK_API find_free_port();\n\nvoid RD_FRAMEWORK_API sleep_this_thread(int64_t ms);\n}\t // namespace util\n}\t // namespace rd\n\n#endif\t  // RD_CPP_WIREUTIL_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_gen_cpp/src/RdTextBuffer.cpp",
    "content": "#include \"RdTextBuffer.h\"\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/src/rd_gen_cpp/src/RdTextBuffer.h",
    "content": "#ifndef RD_CPP_RDTEXTBUFFER_H\n#define RD_CPP_RDTEXTBUFFER_H\n\nnamespace rd\n{\nclass RdTextBuffer\n{\n};\n}\t // namespace rd\n\n#endif\t  // RD_CPP_RDTEXTBUFFER_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/CTPL/LICENSE",
    "content": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n\n   Copyright (C) 2014 by Vitaliy Vitsentiy\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/CTPL/README.md",
    "content": "CTPL\n====\n\nModern and efficient C++ Thread Pool Library\n\n\nA thread pool is a programming pattern for parallel execution of jobs, http://en.wikipedia.org/wiki/Thread_pool_pattern.\n\nMore specifically, there are some threads dedicated to the pool and a container of jobs. The jobs come to the pool dynamically. A job is fetched and deleted from the container when there is an idle thread. The job is then run on that thread.\n\nA thread pool is helpful when you want to minimize time of loading and destroying threads and when you want to limit the number of parallel jobs that run simultanuasly. For example, time consuming event handlers may be processed in a thread pool to make UI more responsive.\n\nFeatures:\n- standard c++ language, tested to compile on MS Visual Studio 2013 (2012?), gcc 4.8.2 and mingw 4.8.1(with posix threads)\n- simple but effiecient solution, one header only, no need to compile a binary library\n- query the number of idle threads and resize the pool dynamically\n- one API to push to the thread pool any collable object: lambdas, functors, functions, result of bind expression\n- collable objects with variadic number of parameters plus index of the thread running the object\n- automatic template argument deduction\n- get returned value of any type with standard c++ futures\n- get fired exceptions with standard c++ futures\n- use for any purpose under Apache license\n- two variants, one depends on Boost Lockfree Queue library, http://boost.org, which is a header only library\n\n\nSample usage\n\n<code>void first(int id) {\n    std::cout << \"hello from \" << id << '\\n';\n}</code>\n\n<code>&#32;&#32;struct Second {\n    void operator()(int id) const {\n        std::cout << \"hello from \" << id << '\\n';\n    }\n} second;\n\n<code>void third(int id, const std::string & additional_param) {}</code>\n\n\n<code>int main () {</code>\n\n<code>&#32;&#32;&#32;&#32;ctpl::thread_pool p(2 /* two threads in the pool */);</code>\n\n<code>&#32;&#32;&#32;&#32;p.push(first);  // function</code>\n\n<code>&#32;&#32;&#32;&#32;p.push(third, \"additional_param\");</code>\n\n<code>&#32;&#32;&#32;&#32;p.push( &#91;&#93; (int id){\n  std::cout << \"hello from \" << id << '\\n';\n});  // lambda</code>\n\n<code>&#32;&#32;&#32;&#32;p.push(std::ref(second));  // functor, reference</code>\n\n<code>&#32;&#32;&#32;&#32;p.push(const_cast&#60;const Second &&#62;(second));  // functor, copy ctor</code>\n\n<code>&#32;&#32;&#32;&#32;p.push(std::move(second));  // functor, move ctor</code>\n\n<code>}</code>\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/CTPL/include/ctpl_stl.h",
    "content": "/*********************************************************\n*\n*  Copyright (C) 2014 by Vitaliy Vitsentiy\n*\n*  Licensed under the Apache License, Version 2.0 (the \"License\");\n*  you may not use this file except in compliance with the License.\n*  You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n*  Unless required by applicable law or agreed to in writing, software\n*  distributed under the License is distributed on an \"AS IS\" BASIS,\n*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n*  See the License for the specific language governing permissions and\n*  limitations under the License.\n*\n*********************************************************/\n\n\n#ifndef __ctpl_stl_thread_pool_H__\n#define __ctpl_stl_thread_pool_H__\n\n#include <functional>\n#include <thread>\n#include <atomic>\n#include <vector>\n#include <memory>\n#include <exception>\n#include <future>\n#include <mutex>\n#include <queue>\n\n\n\n// thread pool to run user's functors with signature\n//      ret func(int id, other_params)\n// where id is the index of the thread that runs the functor\n// ret is some return type\n\n\nnamespace ctpl {\n\n    namespace detail {\n        template <typename T>\n        class Queue {\n        public:\n            bool push(T const & value) {\n                std::unique_lock<std::mutex> lock(this->mutex);\n                this->q.push(value);\n                return true;\n            }\n            // deletes the retrieved element, do not use for non integral types\n            bool pop(T & v) {\n                std::unique_lock<std::mutex> lock(this->mutex);\n                if (this->q.empty())\n                    return false;\n                v = this->q.front();\n                this->q.pop();\n                return true;\n            }\n            bool empty() {\n                std::unique_lock<std::mutex> lock(this->mutex);\n                return this->q.empty();\n            }\n        private:\n            std::queue<T> q;\n            std::mutex mutex;\n        };\n    }\n\n    class thread_pool {\n\n    public:\n\n        thread_pool() { this->init(); }\n        thread_pool(int nThreads) { this->init(); this->resize(nThreads); }\n\n        // the destructor waits for all the functions in the queue to be finished\n        ~thread_pool() {\n            this->stop(true);\n        }\n\n        // get the number of running threads in the pool\n        int size() { return static_cast<int>(this->threads.size()); }\n\n        // number of idle threads\n        int n_idle() { return this->nWaiting; }\n        std::thread & get_thread(int i) { return *this->threads[i]; }\n\n        // change the number of threads in the pool\n        // should be called from one thread, otherwise be careful to not interleave, also with this->stop()\n        // nThreads must be >= 0\n        void resize(int nThreads) {\n            if (!this->isStop && !this->isDone) {\n                int oldNThreads = static_cast<int>(this->threads.size());\n                if (oldNThreads <= nThreads) {  // if the number of threads is increased\n                    this->threads.resize(nThreads);\n                    this->flags.resize(nThreads);\n\n                    for (int i = oldNThreads; i < nThreads; ++i) {\n                        this->flags[i] = std::make_shared<std::atomic<bool>>(false);\n                        this->set_thread(i);\n                    }\n                }\n                else {  // the number of threads is decreased\n                    for (int i = oldNThreads - 1; i >= nThreads; --i) {\n                        *this->flags[i] = true;  // this thread will finish\n                        this->threads[i]->detach();\n                    }\n                    {\n                        // stop the detached threads that were waiting\n                        std::unique_lock<std::mutex> lock(this->mutex);\n                        this->cv.notify_all();\n                    }\n                    this->threads.resize(nThreads);  // safe to delete because the threads are detached\n                    this->flags.resize(nThreads);  // safe to delete because the threads have copies of shared_ptr of the flags, not originals\n                }\n            }\n        }\n\n        // empty the queue\n        void clear_queue() {\n            std::function<void(int id)> * _f;\n            while (this->q.pop(_f))\n                delete _f; // empty the queue\n        }\n\n        // pops a functional wrapper to the original function\n        std::function<void(int)> pop() {\n            std::function<void(int id)> * _f = nullptr;\n            this->q.pop(_f);\n            std::unique_ptr<std::function<void(int id)>> func(_f); // at return, delete the function even if an exception occurred\n            std::function<void(int)> f;\n            if (_f)\n                f = *_f;\n            return f;\n        }\n\n        // wait for all computing threads to finish and stop all threads\n        // may be called asynchronously to not pause the calling thread while waiting\n        // if isWait == true, all the functions in the queue are run, otherwise the queue is cleared without running the functions\n        void stop(bool isWait = false) {\n            if (!isWait) {\n                if (this->isStop)\n                    return;\n                this->isStop = true;\n                for (int i = 0, n = this->size(); i < n; ++i) {\n                    *this->flags[i] = true;  // command the threads to stop\n                }\n                this->clear_queue();  // empty the queue\n            }\n            else {\n                if (this->isDone || this->isStop)\n                    return;\n                this->isDone = true;  // give the waiting threads a command to finish\n            }\n            {\n                std::unique_lock<std::mutex> lock(this->mutex);\n                this->cv.notify_all();  // stop all waiting threads\n            }\n            for (int i = 0; i < static_cast<int>(this->threads.size()); ++i) {  // wait for the computing threads to finish\n                    if (this->threads[i]->joinable())\n                        this->threads[i]->join();\n            }\n            // if there were no threads in the pool but some functors in the queue, the functors are not deleted by the threads\n            // therefore delete them here\n            this->clear_queue();\n            this->threads.clear();\n            this->flags.clear();\n        }\n\n        template<typename F, typename... Rest>\n        auto push(F && f, Rest&&... rest) ->std::future<decltype(f(0, rest...))> {\n            auto pck = std::make_shared<std::packaged_task<decltype(f(0, rest...))(int)>>(\n                std::bind(std::forward<F>(f), std::placeholders::_1, std::forward<Rest>(rest)...)\n                );\n            auto _f = new std::function<void(int id)>([pck](int id) {\n                (*pck)(id);\n            });\n            this->q.push(_f);\n            std::unique_lock<std::mutex> lock(this->mutex);\n            this->cv.notify_one();\n            return pck->get_future();\n        }\n\n        // run the user's function that excepts argument int - id of the running thread. returned value is templatized\n        // operator returns std::future, where the user can get the result and rethrow the catched exceptins\n        template<typename F>\n        auto push(F && f) ->std::future<decltype(f(0))> {\n            auto pck = std::make_shared<std::packaged_task<decltype(f(0))(int)>>(std::forward<F>(f));\n            auto _f = new std::function<void(int id)>([pck](int id) {\n                (*pck)(id);\n            });\n            this->q.push(_f);\n            std::unique_lock<std::mutex> lock(this->mutex);\n            this->cv.notify_one();\n            return pck->get_future();\n        }\n\n\n    private:\n\n        // deleted\n        thread_pool(const thread_pool &);// = delete;\n        thread_pool(thread_pool &&);// = delete;\n        thread_pool & operator=(const thread_pool &);// = delete;\n        thread_pool & operator=(thread_pool &&);// = delete;\n\n        void set_thread(int i) {\n            std::shared_ptr<std::atomic<bool>> flag(this->flags[i]); // a copy of the shared ptr to the flag\n            auto f = [this, i, flag/* a copy of the shared ptr to the flag */]() {\n                std::atomic<bool> & _flag = *flag;\n                std::function<void(int id)> * _f;\n                bool isPop = this->q.pop(_f);\n                while (true) {\n                    while (isPop) {  // if there is anything in the queue\n                        std::unique_ptr<std::function<void(int id)>> func(_f); // at return, delete the function even if an exception occurred\n                        (*_f)(i);\n                        if (_flag)\n                            return;  // the thread is wanted to stop, return even if the queue is not empty yet\n                        else\n                            isPop = this->q.pop(_f);\n                    }\n                    // the queue is empty here, wait for the next command\n                    std::unique_lock<std::mutex> lock(this->mutex);\n                    ++this->nWaiting;\n                    this->cv.wait(lock, [this, &_f, &isPop, &_flag](){ isPop = this->q.pop(_f); return isPop || this->isDone || _flag; });\n                    --this->nWaiting;\n                    if (!isPop)\n                        return;  // if the queue is empty and this->isDone == true or *flag then return\n                }\n            };\n            this->threads[i].reset(new std::thread(f)); // compiler may not support std::make_unique()\n        }\n\n        void init() { this->nWaiting = 0; this->isStop = false; this->isDone = false; }\n\n        std::vector<std::unique_ptr<std::thread>> threads;\n        std::vector<std::shared_ptr<std::atomic<bool>>> flags;\n        detail::Queue<std::function<void(int id)> *> q;\n        std::atomic<bool> isDone;\n        std::atomic<bool> isStop;\n        std::atomic<int> nWaiting;  // how many threads are waiting\n\n        std::mutex mutex;\n        std::condition_variable cv;\n    };\n\n}\n\n#endif // __ctpl_stl_thread_pool_H__\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/clsocket/README",
    "content": "------------------------------------------------------------------------------------------\n* History\n------------------------------------------------------------------------------------------\nWritten by Mark Carrier to provide a mechanism for writing cross platform socket code. This library was originally written to only support blocking TCP sockets. Over the years it has been extended to support UDP and RAW sockets as well. This is the first official release of the library and the following functionality is supported:\n\n    * Cross platform socket support.\n          o Windows 95, Windows 98, Windows XP\n          o Linux, Unix\n          o Macintosh OSX\n    * Support for sychronious, and asychronious sockets\n    * Supports TCP Streams\n    * Supports UDP Datagrams\n    * Supports Raw Sockets\n    * Thread Safe\n    * Signal Safe\n\n------------------------------------------------------------------------------------------\n* Building and Installing\t\n------------------------------------------------------------------------------------------\nThis is a very small library and is very easy to build and configure.  To build and install\nmake sure you are logged in as a user who has access to the recommend GNU installation \ndirectories. Then type\n\nmake -BUILD=Release && make install\n\nThat is it now you are off and running.\n\nNOTE: When using the library with WINDOWS you must define _WIN32 and when using with LINUX\n      you must define _LINUX.\n\n------------------------------------------------------------------------------------------\n* SimpleSocket Class Overview\n------------------------------------------------------------------------------------------\nNetwork communications via sockets can be abstracted into two categories of functionality; the active socket and the passive socket. The active socket object initiates a connection with a known host, whereas the passive socket object waits (or listens) for inbound requests for communication. The functionality of both objects is identical as far as sending and receiving data. This library makes distinction between the two objects because the operations for constructing and destructing the two are different.\n\nThis library is different from other socket libraries which define TCP sockets, UDP sockets, HTTP sockets, etc. The reason is the operations required for TCP, UDP, and RAW network communication is identical from a logical stand point. Thus a program could initially be written employing TCP streams, and then at some future point it could be discovered that UDP datagrams would satisify the solution. Changing between the two transport protocols would only require changing how the object is instantiated. The remaining code would in theory require minimal to no changes.\n\nThis library avoids abstractions like HTTP socket, or SMTP socket, soley because this type of object mixes the application and the transport layer. These types of abstractions can be created using this library as a base class.\n\nThe simple socket library is comprised of two class which can be used to represent all socket communications.\n\n    * Active Socket Class\n    * Passive Socket Class \n\n\n------------------------------------------------------------------------------------------\n* SimpleSocket Class Examples\n------------------------------------------------------------------------------------------\nWhen operating on a socket object most methods will return true or false\nSimple Active Socket\nAs mentioned previously the active socket (CActiveSocket) is used to initiate a connections with a server on some known port. So you want to connect to an existing server...\n\nHow do you do it?\n\nThere are many ways using the existing Berkley Socket API, but the goal of this class is to remove the many calls and man page lookups and replace them with clear, concise set of methods which allow a developer to focus on the logic of network programming.\n\nThe following code will connect to a DAYTIME server on port 13, query for the current time, and close the socket.\n\n#include <string.h>\n#include \"ActiveSocket.h\"       // Include header for active socket object definition\n\nint main(int argc, char **argv)\n{\n    CActiveSocket socket;       // Instantiate active socket object (defaults to TCP).\n    char          time[50];\n\n    memset(&time, 0, 50);\n\n    //--------------------------------------------------------------------------\n    // Initialize our socket object \n    //--------------------------------------------------------------------------\n    socket.Initialize();\n\n    //--------------------------------------------------------------------------\n    // Create a connection to the time server so that data can be sent\n    // and received.\n    //--------------------------------------------------------------------------\n    if (socket.Open(\"time-C.timefreq.bldrdoc.gov\", 13))\n    {\n        //----------------------------------------------------------------------\n        // Send a requtest the server requesting the current time.\n        //----------------------------------------------------------------------\n        if (socket.Send((const uint8 *)\"\\n\", 1))\n        {\n            //----------------------------------------------------------------------\n            // Receive response from the server.\n            //----------------------------------------------------------------------\n            socket.Receive(49);\n            memcpy(&time, socket.GetData(), 49);\n            printf(\"%s\\n\", time);\n\n            //----------------------------------------------------------------------\n            // Close the connection.\n            //----------------------------------------------------------------------\n            socket.Close();\n        }\n    }\n\n\n    return 1;\n}\n\nYou can see that the amount of code required to an object for network communciation is very small and simple.\nSimple Passive Socket\nNow you want to build a server.\n\nHow do you do it?\n\nFor a practical test lets build an echo server. The server will listen on port 6789 an repsond back with what ever has been sent to the server.\n\n#include \"PassiveSocket.h\"       // Include header for active socket object definition\n\n#define MAX_PACKET 4096 \n\nint main(int argc, char **argv)\n{\n    CPassiveSocket socket;\n    CActiveSocket *pClient = NULL;\n\n    //--------------------------------------------------------------------------\n    // Initialize our socket object \n    //--------------------------------------------------------------------------\n    socket.Initialize();\n\n    socket.Listen(\"127.0.0.1\", 6789);\n\n    while (true)\n    {\n        if ((pClient = socket.Accept()) != NULL)\n        {\n            //----------------------------------------------------------------------\n            // Receive request from the client.\n            //----------------------------------------------------------------------\n            if (pClient->Receive(MAX_PACKET))\n            {\n                //------------------------------------------------------------------\n                // Send response to client and close connection to the client.\n                //------------------------------------------------------------------\n                pClient->Send( pClient->GetData(), pClient->GetBytesReceived() );\n                pClient->Close();\n            }\n\n            delete pClient;\n        }\n    }\n\n    //-----------------------------------------------------------------------------\n    // Receive request from the client.\n    //-----------------------------------------------------------------------------\n    socket.Close();\n\n    return 1;\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/clsocket/src/ActiveSocket.cpp",
    "content": "/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* CActiveSocket.cpp - Active Socket Implementation                          */\n/*                                                                           */\n/* Author : Mark Carrier (mark@carrierlabs.com)                              */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n/* Copyright (c) 2007-2009 CarrierLabs, LLC.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * 4. The name \"CarrierLabs\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    mark@carrierlabs.com.\n *\n * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MARK CARRIER OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *----------------------------------------------------------------------------*/\n#include \"ActiveSocket.h\"\n\nCActiveSocket::CActiveSocket(CSocketType nType) : CSimpleSocket(nType)\n{\n}\n\n//------------------------------------------------------------------------------\n//\n// ConnectTCP() -\n//\n//------------------------------------------------------------------------------\nbool CActiveSocket::ConnectTCP(const char *pAddr, uint16_t nPort)\n{\n    bool           bRetVal = false;\n    struct in_addr stIpAddress;\n\n    //------------------------------------------------------------------\n    // Preconnection setup that must be preformed\n    //------------------------------------------------------------------\n    memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));\n    m_stServerSockaddr.sin_family = AF_INET;\n\n    if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)\n    {\n#ifdef _WIN32\n        TranslateSocketError();\n#else\n        if (h_errno == HOST_NOT_FOUND)\n        {\n            SetSocketError(SocketInvalidAddress);\n        }\n#endif\n        return bRetVal;\n    }\n\n    memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);\n    m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;\n\n    if ((int32_t)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)\n    {\n        TranslateSocketError();\n        return bRetVal;\n    }\n\n    m_stServerSockaddr.sin_port = htons(nPort);\n\n    //------------------------------------------------------------------\n    // Connect to address \"xxx.xxx.xxx.xxx\"    (IPv4) address only.\n    //\n    //------------------------------------------------------------------\n    m_timer.Initialize();\n    m_timer.SetStartTime();\n\n    if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) ==\n            CSimpleSocket::SocketError)\n    {\n        //--------------------------------------------------------------\n        // Get error value this might be a non-blocking new_socket so we\n        // must first check.\n        //--------------------------------------------------------------\n        TranslateSocketError();\n\n        //--------------------------------------------------------------\n        // If the new_socket is non-blocking and the current new_socket error\n        // is SocketEinprogress or SocketEwouldblock then poll connection\n        // with select for designated timeout period.\n        // Linux returns EINPROGRESS and Windows returns WSAEWOULDBLOCK.\n        //--------------------------------------------------------------\n        if ((IsNonblocking()) &&\n                ((GetSocketError() == CSimpleSocket::SocketEwouldblock) ||\n                 (GetSocketError() == CSimpleSocket::SocketEinprogress)))\n        {\n            bRetVal = Select(GetConnectTimeoutSec(), GetConnectTimeoutUSec());\n        }\n    }\n    else\n    {\n        TranslateSocketError();\n        bRetVal = true;\n    }\n\n    m_timer.SetEndTime();\n\n    return bRetVal;\n}\n\n//------------------------------------------------------------------------------\n//\n// ConnectUDP() -\n//\n//------------------------------------------------------------------------------\nbool CActiveSocket::ConnectUDP(const char *pAddr, uint16_t nPort)\n{\n    bool           bRetVal = false;\n    struct in_addr stIpAddress;\n\n    //------------------------------------------------------------------\n    // Pre-connection setup that must be preformed\n    //------------------------------------------------------------------\n    memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));\n    m_stServerSockaddr.sin_family = AF_INET;\n\n    if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)\n    {\n#ifdef _WIN32\n        TranslateSocketError();\n#else\n        if (h_errno == HOST_NOT_FOUND)\n        {\n            SetSocketError(SocketInvalidAddress);\n        }\n#endif\n        return bRetVal;\n    }\n\n    memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);\n    m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;\n\n    if ((int32_t)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)\n    {\n        TranslateSocketError();\n        return bRetVal;\n    }\n\n    m_stServerSockaddr.sin_port = htons(nPort);\n\n    //------------------------------------------------------------------\n    // Connect to address \"xxx.xxx.xxx.xxx\"    (IPv4) address only.\n    //\n    //------------------------------------------------------------------\n    m_timer.Initialize();\n    m_timer.SetStartTime();\n\n    if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)\n    {\n        bRetVal = true;\n    }\n\n    TranslateSocketError();\n\n    m_timer.SetEndTime();\n\n    return bRetVal;\n}\n\n//------------------------------------------------------------------------------\n//\n// ConnectRAW() -\n//\n//------------------------------------------------------------------------------\nbool CActiveSocket::ConnectRAW(const char *pAddr, uint16_t nPort)\n{\n    bool           bRetVal = false;\n    struct in_addr stIpAddress;\n    //------------------------------------------------------------------\n    // Pre-connection setup that must be preformed\n    //------------------------------------------------------------------\n    memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));\n    m_stServerSockaddr.sin_family = AF_INET;\n\n    if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)\n    {\n#ifdef _WIN32\n        TranslateSocketError();\n#else\n        if (h_errno == HOST_NOT_FOUND)\n        {\n            SetSocketError(SocketInvalidAddress);\n        }\n#endif\n        return bRetVal;\n    }\n\n    memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);\n    m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;\n\n    if ((int32_t)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)\n    {\n        TranslateSocketError();\n        return bRetVal;\n    }\n\n    m_stServerSockaddr.sin_port = htons(nPort);\n\n    //------------------------------------------------------------------\n    // Connect to address \"xxx.xxx.xxx.xxx\"    (IPv4) address only.\n    //\n    //------------------------------------------------------------------\n    m_timer.Initialize();\n    m_timer.SetStartTime();\n\n    if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)\n    {\n        bRetVal = true;\n    }\n\n    TranslateSocketError();\n\n    m_timer.SetEndTime();\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Open() - Create a connection to a specified address on a specified port\n//\n//------------------------------------------------------------------------------\nbool CActiveSocket::Open(const char *pAddr, uint16_t nPort)\n{\n    bool bRetVal = false;\n\n    if (IsSocketValid() == false)\n    {\n        SetSocketError(CSimpleSocket::SocketInvalidSocket);\n        return bRetVal;\n    }\n\n    if (pAddr == NULL)\n    {\n        SetSocketError(CSimpleSocket::SocketInvalidAddress);\n        return bRetVal;\n    }\n\n    if (nPort == 0)\n    {\n        SetSocketError(CSimpleSocket::SocketInvalidPort);\n        return bRetVal;\n    }\n\n    switch (m_nSocketType)\n    {\n    case CSimpleSocket::SocketTypeTcp :\n    {\n        bRetVal = ConnectTCP(pAddr, nPort);\n        break;\n    }\n    case CSimpleSocket::SocketTypeUdp :\n    {\n        bRetVal = ConnectUDP(pAddr, nPort);\n        break;\n    }\n    case CSimpleSocket::SocketTypeRaw :\n        break;\n    default:\n        break;\n    }\n\n    //--------------------------------------------------------------------------\n    // If successful then create a local copy of the address and port\n    //--------------------------------------------------------------------------\n    if (bRetVal)\n    {\n        socklen_t nSockLen = sizeof(struct sockaddr);\n\n        memset(&m_stServerSockaddr, 0, nSockLen);\n        getpeername(m_socket, (struct sockaddr *)&m_stServerSockaddr, &nSockLen);\n\n        nSockLen = sizeof(struct sockaddr);\n        memset(&m_stClientSockaddr, 0, nSockLen);\n        getsockname(m_socket, (struct sockaddr *)&m_stClientSockaddr, &nSockLen);\n\n        SetSocketError(SocketSuccess);\n    }\n\n    return bRetVal;\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/clsocket/src/ActiveSocket.h",
    "content": "/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* ActiveSocket.h - Active Socket Decleration                                */\n/*                                                                           */\n/* Author : Mark Carrier (mark@carrierlabs.com)                              */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n/* Copyright (c) 2007-2009 CarrierLabs, LLC.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * 4. The name \"CarrierLabs\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    mark@carrierlabs.com.\n *\n * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MARK CARRIER OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *----------------------------------------------------------------------------*/\n#ifndef __ACTIVESOCKET_H__\n#define __ACTIVESOCKET_H__\n\n#include \"SimpleSocket.h\"\n\nclass CPassiveSocket;\n\n/// Provides a platform independent class to create an active socket.\n/// An active socket is used to create a socket which connects to a server.\n/// This type of object would be used when an application needs to send/receive\n/// data from a server.\nclass CActiveSocket : public CSimpleSocket {\npublic:\n    friend class CPassiveSocket;\n\n    CActiveSocket(CSocketType type = SocketTypeTcp);\n\n    CActiveSocket(CActiveSocket &&) noexcept = default;\n\n    CActiveSocket &operator=(CActiveSocket &&) noexcept = default;\n\n    virtual ~CActiveSocket() {\n        Close();\n    };\n\n    /// Established a connection to the address specified by pAddr.\n    /// Connection-based protocol sockets (CSocket::SocketTypeTcp) may\n    /// successfully call Open() only once, however; connectionless protocol\n    /// sockets (CSocket::SocketTypeUdp) may use Open() multiple times to\n    /// change their association.\n    ///  @param pAddr specifies the destination address to connect.\n    ///  @param nPort specifies the destination port.\n    ///  @return true if successful connection made, otherwise false.\n    virtual bool Open(const char *pAddr, uint16_t nPort);\n\nprivate:\n    /// Utility function used to create a TCP connection, called from Open().\n    ///  @return true if successful connection made, otherwise false.\n    bool ConnectTCP(const char *pAddr, uint16_t nPort);\n\n    /// Utility function used to create a UDP connection, called from Open().\n    ///  @return true if successful connection made, otherwise false.\n    bool ConnectUDP(const char *pAddr, uint16_t nPort);\n\n    /// Utility function used to create a RAW connection, called from Open().\n    ///  @return true if successful connection made, otherwise false.\n    bool ConnectRAW(const char *pAddr, uint16_t nPort);\n\nprivate:\n    struct hostent *m_pHE;\n};\n\n#endif /*  __ACTIVESOCKET_H__  */\n\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/clsocket/src/Host.h",
    "content": "/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* Host.h - Basic header file to provide cross-platform solutions via        */\n/*                   macros, conditional compilation, etc.                   */\n/*                                                                           */\n/* Author : Mark Carrier (mark@carrierlabs.com)                              */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n/* Copyright (c) 2007 CarrierLabs, LLC.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * 4. The name \"CarrierLabs\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    mark@carrierlabs.com.\n *\n * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MARK CARRIER OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *----------------------------------------------------------------------------*/\n#ifndef __HOST_H__\n#define __HOST_H__\n\n#include <limits.h>\n#include <cstdint>\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* Type Definition Macros                                                    */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n#ifndef __WORDSIZE\n  /* Assume 32 */\n  #define __WORDSIZE 32\n#endif\n\n#if defined(__linux__) || defined(_DARWIN)\n    typedef int            SOCKET;\n#endif\n\n#ifdef _WIN32\n    struct iovec {\n        void  *iov_base;\n        size_t iov_len;\n    };\n#endif\n\n#ifdef _WIN32\n    typedef int socklen_t;\n#endif\n\n#ifdef _WIN32\n\n  #ifndef UINT8_MAX\n    #define UINT8_MAX  (UCHAR_MAX)\n  #endif\n  #ifndef UINT16_MAX\n    #define UINT16_MAX (USHRT_MAX)\n  #endif\n  #ifndef UINT32_MAX\n    #define UINT32_MAX (ULONG_MAX)\n  #endif\n\n  #if __WORDSIZE == 64\n    #define SIZE_MAX (18446744073709551615UL)\n  #else\n    #ifndef SIZE_MAX\n    #define SIZE_MAX (4294967295U)\n  #endif\n  #endif\n#endif\n\n#if defined(_WIN32)\n  #define ssize_t size_t\n#endif\n\n#ifndef TRUE\n  #define TRUE 1\n#endif\n\n#ifndef FALSE\n  #define FALSE 0\n#endif\n\n#ifndef htonll\n#ifdef _BIG_ENDIAN\n#define htonll(x)   (x)\n#define ntohll(x)   (x)\n#else\n#define htonll(x)   ((((uint64_t)htonl(x)) << 32) + htonl(x >> 32))\n#define ntohll(x)   ((((uint64_t)ntohl(x)) << 32) + ntohl(x >> 32))\n#endif\n#endif\n\n/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* Socket Macros                                                             */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n#ifdef _WIN32\n#define SHUT_RD                0\n#define SHUT_WR                1\n#define SHUT_RDWR              2\n#define ACCEPT(a,b,c)          accept(a,b,c)\n#define CONNECT(a,b,c)         connect(a,b,c)\n#define CLOSE(a)               closesocket(a)\n#define READ(a,b,c)            read(a,b,c)\n#define RECV(a,b,c,d)          recv(a, (char *)b, c, d)\n#define RECVFROM(a,b,c,d,e,f)  recvfrom(a, (char *)b, c, d, (sockaddr *)e, (int *)f)\n#define RECV_FLAGS             MSG_WAITALL\n#define SELECT(a,b,c,d,e)      select((int32_t)a,b,c,d,e)\n#define SEND(a,b,c,d)          send(a, (const char *)b, (int)c, d)\n#define SENDTO(a,b,c,d,e,f)    sendto(a, (const char *)b, (int)c, d, e, f)\n#define SEND_FLAGS             0\n#define SENDFILE(a,b,c,d)      sendfile(a, b, c, d)\n#define SET_SOCKET_ERROR(x,y)  errno=y\n#define SOCKET_ERROR_INTERUPT  EINTR\n#define SOCKET_ERROR_TIMEDOUT  EAGAIN\n#define WRITE(a,b,c)           write(a,b,c)\n#define WRITEV(a,b,c)          Writev(b, c)\n#define GETSOCKOPT(a,b,c,d,e)  getsockopt(a,b,c,(char *)d, (int *)e)\n#define SETSOCKOPT(a,b,c,d,e)  setsockopt(a,b,c,(char *)d, (int)e)\n#define GETHOSTBYNAME(a)       gethostbyname(a)\n#endif\n\n#if defined(__linux__) || defined(_DARWIN)\n#define ACCEPT(a,b,c)          accept(a,b,c)\n#define CONNECT(a,b,c)         connect(a,b,c)\n#define CLOSE(a)               close(a)\n#define READ(a,b,c)            read(a,b,c)\n#define RECV(a,b,c,d)          recv(a, (void *)b, c, d)\n#define RECVFROM(a,b,c,d,e,f)  recvfrom(a, (char *)b, c, d, (sockaddr *)e, f)\n#define RECV_FLAGS             MSG_WAITALL\n#define SELECT(a,b,c,d,e)      select(a,b,c,d,e)\n#define SEND(a,b,c,d)          send(a, (const int8_t *)b, c, d)\n#define SENDTO(a,b,c,d,e,f)    sendto(a, (const int8_t *)b, c, d, e, f)\n#define SEND_FLAGS             0\n#define SENDFILE(a,b,c,d)      sendfile(a, b, c, d)\n#define SET_SOCKET_ERROR(x,y)  errno=y\n#define SOCKET_ERROR_INTERUPT  EINTR\n#define SOCKET_ERROR_TIMEDOUT  EAGAIN\n#define WRITE(a,b,c)           write(a,b,c)\n#define WRITEV(a,b,c)          writev(a, b, c)\n#define GETSOCKOPT(a,b,c,d,e)  getsockopt((int)a,(int)b,(int)c,(void *)d,(socklen_t *)e)\n#define SETSOCKOPT(a,b,c,d,e)  setsockopt((int)a,(int)b,(int)c,(const void *)d,(int)e)\n#define GETHOSTBYNAME(a)       gethostbyname(a)\n#endif\n\n\n/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* File Macros                                                               */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n#define STRUCT_STAT         struct stat\n#define LSTAT(x,y)          lstat(x,y)\n#define FILE_HANDLE         FILE *\n#define CLEARERR(x)         clearerr(x)\n#define FCLOSE(x)           fclose(x)\n#define FEOF(x)             feof(x)\n#define FERROR(x)           ferror(x)\n#define FFLUSH(x)           fflush(x)\n#define FILENO(s)           fileno(s)\n#define FOPEN(x,y)          fopen(x, y)\n  //#define FREAD(a,b,c,d)      fread(a, b, c, d)\n#define FSTAT(s, st)        fstat(FILENO(s), st)\n    //#define FWRITE(a,b,c,d)     fwrite(a, b, c, d)\n#define STAT_BLK_SIZE(x)    ((x).st_blksize)\n\n\n/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* Misc Macros                                                               */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n#if defined(_WIN32)\n  #define GET_CLOCK_COUNT(x) QueryPerformanceCounter((LARGE_INTEGER *)x)\n#else\n  #define GET_CLOCK_COUNT(x) gettimeofday(x, NULL)\n#endif\n\n#if defined(_WIN32)\n  #define STRTOULL(x) _atoi64(x)\n#else\n  #define STRTOULL(x) strtoull(x, NULL, 10)\n#endif\n\n#if defined(_WIN32)\n  #define SNPRINTF _snprintf\n  #define PRINTF   printf\n  #define VPRINTF  vprintf\n  #define FPRINTF  fprintf\n#else\n  #define SNPRINTF snprintf\n  #define PRINTF   printf\n  #define VPRINTF  vprintf\n  #define FPRINTF  fprintf\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __HOST_H__ */\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/clsocket/src/PassiveSocket.cpp",
    "content": "/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* PassiveSocket.cpp - Passive Socket Implementation                         */\n/*                                                                           */\n/* Author : Mark Carrier (mark@carrierlabs.com)                              */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n/* Copyright (c) 2007-2009 CarrierLabs, LLC.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * 4. The name \"CarrierLabs\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    mark@carrierlabs.com.\n *\n * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MARK CARRIER OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *----------------------------------------------------------------------------*/\n#include \"PassiveSocket.h\"\n\n\nCPassiveSocket::CPassiveSocket(CSocketType nType) : CSimpleSocket(nType) {\n}\n\nbool CPassiveSocket::BindMulticast(const char *pInterface, const char *pGroup, uint16_t nPort) {\n    bool bRetVal = false;\n#ifdef _WIN32\n    ULONG inAddr;\n#else\n    in_addr_t      inAddr;\n#endif\n\n    //--------------------------------------------------------------------------\n    // Set the following new_socket option SO_REUSEADDR.  This will allow the file\n    // descriptor to be reused immediately after the new_socket is closed instead\n    // of setting in a TIMED_WAIT state.\n    //--------------------------------------------------------------------------\n    memset(&m_stMulticastGroup, 0, sizeof(m_stMulticastGroup));\n    m_stMulticastGroup.sin_family = AF_INET;\n    m_stMulticastGroup.sin_port = htons(nPort);\n\n    //--------------------------------------------------------------------------\n    // If no IP Address (interface ethn) is supplied, or the loop back is\n    // specified then bind to any interface, else bind to specified interface.\n    //--------------------------------------------------------------------------\n    if ((pInterface == NULL) || (!strlen(pInterface))) {\n        m_stMulticastGroup.sin_addr.s_addr = htonl(INADDR_ANY);\n    } else {\n        if ((inAddr = inet_addr(pInterface)) != INADDR_NONE) {\n            m_stMulticastGroup.sin_addr.s_addr = inAddr;\n        }\n    }\n\n    //--------------------------------------------------------------------------\n    // Bind to the specified port\n    //--------------------------------------------------------------------------\n    if (bind(m_socket, (struct sockaddr *) &m_stMulticastGroup, sizeof(m_stMulticastGroup)) == 0) {\n        //----------------------------------------------------------------------\n        // Join the multicast group\n        //----------------------------------------------------------------------\n        m_stMulticastRequest.imr_multiaddr.s_addr = inet_addr(pGroup);\n        m_stMulticastRequest.imr_interface.s_addr = m_stMulticastGroup.sin_addr.s_addr;\n\n        if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,\n                       (void *) &m_stMulticastRequest,\n                       sizeof(m_stMulticastRequest)) == CSimpleSocket::SocketSuccess) {\n            bRetVal = true;\n        }\n\n        m_timer.SetEndTime();\n    }\n\n    m_timer.Initialize();\n    m_timer.SetStartTime();\n\n\n    //--------------------------------------------------------------------------\n    // If there was a new_socket error then close the new_socket to clean out the\n    // connection in the backlog.\n    //--------------------------------------------------------------------------\n    TranslateSocketError();\n\n    if (bRetVal == false) {\n        Close();\n    }\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Listen() -\n//\n//------------------------------------------------------------------------------\nbool CPassiveSocket::Listen(const char *pAddr, uint16_t nPort, int32_t nConnectionBacklog) {\n    bool bRetVal = false;\n#ifdef _WIN32\n    ULONG inAddr;\n#else\n    in_addr_t      inAddr;\n\n    int32_t          nReuse;\n    nReuse = IPTOS_LOWDELAY;\n\n    //--------------------------------------------------------------------------\n    // Set the following new_socket option SO_REUSEADDR.  This will allow the file\n    // descriptor to be reused immediately after the new_socket is closed instead\n    // of setting in a TIMED_WAIT state.\n    //--------------------------------------------------------------------------\n    SETSOCKOPT(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(int32_t));\n    SETSOCKOPT(m_socket, IPPROTO_TCP, IP_TOS, &nReuse, sizeof(int32_t));\n#endif\n\n    memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));\n    m_stServerSockaddr.sin_family = AF_INET;\n    m_stServerSockaddr.sin_port = htons(nPort);\n\n    //--------------------------------------------------------------------------\n    // If no IP Address (interface ethn) is supplied, or the loop back is\n    // specified then bind to any interface, else bind to specified interface.\n    //--------------------------------------------------------------------------\n    if ((pAddr == NULL) || (!strlen(pAddr))) {\n        m_stServerSockaddr.sin_addr.s_addr = htonl(INADDR_ANY);\n    } else {\n        if ((inAddr = inet_addr(pAddr)) != INADDR_NONE) {\n            m_stServerSockaddr.sin_addr.s_addr = inAddr;\n        }\n    }\n\n    m_timer.Initialize();\n    m_timer.SetStartTime();\n\n    //--------------------------------------------------------------------------\n    // Bind to the specified port\n    //--------------------------------------------------------------------------\n    if (bind(m_socket, (struct sockaddr *) &m_stServerSockaddr, sizeof(m_stServerSockaddr)) !=\n        CSimpleSocket::SocketError) {\n        socklen_t namelen = sizeof(m_stServerSockaddr);\n        if (getsockname(m_socket, (struct sockaddr *) &m_stServerSockaddr, &namelen) != CSimpleSocket::SocketError) {\n            if (m_nSocketType == CSimpleSocket::SocketTypeTcp) {\n                if (listen(m_socket, nConnectionBacklog) != CSimpleSocket::SocketError) {\n                    bRetVal = true;\n                }\n            } else {\n                bRetVal = true;\n            }\n        } else {\n            bRetVal = false;\n        }\n    }\n\n    m_timer.SetEndTime();\n\n    //--------------------------------------------------------------------------\n    // If there was a new_socket error then close the new_socket to clean out the\n    // connection in the backlog.\n    //--------------------------------------------------------------------------\n    TranslateSocketError();\n\n    if (bRetVal == false) {\n        CSocketError err = GetSocketError();\n        Close();\n        SetSocketError(err);\n    }\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Accept() -\n//\n//------------------------------------------------------------------------------\nCActiveSocket *CPassiveSocket::Accept() {\n    uint32_t nSockLen;\n    CActiveSocket *pClientSocket = NULL;\n    SOCKET socket = static_cast<SOCKET>(CSimpleSocket::SocketError);\n\n    if (m_nSocketType != CSimpleSocket::SocketTypeTcp) {\n        SetSocketError(CSimpleSocket::SocketProtocolError);\n        return pClientSocket;\n    }\n\n    pClientSocket = new CActiveSocket();\n\n    //--------------------------------------------------------------------------\n    // Wait for incoming connection.\n    //--------------------------------------------------------------------------\n    if (pClientSocket != NULL) {\n        CSocketError socketErrno = SocketSuccess;\n\n        m_timer.Initialize();\n        m_timer.SetStartTime();\n\n        nSockLen = sizeof(m_stClientSockaddr);\n\n        do {\n            errno = 0;\n            socket = accept(m_socket, (struct sockaddr *) &m_stClientSockaddr, (socklen_t *) &nSockLen);\n\n            if (socket != static_cast<SOCKET>(-1)) {\n                pClientSocket->SetSocketHandle(socket);\n                pClientSocket->TranslateSocketError();\n                socketErrno = pClientSocket->GetSocketError();\n                socklen_t nSockLen = sizeof(struct sockaddr);\n\n                //-------------------------------------------------------------\n                // Store client and server IP and port information for this\n                // connection.\n                //-------------------------------------------------------------\n                getpeername(m_socket, (struct sockaddr *) &pClientSocket->m_stClientSockaddr, &nSockLen);\n                memcpy((void *) &pClientSocket->m_stClientSockaddr, (void *) &m_stClientSockaddr, nSockLen);\n\n                memset(&pClientSocket->m_stServerSockaddr, 0, nSockLen);\n                getsockname(m_socket, (struct sockaddr *) &pClientSocket->m_stServerSockaddr, &nSockLen);\n            } else {\n                TranslateSocketError();\n                socketErrno = GetSocketError();\n            }\n\n        } while (socketErrno == CSimpleSocket::SocketInterrupted);\n\n        m_timer.SetEndTime();\n\n        if (socketErrno != CSimpleSocket::SocketSuccess) {\n            delete pClientSocket;\n            pClientSocket = NULL;\n        }\n    }\n\n    return pClientSocket;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Send() - Send data on a valid new_socket\n//\n//------------------------------------------------------------------------------\nint32_t CPassiveSocket::Send(const uint8_t *pBuf, size_t bytesToSend) {\n    SetSocketError(SocketSuccess);\n    m_nBytesSent = 0;\n\n    switch (m_nSocketType) {\n        case CSimpleSocket::SocketTypeUdp: {\n            if (IsSocketValid()) {\n                if ((bytesToSend > 0) && (pBuf != NULL)) {\n                    m_timer.Initialize();\n                    m_timer.SetStartTime();\n\n                    m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0,\n                                          (const sockaddr *) &m_stClientSockaddr,\n                                          sizeof(m_stClientSockaddr));\n\n                    m_timer.SetEndTime();\n\n                    if (m_nBytesSent == CSimpleSocket::SocketError) {\n                        TranslateSocketError();\n                    }\n                }\n            }\n            break;\n        }\n        case CSimpleSocket::SocketTypeTcp:\n            CSimpleSocket::Send(pBuf, bytesToSend);\n            break;\n        default:\n            SetSocketError(SocketProtocolError);\n            break;\n    }\n\n    return m_nBytesSent;\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/clsocket/src/PassiveSocket.h",
    "content": "/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* Socket.h - Passive Socket Decleration.                                    */\n/*                                                                           */\n/* Author : Mark Carrier (mark@carrierlabs.com)                              */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n/* Copyright (c) 2007-2009 CarrierLabs, LLC.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * 4. The name \"CarrierLabs\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    mark@carrierlabs.com.\n *\n * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MARK CARRIER OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *----------------------------------------------------------------------------*/\n#ifndef __PASSIVESOCKET_H__\n#define __PASSIVESOCKET_H__\n#include \"ActiveSocket.h\"\n\n/// Provides a platform independent class to create a passive new_socket.\n/// A passive new_socket is used to create a \"listening\" new_socket.  This type\n/// of object would be used when an application needs to wait for\n/// inbound connections.  Support for CSimpleSocket::SocketTypeTcp,\n/// CSimpleSocket::SocketTypeUdp, and CSimpleSocket::SocketTypeRaw is handled\n/// in a similar fashion.  The big difference is that the method\n/// CPassiveSocket::Accept should not be called on the latter two new_socket\n/// types.\nclass CPassiveSocket : public CSimpleSocket {\npublic:\n    CPassiveSocket(CSocketType type = SocketTypeTcp);\n    virtual ~CPassiveSocket() {\n        Close();\n    };\n\n    /// Extracts the first connection request on the queue of pending\n    /// connections and creates a newly connected new_socket.  Used with\n    /// CSocketType CSimpleSocket::SocketTypeTcp.  It is the responsibility of\n    /// the caller to delete the returned object when finished.\n    ///  @return if successful a pointer to a newly created CActiveSocket object\n    ///          will be returned and the internal error condition of the CPassiveSocket\n    ///          object will be CPassiveSocket::SocketSuccess.  If an error condition was encountered\n    ///          the NULL will be returned and one of the following error conditions will be set:\n    ///    CPassiveSocket::SocketEwouldblock, CPassiveSocket::SocketInvalidSocket,\n    ///    CPassiveSocket::SocketConnectionAborted, CPassiveSocket::SocketInterrupted\n    ///    CPassiveSocket::SocketProtocolError, CPassiveSocket::SocketFirewallError\n    virtual CActiveSocket *Accept(void);\n\n    /// Bind to a multicast group on  a specified interface, multicast group, and port\n    ///\n    ///  @param pInterface - interface on which to bind.\n    ///  @param pGroup - multicast group address to bind.\n    ///  @param nPort - port on which multicast\n    ///  @return true if able to bind to interface and multicast group.\n    ///      If not successful, the false is returned and one of the following error\n    ///      condiitions will be set: CPassiveSocket::SocketAddressInUse, CPassiveSocket::SocketProtocolError,\n    ///      CPassiveSocket::SocketInvalidSocket.  The following new_socket errors are for Linux/Unix\n    ///      derived systems only: CPassiveSocket::SocketInvalidSocketBuffer\n    bool BindMulticast(const char *pInterface, const char *pGroup, uint16_t nPort);\n\n    /// Create a listening new_socket at local ip address 'x.x.x.x' or 'localhost'\n    /// if pAddr is NULL on port nPort.\n    ///\n    ///  @param pAddr specifies the IP address on which to listen.\n    ///  @param nPort specifies the port on which to listen.\n    ///  @param nConnectionBacklog specifies connection queue backlog (default 30,000)\n    ///  @return true if a listening new_socket was created.\n    ///      If not successful, the false is returned and one of the following error\n    ///      conditions will be set: CPassiveSocket::SocketAddressInUse, CPassiveSocket::SocketProtocolError,\n    ///      CPassiveSocket::SocketInvalidSocket.  The following new_socket errors are for Linux/Unix\n    ///      derived systems only: CPassiveSocket::SocketInvalidSocketBuffer\n    virtual bool Listen(const char *pAddr, uint16_t nPort, int32_t nConnectionBacklog = 30000);\n\n    /// Attempts to send a block of data on an established connection.\n    /// @param pBuf block of data to be sent.\n    /// @param bytesToSend size of data block to be sent.\n    /// @return number of bytes actually sent, return of zero means the\n    /// connection has been shutdown on the other side, and a return of -1\n    /// means that an error has occurred.  If an error was signaled then one\n    /// of the following error codes will be set: CPassiveSocket::SocketInvalidSocket,\n    /// CPassiveSocket::SocketEwouldblock, SimpleSocket::SocketConnectionReset,\n    /// CPassiveSocket::SocketInvalidSocketBuffer, CPassiveSocket::SocketInterrupted,\n    /// CPassiveSocket::SocketProtocolError, CPassiveSocket::SocketNotconnected\n    /// <br>\\b Note: This function is used only for a new_socket of type\n    /// CSimpleSocket::SocketTypeUdp\n    virtual int32_t Send(const uint8_t *pBuf, size_t bytesToSend);\n\nprivate:\n    struct ip_mreq  m_stMulticastRequest;   /// group address for multicast\n\n};\n\n#endif // __PASSIVESOCKET_H__\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/clsocket/src/SimpleSocket.cpp",
    "content": "/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* CSimpleSocket.cpp - CSimpleSocket Implementation                          */\n/*                                                                           */\n/* Author : Mark Carrier (mark@carrierlabs.com)                              */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n/* Copyright (c) 2007-2009 CarrierLabs, LLC.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * 4. The name \"CarrierLabs\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    mark@carrierlabs.com.\n *\n * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MARK CARRIER OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *----------------------------------------------------------------------------*/\n#include \"SimpleSocket.h\"\n\nCSimpleSocket::CSimpleSocket(CSocketType nType) :\n    m_socket(INVALID_SOCKET),\n    m_socketErrno(CSimpleSocket::SocketInvalidSocket),\n    m_pBuffer(NULL), m_nBufferSize(0), m_nSocketDomain(AF_INET),\n    m_nSocketType(SocketTypeInvalid), m_nBytesReceived(-1),\n    m_nBytesSent(-1), m_nFlags(0),\n    m_bIsBlocking(true)\n{\n    SetConnectTimeout(1, 0);\n    memset(&m_stRecvTimeout, 0, sizeof(struct timeval));\n    memset(&m_stSendTimeout, 0, sizeof(struct timeval));\n    memset(&m_stLinger, 0, sizeof(struct linger));\n\n    switch(nType)\n    {\n        //----------------------------------------------------------------------\n        // Declare socket type stream - TCP\n        //----------------------------------------------------------------------\n    case CSimpleSocket::SocketTypeTcp:\n    {\n        m_nSocketDomain = AF_INET;\n        m_nSocketType = CSimpleSocket::SocketTypeTcp;\n        break;\n    }\n    case CSimpleSocket::SocketTypeTcp6:\n    {\n        m_nSocketDomain = AF_INET6;\n        m_nSocketType = CSimpleSocket::SocketTypeTcp6;\n        break;\n    }\n    //----------------------------------------------------------------------\n    // Declare socket type datagram - UDP\n    //----------------------------------------------------------------------\n    case CSimpleSocket::SocketTypeUdp:\n    {\n        m_nSocketDomain = AF_INET;\n        m_nSocketType = CSimpleSocket::SocketTypeUdp;\n        break;\n    }\n    case CSimpleSocket::SocketTypeUdp6:\n    {\n        m_nSocketDomain = AF_INET6;\n        m_nSocketType = CSimpleSocket::SocketTypeUdp6;\n        break;\n    }\n    //----------------------------------------------------------------------\n    // Declare socket type raw Ethernet - Ethernet\n    //----------------------------------------------------------------------\n    case CSimpleSocket::SocketTypeRaw:\n    {\n#if defined(__linux__) && !defined(_DARWIN)\n        m_nSocketDomain = AF_PACKET;\n        m_nSocketType = CSimpleSocket::SocketTypeRaw;\n#endif\n#ifdef _WIN32\n        m_nSocketType = CSimpleSocket::SocketTypeInvalid;\n#endif\n        break;\n    }\n    default:\n        m_nSocketType = CSimpleSocket::SocketTypeInvalid;\n        break;\n    }\n}\n\nCSimpleSocket::CSimpleSocket(CSimpleSocket &socket)\n{\n    m_pBuffer = new uint8_t[socket.m_nBufferSize];\n    m_nBufferSize = socket.m_nBufferSize;\n    memcpy(m_pBuffer, socket.m_pBuffer, socket.m_nBufferSize);\n}\n\nCSimpleSocket *CSimpleSocket::operator=(CSimpleSocket &socket)\n{\n    if (m_nBufferSize != socket.m_nBufferSize)\n    {\n        delete m_pBuffer;\n        m_pBuffer = new uint8_t[socket.m_nBufferSize];\n        m_nBufferSize = socket.m_nBufferSize;\n        memcpy(m_pBuffer, socket.m_pBuffer, socket.m_nBufferSize);\n    }\n\n    return this;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Initialize() - Initialize socket class\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::Initialize()\n{\n    errno = CSimpleSocket::SocketSuccess;\n\n#ifdef _WIN32\n    //-------------------------------------------------------------------------\n    // Data structure containing general Windows Sockets Info\n    //-------------------------------------------------------------------------\n    memset(&m_hWSAData, 0, sizeof(m_hWSAData));\n    WSAStartup(MAKEWORD(2, 0), &m_hWSAData);\n#endif\n\n    //-------------------------------------------------------------------------\n    // Create the basic Socket Handle\n    //-------------------------------------------------------------------------\n    m_timer.Initialize();\n    m_timer.SetStartTime();\n    m_socket = socket(m_nSocketDomain, m_nSocketType, 0);\n    m_timer.SetEndTime();\n\n    TranslateSocketError();\n\n    return (IsSocketValid());\n}\n\n\n//------------------------------------------------------------------------------\n//\n// BindInterface()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::BindInterface(const char *pInterface)\n{\n    bool           bRetVal = false;\n    struct in_addr stInterfaceAddr;\n\n    if (GetMulticast() == true)\n    {\n        if (pInterface)\n        {\n            stInterfaceAddr.s_addr= inet_addr(pInterface);\n            if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_MULTICAST_IF, &stInterfaceAddr, sizeof(stInterfaceAddr)) == SocketSuccess)\n            {\n                bRetVal = true;\n            }\n        }\n    }\n    else\n    {\n        SetSocketError(CSimpleSocket::SocketProtocolError);\n    }\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SetMulticast()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::SetMulticast(bool bEnable, uint8_t multicastTTL)\n{\n    bool bRetVal = false;\n\n    if (GetSocketType() == CSimpleSocket::SocketTypeUdp)\n    {\n        m_bIsMulticast = bEnable;\n        if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&multicastTTL, sizeof(multicastTTL)) == SocketError)\n        {\n            TranslateSocketError();\n            bRetVal = false;\n        }\n        else\n        {\n            bRetVal = true;\n        }\n    }\n    else\n    {\n        m_socketErrno = CSimpleSocket::SocketProtocolError;\n    }\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SetSocketDscp()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::SetSocketDscp(int32_t nDscp)\n{\n    bool  bRetVal = true;\n    int32_t nTempVal = nDscp;\n\n    nTempVal <<= 4;\n    nTempVal /= 4;\n\n    if (IsSocketValid())\n    {\n        if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_TOS, &nTempVal, sizeof(nTempVal)) == SocketError)\n        {\n            TranslateSocketError();\n            bRetVal = false;\n        }\n    }\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// GetSocketDscp()\n//\n//------------------------------------------------------------------------------\nint32_t CSimpleSocket::GetSocketDscp(void)\n{\n    int32_t      nTempVal = 0;\n    socklen_t  nLen = 0;\n\n    if (IsSocketValid())\n    {\n        if (GETSOCKOPT(m_socket, IPPROTO_IP, IP_TOS, &nTempVal, &nLen) == SocketError)\n        {\n            TranslateSocketError();\n        }\n\n        nTempVal *= 4;\n        nTempVal >>= 4;\n    }\n\n    return nTempVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// GetWindowSize()\n//\n//------------------------------------------------------------------------------\nuint32_t CSimpleSocket::GetWindowSize(uint32_t nOptionName)\n{\n    uint32_t nTcpWinSize = 0;\n\n    //-------------------------------------------------------------------------\n    // no socket given, return system default allocate our own new socket\n    //-------------------------------------------------------------------------\n    if (m_socket != static_cast<SOCKET>(CSimpleSocket::SocketError))\n    {\n        socklen_t nLen = sizeof(nTcpWinSize);\n\n        //---------------------------------------------------------------------\n        // query for buffer size\n        //---------------------------------------------------------------------\n        GETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nTcpWinSize, &nLen);\n        TranslateSocketError();\n    }\n    else\n    {\n        SetSocketError(CSimpleSocket::SocketInvalidSocket);\n    }\n\n    return nTcpWinSize;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SetWindowSize()\n//\n//------------------------------------------------------------------------------\nuint32_t CSimpleSocket::SetWindowSize(uint32_t nOptionName, uint32_t nWindowSize)\n{\n    //-------------------------------------------------------------------------\n    // no socket given, return system default allocate our own new socket\n    //-------------------------------------------------------------------------\n    if (m_socket != static_cast<SOCKET>(CSimpleSocket::SocketError))\n    {\n        SETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nWindowSize, sizeof(nWindowSize));\n        TranslateSocketError();\n    }\n    else\n    {\n        SetSocketError(CSimpleSocket::SocketInvalidSocket);\n    }\n\n    return nWindowSize;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// DisableNagleAlgorithm()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::DisableNagleAlgoritm()\n{\n    bool  bRetVal = false;\n    int32_t nTcpNoDelay = 1;\n\n    //----------------------------------------------------------------------\n    // Set TCP NoDelay flag to true\n    //----------------------------------------------------------------------\n    if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(int32_t)) == 0)\n    {\n        bRetVal = true;\n    }\n\n    TranslateSocketError();\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// EnableNagleAlgorithm()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::EnableNagleAlgoritm()\n{\n    bool  bRetVal = false;\n    int32_t nTcpNoDelay = 0;\n\n    //----------------------------------------------------------------------\n    // Set TCP NoDelay flag to false\n    //----------------------------------------------------------------------\n    if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(int32_t)) == 0)\n    {\n        bRetVal = true;\n    }\n\n    TranslateSocketError();\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Send() - Send data on a valid socket\n//\n//------------------------------------------------------------------------------\nint32_t CSimpleSocket::Send(const uint8_t *pBuf, size_t bytesToSend)\n{\n    SetSocketError(SocketSuccess);\n    m_nBytesSent = 0;\n\n    switch(m_nSocketType)\n    {\n    case CSimpleSocket::SocketTypeTcp:\n    {\n        if (IsSocketValid())\n        {\n            if ((bytesToSend > 0) && (pBuf != NULL))\n            {\n                m_timer.Initialize();\n                m_timer.SetStartTime();\n\n                //---------------------------------------------------------\n                // Check error condition and attempt to resend if call\n                // was interrupted by a signal.\n                //---------------------------------------------------------\n                do\n                {\n                    m_nBytesSent = SEND(m_socket, pBuf, bytesToSend, 0);\n                    TranslateSocketError();\n                } while (GetSocketError() == CSimpleSocket::SocketInterrupted);\n\n                m_timer.SetEndTime();\n            }\n        }\n        break;\n    }\n    case CSimpleSocket::SocketTypeUdp:\n    {\n        if (IsSocketValid())\n        {\n            if ((bytesToSend > 0) && (pBuf != NULL))\n            {\n                m_timer.Initialize();\n                m_timer.SetStartTime();\n\n                //---------------------------------------------------------\n                // Check error condition and attempt to resend if call\n                // was interrupted by a signal.\n                //---------------------------------------------------------\n                //                    if (GetMulticast())\n                //                    {\n                //                        do\n                //                        {\n                //                            m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stMulticastGroup,\n                //                                                  sizeof(m_stMulticastGroup));\n                //                            TranslateSocketError();\n                //                        } while (GetSocketError() == CSimpleSocket::SocketInterrupted);\n                //                    }\n                //                    else\n                {\n                    do\n                    {\n                        m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stServerSockaddr, sizeof(m_stServerSockaddr));\n                        TranslateSocketError();\n                    } while (GetSocketError() == CSimpleSocket::SocketInterrupted);\n                }\n\n                m_timer.SetEndTime();\n            }\n        }\n        break;\n    }\n    default:\n        break;\n    }\n\n    return m_nBytesSent;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Close() - Close socket and free up any memory allocated for the socket\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::Close(void)\n{\n    bool bRetVal = false;\n\n    //--------------------------------------------------------------------------\n    // delete internal buffer\n    //--------------------------------------------------------------------------\n    if (m_pBuffer != NULL)\n    {\n        delete [] m_pBuffer;\n        m_pBuffer = NULL;\n    }\n\n    //--------------------------------------------------------------------------\n    // if socket handle is currently valid, close and then invalidate\n    //--------------------------------------------------------------------------\n    if (IsSocketValid())\n    {\n\t\tShutdown(Both);\n        if (CLOSE(m_socket) != CSimpleSocket::SocketError)\n\t\t{\n\t\t\tm_socket = INVALID_SOCKET;\n\t\t\tbRetVal = true;\n\t\t}\n    }\n\n    TranslateSocketError();\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Shtudown()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::Shutdown(CShutdownMode nShutdown)\n{\n    CSocketError nRetVal = SocketEunknown;\n\n    nRetVal = (CSocketError)shutdown(m_socket, nShutdown);\n    TranslateSocketError();\n\n    return nRetVal == CSimpleSocket::SocketSuccess;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Flush()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::Flush()\n{\n    int32_t nTcpNoDelay = 1;\n    int32_t nCurFlags = 0;\n    uint8_t tmpbuf = 0;\n    bool  bRetVal = false;\n\n    //--------------------------------------------------------------------------\n    // Get the current setting of the TCP_NODELAY flag.\n    //--------------------------------------------------------------------------\n    if (GETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nCurFlags, sizeof(int32_t)) == 0)\n    {\n        //----------------------------------------------------------------------\n        // Set TCP NoDelay flag\n        //----------------------------------------------------------------------\n        if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(int32_t)) == 0)\n        {\n            //------------------------------------------------------------------\n            // Send empty byte stream to flush the TCP send buffer\n            //------------------------------------------------------------------\n            if (Send(&tmpbuf, 0) != CSimpleSocket::SocketError)\n            {\n                bRetVal = true;\n            }\n\n            TranslateSocketError();\n        }\n\n        //----------------------------------------------------------------------\n        // Reset the TCP_NODELAY flag to original state.\n        //----------------------------------------------------------------------\n        SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nCurFlags, sizeof(int32_t));\n    }\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Writev -\n//\n//------------------------------------------------------------------------------\nint32_t CSimpleSocket::Writev(const struct iovec *pVector, size_t nCount)\n{\n    int32_t nBytes     = 0;\n    int32_t nBytesSent = 0;\n    int32_t i          = 0;\n\n    //--------------------------------------------------------------------------\n    // Send each buffer as a separate send, windows does not support this\n    // function call.\n    //--------------------------------------------------------------------------\n    for (i = 0; i < (int32_t)nCount; i++)\n    {\n        if ((nBytes = Send((uint8_t *)pVector[i].iov_base, pVector[i].iov_len)) == CSimpleSocket::SocketError)\n        {\n            break;\n        }\n\n        nBytesSent += nBytes;\n    }\n\n    if (i > 0)\n    {\n        Flush();\n    }\n\n    return nBytesSent;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Send() - Send data on a valid socket via a vector of buffers.\n//\n//------------------------------------------------------------------------------\nint32_t CSimpleSocket::Send(const struct iovec *sendVector, int32_t nNumItems)\n{\n    SetSocketError(SocketSuccess);\n    m_nBytesSent = 0;\n\n    if ((m_nBytesSent = WRITEV(m_socket, sendVector, nNumItems)) == CSimpleSocket::SocketError)\n    {\n        TranslateSocketError();\n    }\n\n    return m_nBytesSent;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SetReceiveTimeout()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::SetReceiveTimeout(int32_t nRecvTimeoutSec, int32_t nRecvTimeoutUsec)\n{\n    bool bRetVal = true;\n\n    memset(&m_stRecvTimeout, 0, sizeof(struct timeval));\n\n    m_stRecvTimeout.tv_sec = nRecvTimeoutSec;\n    m_stRecvTimeout.tv_usec = nRecvTimeoutUsec;\n\n    //--------------------------------------------------------------------------\n    // Sanity check to make sure the options are supported!\n    //--------------------------------------------------------------------------\n    if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_RCVTIMEO, &m_stRecvTimeout,\n                   sizeof(struct timeval)) == CSimpleSocket::SocketError)\n    {\n        bRetVal = false;\n        TranslateSocketError();\n    }\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SetSendTimeout()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::SetSendTimeout(int32_t nSendTimeoutSec, int32_t nSendTimeoutUsec)\n{\n    bool bRetVal = true;\n\n    memset(&m_stSendTimeout, 0, sizeof(struct timeval));\n    m_stSendTimeout.tv_sec = nSendTimeoutSec;\n    m_stSendTimeout.tv_usec = nSendTimeoutUsec;\n\n    //--------------------------------------------------------------------------\n    // Sanity check to make sure the options are supported!\n    //--------------------------------------------------------------------------\n    if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_SNDTIMEO, &m_stSendTimeout,\n                   sizeof(struct timeval)) == CSimpleSocket::SocketError)\n    {\n        bRetVal = false;\n        TranslateSocketError();\n    }\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SetOptionReuseAddr()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::SetOptionReuseAddr()\n{\n    bool  bRetVal = false;\n    int32_t nReuse  = IPTOS_LOWDELAY;\n\n    if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(int32_t)) == 0)\n    {\n        bRetVal = true;\n    }\n\n    TranslateSocketError();\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SetOptionLinger()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::SetOptionLinger(bool bEnable, uint16_t nTime)\n{\n    bool bRetVal = false;\n\n    m_stLinger.l_onoff = (bEnable == true) ? 1: 0;\n    m_stLinger.l_linger = nTime;\n\n    if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_LINGER, &m_stLinger, sizeof(m_stLinger)) == 0)\n    {\n        bRetVal = true;\n    }\n\n    TranslateSocketError();\n\n    return bRetVal;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// Receive() - Attempts to receive a block of data on an established\n//             connection.    Data is received in an internal buffer managed\n//             by the class.  This buffer is only valid until the next call\n//             to Receive(), a call to Close(), or until the object goes out\n//             of scope.\n//\n//------------------------------------------------------------------------------\nint32_t CSimpleSocket::Receive(int32_t nMaxBytes, uint8_t * pBuffer )\n{\n    m_nBytesReceived = 0;\n\n    //--------------------------------------------------------------------------\n    // If the socket is invalid then return false.\n    //--------------------------------------------------------------------------\n    if (IsSocketValid() == false)\n    {\n        return m_nBytesReceived;\n    }\n\n    uint8_t * pWorkBuffer = pBuffer;\n    if ( pBuffer == NULL )\n    {\n        //--------------------------------------------------------------------------\n        // Free existing buffer and allocate a new buffer the size of\n        // nMaxBytes.\n        //--------------------------------------------------------------------------\n        if ((m_pBuffer != NULL) && (nMaxBytes != m_nBufferSize))\n        {\n            delete [] m_pBuffer;\n            m_pBuffer = NULL;\n        }\n\n        //--------------------------------------------------------------------------\n        // Allocate a new internal buffer to receive data.\n        //--------------------------------------------------------------------------\n        if (m_pBuffer == NULL)\n        {\n            m_nBufferSize = nMaxBytes;\n            m_pBuffer = new uint8_t[nMaxBytes];\n        }\n\n        pWorkBuffer = m_pBuffer;\n    }\n\n    SetSocketError(SocketSuccess);\n\n    m_timer.Initialize();\n    m_timer.SetStartTime();\n\n    switch (m_nSocketType)\n    {\n        //----------------------------------------------------------------------\n        // If zero bytes are received, then return.  If SocketERROR is\n        // received, free buffer and return CSocket::SocketError (-1) to caller.\n        //----------------------------------------------------------------------\n    case CSimpleSocket::SocketTypeTcp:\n    {\n        do\n        {\n            m_nBytesReceived = RECV(m_socket, (pWorkBuffer + m_nBytesReceived),\n                                    nMaxBytes, m_nFlags);\n            TranslateSocketError();\n        } while ((GetSocketError() == CSimpleSocket::SocketInterrupted));\n\n        break;\n    }\n    case CSimpleSocket::SocketTypeUdp:\n    {\n        uint32_t srcSize;\n\n        srcSize = sizeof(struct sockaddr_in);\n\n        if (GetMulticast() == true)\n        {\n            do\n            {\n                m_nBytesReceived = RECVFROM(m_socket, pWorkBuffer, nMaxBytes, 0,\n                                            &m_stMulticastGroup, &srcSize);\n                TranslateSocketError();\n            } while (GetSocketError() == CSimpleSocket::SocketInterrupted);\n        }\n        else\n        {\n            do\n            {\n                m_nBytesReceived = RECVFROM(m_socket, pWorkBuffer, nMaxBytes, 0,\n                                            &m_stClientSockaddr, &srcSize);\n                TranslateSocketError();\n            } while (GetSocketError() == CSimpleSocket::SocketInterrupted);\n        }\n\n        break;\n    }\n    default:\n        break;\n    }\n\n    m_timer.SetEndTime();\n    TranslateSocketError();\n\n    //--------------------------------------------------------------------------\n    // If we encounter an error translate the error code and return.  One\n    // possible error code could be EAGAIN (EWOULDBLOCK) if the socket is\n    // non-blocking.  This does not mean there is an error, but no data is\n    // yet available on the socket.\n    //--------------------------------------------------------------------------\n    if (m_nBytesReceived == CSimpleSocket::SocketError)\n    {\n        if (m_pBuffer != NULL)\n        {\n            delete [] m_pBuffer;\n            m_pBuffer = NULL;\n        }\n    }\n\n    return m_nBytesReceived;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SetNonblocking()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::SetNonblocking(void)\n{\n    int32_t  nCurFlags;\n\n#ifdef _WIN32\n    nCurFlags = 1;\n\n    if (ioctlsocket(m_socket, FIONBIO, (ULONG *)&nCurFlags) != 0)\n    {\n        TranslateSocketError();\n        return false;\n    }\n#else\n    if ((nCurFlags = fcntl(m_socket, F_GETFL)) < 0)\n    {\n        TranslateSocketError();\n        return false;\n    }\n\n    nCurFlags |= O_NONBLOCK;\n\n    if (fcntl(m_socket, F_SETFL, nCurFlags) != 0)\n    {\n        TranslateSocketError();\n        return false;\n    }\n#endif\n\n    m_bIsBlocking = false;\n\n    return true;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SetBlocking()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::SetBlocking(void)\n{\n    int32_t nCurFlags;\n\n#ifdef _WIN32\n    nCurFlags = 0;\n\n    if (ioctlsocket(m_socket, FIONBIO, (ULONG *)&nCurFlags) != 0)\n    {\n        return false;\n    }\n#else\n    if ((nCurFlags = fcntl(m_socket, F_GETFL)) < 0)\n    {\n        TranslateSocketError();\n        return false;\n    }\n\n    nCurFlags &= (~O_NONBLOCK);\n\n    if (fcntl(m_socket, F_SETFL, nCurFlags) != 0)\n    {\n        TranslateSocketError();\n        return false;\n    }\n#endif\n    m_bIsBlocking = true;\n\n    return true;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// SendFile() - stands-in for system provided sendfile\n//\n//------------------------------------------------------------------------------\nint32_t CSimpleSocket::SendFile(int32_t nOutFd, int32_t nInFd, off_t *pOffset, int32_t nCount)\n{\n    int32_t  nOutCount = CSimpleSocket::SocketError;\n\n    static char szData[SOCKET_SENDFILE_BLOCKSIZE];\n    int32_t       nInCount = 0;\n\n    if (lseek(nInFd, *pOffset, SEEK_SET) == -1)\n    {\n        return -1;\n    }\n\n    while (nOutCount < nCount)\n    {\n        nInCount = (nCount - nOutCount) < SOCKET_SENDFILE_BLOCKSIZE ? (nCount - nOutCount) : SOCKET_SENDFILE_BLOCKSIZE;\n\n        if ((read(nInFd, szData, nInCount)) != (int32_t)nInCount)\n        {\n            return -1;\n        }\n\n        if ((SEND(nOutFd, szData, nInCount, 0)) != (int32_t)nInCount)\n        {\n            return -1;\n        }\n\n        nOutCount += nInCount;\n    }\n\n    *pOffset += nOutCount;\n\n    TranslateSocketError();\n\n    return nOutCount;\n}\n\n\n//------------------------------------------------------------------------------\n//\n// TranslateSocketError() -\n//\n//------------------------------------------------------------------------------\nvoid CSimpleSocket::TranslateSocketError(void)\n{\n#if defined(__linux__) || defined(_DARWIN)\n    switch (errno)\n    {\n    case EXIT_SUCCESS:\n        SetSocketError(CSimpleSocket::SocketSuccess);\n        break;\n    case ENOTCONN:\n        SetSocketError(CSimpleSocket::SocketNotconnected);\n        break;\n    case ENOTSOCK:\n    case EBADF:\n    case EACCES:\n    case EAFNOSUPPORT:\n    case EMFILE:\n    case ENFILE:\n    case ENOBUFS:\n    case ENOMEM:\n    case EPROTONOSUPPORT:\n    case EPIPE:\n        SetSocketError(CSimpleSocket::SocketInvalidSocket);\n        break;\n    case ECONNREFUSED :\n        SetSocketError(CSimpleSocket::SocketConnectionRefused);\n        break;\n    case ETIMEDOUT:\n        SetSocketError(CSimpleSocket::SocketTimedout);\n        break;\n    case EINPROGRESS:\n        SetSocketError(CSimpleSocket::SocketEinprogress);\n        break;\n    case EWOULDBLOCK:\n        //        case EAGAIN:\n        SetSocketError(CSimpleSocket::SocketEwouldblock);\n        break;\n    case EINTR:\n        SetSocketError(CSimpleSocket::SocketInterrupted);\n        break;\n    case ECONNABORTED:\n        SetSocketError(CSimpleSocket::SocketConnectionAborted);\n        break;\n    case EINVAL:\n    case EPROTO:\n        SetSocketError(CSimpleSocket::SocketProtocolError);\n        break;\n    case EPERM:\n        SetSocketError(CSimpleSocket::SocketFirewallError);\n        break;\n    case EFAULT:\n        SetSocketError(CSimpleSocket::SocketInvalidSocketBuffer);\n        break;\n    case ECONNRESET:\n    case ENOPROTOOPT:\n        SetSocketError(CSimpleSocket::SocketConnectionReset);\n        break;\n    default:\n        SetSocketError(CSimpleSocket::SocketEunknown);\n        break;\n    }\n#endif\n#ifdef _WIN32\n    int32_t nError = WSAGetLastError();\n    switch (nError)\n    {\n    case EXIT_SUCCESS:\n        SetSocketError(CSimpleSocket::SocketSuccess);\n        break;\n    case WSAEBADF:\n    case WSAENOTCONN:\n        SetSocketError(CSimpleSocket::SocketNotconnected);\n        break;\n    case WSAEINTR:\n        SetSocketError(CSimpleSocket::SocketInterrupted);\n        break;\n    case WSAEACCES:\n    case WSAEAFNOSUPPORT:\n    case WSAEINVAL:\n    case WSAEMFILE:\n    case WSAENOBUFS:\n    case WSAEPROTONOSUPPORT:\n        SetSocketError(CSimpleSocket::SocketInvalidSocket);\n        break;\n    case WSAECONNREFUSED :\n        SetSocketError(CSimpleSocket::SocketConnectionRefused);\n        break;\n    case WSAETIMEDOUT:\n        SetSocketError(CSimpleSocket::SocketTimedout);\n        break;\n    case WSAEINPROGRESS:\n        SetSocketError(CSimpleSocket::SocketEinprogress);\n        break;\n    case WSAECONNABORTED:\n        SetSocketError(CSimpleSocket::SocketConnectionAborted);\n        break;\n    case WSAEWOULDBLOCK:\n        SetSocketError(CSimpleSocket::SocketEwouldblock);\n        break;\n    case WSAENOTSOCK:\n        SetSocketError(CSimpleSocket::SocketInvalidSocket);\n        break;\n    case WSAECONNRESET:\n        SetSocketError(CSimpleSocket::SocketConnectionReset);\n        break;\n    case WSANO_DATA:\n        SetSocketError(CSimpleSocket::SocketInvalidAddress);\n        break;\n    case WSAEADDRINUSE:\n        SetSocketError(CSimpleSocket::SocketAddressInUse);\n        break;\n    case WSAEFAULT:\n        SetSocketError(CSimpleSocket::SocketInvalidPointer);\n        break;\n    default:\n        SetSocketError(CSimpleSocket::SocketEunknown);\n        break;\n    }\n#endif\n}\n\n//------------------------------------------------------------------------------\n//\n// DescribeError()\n//\n//------------------------------------------------------------------------------\n\nconst char *CSimpleSocket::DescribeError(CSocketError err)\n{\n    switch (err) {\n        case CSimpleSocket::SocketError:\n            return \"Generic socket error translates to error below.\";\n        case CSimpleSocket::SocketSuccess:\n            return \"No socket error.\";\n        case CSimpleSocket::SocketInvalidSocket:\n            return \"Invalid socket handle.\";\n        case CSimpleSocket::SocketInvalidAddress:\n            return \"Invalid destination address specified.\";\n        case CSimpleSocket::SocketInvalidPort:\n            return \"Invalid destination port specified.\";\n        case CSimpleSocket::SocketConnectionRefused:\n            return \"No server is listening at remote address.\";\n        case CSimpleSocket::SocketTimedout:\n            return \"Timed out while attempting operation.\";\n        case CSimpleSocket::SocketEwouldblock:\n            return \"Operation would block if socket were blocking.\";\n        case CSimpleSocket::SocketNotconnected:\n            return \"Currently not connected.\";\n        case CSimpleSocket::SocketEinprogress:\n            return \"Socket is non-blocking and the connection cannot be completed immediately\";\n        case CSimpleSocket::SocketInterrupted:\n            return \"Call was interrupted by a signal that was caught before a valid connection arrived.\";\n        case CSimpleSocket::SocketConnectionAborted:\n            return \"The connection has been aborted.\";\n        case CSimpleSocket::SocketProtocolError:\n            return \"Invalid protocol for operation.\";\n        case CSimpleSocket::SocketFirewallError:\n            return \"Firewall rules forbid connection.\";\n        case CSimpleSocket::SocketInvalidSocketBuffer:\n            return \"The receive buffer point outside the process's address space.\";\n        case CSimpleSocket::SocketConnectionReset:\n            return \"Connection was forcibly closed by the remote host.\";\n        case CSimpleSocket::SocketAddressInUse:\n            return \"Address already in use.\";\n        case CSimpleSocket::SocketInvalidPointer:\n            return \"Pointer type supplied as argument is invalid.\";\n        case CSimpleSocket::SocketEunknown:\n            return \"Unknown error\";\n        default:\n            return \"No such CSimpleSocket error\";\n    }\n}\n\n//------------------------------------------------------------------------------\n//\n// Select()\n//\n//------------------------------------------------------------------------------\nbool CSimpleSocket::Select(int32_t nTimeoutSec, int32_t nTimeoutUSec)\n{\n    bool            bRetVal = false;\n    struct timeval *pTimeout = NULL;\n    struct timeval  timeout;\n    int32_t           nNumDescriptors = -1;\n    int32_t           nError = 0;\n\n    FD_ZERO(&m_errorFds);\n    FD_ZERO(&m_readFds);\n    FD_ZERO(&m_writeFds);\n    FD_SET(m_socket, &m_errorFds);\n    FD_SET(m_socket, &m_readFds);\n    FD_SET(m_socket, &m_writeFds);\n\n    //---------------------------------------------------------------------\n    // If timeout has been specified then set value, otherwise set timeout\n    // to NULL which will block until a descriptor is ready for read/write\n    // or an error has occurred.\n    //---------------------------------------------------------------------\n    if ((nTimeoutSec > 0) || (nTimeoutUSec > 0))\n    {\n        timeout.tv_sec = nTimeoutSec;\n        timeout.tv_usec = nTimeoutUSec;\n        pTimeout = &timeout;\n    }\n\n    nNumDescriptors = SELECT(m_socket+1, &m_readFds, &m_writeFds, &m_errorFds, pTimeout);\n//    nNumDescriptors = SELECT(m_socket+1, &m_readFds, NULL, NULL, pTimeout);\n\n    //----------------------------------------------------------------------\n    // Handle timeout\n    //----------------------------------------------------------------------\n    if (nNumDescriptors == 0)\n    {\n        SetSocketError(CSimpleSocket::SocketTimedout);\n    }\n    //----------------------------------------------------------------------\n    // If a file descriptor (read/write) is set then check the\n    // socket error (SO_ERROR) to see if there is a pending error.\n    //----------------------------------------------------------------------\n    else if ((FD_ISSET(m_socket, &m_readFds)) || (FD_ISSET(m_socket, &m_writeFds)))\n    {\n        int32_t nLen = sizeof(nError);\n\n        if (GETSOCKOPT(m_socket, SOL_SOCKET, SO_ERROR, &nError, &nLen) == 0)\n        {\n            errno = nError;\n\n            if (nError == 0)\n            {\n                bRetVal = true;\n            }\n        }\n\n        TranslateSocketError();\n    }\n\n    return bRetVal;\n}\n\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/clsocket/src/SimpleSocket.h",
    "content": "/*---------------------------------------------------------------------------*/\n/*                                                                           */\n/* SimpleSocket.h - Simple Socket base class decleration.                    */\n/*                                                                           */\n/* Author : Mark Carrier (mark@carrierlabs.com)                              */\n/*                                                                           */\n/*---------------------------------------------------------------------------*/\n/* Copyright (c) 2007-2009 CarrierLabs, LLC.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * 4. The name \"CarrierLabs\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    mark@carrierlabs.com.\n *\n * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MARK CARRIER OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *----------------------------------------------------------------------------*/\n#ifndef __SOCKET_H__\n#define __SOCKET_H__\n\n#include <sys/stat.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <errno.h>\n\n#if defined(__linux__) || defined (_DARWIN)\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#include <netinet/tcp.h>\n#include <netinet/ip.h>\n#include <netdb.h>\n#endif\n#ifdef __linux__\n#include <linux/if_packet.h>\n#include <linux/if_ether.h>\n#include <linux/if.h>\n#include <sys/sendfile.h>\n#endif\n#ifdef _DARWIN\n#include <net/if.h>\n#endif\n#if defined(__linux__) || defined (_DARWIN)\n#include <sys/time.h>\n#include <sys/uio.h>\n#include <unistd.h>\n#include <fcntl.h>\n#endif\n\n#ifdef _WIN32\n#pragma warning( push )\n#pragma warning( disable:4668 )\n\t#include <io.h>\n\t#include <winsock2.h>\n\t#include <Ws2tcpip.h>\n#pragma warning( pop )\n\n#define IPTOS_LOWDELAY  0x10\n\n#endif\n#include \"Host.h\"\n#include \"StatTimer.h\"\n\n//-----------------------------------------------------------------------------\n// General class macro definitions and typedefs\n//-----------------------------------------------------------------------------\n#ifndef INVALID_SOCKET\n#define INVALID_SOCKET    ~(0)\n#endif\n\n#define SOCKET_SENDFILE_BLOCKSIZE 8192\n\n/// Provides a platform independent class to for socket development.\n/// This class is designed to abstract socket communication development in a\n/// platform independent manner.\n/// - Socket types\n///  -# CActiveSocket Class\n///  -# CPassiveSocket Class\nclass CSimpleSocket {\npublic:\n    /// Defines the three possible states for shuting down a socket.\n    typedef enum\n    {\n        Receives = SHUT_RD, ///< Shutdown passive socket.\n        Sends = SHUT_WR,    ///< Shutdown active socket.\n        Both = SHUT_RDWR    ///< Shutdown both active and passive sockets.\n    } CShutdownMode;\n\n    /// Defines the socket types defined by CSimpleSocket class.\n    typedef enum\n    {\n        SocketTypeInvalid,   ///< Invalid socket type.\n        SocketTypeTcp,       ///< Defines socket as TCP socket.\n        SocketTypeUdp,       ///< Defines socket as UDP socket.\n        SocketTypeTcp6,      ///< Defines socket as IPv6 TCP socket.\n        SocketTypeUdp6,      ///< Defines socket as IPv6 UDP socket.\n        SocketTypeRaw        ///< Provides raw network protocol access.\n    } CSocketType;\n\n    /// Defines all error codes handled by the CSimpleSocket class.\n    typedef enum\n    {\n        SocketError = -1,          ///< Generic socket error translates to error below.\n        SocketSuccess = 0,         ///< No socket error.\n        SocketInvalidSocket,       ///< Invalid socket handle.\n        SocketInvalidAddress,      ///< Invalid destination address specified.\n        SocketInvalidPort,         ///< Invalid destination port specified.\n        SocketConnectionRefused,   ///< No server is listening at remote address.\n        SocketTimedout,            ///< Timed out while attempting operation.\n        SocketEwouldblock,         ///< Operation would block if socket were blocking.\n        SocketNotconnected,        ///< Currently not connected.\n        SocketEinprogress,         ///< Socket is non-blocking and the connection cannot be completed immediately\n        SocketInterrupted,         ///< Call was interrupted by a signal that was caught before a valid connection arrived.\n        SocketConnectionAborted,   ///< The connection has been aborted.\n        SocketProtocolError,       ///< Invalid protocol for operation.\n        SocketFirewallError,       ///< Firewall rules forbid connection.\n        SocketInvalidSocketBuffer, ///< The receive buffer point outside the process's address space.\n        SocketConnectionReset,     ///< Connection was forcibly closed by the remote host.\n        SocketAddressInUse,        ///< Address already in use.\n        SocketInvalidPointer,      ///< Pointer type supplied as argument is invalid.\n        SocketEunknown             ///< Unknown error please report to mark@carrierlabs.com\n    } CSocketError;\n\npublic:\n    CSimpleSocket(CSocketType type = SocketTypeTcp);\n    CSimpleSocket(CSimpleSocket &socket);\n\n    CSimpleSocket(CSimpleSocket &&socket) noexcept = default;\n    CSimpleSocket& operator=(CSimpleSocket &&socket) noexcept = default;\n\n    virtual ~CSimpleSocket()\n    {\n        if (m_pBuffer != NULL)\n        {\n            delete [] m_pBuffer;\n            m_pBuffer = NULL;\n        }\n    };\n\n    /// Initialize instance of CSocket.  This method MUST be called before an\n    /// object can be used. Errors : CSocket::SocketProtocolError,\n    /// CSocket::SocketInvalidSocket,\n    /// @return true if properly initialized.\n    virtual bool Initialize(void);\n\n    /// Close socket\n    /// @return true if successfully closed otherwise returns false.\n    virtual bool Close(void);\n\n    /// Shutdown shut down socket send and receive operations\n    ///    CShutdownMode::Receives - Disables further receive operations.\n    ///    CShutdownMode::Sends    - Disables further send operations.\n    ///    CShutdownBoth::         - Disables further send and receive operations.\n    /// @param nShutdown specifies the type of shutdown.\n    /// @return true if successfully shutdown otherwise returns false.\n    virtual bool Shutdown(CShutdownMode nShutdown);\n\n    /// Examine the socket descriptor sets currently owned by the instance of\n    /// the socket class (the readfds, writefds, and errorfds parameters) to\n    /// see whether some of their descriptors are ready for reading, are ready\n    /// for writing, or have an exceptional condition pending, respectively.\n    /// Block until an event happens on the specified file descriptors.\n    /// @return true if socket has data ready, or false if not ready or timed out.\n    virtual bool Select(void) {\n        return Select(0,0);\n    };\n\n    /// Examine the socket descriptor sets currently owned by the instance of\n    /// the socket class (the readfds, writefds, and errorfds parameters) to\n    /// see whether some of their descriptors are ready for reading, are ready\n    /// for writing, or have an exceptional condition pending, respectively.\n    /// @param nTimeoutSec timeout in seconds for select.\n    /// @param nTimeoutUSec timeout in micro seconds for select.\n    /// @return true if socket has data ready, or false if not ready or timed out.\n    virtual bool Select(int32_t nTimeoutSec, int32_t nTimeoutUSec);\n\n    /// Does the current instance of the socket object contain a valid socket\n    /// descriptor.\n    ///  @return true if the socket object contains a valid socket descriptor.\n    virtual bool IsSocketValid(void) {\n        return (m_socket != static_cast<SOCKET>(SocketError));\n    };\n\n    /// Provides a standard error code for cross platform development by\n    /// mapping the operating system error to an error defined by the CSocket\n    /// class.\n    void TranslateSocketError(void);\n\n    /// Returns a human-readable description of the given error code\n    /// or the last error code of a socket\n    static const char *DescribeError(CSocketError err);\n    inline const char *DescribeError() {\n        return DescribeError(m_socketErrno);\n    };\n\n    /// Attempts to receive a block of data on an established connection.\n    /// @param nMaxBytes maximum number of bytes to receive.\n    /// @param pBuffer, memory where to receive the data,\n    ///        NULL receives to internal buffer returned with GetData()\n    ///        Non-NULL receives directly there, but GetData() will return WRONG ptr!\n    /// @return number of bytes actually received.\n    /// @return of zero means the connection has been shutdown on the other side.\n    /// @return of -1 means that an error has occurred.\n    virtual int32_t Receive(int32_t nMaxBytes = 1, uint8_t * pBuffer = 0);\n\n    /// Attempts to send a block of data on an established connection.\n    /// @param pBuf block of data to be sent.\n    /// @param bytesToSend size of data block to be sent.\n    /// @return number of bytes actually sent.\n    /// @return of zero means the connection has been shutdown on the other side.\n    /// @return of -1 means that an error has occurred.\n    virtual int32_t Send(const uint8_t *pBuf, size_t bytesToSend);\n\n    /// Attempts to send at most nNumItem blocks described by sendVector\n    /// to the socket descriptor associated with the socket object.\n    /// @param sendVector pointer to an array of iovec structures\n    /// @param nNumItems number of items in the vector to process\n    /// <br>\\b NOTE: Buffers are processed in the order specified.\n    /// @return number of bytes actually sent, return of zero means the\n    /// connection has been shutdown on the other side, and a return of -1\n    /// means that an error has occurred.\n    virtual int32_t Send(const struct iovec *sendVector, int32_t nNumItems);\n\n    /// Copies data between one file descriptor and another.\n    /// On some systems this copying is done within the kernel, and thus is\n    /// more efficient than the combination of CSimpleSocket::Send and\n    /// CSimpleSocket::Receive, which would require transferring data to and\n    /// from user space.\n    /// <br>\\b Note: This is available on all implementations, but the kernel\n    /// implementation is only available on Unix type systems.\n    /// @param nOutFd descriptor opened for writing.\n    /// @param nInFd descriptor opened for reading.\n    /// @param pOffset from which to start reading data from input file.\n    /// @param nCount number of bytes to copy between file descriptors.\n    /// @return number of bytes written to the out socket descriptor.\n    virtual int32_t SendFile(int32_t nOutFd, int32_t nInFd, off_t *pOffset, int32_t nCount);\n\n    /// Returns blocking/non-blocking state of socket.\n    /// @return true if the socket is non-blocking, else return false.\n    bool IsNonblocking(void) {\n        return (m_bIsBlocking == false);\n    };\n\n    /// Set the socket to blocking.\n    /// @return true if successful set to blocking, else return false;\n    bool SetBlocking(void);\n\n    /// Set the socket as non-blocking.\n    /// @return true if successful set to non-blocking, else return false;\n    bool SetNonblocking(void);\n\n    /// Get a pointer to internal receive buffer.  The user MUST not free this\n    /// pointer when finished.  This memory is managed internally by the CSocket\n    /// class.\n    /// @return pointer to data if valid, else returns NULL.\n    uint8_t *GetData(void)  {\n        return m_pBuffer;\n    };\n\n    /// Returns the number of bytes received on the last call to\n    /// CSocket::Receive().\n    /// @return number of bytes received.\n    int32_t GetBytesReceived(void) {\n        return m_nBytesReceived;\n    };\n\n    /// Returns the number of bytes sent on the last call to\n    /// CSocket::Send().\n    /// @return number of bytes sent.\n    int32_t GetBytesSent(void) {\n        return m_nBytesSent;\n    };\n\n    /// Controls the actions taken when CSimpleSocket::Close is executed on a\n    /// socket object that has unsent data.  The default value for this option\n    /// is \\b off.\n    /// - Following are the three possible scenarios.\n    ///  -# \\b bEnable is false, CSimpleSocket::Close returns immediately, but\n    ///  any unset data is transmitted (after CSimpleSocket::Close returns)\n    ///  -# \\b bEnable is true and \\b nTime is zero, CSimpleSocket::Close return\n    /// immediately and any unsent data is discarded.\n    ///  -# \\b bEnable is true and \\b nTime is nonzero, CSimpleSocket::Close does\n    ///  not return until all unsent data is transmitted (or the connection is\n    ///  Closed by the remote system).\n    /// <br><p>\n    /// @param bEnable true to enable option false to disable option.\n    /// @param nTime time in seconds to linger.\n    /// @return true if option successfully set\n    bool SetOptionLinger(bool bEnable, uint16_t nTime);\n\n    /// Tells the kernel that even if this port is busy (in the TIME_WAIT state),\n    /// go ahead and reuse it anyway.  If it is busy, but with another state,\n    /// you will still get an address already in use error.\n    /// @return true if option successfully set\n    bool SetOptionReuseAddr();\n\n    /// Gets the timeout value that specifies the maximum number of seconds a\n    /// call to CSimpleSocket::Open waits until it completes.\n    /// @return the length of time in seconds\n    int32_t GetConnectTimeoutSec(void) {\n        return  m_stConnectTimeout.tv_sec;\n    };\n\n    /// Gets the timeout value that specifies the maximum number of microseconds\n    /// a call to CSimpleSocket::Open waits until it completes.\n    /// @return the length of time in microseconds\n    int32_t GetConnectTimeoutUSec(void) {\n        return  m_stConnectTimeout.tv_usec;\n    };\n\n    /// Sets the timeout value that specifies the maximum amount of time a call\n    /// to CSimpleSocket::Receive waits until it completes. Use the method\n    /// CSimpleSocket::SetReceiveTimeout to specify the number of seconds to wait.\n    /// If a call to CSimpleSocket::Receive has blocked for the specified length of\n    /// time without receiving additional data, it returns with a partial count\n    /// or CSimpleSocket::GetSocketError set to CSimpleSocket::SocketEwouldblock if no data\n    /// were received.\n    /// @param nConnectTimeoutSec of timeout in seconds.\n    /// @param nConnectTimeoutUsec of timeout in microseconds.\n    /// @return true if socket connection timeout was successfully set.\n    void SetConnectTimeout(int32_t nConnectTimeoutSec, int32_t nConnectTimeoutUsec = 0)\n    {\n        m_stConnectTimeout.tv_sec = nConnectTimeoutSec;\n        m_stConnectTimeout.tv_usec = nConnectTimeoutUsec;\n    };\n\n    /// Gets the timeout value that specifies the maximum number of seconds a\n    /// a call to CSimpleSocket::Receive waits until it completes.\n    /// @return the length of time in seconds\n    int32_t GetReceiveTimeoutSec(void) {\n        return  m_stRecvTimeout.tv_sec;\n    };\n\n    /// Gets the timeout value that specifies the maximum number of microseconds\n    /// a call to CSimpleSocket::Receive waits until it completes.\n    /// @return the length of time in microseconds\n    int32_t GetReceiveTimeoutUSec(void) {\n        return  m_stRecvTimeout.tv_usec;\n    };\n\n    /// Sets the timeout value that specifies the maximum amount of time a call\n    /// to CSimpleSocket::Receive waits until it completes. Use the method\n    /// CSimpleSocket::SetReceiveTimeout to specify the number of seconds to wait.\n    /// If a call to CSimpleSocket::Receive has blocked for the specified length of\n    /// time without receiving additional data, it returns with a partial count\n    /// or CSimpleSocket::GetSocketError set to CSimpleSocket::SocketEwouldblock if no data\n    /// were received.\n    ///  @param nRecvTimeoutSec of timeout in seconds.\n    ///  @param nRecvTimeoutUsec of timeout in microseconds.\n    ///  @return true if socket timeout was successfully set.\n    bool SetReceiveTimeout(int32_t nRecvTimeoutSec, int32_t nRecvTimeoutUsec = 0);\n\n    /// Enable/disable multicast for a socket.  This options is only valid for\n    /// socket descriptors of type CSimpleSocket::SocketTypeUdp.\n    /// @return true if multicast was enabled or false if socket type is not\n    /// CSimpleSocket::SocketTypeUdp and the error will be set to\n    /// CSimpleSocket::SocketProtocolError\n    bool SetMulticast(bool bEnable, uint8_t multicastTTL = 1);\n\n    /// Return true if socket is multicast or false is socket is unicast\n    /// @return true if multicast is enabled\n    bool GetMulticast() {\n        return m_bIsMulticast;\n    };\n\n    /// Bind socket to a specific interface when using multicast.\n    /// @return true if successfully bound to interface\n    bool BindInterface(const char *pInterface);\n\n    /// Gets the timeout value that specifies the maximum number of seconds a\n    /// a call to CSimpleSocket::Send waits until it completes.\n    /// @return the length of time in seconds\n    int32_t GetSendTimeoutSec(void) {\n        return  m_stSendTimeout.tv_sec;\n    };\n\n    /// Gets the timeout value that specifies the maximum number of microseconds\n    /// a call to CSimpleSocket::Send waits until it completes.\n    /// @return the length of time in microseconds\n    int32_t GetSendTimeoutUSec(void) {\n        return  m_stSendTimeout.tv_usec;\n    };\n\n    /// Gets the timeout value that specifies the maximum amount of time a call\n    /// to CSimpleSocket::Send waits until it completes.\n    /// @return the length of time in seconds\n    bool SetSendTimeout(int32_t nSendTimeoutSec, int32_t nSendTimeoutUsec = 0);\n\n    /// Returns the last error that occured for the instace of the CSimpleSocket\n    /// instance.  This method should be called immediately to retrieve the\n    /// error code for the failing mehtod call.\n    ///  @return last error that occured.\n    CSocketError GetSocketError(void) {\n        return m_socketErrno;\n    };\n\n    /// Get the total time the of the last operation in milliseconds.\n    ///  @return number of milliseconds of last operation.\n    uint32_t GetTotalTimeMs() {\n        return m_timer.GetMilliSeconds();\n    };\n\n    /// Get the total time the of the last operation in microseconds.\n    ///  @return number of microseconds or last operation.\n    uint32_t GetTotalTimeUsec() {\n        return m_timer.GetMicroSeconds();\n    };\n\n    /// Return Differentiated Services Code Point (DSCP) value currently set on the socket object.\n    /// @return DSCP for current socket object.\n    /// <br><br> \\b NOTE: Windows special notes http://support.microsoft.com/kb/248611.\n    int GetSocketDscp(void);\n\n    /// Set Differentiated Services Code Point (DSCP) for socket object.\n    ///  @param nDscp value of TOS setting which will be converted to DSCP\n    ///  @return true if DSCP value was properly set\n    /// <br><br> \\b NOTE: Windows special notes http://support.microsoft.com/kb/248611.\n    bool SetSocketDscp(int nDscp);\n\n    /// Return socket descriptor\n    ///  @return socket descriptor which is a signed 32 bit integer.\n    SOCKET GetSocketDescriptor() {\n        return m_socket;\n    };\n\n    /// Return socket descriptor\n    ///  @return socket descriptor which is a signed 32 bit integer.\n    CSocketType GetSocketType() {\n        return m_nSocketType;\n    };\n\n    /// Returns clients Internet host address as a string in standard numbers-and-dots notation.\n    ///  @return NULL if invalid\n    const char *GetClientAddr() {\n        return inet_ntoa(m_stClientSockaddr.sin_addr);\n    };\n\n    /// Returns the port number on which the client is connected.\n    ///  @return client port number.\n    uint16_t GetClientPort() {\n        return m_stClientSockaddr.sin_port;\n    };\n\n    /// Returns server Internet host address as a string in standard numbers-and-dots notation.\n    ///  @return NULL if invalid\n    const char *GetServerAddr() {\n        return inet_ntoa(m_stServerSockaddr.sin_addr);\n    };\n\n    /// Returns the port number on which the server is connected.\n    ///  @return server port number.\n    uint16_t GetServerPort() {\n        return ntohs(m_stServerSockaddr.sin_port);\n    };\n\n    /// Get the TCP receive buffer window size for the current socket object.\n    /// <br><br>\\b NOTE: Linux will set the receive buffer to twice the value passed.\n    ///  @return zero on failure else the number of bytes of the TCP receive buffer window size if successful.\n    uint32_t GetReceiveWindowSize() {\n        return GetWindowSize(SO_RCVBUF);\n    };\n\n    /// Get the TCP send buffer window size for the current socket object.\n    /// <br><br>\\b NOTE: Linux will set the send buffer to twice the value passed.\n    ///  @return zero on failure else the number of bytes of the TCP receive buffer window size if successful.\n    uint32_t GetSendWindowSize() {\n        return GetWindowSize(SO_SNDBUF);\n    };\n\n    /// Set the TCP receive buffer window size for the current socket object.\n    /// <br><br>\\b NOTE: Linux will set the receive buffer to twice the value passed.\n    ///  @return zero on failure else the number of bytes of the TCP send buffer window size if successful.\n    uint32_t SetReceiveWindowSize(uint32_t nWindowSize) {\n        return SetWindowSize(SO_RCVBUF, nWindowSize);\n    };\n\n    /// Set the TCP send buffer window size for the current socket object.\n    /// <br><br>\\b NOTE: Linux will set the send buffer to twice the value passed.\n    ///  @return zero on failure else the number of bytes of the TCP send buffer window size if successful.\n    uint32_t SetSendWindowSize(uint32_t nWindowSize) {\n        return SetWindowSize(SO_SNDBUF, nWindowSize);\n    };\n\n    /// Disable the Nagle algorithm (Set TCP_NODELAY to true)\n    /// @return false if failed to set socket option otherwise return true;\n    bool DisableNagleAlgoritm();\n\n    /// Enable the Nagle algorithm (Set TCP_NODELAY to false)\n    /// @return false if failed to set socket option otherwise return true;\n    bool EnableNagleAlgoritm();\n\n\n    /// Flush the socket descriptor owned by the object.\n    /// @return true data was successfully sent, else return false;\n    bool Flush();\n\nprotected:\n    /// Set internal socket error to that specified error\n    ///  @param error type of error\n    void SetSocketError(CSimpleSocket::CSocketError error) {\n        m_socketErrno = error;\n    };\n\n    /// Set object socket handle to that specified as parameter\n    ///  @param socket value of socket descriptor\n    void SetSocketHandle(SOCKET socket) {\n        m_socket = socket;\n    };\n\nprivate:\n    /// Generic function used to get the send/receive window size\n    ///  @return zero on failure else the number of bytes of the TCP window size if successful.\n    uint32_t GetWindowSize(uint32_t nOptionName);\n\n    /// Generic function used to set the send/receive window size\n    ///  @return zero on failure else the number of bytes of the TCP window size if successful.\n    uint32_t SetWindowSize(uint32_t nOptionName, uint32_t nWindowSize);\n\n\n    /// Attempts to send at most nNumItem blocks described by sendVector\n    /// to the socket descriptor associated with the socket object.\n    /// @param sendVector pointer to an array of iovec structures\n    /// @param nNumItems number of items in the vector to process\n    /// <br>\\b Note: This implementation is for systems that don't natively\n    /// support this functionality.\n    /// @return number of bytes actually sent, return of zero means the\n    /// connection has been shutdown on the other side, and a return of -1\n    /// means that an error has occurred.\n    int32_t Writev(const struct iovec *pVector, size_t nCount);\n\n    CSimpleSocket *operator=(CSimpleSocket &socket);\n\nprotected:\n    SOCKET               m_socket;            /// socket handle\n    CSocketError         m_socketErrno;       /// number of last error\n    uint8_t               *m_pBuffer;           /// internal send/receive buffer\n    int32_t                m_nBufferSize;       /// size of internal send/receive buffer\n    int32_t                m_nSocketDomain;     /// socket type PF_INET, PF_INET6\n    CSocketType          m_nSocketType;       /// socket type - UDP, TCP or RAW\n    int32_t                m_nBytesReceived;    /// number of bytes received\n    int32_t                m_nBytesSent;        /// number of bytes sent\n    uint32_t               m_nFlags;            /// socket flags\n    bool                 m_bIsBlocking;       /// is socket blocking\n    bool                 m_bIsMulticast;      /// is the UDP socket multicast;\n    struct timeval       m_stConnectTimeout;  /// connection timeout\n    struct timeval       m_stRecvTimeout;     /// receive timeout\n    struct timeval       m_stSendTimeout;     /// send timeout\n    struct sockaddr_in   m_stServerSockaddr;  /// server address\n    struct sockaddr_in   m_stClientSockaddr;  /// client address\n    struct sockaddr_in   m_stMulticastGroup;  /// multicast group to bind to\n    struct linger        m_stLinger;          /// linger flag\n    CStatTimer           m_timer;             /// internal statistics.\n#ifdef _WIN32\n    WSADATA              m_hWSAData;          /// Windows\n#endif\n    fd_set               m_writeFds;          /// write file descriptor set\n    fd_set               m_readFds;           /// read file descriptor set\n    fd_set               m_errorFds;          /// error file descriptor set\n};\n\n\n#endif /*  __SOCKET_H__  */\n\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/clsocket/src/StatTimer.h",
    "content": "/*----------------------------------------------------------------------------*/\n/*                                                                            */\n/* StatTimer.h: interface for the CStatTimer class.                           */\n/*                                                                            */\n/* Author: Mark Carrier (mark@carrierlabs.com)                                */\n/*                                                                            */\n/*----------------------------------------------------------------------------*/\n/* Copyright (c) 2006 CarrierLabs, LLC.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * 4. The name \"CarrierLabs\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    mark@carrierlabs.com.\n *\n * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MARK CARRIER OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *----------------------------------------------------------------------------*/\n#ifndef __CSTATTIMER_H__\n#define __CSTATTIMER_H__\n\n#include <string.h>\n\n#ifdef _WIN32\n\n#pragma warning( push )\n#pragma warning( disable:4668 )\n  #include <Winsock2.h>\n  #include <time.h>\n#pragma warning( pop )\n\n#endif\n\n#ifdef __linux__\n  #include <stdio.h>\n  #include <sys/time.h>\n#endif\n\n#include \"Host.h\"\n\n#if defined(_WIN32)\n  #define GET_CLOCK_COUNT(x) QueryPerformanceCounter((LARGE_INTEGER *)x)\n#else\n  #define GET_CLOCK_COUNT(x) gettimeofday(x, NULL)\n#endif\n\n#define MILLISECONDS_CONVERSION 1000\n#define MICROSECONDS_CONVERSION 1000000\n\n/// Class to abstract socket communications in a cross platform manner.\n/// This class is designed\nclass CStatTimer {\npublic:\n    CStatTimer()\n    {\n    };\n\n    ~CStatTimer()\n    {\n    };\n\n    void Initialize()\n    {\n        memset(&m_startTime, 0, sizeof(struct timeval));\n        memset(&m_endTime, 0, sizeof(struct timeval));\n    };\n\n    struct timeval GetStartTime() { return m_startTime; };\n    void SetStartTime() { GET_CLOCK_COUNT(&m_startTime); };\n\n    struct timeval GetEndTime() { return m_endTime; };\n    void SetEndTime() { GET_CLOCK_COUNT(&m_endTime); };\n\n    uint32_t GetMilliSeconds() { return (CalcTotalUSec() / MILLISECONDS_CONVERSION); };\n    uint32_t GetMicroSeconds() { return (CalcTotalUSec()); };\n    uint32_t GetSeconds() { return (CalcTotalUSec() / MICROSECONDS_CONVERSION); };\n\n    uint32_t GetCurrentTime()\n    {\n        struct timeval tmpTime;\n        GET_CLOCK_COUNT(&tmpTime);\n        return ((tmpTime.tv_sec * MICROSECONDS_CONVERSION) + tmpTime.tv_usec);\n    };\n\nprivate:\n    uint32_t CalcTotalUSec() { return (((m_endTime.tv_sec - m_startTime.tv_sec) * MICROSECONDS_CONVERSION) +\n                                    (m_endTime.tv_usec - m_startTime.tv_usec)); };\n\n\nprivate:\n    struct timeval  m_startTime;\n    struct timeval  m_endTime;\n};\n\n#endif // __CSTATTIMER_H__\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/countdownlatch/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Nipun Talukdar\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/countdownlatch/README.md",
    "content": "CountdownLatch for C++ multi-threaded programming\n================================================\n\n**CountdownLatch in C++**\n\n-----------------------\ncountdownlatch is a C++ library providing similar functionalities as availble with standard Java\nCountdownLatch class. It's main usage is: it allows one or more threads to wait until a set of\noperations being performed on other threads completes.\n\n\n**Below is an example regarding how to use the library**\n\n---\n\n```c++\n#include <unistd.h>\n#include <thread>\n#include <vector>\n#include <iostream>\n#include <countdownlatch.hpp>\n\nvoid fun(clatch::countdownlatch *cl) {\n    cl->await();\n    std::cout << \"Wait is over \" << std::endl;\n}\n\nint main() {\n    auto cl = new clatch::countdownlatch(10);\n    int i = 0;\n    std::vector<std::thread*> ts;\n    while (i++ < 2) {\n        std::thread *t  = new std::thread(fun, cl);\n        ts.push_back(t);\n    }\n\n    i = 0;\n    while (i++ < 10) {\n        sleep(1);\n        cl->count_down();\n    }\n    i = 0;\n    while (i < 2) {\n        ts[i++]->join();\n    }\n    i = 0;\n    while (i < 2) {\n        delete ts[i++];\n    }\n    delete cl;\n    return 0;\n}\n\n```\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/countdownlatch/countdownlatch.cpp",
    "content": "#include <chrono>\n#include \"countdownlatch.hpp\"\n\nclatch::countdownlatch::countdownlatch(uint32_t count) {\n   this->count = count; \n}\n\nvoid clatch::countdownlatch::await(uint64_t nanosecs) {\n    std::unique_lock<std::mutex> lck(lock);\n    if (0 == count){\n        return;\n    }\n    if (nanosecs > 0) {\n       cv.wait_for(lck, std::chrono::nanoseconds(nanosecs));\n    } else {\n       cv.wait(lck);\n    }\n}\n\nuint32_t clatch::countdownlatch::get_count() {\n    std::unique_lock<std::mutex> lck(lock);\n    return count;\n}\n\nvoid clatch::countdownlatch::count_down() {\n    std::unique_lock<std::mutex> lck(lock);\n    if (0 == count) {\n        return;\n    } \n    --count;\n    if (0 == count) {\n        cv.notify_all();\n    }\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/countdownlatch/countdownlatch.hpp",
    "content": "#ifndef __COUNTDOWNLATCH_NIPUN__\n#define __COUNTDOWNLATCH_NIPUN__\n\n#include <cinttypes>\n#include <cstdint>\n#include <mutex>\n#include <condition_variable>\n\n\nnamespace clatch \n{\n    class countdownlatch {\n    public:\n        /*! Constructor\n          \\param count, the value the countdownlatch object should be initialized with\n        */\n        explicit countdownlatch(uint32_t count);\n\n\n        /*!\n            await causes the caller to wait until the latch is counted down to zero, \n            if wait time nanosecs is not zero, then maximum wait is for nanosec nanoseconds \n          \\param nanosecs is waittime in nanoseconds, by default it is zero which specifies \n           indefinite wait  \n        */\n        void await(uint64_t nanosecs=0);\n\n        /*!\n          Countdown decrements the count of the latch, signalling all waiting thread if the \n          count reaches zero.\n         */\n        void count_down();\n\n        /*!\n          get_count returns the current count  \n         */\n        uint32_t get_count(); \n\n    private:\n        std::condition_variable cv;\n        std::mutex lock;\n        uint32_t count;\n        \n        // deleted constructors/assignmenet operators\n        countdownlatch() = delete;\n        countdownlatch(const countdownlatch& other) = delete;\n        countdownlatch& operator=(const countdownlatch& opther) = delete;\n    };\n}\n\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/optional/COPYING",
    "content": "Creative Commons Legal Code\n\nCC0 1.0 Universal\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE\n    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN\n    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS\n    INFORMATION ON AN \"AS-IS\" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES\n    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS\n    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM\n    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED\n    HEREUNDER.\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator\nand subsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for\nthe purpose of contributing to a commons of creative, cultural and\nscientific works (\"Commons\") that the public can reliably and without fear\nof later claims of infringement build upon, modify, incorporate in other\nworks, reuse and redistribute as freely as possible in any form whatsoever\nand for any purposes, including without limitation commercial purposes.\nThese owners may contribute to the Commons to promote the ideal of a free\nculture and the further production of creative, cultural and scientific\nworks, or to gain reputation or greater distribution for their Work in\npart through the use and efforts of others.\n\nFor these and/or other purposes and motivations, and without any\nexpectation of additional consideration or compensation, the person\nassociating CC0 with a Work (the \"Affirmer\"), to the extent that he or she\nis an owner of Copyright and Related Rights in the Work, voluntarily\nelects to apply CC0 to the Work and publicly distribute the Work under its\nterms, with knowledge of his or her Copyright and Related Rights in the\nWork and the meaning and intended legal effect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not\nlimited to, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display,\n     communicate, and translate a Work;\n ii. moral rights retained by the original author(s) and/or performer(s);\niii. publicity and privacy rights pertaining to a person's image or\n     likeness depicted in a Work;\n iv. rights protecting against unfair competition in regards to a Work,\n     subject to the limitations in paragraph 4(a), below;\n  v. rights protecting the extraction, dissemination, use and reuse of data\n     in a Work;\n vi. database rights (such as those arising under Directive 96/9/EC of the\n     European Parliament and of the Council of 11 March 1996 on the legal\n     protection of databases, and under any national implementation\n     thereof, including any amended or successor version of such\n     directive); and\nvii. other similar, equivalent or corresponding rights throughout the\n     world based on applicable law or treaty, and any national\n     implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention\nof, applicable law, Affirmer hereby overtly, fully, permanently,\nirrevocably and unconditionally waives, abandons, and surrenders all of\nAffirmer's Copyright and Related Rights and associated claims and causes\nof action, whether now known or unknown (including existing as well as\nfuture claims and causes of action), in the Work (i) in all territories\nworldwide, (ii) for the maximum duration provided by applicable law or\ntreaty (including future time extensions), (iii) in any current or future\nmedium and for any number of copies, and (iv) for any purpose whatsoever,\nincluding without limitation commercial, advertising or promotional\npurposes (the \"Waiver\"). Affirmer makes the Waiver for the benefit of each\nmember of the public at large and to the detriment of Affirmer's heirs and\nsuccessors, fully intending that such Waiver shall not be subject to\nrevocation, rescission, cancellation, termination, or any other legal or\nequitable action to disrupt the quiet enjoyment of the Work by the public\nas contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason\nbe judged legally invalid or ineffective under applicable law, then the\nWaiver shall be preserved to the maximum extent permitted taking into\naccount Affirmer's express Statement of Purpose. In addition, to the\nextent the Waiver is so judged Affirmer hereby grants to each affected\nperson a royalty-free, non transferable, non sublicensable, non exclusive,\nirrevocable and unconditional license to exercise Affirmer's Copyright and\nRelated Rights in the Work (i) in all territories worldwide, (ii) for the\nmaximum duration provided by applicable law or treaty (including future\ntime extensions), (iii) in any current or future medium and for any number\nof copies, and (iv) for any purpose whatsoever, including without\nlimitation commercial, advertising or promotional purposes (the\n\"License\"). The License shall be deemed effective as of the date CC0 was\napplied by Affirmer to the Work. Should any part of the License for any\nreason be judged legally invalid or ineffective under applicable law, such\npartial invalidity or ineffectiveness shall not invalidate the remainder\nof the License, and in such case Affirmer hereby affirms that he or she\nwill not (i) exercise any of his or her remaining Copyright and Related\nRights in the Work or (ii) assert any associated claims and causes of\naction with respect to the Work, in either case contrary to Affirmer's\nexpress Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n a. No trademark or patent rights held by Affirmer are waived, abandoned,\n    surrendered, licensed or otherwise affected by this document.\n b. Affirmer offers the Work as-is and makes no representations or\n    warranties of any kind concerning the Work, express, implied,\n    statutory or otherwise, including without limitation warranties of\n    title, merchantability, fitness for a particular purpose, non\n    infringement, or the absence of latent or other defects, accuracy, or\n    the present or absence of errors, whether or not discoverable, all to\n    the greatest extent permissible under applicable law.\n c. Affirmer disclaims responsibility for clearing rights of other persons\n    that may apply to the Work or any use thereof, including without\n    limitation any person's Copyright and Related Rights in the Work.\n    Further, Affirmer disclaims responsibility for obtaining any necessary\n    consents, permissions or other rights required for any use of the\n    Work.\n d. Affirmer understands and acknowledges that Creative Commons is not a\n    party to this document and has no duty or obligation with respect to\n    this CC0 or use of the Work.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/optional/README.md",
    "content": "# optional\nSingle header implementation of `std::optional` with functional-style extensions and support for references.\n\nClang + GCC: [![Linux Build Status](https://travis-ci.org/TartanLlama/optional.png?branch=master)](https://travis-ci.org/TartanLlama/optional)\nMSVC: [![Windows Build Status](https://ci.appveyor.com/api/projects/status/k5x00xa11y3s5wsg?svg=true)](https://ci.appveyor.com/project/TartanLlama/optional)\n\n`std::optional` is the preferred way to represent an object which may or may not have a value. Unfortunately, chaining together many computations which may or may not produce a value can be verbose, as empty-checking code will be mixed in with the actual programming logic. This implementation provides a number of utilities to make coding with `optional` cleaner.\n\nFor example, instead of writing this code:\n\n```c++\nstd::optional<image> get_cute_cat (const image& img) {\n    auto cropped = crop_to_cat(img);\n    if (!cropped) {\n      return std::nullopt;\n    }\n\n    auto with_tie = add_bow_tie(*cropped);\n    if (!with_tie) {\n      return std::nullopt;\n    }\n\n    auto with_sparkles = make_eyes_sparkle(*with_tie);\n    if (!with_sparkles) {\n      return std::nullopt;\n    }\n\n    return add_rainbow(make_smaller(*with_sparkles));\n}\n```\n\nYou can do this:\n\n```c++\ntl::optional<image> get_cute_cat (const image& img) {\n    return crop_to_cat(img)\n           .and_then(add_bow_tie)\n           .and_then(make_eyes_sparkle)\n           .map(make_smaller)\n           .map(add_rainbow);\n}\n```\n\nFull documentation available at [optional.tartanllama.xyz](https://optional.tartanllama.xyz)\n\nThe interface is the same as `std::optional`, but the following member functions are also defined. Explicit types are for clarity.\n\n- `map`: carries out some operation on the stored object if there is one.\n  * `tl::optional<std::size_t> s = opt_string.map(&std::string::size);`\n- `and_then`: like `map`, but for operations which return a `tl::optional`.\n  * `tl::optional<int> stoi (const std::string& s);`\n  * `tl::optional<int> i = opt_string.and_then(stoi);`\n- `or_else`: calls some function if there is no value stored.\n  * `opt.or_else([] { throw std::runtime_error{\"oh no\"}; });`\n- `map_or`: carries out a `map` if there is a value, otherwise returns a default value.\n  * `tl::optional<std::size_t> s = opt_string.map_or(&std::string::size, 0);`\n- `map_or_else`: carries out a `map` if there is a value, otherwise returns the result of a given default function.\n  * `std::size_t get_default();`\n  * `tl::optional<std::size_t> s = opt_string.map_or(&std::string::size, get_default);`\n- `conjunction`: returns the argument if a value is stored in the optional, otherwise an empty optional.\n  * `tl::make_optional(42).conjunction(13); //13`\n  * `tl::optional<int>){}.conjunction(13); //empty`\n- `disjunction`: returns the argument if the optional is empty, otherwise the current value.\n  * `tl::make_optional(42).disjunction(13); //42`\n  * `tl::optional<int>{}.disjunction(13); //13`\n- `take`: returns the current value, leaving the optional empty.\n  * `opt_string.take().map(&std::string::size); //opt_string now empty;`\n\nIn addition to those member functions, optional references are also supported:\n\n```c++\nint i = 42;\ntl::optional<int&> o = i;\n*o == 42; //true\ni = 12;\n*o = 12; //true\n&*o == &i; //true\n```\n\nAssignment has rebind semantics rather than assign-through semantics:\n\n```c++\nint j = 8;\no = j;\n\n&*o == &j; //true\n```\n\n### Compiler support\n\nTested on:\n\n\n- Linux\n  * clang 6.0.1\n  * clang 5.0.2\n  * clang 4.0.1\n  * clang 3.9\n  * clang 3.8\n  * clang 3.7\n  * clang 3.6\n  * clang 3.5\n  * g++ 8.0.1\n  * g++ 7.3\n  * g++ 6.4\n  * g++ 5.5\n  * g++ 4.9\n  * g++ 4.8\n- Windows\n  * MSVC 2015\n  * MSVC 2017\n\n### Dependencies\n\nRequires [Standardese](https://github.com/foonathan/standardese) for generating documentation.\n\nRequires [Catch](https://github.com/philsquared/Catch) for testing. This is bundled in the test directory.\n\n### Standards Proposal\n\nThis library also serves as an implementation of WG21 standards paper [P0798R0: Monadic operations for std::optional](https://wg21.tartanllama.xyz/monadic-optional). This paper proposes adding `map`, `and_then`, and `or_else` to `std::optional`.\n\n----------\n\n[![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png)](\"http://creativecommons.org/publicdomain/zero/1.0/\")\n\nTo the extent possible under law, [Simon Brand](https://twitter.com/TartanLlama) has waived all copyright and related or neighboring rights to the `optional` library. This work is published from: United Kingdom.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/optional/tl/optional.hpp",
    "content": "\n///\n// optional - An implementation of std::optional with extensions\n// Written in 2017 by Simon Brand (tartanllama@gmail.com, @TartanLlama)\n//\n// To the extent possible under law, the author(s) have dedicated all\n// copyright and related and neighboring rights to this software to the\n// public domain worldwide. This software is distributed without any warranty.\n//\n// You should have received a copy of the CC0 Public Domain Dedication\n// along with this software. If not, see\n// <http://creativecommons.org/publicdomain/zero/1.0/>.\n///\n\n#ifndef TL_OPTIONAL_HPP\n#define TL_OPTIONAL_HPP\n\n#define TL_OPTIONAL_VERSION_MAJOR 0\n#define TL_OPTIONAL_VERSION_MINOR 5\n\n#include <exception>\n#include <functional>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#if (defined(_MSC_VER) && _MSC_VER == 1900)\n#define TL_OPTIONAL_MSVC2015\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \\\n     !defined(__clang__))\n#define TL_OPTIONAL_GCC49\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 &&              \\\n     !defined(__clang__))\n#define TL_OPTIONAL_GCC54\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 &&              \\\n     !defined(__clang__))\n#define TL_OPTIONAL_GCC55\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \\\n     !defined(__clang__))\n// GCC < 5 doesn't support overloading on const&& for member functions\n#define TL_OPTIONAL_NO_CONSTRR\n\n// GCC < 5 doesn't support some standard C++11 type traits\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                                     \\\n  std::has_trivial_copy_constructor<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value\n\n// This one will be different for GCC 5.7 if it's ever supported\n#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value\n\n// GCC 5 < v < 8 has an issue in is_trivially_copy_constructible which breaks std::vector\n// for non-copyable types\n#elif (defined(__GNUC__) && __GNUC__ < 8 &&                                                \\\n     !defined(__clang__))\n#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX\n#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX\nnamespace tl {\n  namespace detail {\n      template<class T>\n      struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T>{};\n#ifdef _GLIBCXX_VECTOR\n      template<class T, class A>\n      struct is_trivially_copy_constructible<std::vector<T,A>>\n          : std::is_trivially_copy_constructible<T>{};\n#endif      \n  }\n}\n#endif\n\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                                     \\\n    tl::detail::is_trivially_copy_constructible<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T)                                        \\\n  std::is_trivially_copy_assignable<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value\n#else\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                                     \\\n  std::is_trivially_copy_constructible<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T)                                        \\\n  std::is_trivially_copy_assignable<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value\n#endif\n\n#if __cplusplus > 201103L\n#define TL_OPTIONAL_CXX14\n#endif\n\n// constexpr implies const in C++11, not C++14\n#if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) ||                \\\n     defined(TL_OPTIONAL_GCC49))\n/// \\exclude\n#define TL_OPTIONAL_11_CONSTEXPR\n#else\n/// \\exclude\n#define TL_OPTIONAL_11_CONSTEXPR constexpr\n#endif\n\nnamespace tl {\n#ifndef TL_MONOSTATE_INPLACE_MUTEX\n#define TL_MONOSTATE_INPLACE_MUTEX\n/// \\brief Used to represent an optional with no data; essentially a bool\nclass monostate {};\n\n/// \\brief A tag type to tell optional to construct its value in-place\nstruct in_place_t {\n  explicit in_place_t() = default;\n};\n/// \\brief A tag to tell optional to construct its value in-place\nstatic constexpr in_place_t in_place{};\n#endif\n\ntemplate <class T> class optional;\n\n/// \\exclude\nnamespace detail {\n#ifndef TL_TRAITS_MUTEX\n#define TL_TRAITS_MUTEX\n// C++14-style aliases for brevity\ntemplate <class T> using remove_const_t = typename std::remove_const<T>::type;\ntemplate <class T>\nusing remove_reference_t = typename std::remove_reference<T>::type;\ntemplate <class T> using decay_t = typename std::decay<T>::type;\ntemplate <bool E, class T = void>\nusing enable_if_t = typename std::enable_if<E, T>::type;\ntemplate <bool B, class T, class F>\nusing conditional_t = typename std::conditional<B, T, F>::type;\n\n// std::conjunction from C++17\ntemplate <class...> struct conjunction : std::true_type {};\ntemplate <class B> struct conjunction<B> : B {};\ntemplate <class B, class... Bs>\nstruct conjunction<B, Bs...>\n    : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};\n\n#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L\n#define TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND\n#endif\n\n// In C++11 mode, there's an issue in libc++'s std::mem_fn\n// which results in a hard-error when using it in a noexcept expression\n// in some cases. This is a check to workaround the common failing case.\n#ifdef TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND\ntemplate <class T> struct is_pointer_to_non_const_member_func : std::false_type{};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)> : std::true_type{};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)&> : std::true_type{};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)&&> : std::true_type{};        \ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile> : std::true_type{};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile&> : std::true_type{};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile&&> : std::true_type{};        \n\ntemplate <class T> struct is_const_or_const_ref : std::false_type{};\ntemplate <class T> struct is_const_or_const_ref<T const&> : std::true_type{};\ntemplate <class T> struct is_const_or_const_ref<T const> : std::true_type{};    \n#endif\n\n// std::invoke from C++17\n// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround\ntemplate <typename Fn, typename... Args,\n#ifdef TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND\n          typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value \n                                 && is_const_or_const_ref<Args...>::value)>, \n#endif\n          typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,\n          int = 0>\nconstexpr auto invoke(Fn &&f, Args &&... args) noexcept(\n    noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))\n    -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {\n  return std::mem_fn(f)(std::forward<Args>(args)...);\n}\n\ntemplate <typename Fn, typename... Args,\n          typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>\nconstexpr auto invoke(Fn &&f, Args &&... args) noexcept(\n    noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))\n    -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {\n  return std::forward<Fn>(f)(std::forward<Args>(args)...);\n}\n\n// std::invoke_result from C++17\ntemplate <class F, class, class... Us> struct invoke_result_impl;\n\ntemplate <class F, class... Us>\nstruct invoke_result_impl<\n    F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),\n    Us...> {\n  using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));\n};\n\ntemplate <class F, class... Us>\nusing invoke_result = invoke_result_impl<F, void, Us...>;\n\ntemplate <class F, class... Us>\nusing invoke_result_t = typename invoke_result<F, Us...>::type;\n#endif\n\n// std::void_t from C++17\ntemplate <class...> struct voider { using type = void; };\ntemplate <class... Ts> using void_t = typename voider<Ts...>::type;\n\n// Trait for checking if a type is a tl::optional\ntemplate <class T> struct is_optional_impl : std::false_type {};\ntemplate <class T> struct is_optional_impl<optional<T>> : std::true_type {};\ntemplate <class T> using is_optional = is_optional_impl<decay_t<T>>;\n\n// Change void to tl::monostate\ntemplate <class U>\nusing fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;\n\ntemplate <class F, class U, class = invoke_result_t<F, U>>\nusing get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;\n\n// Check if invoking F for some Us returns void\ntemplate <class F, class = void, class... U> struct returns_void_impl;\ntemplate <class F, class... U>\nstruct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...>\n    : std::is_void<invoke_result_t<F, U...>> {};\ntemplate <class F, class... U>\nusing returns_void = returns_void_impl<F, void, U...>;\n\ntemplate <class T, class... U>\nusing enable_if_ret_void = enable_if_t<returns_void<T &&, U...>::value>;\n\ntemplate <class T, class... U>\nusing disable_if_ret_void = enable_if_t<!returns_void<T &&, U...>::value>;\n\ntemplate <class T, class U>\nusing enable_forward_value =\n    detail::enable_if_t<std::is_constructible<T, U &&>::value &&\n                        !std::is_same<detail::decay_t<U>, in_place_t>::value &&\n                        !std::is_same<optional<T>, detail::decay_t<U>>::value>;\n\ntemplate <class T, class U, class Other>\nusing enable_from_other = detail::enable_if_t<\n    std::is_constructible<T, Other>::value &&\n    !std::is_constructible<T, optional<U> &>::value &&\n    !std::is_constructible<T, optional<U> &&>::value &&\n    !std::is_constructible<T, const optional<U> &>::value &&\n    !std::is_constructible<T, const optional<U> &&>::value &&\n    !std::is_convertible<optional<U> &, T>::value &&\n    !std::is_convertible<optional<U> &&, T>::value &&\n    !std::is_convertible<const optional<U> &, T>::value &&\n    !std::is_convertible<const optional<U> &&, T>::value>;\n\ntemplate <class T, class U>\nusing enable_assign_forward = detail::enable_if_t<\n    !std::is_same<optional<T>, detail::decay_t<U>>::value &&\n    !detail::conjunction<std::is_scalar<T>,\n                         std::is_same<T, detail::decay_t<U>>>::value &&\n    std::is_constructible<T, U>::value && std::is_assignable<T &, U>::value>;\n\ntemplate <class T, class U, class Other>\nusing enable_assign_from_other = detail::enable_if_t<\n    std::is_constructible<T, Other>::value &&\n    std::is_assignable<T &, Other>::value &&\n    !std::is_constructible<T, optional<U> &>::value &&\n    !std::is_constructible<T, optional<U> &&>::value &&\n    !std::is_constructible<T, const optional<U> &>::value &&\n    !std::is_constructible<T, const optional<U> &&>::value &&\n    !std::is_convertible<optional<U> &, T>::value &&\n    !std::is_convertible<optional<U> &&, T>::value &&\n    !std::is_convertible<const optional<U> &, T>::value &&\n    !std::is_convertible<const optional<U> &&, T>::value &&\n    !std::is_assignable<T &, optional<U> &>::value &&\n    !std::is_assignable<T &, optional<U> &&>::value &&\n    !std::is_assignable<T &, const optional<U> &>::value &&\n    !std::is_assignable<T &, const optional<U> &&>::value>;\n\n#ifdef _MSC_VER\n// TO-DO make a version which works with MSVC\ntemplate <class T, class U = T> struct is_swappable : std::true_type {};\n\ntemplate <class T, class U = T> struct is_nothrow_swappable : std::true_type {};\n#else\n// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept\nnamespace swap_adl_tests {\n// if swap ADL finds this then it would call std::swap otherwise (same\n// signature)\nstruct tag {};\n\ntemplate <class T> tag swap(T &, T &);\ntemplate <class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);\n\n// helper functions to test if an unqualified swap is possible, and if it\n// becomes std::swap\ntemplate <class, class> std::false_type can_swap(...) noexcept(false);\ntemplate <class T, class U,\n          class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>\nstd::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T &>(),\n                                                    std::declval<U &>())));\n\ntemplate <class, class> std::false_type uses_std(...);\ntemplate <class T, class U>\nstd::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>\nuses_std(int);\n\ntemplate <class T>\nstruct is_std_swap_noexcept\n    : std::integral_constant<bool,\n                             std::is_nothrow_move_constructible<T>::value &&\n                                 std::is_nothrow_move_assignable<T>::value> {};\n\ntemplate <class T, std::size_t N>\nstruct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};\n\ntemplate <class T, class U>\nstruct is_adl_swap_noexcept\n    : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};\n} // namespace swap_adl_tests\n\ntemplate <class T, class U = T>\nstruct is_swappable\n    : std::integral_constant<\n          bool,\n          decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&\n              (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||\n               (std::is_move_assignable<T>::value &&\n                std::is_move_constructible<T>::value))> {};\n\ntemplate <class T, std::size_t N>\nstruct is_swappable<T[N], T[N]>\n    : std::integral_constant<\n          bool,\n          decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&\n              (!decltype(\n                   detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||\n               is_swappable<T, T>::value)> {};\n\ntemplate <class T, class U = T>\nstruct is_nothrow_swappable\n    : std::integral_constant<\n          bool,\n          is_swappable<T, U>::value &&\n              ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value\n                    &&detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||\n               (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&\n                    detail::swap_adl_tests::is_adl_swap_noexcept<T,\n                                                                 U>::value))> {\n};\n#endif\n\n// The storage base manages the actual storage, and correctly propagates\n// trivial destruction from T. This case is for when T is not trivially\n// destructible.\ntemplate <class T, bool = ::std::is_trivially_destructible<T>::value>\nstruct optional_storage_base {\n  TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept\n      : m_dummy(), m_has_value(false) {}\n\n  template <class... U>\n  TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)\n      : m_value(std::forward<U>(u)...), m_has_value(true) {}\n\n  ~optional_storage_base() {\n    if (m_has_value) {\n      m_value.~T();\n      m_has_value = false;\n    }\n  }\n\n  struct dummy {};\n  union {\n    dummy m_dummy;\n    T m_value;\n  };\n\n  bool m_has_value;\n};\n\n// This case is for when T is trivially destructible.\ntemplate <class T> struct optional_storage_base<T, true> {\n  TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept\n      : m_dummy(), m_has_value(false) {}\n\n  template <class... U>\n  TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)\n      : m_value(std::forward<U>(u)...), m_has_value(true) {}\n\n  // No destructor, so this class is trivially destructible\n\n  struct dummy {};\n  union {\n    dummy m_dummy;\n    T m_value;\n  };\n\n  bool m_has_value = false;\n};\n\n// This base class provides some handy member functions which can be used in\n// further derived classes\ntemplate <class T> struct optional_operations_base : optional_storage_base<T> {\n  using optional_storage_base<T>::optional_storage_base;\n\n  void hard_reset() noexcept {\n    get().~T();\n    this->m_has_value = false;\n  }\n\n  template <class... Args> void construct(Args &&... args) noexcept {\n    new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);\n    this->m_has_value = true;\n  }\n\n  template <class Opt> void assign(Opt &&rhs) {\n    if (this->has_value()) {\n      if (rhs.has_value()) {\n        this->m_value = std::forward<Opt>(rhs).get();\n      } else {\n        this->m_value.~T();\n        this->m_has_value = false;\n      }\n    }\n\n    else if (rhs.has_value()) {\n      construct(std::forward<Opt>(rhs).get());\n    }\n  }\n\n  bool has_value() const { return this->m_has_value; }\n\n  TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; }\n  TL_OPTIONAL_11_CONSTEXPR const T &get() const & { return this->m_value; }\n  TL_OPTIONAL_11_CONSTEXPR T &&get() && { return std::move(this->m_value); }\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  constexpr const T &&get() const && { return std::move(this->m_value); }\n#endif\n};\n\n// This class manages conditionally having a trivial copy constructor\n// This specialization is for when T is trivially copy constructible\ntemplate <class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>\nstruct optional_copy_base : optional_operations_base<T> {\n  using optional_operations_base<T>::optional_operations_base;\n};\n\n// This specialization is for when T is not trivially copy constructible\ntemplate <class T>\nstruct optional_copy_base<T, false> : optional_operations_base<T> {\n  using optional_operations_base<T>::optional_operations_base;\n\n  optional_copy_base() = default;\n  optional_copy_base(const optional_copy_base &rhs) {\n    if (rhs.has_value()) {\n      this->construct(rhs.get());\n    } else {\n      this->m_has_value = false;\n    }\n  }\n\n  optional_copy_base(optional_copy_base &&rhs) = default;\n  optional_copy_base &operator=(const optional_copy_base &rhs) = default;\n  optional_copy_base &operator=(optional_copy_base &&rhs) = default;\n};\n\n// This class manages conditionally having a trivial move constructor\n// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it\n// doesn't implement an analogue to std::is_trivially_move_constructible. We\n// have to make do with a non-trivial move constructor even if T is trivially\n// move constructible\n#ifndef TL_OPTIONAL_GCC49\ntemplate <class T, bool = std::is_trivially_move_constructible<T>::value>\nstruct optional_move_base : optional_copy_base<T> {\n  using optional_copy_base<T>::optional_copy_base;\n};\n#else\ntemplate <class T, bool = false> struct optional_move_base;\n#endif\ntemplate <class T> struct optional_move_base<T, false> : optional_copy_base<T> {\n  using optional_copy_base<T>::optional_copy_base;\n\n  optional_move_base() = default;\n  optional_move_base(const optional_move_base &rhs) = default;\n\n  optional_move_base(optional_move_base &&rhs) noexcept(\n      std::is_nothrow_move_constructible<T>::value) {\n    if (rhs.has_value()) {\n      this->construct(std::move(rhs.get()));\n    } else {\n      this->m_has_value = false;\n    }\n  }\n  optional_move_base &operator=(const optional_move_base &rhs) = default;\n  optional_move_base &operator=(optional_move_base &&rhs) = default;\n};\n\n// This class manages conditionally having a trivial copy assignment operator\ntemplate <class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) &&\n                          TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) &&\n                          TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)>\nstruct optional_copy_assign_base : optional_move_base<T> {\n  using optional_move_base<T>::optional_move_base;\n};\n\ntemplate <class T>\nstruct optional_copy_assign_base<T, false> : optional_move_base<T> {\n  using optional_move_base<T>::optional_move_base;\n\n  optional_copy_assign_base() = default;\n  optional_copy_assign_base(const optional_copy_assign_base &rhs) = default;\n\n  optional_copy_assign_base(optional_copy_assign_base &&rhs) = default;\n  optional_copy_assign_base &operator=(const optional_copy_assign_base &rhs) {\n    this->assign(rhs);\n    return *this;\n  }\n  optional_copy_assign_base &\n  operator=(optional_copy_assign_base &&rhs) = default;\n};\n\n// This class manages conditionally having a trivial move assignment operator\n// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it\n// doesn't implement an analogue to std::is_trivially_move_assignable. We have\n// to make do with a non-trivial move assignment operator even if T is trivially\n// move assignable\n#ifndef TL_OPTIONAL_GCC49\ntemplate <class T, bool = std::is_trivially_destructible<T>::value\n                       &&std::is_trivially_move_constructible<T>::value\n                           &&std::is_trivially_move_assignable<T>::value>\nstruct optional_move_assign_base : optional_copy_assign_base<T> {\n  using optional_copy_assign_base<T>::optional_copy_assign_base;\n};\n#else\ntemplate <class T, bool = false> struct optional_move_assign_base;\n#endif\n\ntemplate <class T>\nstruct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {\n  using optional_copy_assign_base<T>::optional_copy_assign_base;\n\n  optional_move_assign_base() = default;\n  optional_move_assign_base(const optional_move_assign_base &rhs) = default;\n\n  optional_move_assign_base(optional_move_assign_base &&rhs) = default;\n\n  optional_move_assign_base &\n  operator=(const optional_move_assign_base &rhs) = default;\n\n  optional_move_assign_base &\n  operator=(optional_move_assign_base &&rhs) noexcept(\n      std::is_nothrow_move_constructible<T>::value\n          &&std::is_nothrow_move_assignable<T>::value) {\n    this->assign(std::move(rhs));\n    return *this;\n  }\n};\n\n// optional_delete_ctor_base will conditionally delete copy and move\n// constructors depending on whether T is copy/move constructible\ntemplate <class T, bool EnableCopy = std::is_copy_constructible<T>::value,\n          bool EnableMove = std::is_move_constructible<T>::value>\nstruct optional_delete_ctor_base {\n  optional_delete_ctor_base() = default;\n  optional_delete_ctor_base(const optional_delete_ctor_base &) = default;\n  optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;\n  optional_delete_ctor_base &\n  operator=(const optional_delete_ctor_base &) = default;\n  optional_delete_ctor_base &\n  operator=(optional_delete_ctor_base &&) noexcept = default;\n};\n\ntemplate <class T> struct optional_delete_ctor_base<T, true, false> {\n  optional_delete_ctor_base() = default;\n  optional_delete_ctor_base(const optional_delete_ctor_base &) = default;\n  optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;\n  optional_delete_ctor_base &\n  operator=(const optional_delete_ctor_base &) = default;\n  optional_delete_ctor_base &\n  operator=(optional_delete_ctor_base &&) noexcept = default;\n};\n\ntemplate <class T> struct optional_delete_ctor_base<T, false, true> {\n  optional_delete_ctor_base() = default;\n  optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;\n  optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;\n  optional_delete_ctor_base &\n  operator=(const optional_delete_ctor_base &) = default;\n  optional_delete_ctor_base &\n  operator=(optional_delete_ctor_base &&) noexcept = default;\n};\n\ntemplate <class T> struct optional_delete_ctor_base<T, false, false> {\n  optional_delete_ctor_base() = default;\n  optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;\n  optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;\n  optional_delete_ctor_base &\n  operator=(const optional_delete_ctor_base &) = default;\n  optional_delete_ctor_base &\n  operator=(optional_delete_ctor_base &&) noexcept = default;\n};\n\n// optional_delete_assign_base will conditionally delete copy and move\n// constructors depending on whether T is copy/move constructible + assignable\ntemplate <class T,\n          bool EnableCopy = (std::is_copy_constructible<T>::value &&\n                             std::is_copy_assignable<T>::value),\n          bool EnableMove = (std::is_move_constructible<T>::value &&\n                             std::is_move_assignable<T>::value)>\nstruct optional_delete_assign_base {\n  optional_delete_assign_base() = default;\n  optional_delete_assign_base(const optional_delete_assign_base &) = default;\n  optional_delete_assign_base(optional_delete_assign_base &&) noexcept =\n      default;\n  optional_delete_assign_base &\n  operator=(const optional_delete_assign_base &) = default;\n  optional_delete_assign_base &\n  operator=(optional_delete_assign_base &&) noexcept = default;\n};\n\ntemplate <class T> struct optional_delete_assign_base<T, true, false> {\n  optional_delete_assign_base() = default;\n  optional_delete_assign_base(const optional_delete_assign_base &) = default;\n  optional_delete_assign_base(optional_delete_assign_base &&) noexcept =\n      default;\n  optional_delete_assign_base &\n  operator=(const optional_delete_assign_base &) = default;\n  optional_delete_assign_base &\n  operator=(optional_delete_assign_base &&) noexcept = delete;\n};\n\ntemplate <class T> struct optional_delete_assign_base<T, false, true> {\n  optional_delete_assign_base() = default;\n  optional_delete_assign_base(const optional_delete_assign_base &) = default;\n  optional_delete_assign_base(optional_delete_assign_base &&) noexcept =\n      default;\n  optional_delete_assign_base &\n  operator=(const optional_delete_assign_base &) = delete;\n  optional_delete_assign_base &\n  operator=(optional_delete_assign_base &&) noexcept = default;\n};\n\ntemplate <class T> struct optional_delete_assign_base<T, false, false> {\n  optional_delete_assign_base() = default;\n  optional_delete_assign_base(const optional_delete_assign_base &) = default;\n  optional_delete_assign_base(optional_delete_assign_base &&) noexcept =\n      default;\n  optional_delete_assign_base &\n  operator=(const optional_delete_assign_base &) = delete;\n  optional_delete_assign_base &\n  operator=(optional_delete_assign_base &&) noexcept = delete;\n};\n\n} // namespace detail\n\n/// \\brief A tag type to represent an empty optional\nstruct nullopt_t {\n  struct do_not_use {};\n  constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {}\n};\n/// \\brief Represents an empty optional\n/// \\synopsis static constexpr nullopt_t nullopt;\n///\n/// *Examples*:\n/// ```\n/// tl::optional<int> a = tl::nullopt;\n/// void foo (tl::optional<int>);\n/// foo(tl::nullopt); //pass an empty optional\n/// ```\nstatic constexpr nullopt_t nullopt{nullopt_t::do_not_use{},\n                                   nullopt_t::do_not_use{}};\n\nclass bad_optional_access : public std::exception {\npublic:\n  bad_optional_access() = default;\n  const char *what() const noexcept { return \"Optional has no value\"; }\n};\n\n/// An optional object is an object that contains the storage for another\n/// object and manages the lifetime of this contained object, if any. The\n/// contained object may be initialized after the optional object has been\n/// initialized, and may be destroyed before the optional object has been\n/// destroyed. The initialization state of the contained object is tracked by\n/// the optional object.\ntemplate <class T>\nclass optional : private detail::optional_move_assign_base<T>,\n                 private detail::optional_delete_ctor_base<T>,\n                 private detail::optional_delete_assign_base<T> {\n  using base = detail::optional_move_assign_base<T>;\n\n  static_assert(!std::is_same<T, in_place_t>::value,\n                \"instantiation of optional with in_place_t is ill-formed\");\n  static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value,\n                \"instantiation of optional with nullopt_t is ill-formed\");\n\npublic:\n// The different versions for C++14 and 11 are needed because deduced return\n// types are not SFINAE-safe. This provides better support for things like\n// generic lambdas. C.f.\n// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n  /// \\group and_then\n  /// Carries out some operation which returns an optional on the stored\n  /// object if there is one. \\requires `std::invoke(std::forward<F>(f),\n  /// value())` returns a `std::optional<U>` for some `U`. \\returns Let `U` be\n  /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a\n  /// `std::optional<U>`. The return value is empty if `*this` is empty,\n  /// otherwise the return value of `std::invoke(std::forward<F>(f), value())`\n  /// is returned.\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) &;\n  template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {\n    using result = detail::invoke_result_t<F, T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) &&;\n  template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {\n    using result = detail::invoke_result_t<F, T &&>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : result(nullopt);\n  }\n\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) const &;\n  template <class F> constexpr auto and_then(F &&f) const & {\n    using result = detail::invoke_result_t<F, const T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) const &&;\n  template <class F> constexpr auto and_then(F &&f) const && {\n    using result = detail::invoke_result_t<F, const T &&>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : result(nullopt);\n  }\n#endif\n#else\n  /// \\group and_then\n  /// Carries out some operation which returns an optional on the stored\n  /// object if there is one. \\requires `std::invoke(std::forward<F>(f),\n  /// value())` returns a `std::optional<U>` for some `U`.\n  /// \\returns Let `U` be the result of `std::invoke(std::forward<F>(f),\n  /// value())`. Returns a `std::optional<U>`. The return value is empty if\n  /// `*this` is empty, otherwise the return value of\n  /// `std::invoke(std::forward<F>(f), value())` is returned.\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) &;\n  template <class F>\n  TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {\n    using result = detail::invoke_result_t<F, T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) &&;\n  template <class F>\n  TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &&> and_then(F &&f) && {\n    using result = detail::invoke_result_t<F, T &&>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : result(nullopt);\n  }\n\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) const &;\n  template <class F>\n  constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {\n    using result = detail::invoke_result_t<F, const T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) const &&;\n  template <class F>\n  constexpr detail::invoke_result_t<F, const T &&> and_then(F &&f) const && {\n    using result = detail::invoke_result_t<F, const T &&>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : result(nullopt);\n  }\n#endif\n#endif\n\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n  /// \\brief Carries out some operation on the stored object if there is one.\n  /// \\returns Let `U` be the result of `std::invoke(std::forward<F>(f),\n  /// value())`. Returns a `std::optional<U>`. The return value is empty if\n  /// `*this` is empty, otherwise an `optional<U>` is constructed from the\n  /// return value of `std::invoke(std::forward<F>(f), value())` and is\n  /// returned.\n  ///\n  /// \\group map\n  /// \\synopsis template <class F> constexpr auto map(F &&f) &;\n  template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {\n    return optional_map_impl(*this, std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> constexpr auto map(F &&f) &&;\n  template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {\n    return optional_map_impl(std::move(*this), std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> constexpr auto map(F &&f) const&;\n  template <class F> constexpr auto map(F &&f) const & {\n    return optional_map_impl(*this, std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> constexpr auto map(F &&f) const&&;\n  template <class F> constexpr auto map(F &&f) const && {\n    return optional_map_impl(std::move(*this), std::forward<F>(f));\n  }\n#else\n  /// \\brief Carries out some operation on the stored object if there is one.\n  /// \\returns Let `U` be the result of `std::invoke(std::forward<F>(f),\n  /// value())`. Returns a `std::optional<U>`. The return value is empty if\n  /// `*this` is empty, otherwise an `optional<U>` is constructed from the\n  /// return value of `std::invoke(std::forward<F>(f), value())` and is\n  /// returned.\n  ///\n  /// \\group map\n  /// \\synopsis template <class F> auto map(F &&f) &;\n  template <class F>\n  TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional &>(),\n                                             std::declval<F &&>()))\n  map(F &&f) & {\n    return optional_map_impl(*this, std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> auto map(F &&f) &&;\n  template <class F>\n  TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional &&>(),\n                                             std::declval<F &&>()))\n  map(F &&f) && {\n    return optional_map_impl(std::move(*this), std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> auto map(F &&f) const&;\n  template <class F>\n  constexpr decltype(optional_map_impl(std::declval<const optional &>(),\n                              std::declval<F &&>()))\n  map(F &&f) const & {\n    return optional_map_impl(*this, std::forward<F>(f));\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group map\n  /// \\synopsis template <class F> auto map(F &&f) const&&;\n  template <class F>\n  constexpr decltype(optional_map_impl(std::declval<const optional &&>(),\n                              std::declval<F &&>()))\n  map(F &&f) const && {\n    return optional_map_impl(std::move(*this), std::forward<F>(f));\n  }\n#endif\n#endif\n\n  /// \\brief Calls `f` if the optional is empty\n  /// \\requires `std::invoke_result_t<F>` must be void or convertible to\n  /// `optional<T>`.\n  /// \\effects If `*this` has a value, returns `*this`.\n  /// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns\n  /// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`.\n  ///\n  /// \\group or_else\n  /// \\synopsis template <class F> optional<T> or_else (F &&f) &;\n  template <class F, detail::enable_if_ret_void<F> * = nullptr>\n  optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {\n    if (has_value())\n      return *this;\n\n    std::forward<F>(f)();\n    return nullopt;\n  }\n\n  /// \\exclude\n  template <class F, detail::disable_if_ret_void<F> * = nullptr>\n  optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {\n    return has_value() ? *this : std::forward<F>(f)();\n  }\n\n  /// \\group or_else\n  /// \\synopsis template <class F> optional<T> or_else (F &&f) &&;\n  template <class F, detail::enable_if_ret_void<F> * = nullptr>\n  optional<T> or_else(F &&f) && {\n    if (has_value())\n      return std::move(*this);\n\n    std::forward<F>(f)();\n    return nullopt;\n  }\n\n  /// \\exclude\n  template <class F, detail::disable_if_ret_void<F> * = nullptr>\n  optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {\n    return has_value() ? std::move(*this) : std::forward<F>(f)();\n  }\n\n  /// \\group or_else\n  /// \\synopsis template <class F> optional<T> or_else (F &&f) const &;\n  template <class F, detail::enable_if_ret_void<F> * = nullptr>\n  optional<T> or_else(F &&f) const & {\n    if (has_value())\n      return *this;\n\n    std::forward<F>(f)();\n    return nullopt;\n  }\n\n  /// \\exclude\n  template <class F, detail::disable_if_ret_void<F> * = nullptr>\n  optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {\n    return has_value() ? *this : std::forward<F>(f)();\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\exclude\n  template <class F, detail::enable_if_ret_void<F> * = nullptr>\n  optional<T> or_else(F &&f) const && {\n    if (has_value())\n      return std::move(*this);\n\n    std::forward<F>(f)();\n    return nullopt;\n  }\n\n  /// \\exclude\n  template <class F, detail::disable_if_ret_void<F> * = nullptr>\n  optional<T> or_else(F &&f) const && {\n    return has_value() ? std::move(*this) : std::forward<F>(f)();\n  }\n#endif\n\n  /// \\brief Maps the stored value with `f` if there is one, otherwise returns\n  /// `u`.\n  ///\n  /// \\details If there is a value stored, then `f` is called with `**this`\n  /// and the value is returned. Otherwise `u` is returned.\n  ///\n  /// \\group map_or\n  template <class F, class U> U map_or(F &&f, U &&u) & {\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : std::forward<U>(u);\n  }\n\n  /// \\group map_or\n  template <class F, class U> U map_or(F &&f, U &&u) && {\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : std::forward<U>(u);\n  }\n\n  /// \\group map_or\n  template <class F, class U> U map_or(F &&f, U &&u) const & {\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : std::forward<U>(u);\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group map_or\n  template <class F, class U> U map_or(F &&f, U &&u) const && {\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : std::forward<U>(u);\n  }\n#endif\n\n  /// \\brief Maps the stored value with `f` if there is one, otherwise calls\n  /// `u` and returns the result.\n  ///\n  /// \\details If there is a value stored, then `f` is\n  /// called with `**this` and the value is returned. Otherwise\n  /// `std::forward<U>(u)()` is returned.\n  ///\n  /// \\group map_or_else\n  /// \\synopsis template <class F, class U>\\nauto map_or_else(F &&f, U &&u) &;\n  template <class F, class U>\n  detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : std::forward<U>(u)();\n  }\n\n  /// \\group map_or_else\n  /// \\synopsis template <class F, class U>\\nauto map_or_else(F &&f, U &&u)\n  /// &&;\n  template <class F, class U>\n  detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : std::forward<U>(u)();\n  }\n\n  /// \\group map_or_else\n  /// \\synopsis template <class F, class U>\\nauto map_or_else(F &&f, U &&u)\n  /// const &;\n  template <class F, class U>\n  detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : std::forward<U>(u)();\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group map_or_else\n  /// \\synopsis template <class F, class U>\\nauto map_or_else(F &&f, U &&u)\n  /// const &&;\n  template <class F, class U>\n  detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : std::forward<U>(u)();\n  }\n#endif\n\n  /// \\returns `u` if `*this` has a value, otherwise an empty optional.\n  template <class U>\n  constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {\n    using result = optional<detail::decay_t<U>>;\n    return has_value() ? result{u} : result{nullopt};\n  }\n\n  /// \\returns `rhs` if `*this` is empty, otherwise the current value.\n  /// \\group disjunction\n  TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {\n    return has_value() ? *this : rhs;\n  }\n\n  /// \\group disjunction\n  constexpr optional disjunction(const optional &rhs) const & {\n    return has_value() ? *this : rhs;\n  }\n\n  /// \\group disjunction\n  TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {\n    return has_value() ? std::move(*this) : rhs;\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group disjunction\n  constexpr optional disjunction(const optional &rhs) const && {\n    return has_value() ? std::move(*this) : rhs;\n  }\n#endif\n\n  /// \\group disjunction\n  TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {\n    return has_value() ? *this : std::move(rhs);\n  }\n\n  /// \\group disjunction\n  constexpr optional disjunction(optional &&rhs) const & {\n    return has_value() ? *this : std::move(rhs);\n  }\n\n  /// \\group disjunction\n  TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {\n    return has_value() ? std::move(*this) : std::move(rhs);\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group disjunction\n  constexpr optional disjunction(optional &&rhs) const && {\n    return has_value() ? std::move(*this) : std::move(rhs);\n  }\n#endif\n\n  /// Takes the value out of the optional, leaving it empty\n  /// \\group take\n  optional take() & {\n    optional ret = *this;\n    reset();\n    return ret;\n  }\n\n  /// \\group take\n  optional take() const & {\n    optional ret = *this;\n    reset();\n    return ret;\n  }\n\n  /// \\group take\n  optional take() && {\n    optional ret = std::move(*this);\n    reset();\n    return ret;\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group take\n  optional take() const && {\n    optional ret = std::move(*this);\n    reset();\n    return ret;\n  }\n#endif\n\n  using value_type = T;\n\n  /// Constructs an optional that does not contain a value.\n  /// \\group ctor_empty\n  constexpr optional() noexcept = default;\n\n  /// \\group ctor_empty\n  constexpr optional(nullopt_t) noexcept {}\n\n  /// Copy constructor\n  ///\n  /// If `rhs` contains a value, the stored value is direct-initialized with\n  /// it. Otherwise, the constructed optional is empty.\n  TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) = default;\n\n  /// Move constructor\n  ///\n  /// If `rhs` contains a value, the stored value is direct-initialized with\n  /// it. Otherwise, the constructed optional is empty.\n  TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;\n\n  /// Constructs the stored value in-place using the given arguments.\n  /// \\group in_place\n  /// \\synopsis template <class... Args> constexpr explicit optional(in_place_t, Args&&... args);\n  template <class... Args>\n  constexpr explicit optional(\n      detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>,\n      Args &&... args)\n      : base(in_place, std::forward<Args>(args)...) {}\n\n  /// \\group in_place\n  /// \\synopsis template <class U, class... Args>\\nconstexpr explicit optional(in_place_t, std::initializer_list<U>&, Args&&... args);\n  template <class U, class... Args>\n  TL_OPTIONAL_11_CONSTEXPR explicit optional(\n      detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &,\n                                                Args &&...>::value,\n                          in_place_t>,\n      std::initializer_list<U> il, Args &&... args) {\n    this->construct(il, std::forward<Args>(args)...);\n  }\n\n  /// Constructs the stored value with `u`.\n  /// \\synopsis template <class U=T> constexpr optional(U &&u);\n  template <\n      class U = T,\n      detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,\n      detail::enable_forward_value<T, U> * = nullptr>\n  constexpr optional(U &&u) : base(in_place, std::forward<U>(u)) {}\n\n  /// \\exclude\n  template <\n      class U = T,\n      detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,\n      detail::enable_forward_value<T, U> * = nullptr>\n  constexpr explicit optional(U &&u) : base(in_place, std::forward<U>(u)) {}\n\n  /// Converting copy constructor.\n  /// \\synopsis template <class U> optional(const optional<U> &rhs);\n  template <\n      class U, detail::enable_from_other<T, U, const U &> * = nullptr,\n      detail::enable_if_t<std::is_convertible<const U &, T>::value> * = nullptr>\n  optional(const optional<U> &rhs) {\n    if (rhs.has_value()) {\n      this->construct(*rhs);\n    }\n  }\n\n  /// \\exclude\n  template <class U, detail::enable_from_other<T, U, const U &> * = nullptr,\n            detail::enable_if_t<!std::is_convertible<const U &, T>::value> * =\n                nullptr>\n  explicit optional(const optional<U> &rhs) {\n    if (rhs.has_value()) {\n      this->construct(*rhs);\n    }\n  }\n\n  /// Converting move constructor.\n  /// \\synopsis template <class U> optional(optional<U> &&rhs);\n  template <\n      class U, detail::enable_from_other<T, U, U &&> * = nullptr,\n      detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr>\n  optional(optional<U> &&rhs) {\n    if (rhs.has_value()) {\n      this->construct(std::move(*rhs));\n    }\n  }\n\n  /// \\exclude\n  template <\n      class U, detail::enable_from_other<T, U, U &&> * = nullptr,\n      detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr>\n  explicit optional(optional<U> &&rhs) {\n    if (rhs.has_value()) {\n      this->construct(std::move(*rhs));\n    }\n  }\n\n  /// Destroys the stored value if there is one.\n  ~optional() = default;\n\n  /// Assignment to empty.\n  ///\n  /// Destroys the current value if there is one.\n  optional &operator=(nullopt_t) noexcept {\n    if (has_value()) {\n      this->m_value.~T();\n      this->m_has_value = false;\n    }\n\n    return *this;\n  }\n\n  /// Copy assignment.\n  ///\n  /// Copies the value from `rhs` if there is one. Otherwise resets the stored\n  /// value in `*this`.\n  optional &operator=(const optional &rhs) = default;\n\n  /// Move assignment.\n  ///\n  /// Moves the value from `rhs` if there is one. Otherwise resets the stored\n  /// value in `*this`.\n  optional &operator=(optional &&rhs) = default;\n\n  /// Assigns the stored value from `u`, destroying the old value if there was\n  /// one.\n  /// \\synopsis optional &operator=(U &&u);\n  template <class U = T, detail::enable_assign_forward<T, U> * = nullptr>\n  optional &operator=(U &&u) {\n    if (has_value()) {\n      this->m_value = std::forward<U>(u);\n    } else {\n      this->construct(std::forward<U>(u));\n    }\n\n    return *this;\n  }\n\n  /// Converting copy assignment operator.\n  ///\n  /// Copies the value from `rhs` if there is one. Otherwise resets the stored\n  /// value in `*this`.\n  /// \\synopsis optional &operator=(const optional<U> & rhs);\n  template <class U,\n            detail::enable_assign_from_other<T, U, const U &> * = nullptr>\n  optional &operator=(const optional<U> &rhs) {\n    if (has_value()) {\n      if (rhs.has_value()) {\n        this->m_value = *rhs;\n      } else {\n        this->hard_reset();\n      }\n    }\n\n    if (rhs.has_value()) {\n      this->construct(*rhs);\n    }\n\n    return *this;\n  }\n\n  // TO-DO check exception guarantee\n  /// Converting move assignment operator.\n  ///\n  /// Moves the value from `rhs` if there is one. Otherwise resets the stored\n  /// value in `*this`.\n  /// \\synopsis optional &operator=(optional<U> && rhs);\n  template <class U, detail::enable_assign_from_other<T, U, U> * = nullptr>\n  optional &operator=(optional<U> &&rhs) {\n    if (has_value()) {\n      if (rhs.has_value()) {\n        this->m_value = std::move(*rhs);\n      } else {\n        this->hard_reset();\n      }\n    }\n\n    if (rhs.has_value()) {\n      this->construct(std::move(*rhs));\n    }\n\n    return *this;\n  }\n\n  /// Constructs the value in-place, destroying the current one if there is\n  /// one.\n  /// \\group emplace\n  template <class... Args> T &emplace(Args &&... args) {\n    static_assert(std::is_constructible<T, Args &&...>::value,\n                  \"T must be constructible with Args\");\n\n    *this = nullopt;\n    this->construct(std::forward<Args>(args)...);\n    return value();\n  }\n\n  /// \\group emplace\n  /// \\synopsis template <class U, class... Args>\\nT& emplace(std::initializer_list<U> il, Args &&... args);\n  template <class U, class... Args>\n  detail::enable_if_t<\n      std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value,\n      T &>\n  emplace(std::initializer_list<U> il, Args &&... args) {\n    *this = nullopt;\n    this->construct(il, std::forward<Args>(args)...);\n    return value();    \n  }\n\n  /// Swaps this optional with the other.\n  ///\n  /// If neither optionals have a value, nothing happens.\n  /// If both have a value, the values are swapped.\n  /// If one has a value, it is moved to the other and the movee is left\n  /// valueless.\n  void\n  swap(optional &rhs) noexcept(std::is_nothrow_move_constructible<T>::value\n                                   &&detail::is_nothrow_swappable<T>::value) {\n    if (has_value()) {\n      if (rhs.has_value()) {\n        using std::swap;\n        swap(**this, *rhs);\n      } else {\n        new (std::addressof(rhs.m_value)) T(std::move(this->m_value));\n        this->m_value.T::~T();\n      }\n    } else if (rhs.has_value()) {\n      new (std::addressof(this->m_value)) T(std::move(rhs.m_value));\n      rhs.m_value.T::~T();\n    }\n  }\n\n  /// \\returns a pointer to the stored value\n  /// \\requires a value is stored\n  /// \\group pointer\n  /// \\synopsis constexpr const T *operator->() const;\n  constexpr const T *operator->() const {\n    return std::addressof(this->m_value);\n  }\n\n  /// \\group pointer\n  /// \\synopsis constexpr T *operator->();\n  TL_OPTIONAL_11_CONSTEXPR T *operator->() {\n    return std::addressof(this->m_value);\n  }\n\n  /// \\returns the stored value\n  /// \\requires a value is stored\n  /// \\group deref\n  /// \\synopsis constexpr T &operator*();\n  TL_OPTIONAL_11_CONSTEXPR T &operator*() & { return this->m_value; }\n\n  /// \\group deref\n  /// \\synopsis constexpr const T &operator*() const;\n  constexpr const T &operator*() const & { return this->m_value; }\n\n  /// \\exclude\n  TL_OPTIONAL_11_CONSTEXPR T &&operator*() && {\n    return std::move(this->m_value);\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\exclude\n  constexpr const T &&operator*() const && { return std::move(this->m_value); }\n#endif\n\n  /// \\returns whether or not the optional has a value\n  /// \\group has_value\n  constexpr bool has_value() const noexcept { return this->m_has_value; }\n\n  /// \\group has_value\n  constexpr explicit operator bool() const noexcept {\n    return this->m_has_value;\n  }\n\n  /// \\returns the contained value if there is one, otherwise throws\n  /// [bad_optional_access]\n  /// \\group value\n  /// \\synopsis constexpr T &value();\n  TL_OPTIONAL_11_CONSTEXPR T &value() & {\n    if (has_value())\n      return this->m_value;\n    throw bad_optional_access();\n  }\n  /// \\group value\n  /// \\synopsis constexpr const T &value() const;\n  TL_OPTIONAL_11_CONSTEXPR const T &value() const & {\n    if (has_value())\n      return this->m_value;\n    throw bad_optional_access();\n  }\n  /// \\exclude\n  TL_OPTIONAL_11_CONSTEXPR T &&value() && {\n    if (has_value())\n      return std::move(this->m_value);\n    throw bad_optional_access();\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\exclude\n  TL_OPTIONAL_11_CONSTEXPR const T &&value() const && {\n    if (has_value())\n      return std::move(this->m_value);\n    throw bad_optional_access();\n  }\n#endif\n\n  /// \\returns the stored value if there is one, otherwise returns `u`\n  /// \\group value_or\n  template <class U> constexpr T value_or(U &&u) const & {\n    static_assert(std::is_copy_constructible<T>::value &&\n                      std::is_convertible<U &&, T>::value,\n                  \"T must be copy constructible and convertible from U\");\n    return has_value() ? **this : static_cast<T>(std::forward<U>(u));\n  }\n\n  /// \\group value_or\n  template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && {\n    static_assert(std::is_move_constructible<T>::value &&\n                      std::is_convertible<U &&, T>::value,\n                  \"T must be move constructible and convertible from U\");\n    return has_value() ? **this : static_cast<T>(std::forward<U>(u));\n  }\n\n  /// Destroys the stored value if one exists, making the optional empty\n  void reset() noexcept {\n    if (has_value()) {\n      this->m_value.~T();\n      this->m_has_value = false;\n    }\n  }\n}; // namespace tl\n\n/// \\group relop\n/// \\brief Compares two optional objects\n/// \\details If both optionals contain a value, they are compared with `T`s\n/// relational operators. Otherwise `lhs` and `rhs` are equal only if they are\n/// both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs`\n/// is not.\ntemplate <class T, class U>\ninline constexpr bool operator==(const optional<T> &lhs,\n                                 const optional<U> &rhs) {\n  return lhs.has_value() == rhs.has_value() &&\n         (!lhs.has_value() || *lhs == *rhs);\n}\n/// \\group relop\ntemplate <class T, class U>\ninline constexpr bool operator!=(const optional<T> &lhs,\n                                 const optional<U> &rhs) {\n  return lhs.has_value() != rhs.has_value() ||\n         (lhs.has_value() && *lhs != *rhs);\n}\n/// \\group relop\ntemplate <class T, class U>\ninline constexpr bool operator<(const optional<T> &lhs,\n                                const optional<U> &rhs) {\n  return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);\n}\n/// \\group relop\ntemplate <class T, class U>\ninline constexpr bool operator>(const optional<T> &lhs,\n                                const optional<U> &rhs) {\n  return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);\n}\n/// \\group relop\ntemplate <class T, class U>\ninline constexpr bool operator<=(const optional<T> &lhs,\n                                 const optional<U> &rhs) {\n  return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);\n}\n/// \\group relop\ntemplate <class T, class U>\ninline constexpr bool operator>=(const optional<T> &lhs,\n                                 const optional<U> &rhs) {\n  return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);\n}\n\n/// \\group relop_nullopt\n/// \\brief Compares an optional to a `nullopt`\n/// \\details Equivalent to comparing the optional to an empty optional\ntemplate <class T>\ninline constexpr bool operator==(const optional<T> &lhs, nullopt_t) noexcept {\n  return !lhs.has_value();\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator==(nullopt_t, const optional<T> &rhs) noexcept {\n  return !rhs.has_value();\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator!=(const optional<T> &lhs, nullopt_t) noexcept {\n  return lhs.has_value();\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator!=(nullopt_t, const optional<T> &rhs) noexcept {\n  return rhs.has_value();\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator<(const optional<T> &, nullopt_t) noexcept {\n  return false;\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator<(nullopt_t, const optional<T> &rhs) noexcept {\n  return rhs.has_value();\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator<=(const optional<T> &lhs, nullopt_t) noexcept {\n  return !lhs.has_value();\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator<=(nullopt_t, const optional<T> &) noexcept {\n  return true;\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator>(const optional<T> &lhs, nullopt_t) noexcept {\n  return lhs.has_value();\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator>(nullopt_t, const optional<T> &) noexcept {\n  return false;\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator>=(const optional<T> &, nullopt_t) noexcept {\n  return true;\n}\n/// \\group relop_nullopt\ntemplate <class T>\ninline constexpr bool operator>=(nullopt_t, const optional<T> &rhs) noexcept {\n  return !rhs.has_value();\n}\n\n/// \\group relop_t\n/// \\brief Compares the optional with a value.\n/// \\details If the optional has a value, it is compared with the other value\n/// using `T`s relational operators. Otherwise, the optional is considered\n/// less than the value.\ntemplate <class T, class U>\ninline constexpr bool operator==(const optional<T> &lhs, const U &rhs) {\n  return lhs.has_value() ? *lhs == rhs : false;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator==(const U &lhs, const optional<T> &rhs) {\n  return rhs.has_value() ? lhs == *rhs : false;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator!=(const optional<T> &lhs, const U &rhs) {\n  return lhs.has_value() ? *lhs != rhs : true;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator!=(const U &lhs, const optional<T> &rhs) {\n  return rhs.has_value() ? lhs != *rhs : true;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator<(const optional<T> &lhs, const U &rhs) {\n  return lhs.has_value() ? *lhs < rhs : true;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator<(const U &lhs, const optional<T> &rhs) {\n  return rhs.has_value() ? lhs < *rhs : false;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator<=(const optional<T> &lhs, const U &rhs) {\n  return lhs.has_value() ? *lhs <= rhs : true;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator<=(const U &lhs, const optional<T> &rhs) {\n  return rhs.has_value() ? lhs <= *rhs : false;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator>(const optional<T> &lhs, const U &rhs) {\n  return lhs.has_value() ? *lhs > rhs : false;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator>(const U &lhs, const optional<T> &rhs) {\n  return rhs.has_value() ? lhs > *rhs : true;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator>=(const optional<T> &lhs, const U &rhs) {\n  return lhs.has_value() ? *lhs >= rhs : false;\n}\n/// \\group relop_t\ntemplate <class T, class U>\ninline constexpr bool operator>=(const U &lhs, const optional<T> &rhs) {\n  return rhs.has_value() ? lhs >= *rhs : true;\n}\n\n/// \\synopsis template <class T>\\nvoid swap(optional<T> &lhs, optional<T> &rhs);\ntemplate <class T,\n          detail::enable_if_t<std::is_move_constructible<T>::value> * = nullptr,\n          detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr>\nvoid swap(optional<T> &lhs,\n          optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {\n  return lhs.swap(rhs);\n}\n\nnamespace detail {\nstruct i_am_secret {};\n} // namespace detail\n\ntemplate <class T = detail::i_am_secret, class U,\n          class Ret =\n              detail::conditional_t<std::is_same<T, detail::i_am_secret>::value,\n                                    detail::decay_t<U>, T>>\ninline constexpr optional<Ret> make_optional(U &&v) {\n  return optional<Ret>(std::forward<U>(v));\n}\n\ntemplate <class T, class... Args>\ninline constexpr optional<T> make_optional(Args &&... args) {\n  return optional<T>(in_place, std::forward<Args>(args)...);\n}\ntemplate <class T, class U, class... Args>\ninline constexpr optional<T> make_optional(std::initializer_list<U> il,\n                                           Args &&... args) {\n  return optional<T>(in_place, il, std::forward<Args>(args)...);\n}\n\n#if __cplusplus >= 201703L\ntemplate <class T> optional(T)->optional<T>;\n#endif\n\n/// \\exclude\nnamespace detail {\n#ifdef TL_OPTIONAL_CXX14\ntemplate <class Opt, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Opt>())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nconstexpr auto optional_map_impl(Opt &&opt, F &&f) {\n  return opt.has_value()\n             ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))\n             : optional<Ret>(nullopt);\n}\n\ntemplate <class Opt, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Opt>())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\nauto optional_map_impl(Opt &&opt, F &&f) {\n  if (opt.has_value()) {\n    detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));\n    return make_optional(monostate{});\n  }\n\n  return optional<monostate>(nullopt);\n}\n#else\ntemplate <class Opt, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Opt>())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\n\nconstexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret> {\n  return opt.has_value()\n             ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))\n             : optional<Ret>(nullopt);\n}\n\ntemplate <class Opt, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Opt>())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\n\nauto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate> {\n  if (opt.has_value()) {\n    detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));\n    return monostate{};\n  }\n\n  return nullopt;\n}\n#endif\n} // namespace detail\n\n/// Specialization for when `T` is a reference. `optional<T&>` acts similarly\n/// to a `T*`, but provides more operations and shows intent more clearly.\n///\n/// *Examples*:\n///\n/// ```\n/// int i = 42;\n/// tl::optional<int&> o = i;\n/// *o == 42; //true\n/// i = 12;\n/// *o = 12; //true\n/// &*o == &i; //true\n/// ```\n///\n/// Assignment has rebind semantics rather than assign-through semantics:\n///\n/// ```\n/// int j = 8;\n/// o = j;\n///\n/// &*o == &j; //true\n/// ```\ntemplate <class T> class optional<T &> {\npublic:\n// The different versions for C++14 and 11 are needed because deduced return\n// types are not SFINAE-safe. This provides better support for things like\n// generic lambdas. C.f.\n// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n  /// \\group and_then\n  /// Carries out some operation which returns an optional on the stored\n  /// object if there is one. \\requires `std::invoke(std::forward<F>(f),\n  /// value())` returns a `std::optional<U>` for some `U`. \\returns Let `U` be\n  /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a\n  /// `std::optional<U>`. The return value is empty if `*this` is empty,\n  /// otherwise the return value of `std::invoke(std::forward<F>(f), value())`\n  /// is returned.\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) &;\n  template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {\n    using result = detail::invoke_result_t<F, T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) &&;\n  template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {\n    using result = detail::invoke_result_t<F, T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) const &;\n  template <class F> constexpr auto and_then(F &&f) const & {\n    using result = detail::invoke_result_t<F, const T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) const &&;\n  template <class F> constexpr auto and_then(F &&f) const && {\n    using result = detail::invoke_result_t<F, const T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n#endif\n#else\n  /// \\group and_then\n  /// Carries out some operation which returns an optional on the stored\n  /// object if there is one. \\requires `std::invoke(std::forward<F>(f),\n  /// value())` returns a `std::optional<U>` for some `U`. \\returns Let `U` be\n  /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a\n  /// `std::optional<U>`. The return value is empty if `*this` is empty,\n  /// otherwise the return value of `std::invoke(std::forward<F>(f), value())`\n  /// is returned.\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) &;\n  template <class F>\n  TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {\n    using result = detail::invoke_result_t<F, T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) &&;\n  template <class F>\n  TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) && {\n    using result = detail::invoke_result_t<F, T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) const &;\n  template <class F>\n  constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {\n    using result = detail::invoke_result_t<F, const T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group and_then\n  /// \\synopsis template <class F>\\nconstexpr auto and_then(F &&f) const &&;\n  template <class F>\n  constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const && {\n    using result = detail::invoke_result_t<F, const T &>;\n    static_assert(detail::is_optional<result>::value,\n                  \"F must return an optional\");\n\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : result(nullopt);\n  }\n#endif\n#endif\n\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n  /// \\brief Carries out some operation on the stored object if there is one.\n  /// \\returns Let `U` be the result of `std::invoke(std::forward<F>(f),\n  /// value())`. Returns a `std::optional<U>`. The return value is empty if\n  /// `*this` is empty, otherwise an `optional<U>` is constructed from the\n  /// return value of `std::invoke(std::forward<F>(f), value())` and is\n  /// returned.\n  ///\n  /// \\group map\n  /// \\synopsis template <class F> constexpr auto map(F &&f) &;\n  template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {\n    return detail::optional_map_impl(*this, std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> constexpr auto map(F &&f) &&;\n  template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {\n    return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> constexpr auto map(F &&f) const&;\n  template <class F> constexpr auto map(F &&f) const & {\n    return detail::optional_map_impl(*this, std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> constexpr auto map(F &&f) const&&;\n  template <class F> constexpr auto map(F &&f) const && {\n    return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n  }\n#else\n  /// \\brief Carries out some operation on the stored object if there is one.\n  /// \\returns Let `U` be the result of `std::invoke(std::forward<F>(f),\n  /// value())`. Returns a `std::optional<U>`. The return value is empty if\n  /// `*this` is empty, otherwise an `optional<U>` is constructed from the\n  /// return value of `std::invoke(std::forward<F>(f), value())` and is\n  /// returned.\n  ///\n  /// \\group map\n  /// \\synopsis template <class F> auto map(F &&f) &;\n  template <class F>\n  TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &>(),\n                                                     std::declval<F &&>()))\n  map(F &&f) & {\n    return detail::optional_map_impl(*this, std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> auto map(F &&f) &&;\n  template <class F>\n  TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &&>(),\n                                                     std::declval<F &&>()))\n  map(F &&f) && {\n    return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n  }\n\n  /// \\group map\n  /// \\synopsis template <class F> auto map(F &&f) const&;\n  template <class F>\n  constexpr decltype(detail::optional_map_impl(std::declval<const optional &>(),\n                                      std::declval<F &&>()))\n  map(F &&f) const & {\n    return detail::optional_map_impl(*this, std::forward<F>(f));\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group map\n  /// \\synopsis template <class F> auto map(F &&f) const&&;\n  template <class F>\n  constexpr decltype(detail::optional_map_impl(std::declval<const optional &&>(),\n                                      std::declval<F &&>()))\n  map(F &&f) const && {\n    return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n  }\n#endif\n#endif\n\n  /// \\brief Calls `f` if the optional is empty\n  /// \\requires `std::invoke_result_t<F>` must be void or convertible to\n  /// `optional<T>`. \\effects If `*this` has a value, returns `*this`.\n  /// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns\n  /// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`.\n  ///\n  /// \\group or_else\n  /// \\synopsis template <class F> optional<T> or_else (F &&f) &;\n  template <class F, detail::enable_if_ret_void<F> * = nullptr>\n  optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {\n    if (has_value())\n      return *this;\n\n    std::forward<F>(f)();\n    return nullopt;\n  }\n\n  /// \\exclude\n  template <class F, detail::disable_if_ret_void<F> * = nullptr>\n  optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {\n    return has_value() ? *this : std::forward<F>(f)();\n  }\n\n  /// \\group or_else\n  /// \\synopsis template <class F> optional<T> or_else (F &&f) &&;\n  template <class F, detail::enable_if_ret_void<F> * = nullptr>\n  optional<T> or_else(F &&f) && {\n    if (has_value())\n      return std::move(*this);\n\n    std::forward<F>(f)();\n    return nullopt;\n  }\n\n  /// \\exclude\n  template <class F, detail::disable_if_ret_void<F> * = nullptr>\n  optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {\n    return has_value() ? std::move(*this) : std::forward<F>(f)();\n  }\n\n  /// \\group or_else\n  /// \\synopsis template <class F> optional<T> or_else (F &&f) const &;\n  template <class F, detail::enable_if_ret_void<F> * = nullptr>\n  optional<T> or_else(F &&f) const & {\n    if (has_value())\n      return *this;\n\n    std::forward<F>(f)();\n    return nullopt;\n  }\n\n  /// \\exclude\n  template <class F, detail::disable_if_ret_void<F> * = nullptr>\n  optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {\n    return has_value() ? *this : std::forward<F>(f)();\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\exclude\n  template <class F, detail::enable_if_ret_void<F> * = nullptr>\n  optional<T> or_else(F &&f) const && {\n    if (has_value())\n      return std::move(*this);\n\n    std::forward<F>(f)();\n    return nullopt;\n  }\n\n  /// \\exclude\n  template <class F, detail::disable_if_ret_void<F> * = nullptr>\n  optional<T> or_else(F &&f) const && {\n    return has_value() ? std::move(*this) : std::forward<F>(f)();\n  }\n#endif\n\n  /// \\brief Maps the stored value with `f` if there is one, otherwise returns\n  /// `u`.\n  ///\n  /// \\details If there is a value stored, then `f` is called with `**this`\n  /// and the value is returned. Otherwise `u` is returned.\n  ///\n  /// \\group map_or\n  template <class F, class U> U map_or(F &&f, U &&u) & {\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : std::forward<U>(u);\n  }\n\n  /// \\group map_or\n  template <class F, class U> U map_or(F &&f, U &&u) && {\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : std::forward<U>(u);\n  }\n\n  /// \\group map_or\n  template <class F, class U> U map_or(F &&f, U &&u) const & {\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : std::forward<U>(u);\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group map_or\n  template <class F, class U> U map_or(F &&f, U &&u) const && {\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : std::forward<U>(u);\n  }\n#endif\n\n  /// \\brief Maps the stored value with `f` if there is one, otherwise calls\n  /// `u` and returns the result.\n  ///\n  /// \\details If there is a value stored, then `f` is\n  /// called with `**this` and the value is returned. Otherwise\n  /// `std::forward<U>(u)()` is returned.\n  ///\n  /// \\group map_or_else\n  /// \\synopsis template <class F, class U>\\nauto map_or_else(F &&f, U &&u) &;\n  template <class F, class U>\n  detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : std::forward<U>(u)();\n  }\n\n  /// \\group map_or_else\n  /// \\synopsis template <class F, class U>\\nauto map_or_else(F &&f, U &&u)\n  /// &&;\n  template <class F, class U>\n  detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : std::forward<U>(u)();\n  }\n\n  /// \\group map_or_else\n  /// \\synopsis template <class F, class U>\\nauto map_or_else(F &&f, U &&u)\n  /// const &;\n  template <class F, class U>\n  detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {\n    return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                       : std::forward<U>(u)();\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group map_or_else\n  /// \\synopsis template <class F, class U>\\nauto map_or_else(F &&f, U &&u)\n  /// const &&;\n  template <class F, class U>\n  detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {\n    return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))\n                       : std::forward<U>(u)();\n  }\n#endif\n\n  /// \\returns `u` if `*this` has a value, otherwise an empty optional.\n  template <class U>\n  constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {\n    using result = optional<detail::decay_t<U>>;\n    return has_value() ? result{u} : result{nullopt};\n  }\n\n  /// \\returns `rhs` if `*this` is empty, otherwise the current value.\n  /// \\group disjunction\n  TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {\n    return has_value() ? *this : rhs;\n  }\n\n  /// \\group disjunction\n  constexpr optional disjunction(const optional &rhs) const & {\n    return has_value() ? *this : rhs;\n  }\n\n  /// \\group disjunction\n  TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {\n    return has_value() ? std::move(*this) : rhs;\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group disjunction\n  constexpr optional disjunction(const optional &rhs) const && {\n    return has_value() ? std::move(*this) : rhs;\n  }\n#endif\n\n  /// \\group disjunction\n  TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {\n    return has_value() ? *this : std::move(rhs);\n  }\n\n  /// \\group disjunction\n  constexpr optional disjunction(optional &&rhs) const & {\n    return has_value() ? *this : std::move(rhs);\n  }\n\n  /// \\group disjunction\n  TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {\n    return has_value() ? std::move(*this) : std::move(rhs);\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group disjunction\n  constexpr optional disjunction(optional &&rhs) const && {\n    return has_value() ? std::move(*this) : std::move(rhs);\n  }\n#endif\n\n  /// Takes the value out of the optional, leaving it empty\n  /// \\group take\n  optional take() & {\n    optional ret = *this;\n    reset();\n    return ret;\n  }\n\n  /// \\group take\n  optional take() const & {\n    optional ret = *this;\n    reset();\n    return ret;\n  }\n\n  /// \\group take\n  optional take() && {\n    optional ret = std::move(*this);\n    reset();\n    return ret;\n  }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n  /// \\group take\n  optional take() const && {\n    optional ret = std::move(*this);\n    reset();\n    return ret;\n  }\n#endif\n\n  using value_type = T &;\n\n  /// Constructs an optional that does not contain a value.\n  /// \\group ctor_empty\n  constexpr optional() noexcept : m_value(nullptr) {}\n\n  /// \\group ctor_empty\n  constexpr optional(nullopt_t) noexcept : m_value(nullptr) {}\n\n  /// Copy constructor\n  ///\n  /// If `rhs` contains a value, the stored value is direct-initialized with\n  /// it. Otherwise, the constructed optional is empty.\n  TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) noexcept = default;\n\n  /// Move constructor\n  ///\n  /// If `rhs` contains a value, the stored value is direct-initialized with\n  /// it. Otherwise, the constructed optional is empty.\n  TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;\n\n  /// Constructs the stored value with `u`.\n  /// \\synopsis template <class U=T> constexpr optional(U &&u);\n  template <class U = T,\n            detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>\n                * = nullptr>\n  constexpr optional(U &&u) : m_value(std::addressof(u)) {\n    static_assert(std::is_lvalue_reference<U>::value, \"U must be an lvalue\");\n  }\n\n  /// \\exclude\n  template <class U>\n  constexpr explicit optional(const optional<U> &rhs) : optional(*rhs) {}\n\n  /// No-op\n  ~optional() = default;\n\n  /// Assignment to empty.\n  ///\n  /// Destroys the current value if there is one.\n  optional &operator=(nullopt_t) noexcept {\n    m_value = nullptr;\n    return *this;\n  }\n\n  /// Copy assignment.\n  ///\n  /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise\n  /// resets the stored value in `*this`.\n  optional &operator=(const optional &rhs) = default;\n\n  /// Rebinds this optional to `u`.\n  ///\n  /// \\requires `U` must be an lvalue reference.\n  /// \\synopsis optional &operator=(U &&u);\n  template <class U = T,\n            detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>\n                * = nullptr>\n  optional &operator=(U &&u) {\n    static_assert(std::is_lvalue_reference<U>::value, \"U must be an lvalue\");\n    m_value = std::addressof(u);\n    return *this;\n  }\n\n  /// Converting copy assignment operator.\n  ///\n  /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise\n  /// resets the stored value in `*this`.\n  template <class U> optional &operator=(const optional<U> &rhs) {\n    m_value = std::addressof(rhs.value());\n    return *this;\n  }\n\n  /// Constructs the value in-place, destroying the current one if there is\n  /// one.\n  ///\n  /// \\group emplace\n  template <class... Args> T &emplace(Args &&... args) noexcept {\n    static_assert(std::is_constructible<T, Args &&...>::value,\n                  \"T must be constructible with Args\");\n\n    *this = nullopt;\n    this->construct(std::forward<Args>(args)...);\n    return value();\n  }\n\n  /// Swaps this optional with the other.\n  ///\n  /// If neither optionals have a value, nothing happens.\n  /// If both have a value, the values are swapped.\n  /// If one has a value, it is moved to the other and the movee is left\n  /// valueless.\n  void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); }\n\n  /// \\returns a pointer to the stored value\n  /// \\requires a value is stored\n  /// \\group pointer\n  /// \\synopsis constexpr const T *operator->() const;\n  constexpr const T *operator->() const { return m_value; }\n\n  /// \\group pointer\n  /// \\synopsis constexpr T *operator->();\n  TL_OPTIONAL_11_CONSTEXPR T *operator->() { return m_value; }\n\n  /// \\returns the stored value\n  /// \\requires a value is stored\n  /// \\group deref\n  /// \\synopsis constexpr T &operator*();\n  TL_OPTIONAL_11_CONSTEXPR T &operator*() { return *m_value; }\n\n  /// \\group deref\n  /// \\synopsis constexpr const T &operator*() const;\n  constexpr const T &operator*() const { return *m_value; }\n\n  /// \\returns whether or not the optional has a value\n  /// \\group has_value\n  constexpr bool has_value() const noexcept { return m_value != nullptr; }\n\n  /// \\group has_value\n  constexpr explicit operator bool() const noexcept {\n    return m_value != nullptr;\n  }\n\n  /// \\returns the contained value if there is one, otherwise throws\n  /// [bad_optional_access]\n  /// \\group value\n  /// synopsis constexpr T &value();\n  TL_OPTIONAL_11_CONSTEXPR T &value() {\n    if (has_value())\n      return *m_value;\n    throw bad_optional_access();\n  }\n  /// \\group value\n  /// \\synopsis constexpr const T &value() const;\n  TL_OPTIONAL_11_CONSTEXPR const T &value() const {\n    if (has_value())\n      return *m_value;\n    throw bad_optional_access();\n  }\n\n  /// \\returns the stored value if there is one, otherwise returns `u`\n  /// \\group value_or\n  template <class U> constexpr T value_or(U &&u) const & {\n    static_assert(std::is_copy_constructible<T>::value &&\n                      std::is_convertible<U &&, T>::value,\n                  \"T must be copy constructible and convertible from U\");\n    return has_value() ? **this : static_cast<T>(std::forward<U>(u));\n  }\n\n  /// \\group value_or\n  template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && {\n    static_assert(std::is_move_constructible<T>::value &&\n                      std::is_convertible<U &&, T>::value,\n                  \"T must be move constructible and convertible from U\");\n    return has_value() ? **this : static_cast<T>(std::forward<U>(u));\n  }\n\n  /// Destroys the stored value if one exists, making the optional empty\n  void reset() noexcept { m_value = nullptr; }\n\nprivate:\n  T *m_value;\n}; // namespace tl\n\n\n\n} // namespace tl\n\nnamespace std {\n// TO-DO SFINAE\ntemplate <class T> struct hash<tl::optional<T>> {\n  ::std::size_t operator()(const tl::optional<T> &o) const {\n    if (!o.has_value())\n      return 0;\n\n    return std::hash<tl::detail::remove_const_t<T>>()(*o);\n  }\n};\n} // namespace std\n\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/ordered-map/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Tessil\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/ordered-map/README.md",
    "content": "[![Build Status](https://travis-ci.org/Tessil/ordered-map.svg?branch=master)](https://travis-ci.org/Tessil/ordered-map) [![Build status](https://ci.appveyor.com/api/projects/status/7fug7piv59d0in36/branch/master?svg=true)](https://ci.appveyor.com/project/Tessil/ordered-map/branch/master)\n\n## C++ hash map and hash set which preserves the order of insertion\n\nThe ordered-map library provides a hash map and a hash set which preserve the order of insertion in a way similar to Python's [OrderedDict](https://docs.python.org/3/library/collections.html#collections.OrderedDict). When iterating over the map, the values will be returned in the same order as they were inserted.\n\nThe values are stored contiguously in an underlying structure, no holes in-between values even after an erase operation. By default a `std::deque` is used for this structure, but it's also possible to  use a `std::vector`. This structure is directly accessible through the `values_container()` method and if the structure is a `std::vector`, a `data()` method is also provided to easily interact with C APIs.\n\nTo resolve collisions on hashes, the library uses linear robin hood probing with backward shift deletion.\n\nThe library provides a behaviour similar to a `std::deque/std::vector` with unique values but with an average time complexity of O(1) for lookups and an amortised time complexity of O(1) for insertions. This comes at the price of a little higher memory footprint (8 bytes per bucket by default).\n\nTwo classes are provided: `tsl::ordered_map` and `tsl::ordered_set`.\n\n**Note**: The library uses a power of two for the size of its buckets array to take advantage of the [fast modulo](https://en.wikipedia.org/wiki/Modulo_operation#Performance_issues). For good performances, it requires the hash table to have a well-distributed hash function. If you encounter performance issues check your hash function.\n\n### Key features\n\n- Header-only library, just add the [include](include/) directory to your include path and you are ready to go. If you use CMake, you can also use the `tsl::ordered_map` exported target from the [CMakeLists.txt](CMakeLists.txt).\n- Values are stored in the same order as the insertion order. The library provides a direct access to the underlying structure which stores the values.\n- O(1) average time complexity for lookups with performances similar to `std::unordered_map` but with faster insertions and reduced memory usage (see [benchmark](https://tessil.github.io/2016/08/29/benchmark-hopscotch-map.html) for details).\n- Provide random access iterators and also reverse iterators.\n- Support for heterogeneous lookups allowing the usage of `find` with a type different than `Key` (e.g. if you have a map that uses `std::unique_ptr<foo>` as key, you can use a `foo*` or a `std::uintptr_t` as key parameter to `find` without constructing a `std::unique_ptr<foo>`, see [example](#heterogeneous-lookups)).\n- If the hash is known before a lookup, it is possible to pass it as parameter to speed-up the lookup (see `precalculated_hash` parameter in [API](https://tessil.github.io/ordered-map/classtsl_1_1ordered__map.html#a7fcde27edc6697a0b127f4b1aefa8a7d)).\n- The library can be used with exceptions disabled (through `-fno-exceptions` option on Clang and GCC, without an `/EH` option on MSVC or simply by defining `TSL_NO_EXCEPTIONS`). `std::terminate` is used in replacement of the `throw` instruction when exceptions are disabled.\n- API closely similar to `std::unordered_map` and `std::unordered_set`.\n\n### Differences compare to `std::unordered_map`\n`tsl::ordered_map` tries to have an interface similar to `std::unordered_map`, but some differences exist.\n- The iterators are `RandomAccessIterator`.\n- Iterator invalidation behaves in a way closer to `std::vector` and `std::deque` (see [API](https://tessil.github.io/ordered-map/classtsl_1_1ordered__map.html#details) for details). If you use `std::vector` as `ValueTypeContainer`, you can use `reserve()` to preallocate some space and avoid the invalidation of the iterators on insert.\n- Slow `erase()` operation, it has a complexity of O(n). A faster O(1) version `unordered_erase()` exists, but it breaks the insertion order (see [API](https://tessil.github.io/ordered-map/classtsl_1_1ordered__map.html#a9f94a7889fa7fa92eea41ca63b3f98a4) for details). An O(1) `pop_back()` is also available.\n- The equality oprators `operator==` and `operator!=` are order dependent. Two `tsl::ordered_map` with the same values but inserted in a different order don't compare equal.\n- For iterators, `operator*()` and `operator->()` return a reference and a pointer to `const std::pair<Key, T>` instead of `std::pair<const Key, T>` making the value `T` not modifiable. To modify the value you have to call the `value()` method of the iterator to get a mutable reference. Example:\n```c++\ntsl::ordered_map<int, int> map = {{1, 1}, {2, 1}, {3, 1}};\nfor(auto it = map.begin(); it != map.end(); ++it) {\n    //it->second = 2; // Illegal\n    it.value() = 2; // Ok\n}\n```\n- By default the map can only hold up to 2<sup>32</sup> - 1 values, that is 4 294 967 295 values. This can be raised through the `IndexType` class template parameter, check the [API](https://tessil.github.io/ordered-map/classtsl_1_1ordered__map.html#details) for details. \n- No support for some bucket related methods (like `bucket_size`, `bucket`, ...).\n\n\nThread-safety guarantee is the same as `std::unordered_map`  (i.e. possible to have multiple concurrent readers with no writer).\n\nConcerning the strong exception guarantee, it holds only if `ValueContainer::emplace_back` has the strong exception guarantee (which is true for `std::vector` and `std::deque` as long as the type `T` is not a move-only type with a move constructor that may throw an exception, see [details](http://en.cppreference.com/w/cpp/container/vector/emplace_back#Exceptions)).\n\nThese differences also apply between `std::unordered_set` and `tsl::ordered_set`.\n\n\n### Installation\n\nTo use ordered-map, just add the [include](include/) directory to your include path. It is a **header-only** library.\n\nIf you use CMake, you can also use the `tsl::ordered_map` exported target from the [CMakeLists.txt](CMakeLists.txt) with `target_link_libraries`. \n```cmake\n# Example where the ordered-map project is stored in a third-party directory\nadd_subdirectory(third-party/ordered-map)\ntarget_link_libraries(your_target PRIVATE tsl::ordered_map)  \n```\n\nThe code should work with any C++11 standard-compliant compiler and has been tested with GCC 4.8.4, Clang 3.5.0 and Visual Studio 2015.\n\nTo run the tests you will need the Boost Test library and CMake.\n\n```bash\ngit clone https://github.com/Tessil/ordered-map.git\ncd ordered-map/tests\nmkdir build\ncd build\ncmake ..\ncmake --build .\n./tsl_ordered_map_tests \n```\n\n### Usage\n\nThe API can be found [here](https://tessil.github.io/ordered-map/).\n\n### Example\n\n```c++\n#include <iostream>\n#include <string>\n#include <cstdlib>\n#include <tsl/ordered_map.h>\n#include <tsl/ordered_set.h>\n\nint main() {\n    tsl::ordered_map<char, int> map = {{'d', 1}, {'a', 2}, {'g', 3}};\n    map.insert({'b', 4});\n    map['h'] = 5;\n    map['e'] = 6;\n    \n    map.erase('a');\n    \n    \n    // {d, 1} {g, 3} {b, 4} {h, 5} {e, 6}\n    for(const auto& key_value : map) {\n        std::cout << \"{\" << key_value.first << \", \" << key_value.second << \"}\" << std::endl;\n    }\n    \n    \n    map.unordered_erase('b');\n    \n    // Break order: {d, 1} {g, 3} {e, 6} {h, 5}\n    for(const auto& key_value : map) {\n        std::cout << \"{\" << key_value.first << \", \" << key_value.second << \"}\" << std::endl;\n    }\n    \n    \n    for(auto it = map.begin(); it != map.end(); ++it) {\n        //it->second += 2; // Not valid.\n        it.value() += 2;\n    }\n    \n    \n    if(map.find('d') != map.end()) {\n        std::cout << \"Found 'd'.\" << std::endl;\n    }\n    \n    const std::size_t precalculated_hash = std::hash<char>()('d');\n    // If we already know the hash beforehand, we can pass it as argument to speed-up the lookup.\n    if(map.find('d', precalculated_hash) != map.end()) {\n        std::cout << \"Found 'd' with hash \" << precalculated_hash << \".\" << std::endl;\n    }\n    \n    \n    tsl::ordered_set<char, std::hash<char>, std::equal_to<char>,\n                     std::allocator<char>, std::vector<char>> set;\n    set.reserve(6);\n    \n    set = {'3', '4', '9', '2'};\n    set.erase('2');\n    set.insert('1');\n    set.insert('\\0');\n    \n    set.pop_back();\n    set.insert({'0', '\\0'});\n    \n    // Get raw buffer for C API: 34910\n    std::cout << atoi(set.data()) << std::endl;\n}\n```\n\n#### Heterogeneous lookup\n\nHeterogeneous overloads allow the usage of other types than `Key` for lookup and erase operations as long as the used types are hashable and comparable to `Key`.\n\nTo activate the heterogeneous overloads in `tsl::ordered_map/set`, the qualified-id `KeyEqual::is_transparent` must be valid. It works the same way as for [`std::map::find`](http://en.cppreference.com/w/cpp/container/map/find). You can either use [`std::equal_to<>`](http://en.cppreference.com/w/cpp/utility/functional/equal_to_void) or define your own function object.\n\nBoth `KeyEqual` and `Hash` will need to be able to deal with the different types.\n\n```c++\n#include <functional>\n#include <iostream>\n#include <string>\n#include <tsl/ordered_map.h>\n\n\n\nstruct employee {\n    employee(int id, std::string name) : m_id(id), m_name(std::move(name)) {\n    }\n    \n    // Either we include the comparators in the class and we use `std::equal_to<>`...\n    friend bool operator==(const employee& empl, int empl_id) {\n        return empl.m_id == empl_id;\n    }\n    \n    friend bool operator==(int empl_id, const employee& empl) {\n        return empl_id == empl.m_id;\n    }\n    \n    friend bool operator==(const employee& empl1, const employee& empl2) {\n        return empl1.m_id == empl2.m_id;\n    }\n    \n    \n    int m_id;\n    std::string m_name;\n};\n\n// ... or we implement a separate class to compare employees.\nstruct equal_employee {\n    using is_transparent = void;\n    \n    bool operator()(const employee& empl, int empl_id) const {\n        return empl.m_id == empl_id;\n    }\n    \n    bool operator()(int empl_id, const employee& empl) const {\n        return empl_id == empl.m_id;\n    }\n    \n    bool operator()(const employee& empl1, const employee& empl2) const {\n        return empl1.m_id == empl2.m_id;\n    }\n};\n\nstruct hash_employee {\n    std::size_t operator()(const employee& empl) const {\n        return std::hash<int>()(empl.m_id);\n    }\n    \n    std::size_t operator()(int id) const {\n        return std::hash<int>()(id);\n    }\n};\n\n\nint main() {\n    // Use std::equal_to<> which will automatically deduce and forward the parameters\n    tsl::ordered_map<employee, int, hash_employee, std::equal_to<>> map; \n    map.insert({employee(1, \"John Doe\"), 2001});\n    map.insert({employee(2, \"Jane Doe\"), 2002});\n    map.insert({employee(3, \"John Smith\"), 2003});\n\n    // John Smith 2003\n    auto it = map.find(3);\n    if(it != map.end()) {\n        std::cout << it->first.m_name << \" \" << it->second << std::endl;\n    }\n\n    map.erase(1);\n\n\n\n    // Use a custom KeyEqual which has an is_transparent member type\n    tsl::ordered_map<employee, int, hash_employee, equal_employee> map2;\n    map2.insert({employee(4, \"Johnny Doe\"), 2004});\n\n    // 2004\n    std::cout << map2.at(4) << std::endl;\n} \n```\n\n### License\n\nThe code is licensed under the MIT license, see the [LICENSE file](LICENSE) for details.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/ordered-map/include/tsl/ordered_hash.h",
    "content": "/**\n * MIT License\n * \n * Copyright (c) 2017 Tessil\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n#ifndef TSL_ORDERED_HASH_H\n#define TSL_ORDERED_HASH_H\n\n\n#include <algorithm>\n#include <cassert>\n#include <climits>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <exception>\n#include <functional>\n#include <iterator>\n#include <limits>\n#include <memory>\n#include <stdexcept>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n\n/**\n * Macros for compatibility with GCC 4.8\n */\n#if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 9))\n#    define TSL_OH_NO_CONTAINER_ERASE_CONST_ITERATOR\n#    define TSL_OH_NO_CONTAINER_EMPLACE_CONST_ITERATOR\n#endif\n\n/**\n * Only activate tsl_oh_assert if TSL_DEBUG is defined. \n * This way we avoid the performance hit when NDEBUG is not defined with assert as tsl_oh_assert is used a lot\n * (people usually compile with \"-O3\" and not \"-O3 -DNDEBUG\").\n */\n#ifdef TSL_DEBUG\n#    define tsl_oh_assert(expr) assert(expr)\n#else\n#    define tsl_oh_assert(expr) (static_cast<void>(0))\n#endif\n\n/**\n * If exceptions are enabled, throw the exception passed in parameter, otherwise call std::terminate.\n */\n#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (defined (_MSC_VER) && defined (_CPPUNWIND))) && !defined(TSL_NO_EXCEPTIONS)\n#    define TSL_OH_THROW_OR_TERMINATE(ex, msg) throw ex(msg)\n#else\n#    ifdef NDEBUG\n#        define TSL_OH_THROW_OR_TERMINATE(ex, msg) std::terminate()\n#    else\n#        include <cstdio>\n#        define TSL_OH_THROW_OR_TERMINATE(ex, msg) do { std::fprintf(stderr, msg); std::terminate(); } while(0)\n#    endif\n#endif\n\n#undef min\n#undef max\n\nnamespace tsl {\n\nnamespace detail_ordered_hash {\n    \ntemplate<typename T>\nstruct make_void {\n    using type = void;\n};\n\ntemplate<typename T, typename = void>\nstruct has_is_transparent: std::false_type {\n};\n\ntemplate<typename T>\nstruct has_is_transparent<T, typename make_void<typename T::is_transparent>::type>: std::true_type {\n};\n\n\ntemplate<typename T, typename = void>\nstruct is_vector: std::false_type {\n};\n\ntemplate<typename T>\nstruct is_vector<T, typename std::enable_if<\n                        std::is_same<T, std::vector<typename T::value_type, typename T::allocator_type>>::value\n                    >::type>: std::true_type {\n};\n\n\n/**\n * Each bucket entry stores an index which is the index in m_values corresponding to the bucket's value \n * and a hash (which may be truncated to 32 bits depending on IndexType) corresponding to the hash of the value.\n * \n * The size of IndexType limits the size of the hash table to std::numeric_limits<IndexType>::max() - 1 elements (-1 due to \n * a reserved value used to mark a bucket as empty).\n */\ntemplate<class IndexType>\nclass bucket_entry {\n    static_assert(std::is_unsigned<IndexType>::value, \"IndexType must be an unsigned value.\");\n    static_assert(std::numeric_limits<IndexType>::max() <= std::numeric_limits<std::size_t>::max(), \n                  \"std::numeric_limits<IndexType>::max() must be <= std::numeric_limits<std::size_t>::max().\");\n    \npublic:\n    using index_type = IndexType;\n    using truncated_hash_type = typename std::conditional<std::numeric_limits<IndexType>::max() <= \n                                                          std::numeric_limits<std::uint_least32_t>::max(),\n                                                              std::uint_least32_t, \n                                                              std::size_t>::type;\n    \n    bucket_entry() noexcept: m_index(EMPTY_MARKER_INDEX), m_hash(0) {\n    }\n    \n    bool empty() const noexcept {\n        return m_index == EMPTY_MARKER_INDEX;\n    }\n    \n    void clear() noexcept {\n        m_index = EMPTY_MARKER_INDEX;\n    }\n    \n    index_type index() const noexcept {\n        tsl_oh_assert(!empty());\n        return m_index;\n    }\n    \n    index_type& index_ref() noexcept {\n        tsl_oh_assert(!empty());\n        return m_index;\n    }\n    \n    void set_index(index_type index) noexcept {\n        tsl_oh_assert(index <= max_size());\n        \n        m_index = index;\n    }\n    \n    truncated_hash_type truncated_hash() const noexcept {\n        tsl_oh_assert(!empty());\n        return m_hash;\n    }\n    \n    truncated_hash_type& truncated_hash_ref() noexcept {\n        tsl_oh_assert(!empty());\n        return m_hash;\n    }\n    \n    void set_hash(std::size_t hash) noexcept {\n        m_hash = truncate_hash(hash);\n    }\n    \n    \n    \n    static truncated_hash_type truncate_hash(std::size_t hash) noexcept {\n        return truncated_hash_type(hash);\n    }\n    \n    static std::size_t max_size() noexcept {\n        return static_cast<std::size_t>(std::numeric_limits<index_type>::max()) - NB_RESERVED_INDEXES;\n    }\n    \nprivate:\n    static const index_type EMPTY_MARKER_INDEX = std::numeric_limits<index_type>::max();\n    static const std::size_t NB_RESERVED_INDEXES = 1;\n    \n    index_type m_index;\n    truncated_hash_type m_hash;\n};\n\n\n\n/**\n * Internal common class used by ordered_map and ordered_set.\n * \n * ValueType is what will be stored by ordered_hash (usually std::pair<Key, T> for map and Key for set).\n * \n * KeySelect should be a FunctionObject which takes a ValueType in parameter and return a reference to the key.\n * \n * ValueSelect should be a FunctionObject which takes a ValueType in parameter and return a reference to the value. \n * ValueSelect should be void if there is no value (in set for example).\n * \n * ValueTypeContainer is the container which will be used to store ValueType values. \n * Usually a std::deque<ValueType, Allocator> or std::vector<ValueType, Allocator>.\n * \n * \n * \n * The orderd_hash structure is a hash table which preserves the order of insertion of the elements.\n * To do so, it stores the values in the ValueTypeContainer (m_values) using emplace_back at each\n * insertion of a new element. Another structure (m_buckets of type std::vector<bucket_entry>) will \n * serve as buckets array for the hash table part. Each bucket stores an index which corresponds to \n * the index in m_values where the bucket's value is and the (truncated) hash of this value. An index\n * is used instead of a pointer to the value to reduce the size of each bucket entry.\n * \n * To resolve collisions in the buckets array, the structures use robin hood linear probing with \n * backward shift deletion.\n */\ntemplate<class ValueType,\n         class KeySelect,\n         class ValueSelect,\n         class Hash,\n         class KeyEqual,\n         class Allocator,\n         class ValueTypeContainer,\n         class IndexType>\nclass ordered_hash: private Hash, private KeyEqual {\nprivate:\n    template<typename U>\n    using has_mapped_type = typename std::integral_constant<bool, !std::is_same<U, void>::value>;\n    \n    static_assert(std::is_same<typename ValueTypeContainer::value_type, ValueType>::value, \n                  \"ValueTypeContainer::value_type != ValueType. \"\n                  \"Check that the ValueTypeContainer has 'Key' as type for a set or 'std::pair<Key, T>' as type for a map.\");\n    \n    static_assert(std::is_same<typename ValueTypeContainer::allocator_type, Allocator>::value, \n                  \"ValueTypeContainer::allocator_type != Allocator. \"\n                  \"Check that the allocator for ValueTypeContainer is the same as Allocator.\");\n    \n    static_assert(std::is_same<typename Allocator::value_type, ValueType>::value, \n                  \"Allocator::value_type != ValueType. \"\n                  \"Check that the allocator has 'Key' as type for a set or 'std::pair<Key, T>' as type for a map.\");\n    \n    \npublic:\n    template<bool IsConst>\n    class ordered_iterator;\n    \n    using key_type = typename KeySelect::key_type;\n    using value_type = ValueType;\n    using size_type = std::size_t;\n    using difference_type = std::ptrdiff_t;\n    using hasher = Hash;\n    using key_equal = KeyEqual;\n    using allocator_type = Allocator;\n    using reference = value_type&;\n    using const_reference = const value_type&;\n    using pointer = value_type*;\n    using const_pointer = const value_type*;\n    using iterator = ordered_iterator<false>;\n    using const_iterator = ordered_iterator<true>;\n    using reverse_iterator = std::reverse_iterator<iterator>;\n    using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n    \n    using values_container_type = ValueTypeContainer;\n    \npublic:\n    template<bool IsConst>\n    class ordered_iterator {\n        friend class ordered_hash;\n        \n    private:\n        using iterator = typename std::conditional<IsConst, \n                                                    typename values_container_type::const_iterator, \n                                                    typename values_container_type::iterator>::type;\n    \n        \n        ordered_iterator(iterator it) noexcept: m_iterator(it) {\n        }\n        \n    public:\n        using iterator_category = std::random_access_iterator_tag;\n        using value_type = const typename ordered_hash::value_type;\n        using difference_type = typename iterator::difference_type;\n        using reference = value_type&;\n        using pointer = value_type*;\n        \n        \n        ordered_iterator() noexcept {\n        }\n        \n        ordered_iterator(const ordered_iterator<false>& other) noexcept: m_iterator(other.m_iterator) {\n        }\n\n        const typename ordered_hash::key_type& key() const {\n            return KeySelect()(*m_iterator);\n        }\n\n        template<class U = ValueSelect, typename std::enable_if<has_mapped_type<U>::value && IsConst>::type* = nullptr>\n        const typename U::value_type& value() const {\n            return U()(*m_iterator);\n        }\n\n        template<class U = ValueSelect, typename std::enable_if<has_mapped_type<U>::value && !IsConst>::type* = nullptr>\n        typename U::value_type& value() {\n            return U()(*m_iterator);\n        }\n        \n        reference operator*() const { return *m_iterator; }\n        pointer operator->() const { return m_iterator.operator->(); }\n        \n        ordered_iterator& operator++() { ++m_iterator; return *this; }\n        ordered_iterator& operator--() { --m_iterator; return *this; }\n        \n        ordered_iterator operator++(int) { ordered_iterator tmp(*this); ++(*this); return tmp; }\n        ordered_iterator operator--(int) { ordered_iterator tmp(*this); --(*this); return tmp; }\n        \n        reference operator[](difference_type n) const { return m_iterator[n]; }\n        \n        ordered_iterator& operator+=(difference_type n) { m_iterator += n; return *this; }\n        ordered_iterator& operator-=(difference_type n) { m_iterator -= n; return *this; }\n        \n        ordered_iterator operator+(difference_type n) { ordered_iterator tmp(*this); tmp += n; return tmp; }\n        ordered_iterator operator-(difference_type n) { ordered_iterator tmp(*this); tmp -= n; return tmp; }\n        \n        friend bool operator==(const ordered_iterator& lhs, const ordered_iterator& rhs) { \n            return lhs.m_iterator == rhs.m_iterator; \n        }\n        \n        friend bool operator!=(const ordered_iterator& lhs, const ordered_iterator& rhs) { \n            return lhs.m_iterator != rhs.m_iterator; \n        }\n        \n        friend bool operator<(const ordered_iterator& lhs, const ordered_iterator& rhs) { \n            return lhs.m_iterator < rhs.m_iterator; \n        }\n        \n        friend bool operator>(const ordered_iterator& lhs, const ordered_iterator& rhs) { \n            return lhs.m_iterator > rhs.m_iterator; \n        }\n        \n        friend bool operator<=(const ordered_iterator& lhs, const ordered_iterator& rhs) { \n            return lhs.m_iterator <= rhs.m_iterator; \n        }\n        \n        friend bool operator>=(const ordered_iterator& lhs, const ordered_iterator& rhs) { \n            return lhs.m_iterator >= rhs.m_iterator; \n        }\n\n        friend ordered_iterator operator+(difference_type n, const ordered_iterator& it) { \n            return n + it.m_iterator;\n        }\n\n        friend difference_type operator-(const ordered_iterator& lhs, const ordered_iterator& rhs) { \n            return lhs.m_iterator - rhs.m_iterator; \n        }\n\n    private:\n        iterator m_iterator;\n    };\n    \n    \nprivate:\n    using bucket_entry = tsl::detail_ordered_hash::bucket_entry<IndexType>;\n                                         \n    using buckets_container_allocator = typename \n                            std::allocator_traits<allocator_type>::template rebind_alloc<bucket_entry>; \n                            \n    using buckets_container_type = std::vector<bucket_entry, buckets_container_allocator>;\n    \n    \n    using truncated_hash_type = typename bucket_entry::truncated_hash_type;\n    using index_type = typename bucket_entry::index_type;\n    \npublic:\n    ordered_hash(size_type bucket_count, \n                 const Hash& hash,\n                 const KeyEqual& equal,\n                 const Allocator& alloc,\n                 float max_load_factor): Hash(hash),\n                                         KeyEqual(equal), \n                                         m_buckets(alloc), \n                                         m_first_or_empty_bucket(static_empty_bucket_ptr()), \n                                         m_mask(0),\n                                         m_values(alloc), \n                                         m_grow_on_next_insert(false)\n    {\n        if(bucket_count > max_bucket_count()) {\n            TSL_OH_THROW_OR_TERMINATE(std::length_error, \"The map exceeds its maxmimum size.\");\n        }\n        \n        if(bucket_count > 0) {\n            bucket_count = round_up_to_power_of_two(bucket_count);\n            \n            m_buckets.resize(bucket_count);\n            m_first_or_empty_bucket = m_buckets.data(),\n            m_mask = bucket_count - 1; \n        }\n        \n        this->max_load_factor(max_load_factor);\n    }\n    \n    ordered_hash(const ordered_hash& other): Hash(other),\n                                             KeyEqual(other),\n                                             m_buckets(other.m_buckets),\n                                             m_first_or_empty_bucket(m_buckets.empty()?static_empty_bucket_ptr():m_buckets.data()),\n                                             m_mask(other.m_mask),\n                                             m_values(other.m_values),\n                                             m_grow_on_next_insert(other.m_grow_on_next_insert),\n                                             m_max_load_factor(other.m_max_load_factor),\n                                             m_load_threshold(other.m_load_threshold)\n    {\n    }\n    \n    ordered_hash(ordered_hash&& other) noexcept(std::is_nothrow_move_constructible<Hash>::value &&\n                                                std::is_nothrow_move_constructible<KeyEqual>::value &&\n                                                std::is_nothrow_move_constructible<buckets_container_type>::value &&\n                                                std::is_nothrow_move_constructible<values_container_type>::value)\n                                          : Hash(std::move(static_cast<Hash&>(other))),\n                                            KeyEqual(std::move(static_cast<KeyEqual&>(other))),\n                                            m_buckets(std::move(other.m_buckets)),\n                                            m_first_or_empty_bucket(m_buckets.empty()?static_empty_bucket_ptr():m_buckets.data()),\n                                            m_mask(other.m_mask),\n                                            m_values(std::move(other.m_values)),\n                                            m_grow_on_next_insert(other.m_grow_on_next_insert),\n                                            m_max_load_factor(other.m_max_load_factor),\n                                            m_load_threshold(other.m_load_threshold)\n    {\n        other.m_buckets.clear();\n        other.m_first_or_empty_bucket = static_empty_bucket_ptr();\n        other.m_mask = 0;\n        other.m_values.clear();\n        other.m_grow_on_next_insert = false;\n        other.m_load_threshold = 0;\n    }\n    \n    ordered_hash& operator=(const ordered_hash& other) {\n        if(&other != this) {\n            Hash::operator=(other);\n            KeyEqual::operator=(other);\n            \n            m_buckets = other.m_buckets;\n            m_first_or_empty_bucket = m_buckets.empty()?static_empty_bucket_ptr():\n                                                        m_buckets.data();\n                                                        \n            m_mask = other.m_mask;\n            m_values = other.m_values;\n            m_grow_on_next_insert = other.m_grow_on_next_insert;\n            m_max_load_factor = other.m_max_load_factor;\n            m_load_threshold = other.m_load_threshold;\n        }\n        \n        return *this;\n    }\n    \n    ordered_hash& operator=(ordered_hash&& other) {\n        other.swap(*this);\n        other.clear();\n        \n        return *this;\n    }\n    \n    allocator_type get_allocator() const {\n        return m_values.get_allocator();\n    }\n    \n    \n    /*\n     * Iterators\n     */\n    iterator begin() noexcept {\n        return iterator(m_values.begin());\n    }\n    \n    const_iterator begin() const noexcept {\n        return cbegin();\n    }\n    \n    const_iterator cbegin() const noexcept {\n        return const_iterator(m_values.cbegin());\n    }\n    \n    iterator end() noexcept {\n        return iterator(m_values.end());\n    }\n    \n    const_iterator end() const noexcept {\n        return cend();\n    }\n    \n    const_iterator cend() const noexcept {\n        return const_iterator(m_values.cend());\n    }  \n    \n    \n    reverse_iterator rbegin() noexcept {\n        return reverse_iterator(m_values.end());\n    }\n    \n    const_reverse_iterator rbegin() const noexcept {\n        return rcbegin();\n    }\n    \n    const_reverse_iterator rcbegin() const noexcept {\n        return const_reverse_iterator(m_values.cend());\n    }\n    \n    reverse_iterator rend() noexcept {\n        return reverse_iterator(m_values.begin());\n    }\n    \n    const_reverse_iterator rend() const noexcept {\n        return rcend();\n    }\n    \n    const_reverse_iterator rcend() const noexcept {\n        return const_reverse_iterator(m_values.cbegin());\n    }  \n    \n    \n    /*\n     * Capacity\n     */\n    bool empty() const noexcept {\n        return m_values.empty();\n    }\n    \n    size_type size() const noexcept {\n        return m_values.size();\n    }\n    \n    size_type max_size() const noexcept {\n        return std::min(bucket_entry::max_size(), m_values.max_size());\n    }\n    \n\n    /*\n     * Modifiers\n     */\n    void clear() noexcept {\n        for(auto& bucket: m_buckets) {\n            bucket.clear();\n        }\n        \n        m_values.clear();\n        m_grow_on_next_insert = false;\n    }\n    \n    template<typename P>\n    std::pair<iterator, bool> insert(P&& value) {\n        return insert_impl(KeySelect()(value), std::forward<P>(value));\n    }\n    \n    template<typename P>\n    iterator insert(const_iterator hint, P&& value) { \n        if(hint != cend() && compare_keys(KeySelect()(*hint), KeySelect()(value))) { \n            return mutable_iterator(hint); \n        }\n        \n        return insert(std::forward<P>(value)).first; \n    }\n    \n    template<class InputIt>\n    void insert(InputIt first, InputIt last) {\n        if(std::is_base_of<std::forward_iterator_tag, \n                           typename std::iterator_traits<InputIt>::iterator_category>::value) \n        {\n            const auto nb_elements_insert = std::distance(first, last);\n            const size_type nb_free_buckets = m_load_threshold - size();\n            tsl_oh_assert(m_load_threshold >= size());\n            \n            if(nb_elements_insert > 0 && nb_free_buckets < size_type(nb_elements_insert)) {\n                reserve(size() + size_type(nb_elements_insert));\n            }\n        }\n        \n        for(; first != last; ++first) {\n            insert(*first);\n        }\n    }\n    \n    \n    \n    template<class K, class M>\n    std::pair<iterator, bool> insert_or_assign(K&& key, M&& value) {\n        auto it = try_emplace(std::forward<K>(key), std::forward<M>(value));\n        if(!it.second) {\n            it.first.value() = std::forward<M>(value);\n        }\n        \n        return it;\n    }\n    \n    template<class K, class M>\n    iterator insert_or_assign(const_iterator hint, K&& key, M&& obj) {\n        if(hint != cend() && compare_keys(KeySelect()(*hint), key)) { \n            auto it = mutable_iterator(hint); \n            it.value() = std::forward<M>(obj);\n            \n            return it;\n        }\n        \n        return insert_or_assign(std::forward<K>(key), std::forward<M>(obj)).first;\n    }\n    \n    \n    \n    template<class... Args>\n    std::pair<iterator, bool> emplace(Args&&... args) {\n        return insert(value_type(std::forward<Args>(args)...));\n    }\n    \n    template<class... Args>\n    iterator emplace_hint(const_iterator hint, Args&&... args) { \n        return insert(hint, value_type(std::forward<Args>(args)...));\n    }\n    \n    \n    \n    template<class K, class... Args>\n    std::pair<iterator, bool> try_emplace(K&& key, Args&&... value_args) {\n        return insert_impl(key, std::piecewise_construct, \n                                std::forward_as_tuple(std::forward<K>(key)), \n                                std::forward_as_tuple(std::forward<Args>(value_args)...));     \n    }\n    \n    template<class K, class... Args>\n    iterator try_emplace(const_iterator hint, K&& key, Args&&... args) {\n        if(hint != cend() && compare_keys(KeySelect()(*hint), key)) { \n            return mutable_iterator(hint); \n        }\n        \n        return try_emplace(std::forward<K>(key), std::forward<Args>(args)...).first;\n    }\n    \n    \n    \n    /**\n     * Here to avoid `template<class K> size_type erase(const K& key)` being used when\n     * we use an `iterator` instead of a `const_iterator`.\n     */\n    iterator erase(iterator pos) {\n        return erase(const_iterator(pos));\n    }\n    \n    iterator erase(const_iterator pos) {\n        tsl_oh_assert(pos != cend());\n        \n        const std::size_t index_erase = iterator_to_index(pos);\n        \n        auto it_bucket = find_key(pos.key(), hash_key(pos.key()));\n        tsl_oh_assert(it_bucket != m_buckets.end());\n        \n        erase_value_from_bucket(it_bucket);\n        \n        /*\n         * One element was removed from m_values, due to the left shift the next element \n         * is now at the position of the previous element (or end if none).\n         */\n        return begin() + index_erase;\n    }\n\n    iterator erase(const_iterator first, const_iterator last) {\n        if(first == last) {\n            return mutable_iterator(first);\n        }\n        \n        tsl_oh_assert(std::distance(first, last) > 0);\n        const std::size_t start_index = iterator_to_index(first);\n        const std::size_t nb_values = std::size_t(std::distance(first, last));\n        const std::size_t end_index = start_index + nb_values;\n        \n        // Delete all values\n#ifdef TSL_OH_NO_CONTAINER_ERASE_CONST_ITERATOR     \n        auto next_it = m_values.erase(mutable_iterator(first).m_iterator, mutable_iterator(last).m_iterator);   \n#else\n        auto next_it = m_values.erase(first.m_iterator, last.m_iterator);\n#endif\n        \n        /*\n         * Mark the buckets corresponding to the values as empty and do a backward shift.\n         * \n         * Also, the erase operation on m_values has shifted all the values on the right of last.m_iterator.\n         * Adapt the indexes for these values.\n         */\n        std::size_t ibucket = 0;\n        while(ibucket < m_buckets.size()) {\n            if(m_buckets[ibucket].empty()) {\n                ibucket++;\n            }\n            else if(m_buckets[ibucket].index() >= start_index && m_buckets[ibucket].index() < end_index) {\n                m_buckets[ibucket].clear();\n                backward_shift(ibucket);\n                // Don't increment ibucket, backward_shift may have replaced current bucket.\n            }\n            else if(m_buckets[ibucket].index() >= end_index) {\n                m_buckets[ibucket].set_index(index_type(m_buckets[ibucket].index() - nb_values));\n                ibucket++;\n            }\n            else {\n                ibucket++;\n            }\n        }\n        \n        return iterator(next_it);\n    }\n    \n\n    template<class K>\n    size_type erase(const K& key) {\n        return erase(key, hash_key(key));\n    }\n    \n    template<class K>\n    size_type erase(const K& key, std::size_t hash) {\n        return erase_impl(key, hash);\n    }\n    \n    void swap(ordered_hash& other) {\n        using std::swap;\n        \n        swap(static_cast<Hash&>(*this), static_cast<Hash&>(other));\n        swap(static_cast<KeyEqual&>(*this), static_cast<KeyEqual&>(other));\n        swap(m_buckets, other.m_buckets);\n        swap(m_first_or_empty_bucket, other.m_first_or_empty_bucket);\n        swap(m_mask, other.m_mask);\n        swap(m_values, other.m_values);\n        swap(m_grow_on_next_insert, other.m_grow_on_next_insert);\n        swap(m_max_load_factor, other.m_max_load_factor);\n        swap(m_load_threshold, other.m_load_threshold);\n    }\n    \n        \n    \n\n    /*\n     * Lookup\n     */    \n    template<class K, class U = ValueSelect, typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>\n    typename U::value_type& at(const K& key) {\n        return at(key, hash_key(key));\n    }\n    \n    template<class K, class U = ValueSelect, typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>\n    typename U::value_type& at(const K& key, std::size_t hash) {\n        return const_cast<typename U::value_type&>(static_cast<const ordered_hash*>(this)->at(key, hash));\n    }\n    \n    template<class K, class U = ValueSelect, typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>\n    const typename U::value_type& at(const K& key) const {\n        return at(key, hash_key(key));\n    }\n    \n    template<class K, class U = ValueSelect, typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>\n    const typename U::value_type& at(const K& key, std::size_t hash) const {\n        auto it = find(key, hash);\n        if(it != end()) {\n            return it.value();\n        }\n        else {\n            TSL_OH_THROW_OR_TERMINATE(std::out_of_range, \"Couldn't find the key.\");\n        }\n    }\n    \n    \n    template<class K, class U = ValueSelect, typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>\n    typename U::value_type& operator[](K&& key) {\n        return try_emplace(std::forward<K>(key)).first.value();\n    }\n    \n    \n    template<class K>\n    size_type count(const K& key) const {\n        return count(key, hash_key(key));\n    }\n    \n    template<class K>\n    size_type count(const K& key, std::size_t hash) const {\n        if(find(key, hash) == cend()) {\n            return 0;\n        }\n        else {\n            return 1;\n        }\n    }\n    \n    template<class K>\n    iterator find(const K& key) {\n        return find(key, hash_key(key));\n    }\n    \n    template<class K>\n    iterator find(const K& key, std::size_t hash) {\n        auto it_bucket = find_key(key, hash);\n        return (it_bucket != m_buckets.end())?iterator(m_values.begin() + it_bucket->index()):end();\n    }\n    \n    template<class K>\n    const_iterator find(const K& key) const {\n        return find(key, hash_key(key));\n    }\n    \n    template<class K>\n    const_iterator find(const K& key, std::size_t hash) const {\n        auto it_bucket = find_key(key, hash);\n        return (it_bucket != m_buckets.cend())?const_iterator(m_values.begin() + it_bucket->index()):end();\n    }\n    \n    \n    template<class K>\n    std::pair<iterator, iterator> equal_range(const K& key) {\n        return equal_range(key, hash_key(key));\n    }\n    \n    template<class K>\n    std::pair<iterator, iterator> equal_range(const K& key, std::size_t hash) {\n        iterator it = find(key, hash);\n        return std::make_pair(it, (it == end())?it:std::next(it));\n    }\n    \n    template<class K>\n    std::pair<const_iterator, const_iterator> equal_range(const K& key) const {\n        return equal_range(key, hash_key(key));\n    }\n    \n    template<class K>\n    std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t hash) const {\n        const_iterator it = find(key, hash);\n        return std::make_pair(it, (it == cend())?it:std::next(it));\n    }    \n    \n    \n    /*\n     * Bucket interface \n     */\n    size_type bucket_count() const {\n        return m_buckets.size(); \n    }\n    \n    size_type max_bucket_count() const {\n        return m_buckets.max_size();\n    }    \n    \n    /*\n     *  Hash policy \n     */\n    float load_factor() const {\n        if(bucket_count() == 0) {\n            return 0;\n        }\n        \n        return float(size())/float(bucket_count());\n    }\n    \n    float max_load_factor() const {\n        return m_max_load_factor;\n    }\n    \n    void max_load_factor(float ml) {\n        m_max_load_factor = std::max(0.1f, std::min(ml, 0.95f));\n        m_load_threshold = size_type(float(bucket_count())*m_max_load_factor);\n    }\n    \n    void rehash(size_type count) {\n        count = std::max(count, size_type(std::ceil(float(size())/max_load_factor())));\n        rehash_impl(count);\n    }\n    \n    void reserve(size_type count) {\n        reserve_space_for_values(count);\n        \n        count = size_type(std::ceil(float(count)/max_load_factor()));\n        rehash(count);\n    }\n    \n    \n    /*\n     * Observers\n     */\n    hasher hash_function() const {\n        return static_cast<const Hash&>(*this);\n    }\n    \n    key_equal key_eq() const {\n        return static_cast<const KeyEqual&>(*this);\n    }\n\n    \n    /*\n     * Other\n     */\n    iterator mutable_iterator(const_iterator pos) {\n        return iterator(m_values.begin() + iterator_to_index(pos));\n    }\n    \n    iterator nth(size_type index) {\n        tsl_oh_assert(index <= size());\n        return iterator(m_values.begin() + index);\n    }\n    \n    const_iterator nth(size_type index) const {\n        tsl_oh_assert(index <= size());\n        return const_iterator(m_values.cbegin() + index);\n    }\n    \n    const_reference front() const {\n        tsl_oh_assert(!empty());\n        return m_values.front();\n    }\n    \n    const_reference back() const {\n        tsl_oh_assert(!empty());\n        return m_values.back();\n    }\n    \n    const values_container_type& values_container() const noexcept {\n        return m_values;\n    }\n    \n    template<class U = values_container_type, typename std::enable_if<is_vector<U>::value>::type* = nullptr>    \n    const typename values_container_type::value_type* data() const noexcept {\n        return m_values.data();\n    }\n    \n    template<class U = values_container_type, typename std::enable_if<is_vector<U>::value>::type* = nullptr>    \n    size_type capacity() const noexcept {\n        return m_values.capacity();\n    }\n    \n    void shrink_to_fit() {\n        m_values.shrink_to_fit();\n    }\n    \n    \n    template<typename P>\n    std::pair<iterator, bool> insert_at_position(const_iterator pos, P&& value) {\n        return insert_at_position_impl(pos.m_iterator, KeySelect()(value), std::forward<P>(value));\n    }\n    \n    template<class... Args>\n    std::pair<iterator, bool> emplace_at_position(const_iterator pos, Args&&... args) {\n        return insert_at_position(pos, value_type(std::forward<Args>(args)...));\n    }\n    \n    template<class K, class... Args>\n    std::pair<iterator, bool> try_emplace_at_position(const_iterator pos, K&& key, Args&&... value_args) {\n        return insert_at_position_impl(pos.m_iterator, key, \n                                       std::piecewise_construct, \n                                       std::forward_as_tuple(std::forward<K>(key)), \n                                       std::forward_as_tuple(std::forward<Args>(value_args)...));\n    }\n    \n\n    void pop_back() {\n        tsl_oh_assert(!empty());\n        erase(std::prev(end()));\n    }\n    \n    \n    /**\n     * Here to avoid `template<class K> size_type unordered_erase(const K& key)` being used when\n     * we use a iterator instead of a const_iterator.\n     */    \n    iterator unordered_erase(iterator pos) {\n        return unordered_erase(const_iterator(pos));\n    }\n    \n    iterator unordered_erase(const_iterator pos) {\n        const std::size_t index_erase = iterator_to_index(pos);\n        unordered_erase(pos.key());\n        \n        /*\n         * One element was deleted, index_erase now points to the next element as the elements after\n         * the deleted value were shifted to the left in m_values (will be end() if we deleted the last element).\n         */\n        return begin() + index_erase;\n    }\n    \n    template<class K>\n    size_type unordered_erase(const K& key) {\n        return unordered_erase(key, hash_key(key));\n    }\n    \n    template<class K>\n    size_type unordered_erase(const K& key, std::size_t hash) {\n        auto it_bucket_key = find_key(key, hash);\n        if(it_bucket_key == m_buckets.end()) {\n            return 0;\n        }\n        \n        /**\n         * If we are not erasing the last element in m_values, we swap \n         * the element we are erasing with the last element. We then would \n         * just have to do a pop_back() in m_values.\n         */\n        if(!compare_keys(key, KeySelect()(back()))) {\n            auto it_bucket_last_elem = find_key(KeySelect()(back()), hash_key(KeySelect()(back())));\n            tsl_oh_assert(it_bucket_last_elem != m_buckets.end());\n            tsl_oh_assert(it_bucket_last_elem->index() == m_values.size() - 1);\n            \n            using std::swap;\n            swap(m_values[it_bucket_key->index()], m_values[it_bucket_last_elem->index()]);\n            swap(it_bucket_key->index_ref(), it_bucket_last_elem->index_ref());\n        }\n        \n        erase_value_from_bucket(it_bucket_key);\n        \n        return 1;\n    }\n    \n    friend bool operator==(const ordered_hash& lhs, const ordered_hash& rhs) {\n        return lhs.m_values == rhs.m_values;\n    }\n    \n    friend bool operator!=(const ordered_hash& lhs, const ordered_hash& rhs) {\n        return lhs.m_values != rhs.m_values;\n    }\n    \n    friend bool operator<(const ordered_hash& lhs, const ordered_hash& rhs) {\n        return lhs.m_values < rhs.m_values;\n    }\n    \n    friend bool operator<=(const ordered_hash& lhs, const ordered_hash& rhs) {\n        return lhs.m_values <= rhs.m_values;\n    }\n    \n    friend bool operator>(const ordered_hash& lhs, const ordered_hash& rhs) {\n        return lhs.m_values > rhs.m_values;\n    }\n    \n    friend bool operator>=(const ordered_hash& lhs, const ordered_hash& rhs) {\n        return lhs.m_values >= rhs.m_values;\n    }\n    \n    \nprivate:\n    template<class K>\n    std::size_t hash_key(const K& key) const {\n        return Hash::operator()(key);\n    }\n    \n    template<class K1, class K2>\n    bool compare_keys(const K1& key1, const K2& key2) const {\n        return KeyEqual::operator()(key1, key2);\n    }\n    \n    template<class K>\n    typename buckets_container_type::iterator find_key(const K& key, std::size_t hash) {\n        auto it = static_cast<const ordered_hash*>(this)->find_key(key, hash);\n        return m_buckets.begin() + std::distance(m_buckets.cbegin(), it);\n    }\n    \n    /**\n     * Return bucket which has the key 'key' or m_buckets.end() if none.\n     * \n     * From the bucket_for_hash, search for the value until we either find an empty bucket\n     * or a bucket which has a value with a distance from its ideal bucket longer\n     * than the probe length for the value we are looking for.\n     */\n    template<class K>\n    typename buckets_container_type::const_iterator find_key(const K& key, std::size_t hash) const {\n        for(std::size_t ibucket = bucket_for_hash(hash), dist_from_ideal_bucket = 0; ; \n            ibucket = next_bucket(ibucket), dist_from_ideal_bucket++) \n        {\n            if((m_first_or_empty_bucket + ibucket)->empty()) {\n                return m_buckets.end();\n            }\n            else if((m_first_or_empty_bucket + ibucket)->truncated_hash() == bucket_entry::truncate_hash(hash) && \n                    compare_keys(key, KeySelect()(m_values[(m_first_or_empty_bucket + ibucket)->index()]))) \n            {\n                return m_buckets.begin() + ibucket;\n            }\n            else if(dist_from_ideal_bucket > distance_from_ideal_bucket(ibucket)) {\n                return m_buckets.end();\n            }\n        }\n    }\n    \n    void rehash_impl(size_type bucket_count) {\n        tsl_oh_assert(bucket_count >= size_type(std::ceil(float(size())/max_load_factor())));\n        \n        if(bucket_count > max_bucket_count()) {\n            TSL_OH_THROW_OR_TERMINATE(std::length_error, \"The map exceeds its maxmimum size.\");\n        }\n        \n        if(bucket_count > 0) {\n            bucket_count = round_up_to_power_of_two(bucket_count);\n        }\n        \n        if(bucket_count == this->bucket_count()) {\n            return;\n        }\n        \n        \n        buckets_container_type old_buckets(bucket_count);\n        m_buckets.swap(old_buckets);\n        m_first_or_empty_bucket = m_buckets.data();\n        // Everything should be noexcept from here.\n        \n        m_mask = (bucket_count > 0)?(bucket_count - 1):0;\n        this->max_load_factor(m_max_load_factor);\n        m_grow_on_next_insert = false;\n        \n        \n        \n        for(const bucket_entry& old_bucket: old_buckets) {\n            if(old_bucket.empty()) {\n                continue;\n            }\n            \n            truncated_hash_type insert_hash = old_bucket.truncated_hash();\n            index_type insert_index = old_bucket.index();\n            \n            for(std::size_t ibucket = bucket_for_hash(insert_hash), dist_from_ideal_bucket = 0; ; \n                ibucket = next_bucket(ibucket), dist_from_ideal_bucket++) \n            {\n                if(m_buckets[ibucket].empty()) {\n                    m_buckets[ibucket].set_index(insert_index);\n                    m_buckets[ibucket].set_hash(insert_hash);\n                    break;\n                }\n                \n                const std::size_t distance = distance_from_ideal_bucket(ibucket);\n                if(dist_from_ideal_bucket > distance) {\n                    std::swap(insert_index, m_buckets[ibucket].index_ref());\n                    std::swap(insert_hash, m_buckets[ibucket].truncated_hash_ref());\n                    dist_from_ideal_bucket = distance;\n                }\n            }\n        }\n    }\n    \n    template<class T = values_container_type, typename std::enable_if<is_vector<T>::value>::type* = nullptr>\n    void reserve_space_for_values(size_type count) {\n        m_values.reserve(count);\n    }\n    \n    template<class T = values_container_type, typename std::enable_if<!is_vector<T>::value>::type* = nullptr>\n    void reserve_space_for_values(size_type /*count*/) {\n    }\n    \n    /**\n     * Swap the empty bucket with the values on its right until we cross another empty bucket\n     * or if the other bucket has a distance_from_ideal_bucket == 0.\n     */\n    void backward_shift(std::size_t empty_ibucket) noexcept {\n        tsl_oh_assert(m_buckets[empty_ibucket].empty());\n        \n        std::size_t previous_ibucket = empty_ibucket;\n        for(std::size_t current_ibucket = next_bucket(previous_ibucket); \n            !m_buckets[current_ibucket].empty() && distance_from_ideal_bucket(current_ibucket) > 0;\n            previous_ibucket = current_ibucket, current_ibucket = next_bucket(current_ibucket)) \n        {\n            std::swap(m_buckets[current_ibucket], m_buckets[previous_ibucket]);\n        }\n    }\n    \n    void erase_value_from_bucket(typename buckets_container_type::iterator it_bucket) {\n        tsl_oh_assert(it_bucket != m_buckets.end() && !it_bucket->empty());\n        \n        m_values.erase(m_values.begin() + it_bucket->index());\n        \n        /*\n         * m_values.erase shifted all the values on the right of the erased value, \n         * shift the indexes by -1 in the buckets array for these values.\n         */\n        if(it_bucket->index() != m_values.size()) {\n            shift_indexes_in_buckets(it_bucket->index(), char(-1));\n        }        \n        \n        // Mark the bucket as empty and do a backward shift of the values on the right\n        it_bucket->clear();\n        backward_shift(std::size_t(std::distance(m_buckets.begin(), it_bucket)));\n    }\n    \n    /**\n     * Go through each value from [from_ivalue, m_values.size()) in m_values and for each\n     * bucket corresponding to the value, shift the index by delta.\n     */\n    void shift_indexes_in_buckets(index_type from_ivalue, char delta) noexcept  {\n        tsl_oh_assert(delta == 1 || delta == -1);\n        \n        for(std::size_t ivalue = from_ivalue; ivalue < m_values.size(); ivalue++) {\n            // All the values in m_values have been shifted by delta. Find the bucket corresponding \n            // to the value m_values[ivalue]\n            const index_type old_index = static_cast<index_type>(ivalue - delta);\n            \n            std::size_t ibucket = bucket_for_hash(hash_key(KeySelect()(m_values[ivalue])));\n            while(m_buckets[ibucket].index() != old_index) {\n                ibucket = next_bucket(ibucket);\n            }\n            \n            m_buckets[ibucket].set_index(index_type(ivalue));\n        }\n    }\n    \n    template<class K>\n    size_type erase_impl(const K& key, std::size_t hash) {\n        auto it_bucket = find_key(key, hash);\n        if(it_bucket != m_buckets.end()) {\n            erase_value_from_bucket(it_bucket);\n            \n            return 1;\n        }\n        else {\n            return 0;\n        }\n    }\n    \n    /**\n     * Insert the element at the end.\n     */\n    template<class K, class... Args>\n    std::pair<iterator, bool> insert_impl(const K& key, Args&&... value_type_args) {\n        const std::size_t hash = hash_key(key);\n        \n        std::size_t ibucket = bucket_for_hash(hash); \n        std::size_t dist_from_ideal_bucket = 0;\n        \n        while(!(m_first_or_empty_bucket + ibucket)->empty() && dist_from_ideal_bucket <= distance_from_ideal_bucket(ibucket)) {\n            if((m_first_or_empty_bucket + ibucket)->truncated_hash() == bucket_entry::truncate_hash(hash) && \n               compare_keys(key, KeySelect()(m_values[(m_first_or_empty_bucket + ibucket)->index()]))) \n            {\n                return std::make_pair(begin() + (m_first_or_empty_bucket + ibucket)->index(), false);\n            }\n            \n            ibucket = next_bucket(ibucket);\n            dist_from_ideal_bucket++;\n        }\n        \n        if(size() >= max_size()) {\n            TSL_OH_THROW_OR_TERMINATE(std::length_error, \"We reached the maximum size for the hash table.\");\n        }\n        \n        \n        if(grow_on_high_load()) {\n            ibucket = bucket_for_hash(hash);\n            dist_from_ideal_bucket = 0;\n        }\n        \n                \n        m_values.emplace_back(std::forward<Args>(value_type_args)...);\n        insert_index(ibucket, dist_from_ideal_bucket, \n                     index_type(m_values.size() - 1), bucket_entry::truncate_hash(hash));\n        \n        \n        return std::make_pair(std::prev(end()), true);\n    }\n    \n    /**\n     * Insert the element before insert_position.\n     */\n    template<class K, class... Args>\n    std::pair<iterator, bool> insert_at_position_impl(typename values_container_type::const_iterator insert_position,\n                                                      const K& key, Args&&... value_type_args) \n    {\n        const std::size_t hash = hash_key(key);\n        \n        std::size_t ibucket = bucket_for_hash(hash); \n        std::size_t dist_from_ideal_bucket = 0;\n        \n        while(!(m_first_or_empty_bucket + ibucket)->empty() && dist_from_ideal_bucket <= distance_from_ideal_bucket(ibucket)) {\n            if((m_first_or_empty_bucket + ibucket)->truncated_hash() == bucket_entry::truncate_hash(hash) && \n               compare_keys(key, KeySelect()(m_values[(m_first_or_empty_bucket + ibucket)->index()]))) \n            {\n                return std::make_pair(begin() + (m_first_or_empty_bucket + ibucket)->index(), false);\n            }\n            \n            ibucket = next_bucket(ibucket);\n            dist_from_ideal_bucket++;\n        }\n        \n        if(size() >= max_size()) {\n            TSL_OH_THROW_OR_TERMINATE(std::length_error, \"We reached the maximum size for the hash table.\");\n        }\n        \n        \n        if(grow_on_high_load()) {\n            ibucket = bucket_for_hash(hash);\n            dist_from_ideal_bucket = 0;\n        }\n        \n        \n        const index_type index_insert_position = index_type(std::distance(m_values.cbegin(), insert_position));\n        \n#ifdef TSL_OH_NO_CONTAINER_EMPLACE_CONST_ITERATOR\n        m_values.emplace(m_values.begin() + std::distance(m_values.cbegin(), insert_position), std::forward<Args>(value_type_args)...);\n#else        \n        m_values.emplace(insert_position, std::forward<Args>(value_type_args)...);\n#endif        \n\n        insert_index(ibucket, dist_from_ideal_bucket, \n                     index_insert_position, bucket_entry::truncate_hash(hash));\n        \n        /*\n         * The insertion didn't happend at the end of the m_values container, \n         * we need to shift the indexes in m_buckets.\n         */\n        if(index_insert_position != m_values.size() - 1) {\n            shift_indexes_in_buckets(index_insert_position + 1, char(1));\n        }\n        \n        return std::make_pair(iterator(m_values.begin() + index_insert_position), true);\n    }\n    \n    void insert_index(std::size_t ibucket, std::size_t dist_from_ideal_bucket, \n                      index_type index_insert, truncated_hash_type hash_insert) noexcept\n    {\n        while(!m_buckets[ibucket].empty()) {\n            const std::size_t distance = distance_from_ideal_bucket(ibucket);\n            if(dist_from_ideal_bucket > distance) {\n                std::swap(index_insert, m_buckets[ibucket].index_ref());\n                std::swap(hash_insert, m_buckets[ibucket].truncated_hash_ref());\n                \n                dist_from_ideal_bucket = distance;\n            }\n\n            \n            ibucket = next_bucket(ibucket);\n            dist_from_ideal_bucket++;\n            \n            \n            if(dist_from_ideal_bucket > REHASH_ON_HIGH_NB_PROBES__NPROBES && !m_grow_on_next_insert &&\n               load_factor() >= REHASH_ON_HIGH_NB_PROBES__MIN_LOAD_FACTOR)\n            {\n                // We don't want to grow the map now as we need this method to be noexcept.\n                // Do it on next insert.\n                m_grow_on_next_insert = true;\n            }\n        }\n        \n        \n        m_buckets[ibucket].set_index(index_insert);\n        m_buckets[ibucket].set_hash(hash_insert); \n    }\n    \n    std::size_t distance_from_ideal_bucket(std::size_t ibucket) const noexcept {\n        const std::size_t ideal_bucket = bucket_for_hash(m_buckets[ibucket].truncated_hash());\n        \n        if(ibucket >= ideal_bucket) {\n            return ibucket - ideal_bucket;\n        }\n        // If the bucket is smaller than the ideal bucket for the value, there was a wrapping at the end of the \n        // bucket array due to the modulo.\n        else {\n            return (bucket_count() + ibucket) - ideal_bucket;\n        }\n    }\n    \n    std::size_t next_bucket(std::size_t index) const noexcept {\n        tsl_oh_assert(index < m_buckets.size());\n        \n        index++;\n        return (index < m_buckets.size())?index:0;\n    }\n    \n    std::size_t bucket_for_hash(std::size_t hash) const noexcept {\n        return hash & m_mask;\n    }    \n    \n    std::size_t iterator_to_index(const_iterator it) const noexcept {\n        const auto dist = std::distance(cbegin(), it);\n        tsl_oh_assert(dist >= 0);\n        \n        return std::size_t(dist);\n    }\n    \n    /**\n     * Return true if the map has been rehashed.\n     */\n    bool grow_on_high_load() {\n        if(m_grow_on_next_insert || size() >= m_load_threshold) {\n            rehash_impl(std::max(size_type(1), bucket_count() * 2));\n            m_grow_on_next_insert = false;\n            \n            return true;\n        }\n        else {\n            return false;\n        }\n    }\n    \n    static std::size_t round_up_to_power_of_two(std::size_t value) {\n        if(is_power_of_two(value)) {\n            return value;\n        }\n        \n        if(value == 0) {\n            return 1;\n        }\n        \n        --value;\n        for(std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) {\n            value |= value >> i;\n        }\n        \n        return value + 1;\n    }\n    \n    static constexpr bool is_power_of_two(std::size_t value) {\n        return value != 0 && (value & (value - 1)) == 0;\n    }\n\n    \npublic:\n    static const size_type DEFAULT_INIT_BUCKETS_SIZE = 16;\n    static constexpr float DEFAULT_MAX_LOAD_FACTOR = 0.75f;\n\nprivate:    \n    static const size_type REHASH_ON_HIGH_NB_PROBES__NPROBES = 128;\n    static constexpr float REHASH_ON_HIGH_NB_PROBES__MIN_LOAD_FACTOR = 0.15f;\n    \n    \n    /**\n     * Return an always valid pointer to an static empty bucket_entry with last_bucket() == true.\n     */            \n    bucket_entry* static_empty_bucket_ptr() {\n        static bucket_entry empty_bucket;\n        return &empty_bucket;\n    }\n    \nprivate:\n    buckets_container_type m_buckets;\n    \n    /**\n     * Points to m_buckets.data() if !m_buckets.empty() otherwise points to static_empty_bucket_ptr.\n     * This variable is useful to avoid the cost of checking if m_buckets is empty when trying \n     * to find an element.\n     */\n    bucket_entry* m_first_or_empty_bucket;\n    \n    size_type m_mask;\n    \n    values_container_type m_values;\n    \n    bool m_grow_on_next_insert;\n    float m_max_load_factor;\n    size_type m_load_threshold;\n};\n\n\n} // end namespace detail_ordered_hash\n\n} // end namespace tsl\n\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/ordered-map/include/tsl/ordered_map.h",
    "content": "/**\n * MIT License\n * \n * Copyright (c) 2017 Tessil\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n#ifndef TSL_ORDERED_MAP_H\n#define TSL_ORDERED_MAP_H\n\n\n#include <cstddef>\n#include <cstdint>\n#include <deque>\n#include <functional>\n#include <initializer_list>\n#include <memory>\n#include <type_traits>\n#include <utility>\n#include <vector>\n#include \"ordered_hash.h\"\n\n\nnamespace tsl {\n\n\n/**\n * Implementation of an hash map using open adressing with robin hood with backshift delete to resolve collisions.\n * \n * The particularity of this hash map is that it remembers the order in which the elements were added and\n * provide a way to access the structure which stores these values through the 'values_container()' method. \n * The used container is defined by ValueTypeContainer, by default a std::deque is used (grows faster) but\n * a std::vector may be used. In this case the map provides a 'data()' method which give a direct access \n * to the memory used to store the values (which can be usefull to communicate with C API's).\n * \n * The Key and T must be copy constructible and/or move constructible. To use `unordered_erase` they both\n * must be swappable.\n * \n * The behaviour of the hash map is undefinded if the destructor of Key or T throws an exception.\n * \n * By default the maximum size of a map is limited to 2^32 - 1 values, if needed this can be changed through\n * the IndexType template parameter. Using an `uint64_t` will raise this limit to 2^64 - 1 values but each\n * bucket will use 16 bytes instead of 8 bytes in addition to the space needed to store the values.\n * \n * Iterators invalidation:\n *  - clear, operator=, reserve, rehash: always invalidate the iterators (also invalidate end()).\n *  - insert, emplace, emplace_hint, operator[]: when a std::vector is used as ValueTypeContainer \n *                                               and if size() < capacity(), only end(). \n *                                               Otherwise all the iterators are invalidated if an insert occurs.\n *  - erase, unordered_erase: when a std::vector is used as ValueTypeContainer invalidate the iterator of \n *                            the erased element and all the ones after the erased element (including end()). \n *                            Otherwise all the iterators are invalidated if an erase occurs.\n */\ntemplate<class Key, \n         class T, \n         class Hash = std::hash<Key>,\n         class KeyEqual = std::equal_to<Key>,\n         class Allocator = std::allocator<std::pair<Key, T>>,\n         class ValueTypeContainer = std::deque<std::pair<Key, T>, Allocator>,\n         class IndexType = std::uint_least32_t>\nclass ordered_map {\nprivate:\n    template<typename U>\n    using has_is_transparent = tsl::detail_ordered_hash::has_is_transparent<U>;\n    \n    class KeySelect {\n    public:\n        using key_type = Key;\n        \n        const key_type& operator()(const std::pair<Key, T>& key_value) const noexcept {\n            return key_value.first;\n        }\n        \n        key_type& operator()(std::pair<Key, T>& key_value) noexcept {\n            return key_value.first;\n        }\n    };  \n    \n    class ValueSelect {\n    public:\n        using value_type = T;\n        \n        const value_type& operator()(const std::pair<Key, T>& key_value) const noexcept {\n            return key_value.second;\n        }\n        \n        value_type& operator()(std::pair<Key, T>& key_value) noexcept {\n            return key_value.second;\n        }\n    };\n    \n    using ht = detail_ordered_hash::ordered_hash<std::pair<Key, T>, KeySelect, ValueSelect,\n                                                 Hash, KeyEqual, Allocator, ValueTypeContainer, IndexType>;\n    \npublic:\n    using key_type = typename ht::key_type;\n    using mapped_type = T;\n    using value_type = typename ht::value_type;\n    using size_type = typename ht::size_type;\n    using difference_type = typename ht::difference_type;\n    using hasher = typename ht::hasher;\n    using key_equal = typename ht::key_equal;\n    using allocator_type = typename ht::allocator_type;\n    using reference = typename ht::reference;\n    using const_reference = typename ht::const_reference;\n    using pointer = typename ht::pointer;\n    using const_pointer = typename ht::const_pointer;\n    using iterator = typename ht::iterator;\n    using const_iterator = typename ht::const_iterator;\n    using reverse_iterator = typename ht::reverse_iterator;\n    using const_reverse_iterator = typename ht::const_reverse_iterator;\n    \n    using values_container_type = typename ht::values_container_type;\n    \n    \n    /*\n     * Constructors\n     */\n    ordered_map(): ordered_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {\n    }\n    \n    explicit ordered_map(size_type bucket_count, \n                         const Hash& hash = Hash(),\n                         const KeyEqual& equal = KeyEqual(),\n                         const Allocator& alloc = Allocator()): \n                     m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)\n    {\n    }\n    \n    ordered_map(size_type bucket_count,\n                const Allocator& alloc): ordered_map(bucket_count, Hash(), KeyEqual(), alloc)\n    {\n    }\n    \n    ordered_map(size_type bucket_count,\n                const Hash& hash,\n                const Allocator& alloc): ordered_map(bucket_count, hash, KeyEqual(), alloc)\n    {\n    }\n    \n    explicit ordered_map(const Allocator& alloc): ordered_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {\n    }\n    \n    template<class InputIt>\n    ordered_map(InputIt first, InputIt last,\n                size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,\n                const Hash& hash = Hash(),\n                const KeyEqual& equal = KeyEqual(),\n                const Allocator& alloc = Allocator()): ordered_map(bucket_count, hash, equal, alloc)\n    {\n        insert(first, last);\n    }\n    \n    template<class InputIt>\n    ordered_map(InputIt first, InputIt last,\n                size_type bucket_count,\n                const Allocator& alloc): ordered_map(first, last, bucket_count, Hash(), KeyEqual(), alloc)\n    {\n    }\n    \n    template<class InputIt>\n    ordered_map(InputIt first, InputIt last,\n                size_type bucket_count,\n                const Hash& hash,\n                const Allocator& alloc): ordered_map(first, last, bucket_count, hash, KeyEqual(), alloc)\n    {\n    }\n\n    ordered_map(std::initializer_list<value_type> init,\n                size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,\n                const Hash& hash = Hash(),\n                const KeyEqual& equal = KeyEqual(),\n                const Allocator& alloc = Allocator()): \n            ordered_map(init.begin(), init.end(), bucket_count, hash, equal, alloc)\n    {\n    }\n\n    ordered_map(std::initializer_list<value_type> init,\n                size_type bucket_count,\n                const Allocator& alloc): \n            ordered_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)\n    {\n    }\n\n    ordered_map(std::initializer_list<value_type> init,\n                size_type bucket_count,\n                const Hash& hash,\n                const Allocator& alloc): \n            ordered_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)\n    {\n    }\n\n    \n    ordered_map& operator=(std::initializer_list<value_type> ilist) {\n        m_ht.clear();\n        \n        m_ht.reserve(ilist.size());\n        m_ht.insert(ilist.begin(), ilist.end());\n        \n        return *this;\n    }\n    \n    allocator_type get_allocator() const { return m_ht.get_allocator(); }\n    \n\n    \n    /*\n     * Iterators\n     */\n    iterator begin() noexcept { return m_ht.begin(); }\n    const_iterator begin() const noexcept { return m_ht.begin(); }\n    const_iterator cbegin() const noexcept { return m_ht.cbegin(); }\n    \n    iterator end() noexcept { return m_ht.end(); }\n    const_iterator end() const noexcept { return m_ht.end(); }\n    const_iterator cend() const noexcept { return m_ht.cend(); }\n    \n    reverse_iterator rbegin() noexcept { return m_ht.rbegin(); }\n    const_reverse_iterator rbegin() const noexcept { return m_ht.rbegin(); }\n    const_reverse_iterator rcbegin() const noexcept { return m_ht.rcbegin(); }\n    \n    reverse_iterator rend() noexcept { return m_ht.rend(); }\n    const_reverse_iterator rend() const noexcept { return m_ht.rend(); }\n    const_reverse_iterator rcend() const noexcept { return m_ht.rcend(); }\n    \n    \n    /*\n     * Capacity\n     */\n    bool empty() const noexcept { return m_ht.empty(); }\n    size_type size() const noexcept { return m_ht.size(); }\n    size_type max_size() const noexcept { return m_ht.max_size(); }\n    \n    /*\n     * Modifiers\n     */\n    void clear() noexcept { m_ht.clear(); }\n    \n    \n    \n    std::pair<iterator, bool> insert(const value_type& value) { return m_ht.insert(value); }\n        \n    template<class P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>\n    std::pair<iterator, bool> insert(P&& value) { return m_ht.emplace(std::forward<P>(value)); }\n    \n    std::pair<iterator, bool> insert(value_type&& value) { return m_ht.insert(std::move(value)); }\n    \n    \n    iterator insert(const_iterator hint, const value_type& value) {\n        return m_ht.insert(hint, value);\n    }\n        \n    template<class P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>\n    iterator insert(const_iterator hint, P&& value) {\n        return m_ht.emplace_hint(hint, std::forward<P>(value));\n    }\n    \n    iterator insert(const_iterator hint, value_type&& value) { \n        return m_ht.insert(hint, std::move(value));\n    }\n    \n    \n    template<class InputIt>\n    void insert(InputIt first, InputIt last) { m_ht.insert(first, last); }\n    void insert(std::initializer_list<value_type> ilist) { m_ht.insert(ilist.begin(), ilist.end()); }\n\n    \n    \n    \n    template<class M>\n    std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj) { \n        return m_ht.insert_or_assign(k, std::forward<M>(obj)); \n    }\n\n    template<class M>\n    std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj) { \n        return m_ht.insert_or_assign(std::move(k), std::forward<M>(obj)); \n    }\n    \n    \n    template<class M>\n    iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj) {\n        return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));\n    }\n    \n    template<class M>\n    iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj) {\n        return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));\n    }\n    \n    /**\n     * Due to the way elements are stored, emplace will need to move or copy the key-value once.\n     * The method is equivalent to insert(value_type(std::forward<Args>(args)...));\n     * \n     * Mainly here for compatibility with the std::unordered_map interface.\n     */\n    template<class... Args>\n    std::pair<iterator, bool> emplace(Args&&... args) { return m_ht.emplace(std::forward<Args>(args)...); }\n    \n    /**\n     * Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.\n     * The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));\n     * \n     * Mainly here for compatibility with the std::unordered_map interface.\n     */\n    template <class... Args>\n    iterator emplace_hint(const_iterator hint, Args&&... args) {\n        return m_ht.emplace_hint(hint, std::forward<Args>(args)...);\n    }\n    \n    \n    \n    \n    template<class... Args>\n    std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args) { \n        return m_ht.try_emplace(k, std::forward<Args>(args)...);\n    }\n    \n    template<class... Args>\n    std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args) {\n        return m_ht.try_emplace(std::move(k), std::forward<Args>(args)...);\n    }\n    \n    template<class... Args>\n    iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args) {\n        return m_ht.try_emplace(hint, k, std::forward<Args>(args)...);\n    }\n    \n    template<class... Args>\n    iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args) {\n        return m_ht.try_emplace(hint, std::move(k), std::forward<Args>(args)...);\n    }\n    \n    \n    \n\n    /**\n     * When erasing an element, the insert order will be preserved and no holes will be present in the container\n     * returned by 'values_container()'. \n     * \n     * The method is in O(n), if the order is not important 'unordered_erase(...)' method is faster with an O(1)\n     * average complexity.\n     */\n    iterator erase(iterator pos) { return m_ht.erase(pos); }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     */\n    iterator erase(const_iterator pos) { return m_ht.erase(pos); }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     */    \n    iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     */    \n    size_type erase(const key_type& key) { return m_ht.erase(key); }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.\n     */    \n    size_type erase(const key_type& key, std::size_t precalculated_hash) { \n        return m_ht.erase(key, precalculated_hash); \n    }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     * \n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type erase(const K& key) { return m_ht.erase(key); }\n    \n    /**\n     * @copydoc erase(const key_type& key, std::size_t precalculated_hash)\n     * \n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type erase(const K& key, std::size_t precalculated_hash) { \n        return m_ht.erase(key, precalculated_hash); \n    }\n    \n    \n    \n    void swap(ordered_map& other) { other.m_ht.swap(m_ht); }\n    \n    /*\n     * Lookup\n     */\n    T& at(const Key& key) { return m_ht.at(key); }\n    \n    /**\n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    T& at(const Key& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }\n    \n    \n    const T& at(const Key& key) const { return m_ht.at(key); }\n    \n    /**\n     * @copydoc at(const Key& key, std::size_t precalculated_hash)\n     */\n    const T& at(const Key& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }\n    \n    \n    /**\n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    T& at(const K& key) { return m_ht.at(key); }\n    \n    /**\n     * @copydoc at(const K& key)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */    \n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    T& at(const K& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }\n    \n    /**\n     * @copydoc at(const K& key)\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>     \n    const T& at(const K& key) const { return m_ht.at(key); }\n    \n    /**\n     * @copydoc at(const K& key, std::size_t precalculated_hash)\n     */    \n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    const T& at(const K& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }\n    \n    \n    \n    T& operator[](const Key& key) { return m_ht[key]; }    \n    T& operator[](Key&& key) { return m_ht[std::move(key)]; }\n    \n    \n    \n    size_type count(const Key& key) const { return m_ht.count(key); }\n    \n    /**\n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    size_type count(const Key& key, std::size_t precalculated_hash) const { \n        return m_ht.count(key, precalculated_hash); \n    }\n    \n    /**\n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>     \n    size_type count(const K& key) const { return m_ht.count(key); }\n    \n    /**\n     * @copydoc count(const K& key) const\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */     \n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type count(const K& key, std::size_t precalculated_hash) const { \n        return m_ht.count(key, precalculated_hash);\n    }\n    \n    \n    \n    iterator find(const Key& key) { return m_ht.find(key); }\n    \n    /**\n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }\n    \n    const_iterator find(const Key& key) const { return m_ht.find(key); }\n    \n    /**\n     * @copydoc find(const Key& key, std::size_t precalculated_hash)\n     */\n    const_iterator find(const Key& key, std::size_t precalculated_hash) const { \n        return m_ht.find(key, precalculated_hash);\n    }\n    \n    /**\n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    iterator find(const K& key) { return m_ht.find(key); }\n    \n    /**\n     * @copydoc find(const K& key)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }\n    \n    /**\n     * @copydoc find(const K& key)\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    const_iterator find(const K& key) const { return m_ht.find(key); }\n    \n    /**\n     * @copydoc find(const K& key)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    const_iterator find(const K& key, std::size_t precalculated_hash) const { \n        return m_ht.find(key, precalculated_hash); \n    }\n    \n    \n    \n    std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }\n    \n    /**\n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) { \n        return m_ht.equal_range(key, precalculated_hash); \n    }\n    \n    std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }\n    \n    /**\n     * @copydoc equal_range(const Key& key, std::size_t precalculated_hash)\n     */\n    std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const { \n        return m_ht.equal_range(key, precalculated_hash); \n    }\n\n    /**\n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>     \n    std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }\n    \n    /**\n     * @copydoc equal_range(const K& key)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) { \n        return m_ht.equal_range(key, precalculated_hash); \n    }\n    \n    /**\n     * @copydoc equal_range(const K& key)\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>     \n    std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }\n    \n    /**\n     * @copydoc equal_range(const K& key, std::size_t precalculated_hash)\n     */    \n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const { \n        return m_ht.equal_range(key, precalculated_hash); \n    }\n    \n    \n    \n    /*\n     * Bucket interface \n     */\n    size_type bucket_count() const { return m_ht.bucket_count(); }\n    size_type max_bucket_count() const { return m_ht.max_bucket_count(); }\n    \n    \n    /*\n     * Hash policy \n     */\n    float load_factor() const { return m_ht.load_factor(); }\n    float max_load_factor() const { return m_ht.max_load_factor(); }\n    void max_load_factor(float ml) { m_ht.max_load_factor(ml); }\n    \n    void rehash(size_type count) { m_ht.rehash(count); }\n    void reserve(size_type count) { m_ht.reserve(count); }\n    \n    \n    /*\n     * Observers\n     */\n    hasher hash_function() const { return m_ht.hash_function(); }\n    key_equal key_eq() const { return m_ht.key_eq(); }\n    \n    \n    \n    /*\n     * Other\n     */\n    \n    /**\n     * Convert a const_iterator to an iterator.\n     */\n    iterator mutable_iterator(const_iterator pos) {\n        return m_ht.mutable_iterator(pos);\n    }\n    \n    /**\n     * Requires index <= size().\n     * \n     * Return an iterator to the element at index. Return end() if index == size().\n     */\n    iterator nth(size_type index) { return m_ht.nth(index); }\n    \n    /**\n     * @copydoc nth(size_type index)\n     */\n    const_iterator nth(size_type index) const { return m_ht.nth(index); }\n    \n    \n    /**\n     * Return const_reference to the first element. Requires the container to not be empty.\n     */\n    const_reference front() const { return m_ht.front(); }\n    \n    /**\n     * Return const_reference to the last element. Requires the container to not be empty.\n     */\n    const_reference back() const { return m_ht.back(); }\n    \n    \n    /**\n     * Only available if ValueTypeContainer is a std::vector. Same as calling 'values_container().data()'.\n     */\n    template<class U = values_container_type, typename std::enable_if<tsl::detail_ordered_hash::is_vector<U>::value>::type* = nullptr>    \n    const typename values_container_type::value_type* data() const noexcept { return m_ht.data(); }\n        \n    /**\n     * Return the container in which the values are stored. The values are in the same order as the insertion order\n     * and are contiguous in the structure, no holes (size() == values_container().size()).\n     */\n    const values_container_type& values_container() const noexcept { return m_ht.values_container(); }\n\n    template<class U = values_container_type, typename std::enable_if<tsl::detail_ordered_hash::is_vector<U>::value>::type* = nullptr>    \n    size_type capacity() const noexcept { return m_ht.capacity(); }\n    \n    void shrink_to_fit() { m_ht.shrink_to_fit(); }\n    \n    \n    \n    /**\n     * Insert the value before pos shifting all the elements on the right of pos (including pos) one position \n     * to the right.\n     * \n     * Amortized linear time-complexity in the distance between pos and end().\n     */\n    std::pair<iterator, bool> insert_at_position(const_iterator pos, const value_type& value) { \n        return m_ht.insert_at_position(pos, value); \n    }\n    \n    /**\n     * @copydoc insert_at_position(const_iterator pos, const value_type& value)\n     */\n    std::pair<iterator, bool> insert_at_position(const_iterator pos, value_type&& value) { \n        return m_ht.insert_at_position(pos, std::move(value)); \n    }\n    \n    /**\n     * @copydoc insert_at_position(const_iterator pos, const value_type& value)\n     * \n     * Same as insert_at_position(pos, value_type(std::forward<Args>(args)...), mainly\n     * here for coherence.\n     */\n    template<class... Args>\n    std::pair<iterator, bool> emplace_at_position(const_iterator pos, Args&&... args) {\n        return m_ht.emplace_at_position(pos, std::forward<Args>(args)...); \n    }\n       \n    /**\n     * @copydoc insert_at_position(const_iterator pos, const value_type& value)\n     */       \n    template<class... Args>\n    std::pair<iterator, bool> try_emplace_at_position(const_iterator pos, const key_type& k, Args&&... args) { \n        return m_ht.try_emplace_at_position(pos, k, std::forward<Args>(args)...);\n    }\n    \n    /**\n     * @copydoc insert_at_position(const_iterator pos, const value_type& value)\n     */    \n    template<class... Args>\n    std::pair<iterator, bool> try_emplace_at_position(const_iterator pos, key_type&& k, Args&&... args) {\n        return m_ht.try_emplace_at_position(pos, std::move(k), std::forward<Args>(args)...);\n    }\n    \n    \n    \n    void pop_back() { m_ht.pop_back(); }\n    \n    /**\n     * Faster erase operation with an O(1) average complexity but it doesn't preserve the insertion order.\n     * \n     * If an erasure occurs, the last element of the map will take the place of the erased element.\n     */\n    iterator unordered_erase(iterator pos) { return m_ht.unordered_erase(pos); }\n    \n    /**\n     * @copydoc unordered_erase(iterator pos)\n     */\n    iterator unordered_erase(const_iterator pos) { return m_ht.unordered_erase(pos); }\n    \n    /**\n     * @copydoc unordered_erase(iterator pos)\n     */    \n    size_type unordered_erase(const key_type& key) { return m_ht.unordered_erase(key); }\n    \n    /**\n     * @copydoc unordered_erase(iterator pos)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */    \n    size_type unordered_erase(const key_type& key, std::size_t precalculated_hash) { \n        return m_ht.unordered_erase(key, precalculated_hash); \n    }\n    \n    /**\n     * @copydoc unordered_erase(iterator pos)\n     * \n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type unordered_erase(const K& key) { return m_ht.unordered_erase(key); }\n    \n    /**\n     * @copydoc unordered_erase(const K& key)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type unordered_erase(const K& key, std::size_t precalculated_hash) { \n        return m_ht.unordered_erase(key, precalculated_hash); \n    }\n    \n    \n    \n    friend bool operator==(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht == rhs.m_ht; }\n    friend bool operator!=(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht != rhs.m_ht; }\n    friend bool operator<(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht < rhs.m_ht; }\n    friend bool operator<=(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht <= rhs.m_ht; }\n    friend bool operator>(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht > rhs.m_ht; }\n    friend bool operator>=(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht >= rhs.m_ht; }\n    \n    friend void swap(ordered_map& lhs, ordered_map& rhs) { lhs.swap(rhs); }\n\nprivate:\n    ht m_ht;\n};\n\n} // end namespace tsl\n\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/ordered-map/include/tsl/ordered_set.h",
    "content": "/**\n * MIT License\n * \n * Copyright (c) 2017 Tessil\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n#ifndef TSL_ORDERED_SET_H\n#define TSL_ORDERED_SET_H\n\n\n#include <cstddef>\n#include <cstdint>\n#include <deque>\n#include <functional>\n#include <initializer_list>\n#include <memory>\n#include <type_traits>\n#include <utility>\n#include <vector>\n#include \"ordered_hash.h\"\n\n\nnamespace tsl {\n\n\n/**\n * Implementation of an hash set using open adressing with robin hood with backshift delete to resolve collisions.\n * \n * The particularity of this hash set is that it remembers the order in which the elements were added and\n * provide a way to access the structure which stores these values through the 'values_container()' method. \n * The used container is defined by ValueTypeContainer, by default a std::deque is used (grows faster) but\n * a std::vector may be used. In this case the set provides a 'data()' method which give a direct access \n * to the memory used to store the values (which can be usefull to communicate with C API's).\n * \n * The Key must be copy constructible and/or move constructible. To use `unordered_erase` it also must be swappable.\n * \n * The behaviour of the hash set is undefinded if the destructor of Key throws an exception.\n * \n * By default the maximum size of a set is limited to 2^32 - 1 values, if needed this can be changed through\n * the IndexType template parameter. Using an `uint64_t` will raise this limit to 2^64 - 1 values but each\n * bucket will use 16 bytes instead of 8 bytes in addition to the space needed to store the values.\n * \n * Iterators invalidation:\n *  - clear, operator=, reserve, rehash: always invalidate the iterators (also invalidate end()).\n *  - insert, emplace, emplace_hint, operator[]: when a std::vector is used as ValueTypeContainer \n *                                               and if size() < capacity(), only end(). \n *                                               Otherwise all the iterators are invalidated if an insert occurs.\n *  - erase, unordered_erase: when a std::vector is used as ValueTypeContainer invalidate the iterator of \n *                            the erased element and all the ones after the erased element (including end()). \n *                            Otherwise all the iterators are invalidated if an erase occurs.\n */\ntemplate<class Key, \n         class Hash = std::hash<Key>,\n         class KeyEqual = std::equal_to<Key>,\n         class Allocator = std::allocator<Key>,\n         class ValueTypeContainer = std::deque<Key, Allocator>,\n         class IndexType = std::uint_least32_t>\nclass ordered_set {\nprivate:\n    template<typename U>\n    using has_is_transparent = tsl::detail_ordered_hash::has_is_transparent<U>;\n    \n    class KeySelect {\n    public:\n        using key_type = Key;\n        \n        const key_type& operator()(const Key& key) const noexcept {\n            return key;\n        }\n        \n        key_type& operator()(Key& key) noexcept {\n            return key;\n        }\n    };\n    \n    using ht = detail_ordered_hash::ordered_hash<Key, KeySelect, void,\n                                                 Hash, KeyEqual, Allocator, ValueTypeContainer, IndexType>;\n            \npublic:\n    using key_type = typename ht::key_type;\n    using value_type = typename ht::value_type;\n    using size_type = typename ht::size_type;\n    using difference_type = typename ht::difference_type;\n    using hasher = typename ht::hasher;\n    using key_equal = typename ht::key_equal;\n    using allocator_type = typename ht::allocator_type;\n    using reference = typename ht::reference;\n    using const_reference = typename ht::const_reference;\n    using pointer = typename ht::pointer;\n    using const_pointer = typename ht::const_pointer;\n    using iterator = typename ht::iterator;\n    using const_iterator = typename ht::const_iterator;\n    using reverse_iterator = typename ht::reverse_iterator;\n    using const_reverse_iterator = typename ht::const_reverse_iterator;\n    \n    using values_container_type = typename ht::values_container_type;\n\n    \n    /*\n     * Constructors\n     */\n    ordered_set(): ordered_set(ht::DEFAULT_INIT_BUCKETS_SIZE) {\n    }\n    \n    explicit ordered_set(size_type bucket_count, \n                         const Hash& hash = Hash(),\n                         const KeyEqual& equal = KeyEqual(),\n                         const Allocator& alloc = Allocator()): \n                        m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)\n    {\n    }\n    \n    ordered_set(size_type bucket_count,\n                const Allocator& alloc): ordered_set(bucket_count, Hash(), KeyEqual(), alloc)\n    {\n    }\n    \n    ordered_set(size_type bucket_count,\n                const Hash& hash,\n                const Allocator& alloc): ordered_set(bucket_count, hash, KeyEqual(), alloc)\n    {\n    }\n    \n    explicit ordered_set(const Allocator& alloc): ordered_set(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {\n    }\n    \n    template<class InputIt>\n    ordered_set(InputIt first, InputIt last,\n                size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,\n                const Hash& hash = Hash(),\n                const KeyEqual& equal = KeyEqual(),\n                const Allocator& alloc = Allocator()): ordered_set(bucket_count, hash, equal, alloc)\n    {\n        insert(first, last);\n    }\n    \n    template<class InputIt>\n    ordered_set(InputIt first, InputIt last,\n                size_type bucket_count,\n                const Allocator& alloc): ordered_set(first, last, bucket_count, Hash(), KeyEqual(), alloc)\n    {\n    }\n    \n    template<class InputIt>\n    ordered_set(InputIt first, InputIt last,\n                size_type bucket_count,\n                const Hash& hash,\n                const Allocator& alloc): ordered_set(first, last, bucket_count, hash, KeyEqual(), alloc)\n    {\n    }\n\n    ordered_set(std::initializer_list<value_type> init,\n                size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,\n                const Hash& hash = Hash(),\n                const KeyEqual& equal = KeyEqual(),\n                const Allocator& alloc = Allocator()): \n            ordered_set(init.begin(), init.end(), bucket_count, hash, equal, alloc)\n    {\n    }\n\n    ordered_set(std::initializer_list<value_type> init,\n                size_type bucket_count,\n                const Allocator& alloc): \n            ordered_set(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)\n    {\n    }\n\n    ordered_set(std::initializer_list<value_type> init,\n                size_type bucket_count,\n                const Hash& hash,\n                const Allocator& alloc): \n            ordered_set(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)\n    {\n    }\n\n    \n    ordered_set& operator=(std::initializer_list<value_type> ilist) {\n        m_ht.clear();\n        \n        m_ht.reserve(ilist.size());\n        m_ht.insert(ilist.begin(), ilist.end());\n        \n        return *this;\n    }\n    \n    allocator_type get_allocator() const { return m_ht.get_allocator(); }\n    \n    \n    /*\n     * Iterators\n     */\n    iterator begin() noexcept { return m_ht.begin(); }\n    const_iterator begin() const noexcept { return m_ht.begin(); }\n    const_iterator cbegin() const noexcept { return m_ht.cbegin(); }\n    \n    iterator end() noexcept { return m_ht.end(); }\n    const_iterator end() const noexcept { return m_ht.end(); }\n    const_iterator cend() const noexcept { return m_ht.cend(); }\n    \n    reverse_iterator rbegin() noexcept { return m_ht.rbegin(); }\n    const_reverse_iterator rbegin() const noexcept { return m_ht.rbegin(); }\n    const_reverse_iterator rcbegin() const noexcept { return m_ht.rcbegin(); }\n    \n    reverse_iterator rend() noexcept { return m_ht.rend(); }\n    const_reverse_iterator rend() const noexcept { return m_ht.rend(); }\n    const_reverse_iterator rcend() const noexcept { return m_ht.rcend(); }\n    \n    \n    /*\n     * Capacity\n     */\n    bool empty() const noexcept { return m_ht.empty(); }\n    size_type size() const noexcept { return m_ht.size(); }\n    size_type max_size() const noexcept { return m_ht.max_size(); }\n    \n    /*\n     * Modifiers\n     */\n    void clear() noexcept { m_ht.clear(); }\n    \n    \n    \n    std::pair<iterator, bool> insert(const value_type& value) { return m_ht.insert(value); }\n    std::pair<iterator, bool> insert(value_type&& value) { return m_ht.insert(std::move(value)); }\n    \n    iterator insert(const_iterator hint, const value_type& value) {\n        return m_ht.insert(hint, value); \n    }\n    \n    iterator insert(const_iterator hint, value_type&& value) { \n        return m_ht.insert(hint, std::move(value)); \n    }\n    \n    template<class InputIt>\n    void insert(InputIt first, InputIt last) { m_ht.insert(first, last); }\n    void insert(std::initializer_list<value_type> ilist) { m_ht.insert(ilist.begin(), ilist.end()); }\n\n    \n    \n    /**\n     * Due to the way elements are stored, emplace will need to move or copy the key-value once.\n     * The method is equivalent to insert(value_type(std::forward<Args>(args)...));\n     * \n     * Mainly here for compatibility with the std::unordered_map interface.\n     */\n    template<class... Args>\n    std::pair<iterator, bool> emplace(Args&&... args) { return m_ht.emplace(std::forward<Args>(args)...); }\n    \n    /**\n     * Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.\n     * The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));\n     * \n     * Mainly here for compatibility with the std::unordered_map interface.\n     */\n    template<class... Args>\n    iterator emplace_hint(const_iterator hint, Args&&... args) {\n        return m_ht.emplace_hint(hint, std::forward<Args>(args)...); \n    }\n\n    /**\n     * When erasing an element, the insert order will be preserved and no holes will be present in the container\n     * returned by 'values_container()'. \n     * \n     * The method is in O(n), if the order is not important 'unordered_erase(...)' method is faster with an O(1)\n     * average complexity.\n     */    \n    iterator erase(iterator pos) { return m_ht.erase(pos); }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     */    \n    iterator erase(const_iterator pos) { return m_ht.erase(pos); }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     */    \n    iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     */    \n    size_type erase(const key_type& key) { return m_ht.erase(key); }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.\n     */    \n    size_type erase(const key_type& key, std::size_t precalculated_hash) { \n        return m_ht.erase(key, precalculated_hash); \n    }\n    \n    /**\n     * @copydoc erase(iterator pos)\n     * \n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type erase(const K& key) { return m_ht.erase(key); }\n    \n    /**\n     * @copydoc erase(const key_type& key, std::size_t precalculated_hash)\n     * \n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type erase(const K& key, std::size_t precalculated_hash) { \n        return m_ht.erase(key, precalculated_hash); \n    }\n    \n    \n    \n    void swap(ordered_set& other) { other.m_ht.swap(m_ht); }\n    \n    /*\n     * Lookup\n     */\n    size_type count(const Key& key) const { return m_ht.count(key); }\n    \n    /**\n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    size_type count(const Key& key, std::size_t precalculated_hash) const { \n        return m_ht.count(key, precalculated_hash); \n    }\n    \n    /**\n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>\n    size_type count(const K& key) const { return m_ht.count(key); }\n    \n    /**\n     * @copydoc count(const K& key) const\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */     \n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type count(const K& key, std::size_t precalculated_hash) const { \n        return m_ht.count(key, precalculated_hash);\n    }\n    \n    \n    \n    \n    iterator find(const Key& key) { return m_ht.find(key); }\n    \n    /**\n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }\n    \n    const_iterator find(const Key& key) const { return m_ht.find(key); }\n    \n    /**\n     * @copydoc find(const Key& key, std::size_t precalculated_hash)\n     */\n    const_iterator find(const Key& key, std::size_t precalculated_hash) const { \n        return m_ht.find(key, precalculated_hash);\n    }\n    \n    /**\n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>\n    iterator find(const K& key) { return m_ht.find(key); }\n    \n    /**\n     * @copydoc find(const K& key)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }\n    \n    /**\n     * @copydoc find(const K& key)\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>\n    const_iterator find(const K& key) const { return m_ht.find(key); }\n    \n    /**\n     * @copydoc find(const K& key)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    const_iterator find(const K& key, std::size_t precalculated_hash) const { \n        return m_ht.find(key, precalculated_hash); \n    }\n    \n    \n    \n    std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }\n    \n    /**\n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) { \n        return m_ht.equal_range(key, precalculated_hash); \n    }\n    \n    std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }\n    \n    /**\n     * @copydoc equal_range(const Key& key, std::size_t precalculated_hash)\n     */\n    std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const { \n        return m_ht.equal_range(key, precalculated_hash); \n    }\n    \n    /**\n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>     \n    std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }\n    \n    /**\n     * @copydoc equal_range(const K& key)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) { \n        return m_ht.equal_range(key, precalculated_hash); \n    }\n    \n    /**\n     * @copydoc equal_range(const K& key)\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>     \n    std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }\n    \n    /**\n     * @copydoc equal_range(const K& key, std::size_t precalculated_hash)\n     */    \n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const { \n        return m_ht.equal_range(key, precalculated_hash); \n    }\n    \n\n    /*\n     * Bucket interface \n     */\n    size_type bucket_count() const { return m_ht.bucket_count(); }\n    size_type max_bucket_count() const { return m_ht.max_bucket_count(); }\n    \n    \n    /*\n     *  Hash policy \n     */\n    float load_factor() const { return m_ht.load_factor(); }\n    float max_load_factor() const { return m_ht.max_load_factor(); }\n    void max_load_factor(float ml) { m_ht.max_load_factor(ml); }\n    \n    void rehash(size_type count) { m_ht.rehash(count); }\n    void reserve(size_type count) { m_ht.reserve(count); }\n    \n    \n    /*\n     * Observers\n     */\n    hasher hash_function() const { return m_ht.hash_function(); }\n    key_equal key_eq() const { return m_ht.key_eq(); }\n    \n    \n    /*\n     * Other\n     */\n    \n    /**\n     * Convert a const_iterator to an iterator.\n     */\n    iterator mutable_iterator(const_iterator pos) {\n        return m_ht.mutable_iterator(pos);\n    }\n    \n    /**\n     * Requires index <= size().\n     * \n     * Return an iterator to the element at index. Return end() if index == size().\n     */\n    iterator nth(size_type index) { return m_ht.nth(index); }\n    \n    /**\n     * @copydoc nth(size_type index)\n     */\n    const_iterator nth(size_type index) const { return m_ht.nth(index); }\n    \n    \n    /**\n     * Return const_reference to the first element. Requires the container to not be empty.\n     */\n    const_reference front() const { return m_ht.front(); }\n    \n    /**\n     * Return const_reference to the last element. Requires the container to not be empty.\n     */\n    const_reference back() const { return m_ht.back(); }\n    \n    \n    /**\n     * Only available if ValueTypeContainer is a std::vector. Same as calling 'values_container().data()'.\n     */ \n    template<class U = values_container_type, typename std::enable_if<tsl::detail_ordered_hash::is_vector<U>::value>::type* = nullptr>    \n    const typename values_container_type::value_type* data() const noexcept { return m_ht.data(); }\n    \n    /**\n     * Return the container in which the values are stored. The values are in the same order as the insertion order\n     * and are contiguous in the structure, no holes (size() == values_container().size()).\n     */        \n    const values_container_type& values_container() const noexcept { return m_ht.values_container(); }\n\n    template<class U = values_container_type, typename std::enable_if<tsl::detail_ordered_hash::is_vector<U>::value>::type* = nullptr>    \n    size_type capacity() const noexcept { return m_ht.capacity(); }\n    \n    void shrink_to_fit() { m_ht.shrink_to_fit(); }\n    \n    \n    \n    /**\n     * Insert the value before pos shifting all the elements on the right of pos (including pos) one position \n     * to the right.\n     * \n     * Amortized linear time-complexity in the distance between pos and end().\n     */\n    std::pair<iterator, bool> insert_at_position(const_iterator pos, const value_type& value) { \n        return m_ht.insert_at_position(pos, value); \n    }\n    \n    /**\n     * @copydoc insert_at_position(const_iterator pos, const value_type& value)\n     */\n    std::pair<iterator, bool> insert_at_position(const_iterator pos, value_type&& value) { \n        return m_ht.insert_at_position(pos, std::move(value)); \n    }\n    \n    /**\n     * @copydoc insert_at_position(const_iterator pos, const value_type& value)\n     * \n     * Same as insert_at_position(pos, value_type(std::forward<Args>(args)...), mainly\n     * here for coherence.\n     */\n    template<class... Args>\n    std::pair<iterator, bool> emplace_at_position(const_iterator pos, Args&&... args) {\n        return m_ht.emplace_at_position(pos, std::forward<Args>(args)...); \n    }\n    \n    \n    \n    void pop_back() { m_ht.pop_back(); }\n    \n    /**\n     * Faster erase operation with an O(1) average complexity but it doesn't preserve the insertion order.\n     * \n     * If an erasure occurs, the last element of the map will take the place of the erased element.\n     */    \n    iterator unordered_erase(iterator pos) { return m_ht.unordered_erase(pos); }\n    \n    /**\n     * @copydoc unordered_erase(iterator pos)\n     */    \n    iterator unordered_erase(const_iterator pos) { return m_ht.unordered_erase(pos); }\n    \n    /**\n     * @copydoc unordered_erase(iterator pos)\n     */    \n    size_type unordered_erase(const key_type& key) { return m_ht.unordered_erase(key); }\n    \n    /**\n     * @copydoc unordered_erase(iterator pos)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */    \n    size_type unordered_erase(const key_type& key, std::size_t precalculated_hash) { \n        return m_ht.unordered_erase(key, precalculated_hash); \n    }\n    \n    /**\n     * @copydoc unordered_erase(iterator pos)\n     * \n     * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists. \n     * If so, K must be hashable and comparable to Key.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type unordered_erase(const K& key) { return m_ht.unordered_erase(key); }\n    \n    /**\n     * @copydoc unordered_erase(const K& key)\n     * \n     * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same\n     * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.\n     */\n    template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr> \n    size_type unordered_erase(const K& key, std::size_t precalculated_hash) { \n        return m_ht.unordered_erase(key, precalculated_hash); \n    }\n    \n    \n    \n    friend bool operator==(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht == rhs.m_ht; }\n    friend bool operator!=(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht != rhs.m_ht; }\n    friend bool operator<(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht < rhs.m_ht; }\n    friend bool operator<=(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht <= rhs.m_ht; }\n    friend bool operator>(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht > rhs.m_ht; }\n    friend bool operator>=(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht >= rhs.m_ht; }\n    \n    friend void swap(ordered_set& lhs, ordered_set& rhs) { lhs.swap(rhs); }\n    \nprivate:\n    ht m_ht;    \n};\n\n} // end namespace tsl\n\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Gabi Melman.                                       \n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-- NOTE: Third party dependency used by this software --\nThis software depends on the fmt lib (MIT License),\nand users must comply to its license: https://github.com/fmtlib/fmt/blob/master/LICENSE.rst\n\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/README.md",
    "content": "# spdlog\n\nVery fast, header-only/compiled, C++ logging library. [![Build Status](https://app.travis-ci.com/gabime/spdlog.svg?branch=v1.x)](https://app.travis-ci.com/gabime/spdlog)&nbsp; [![Build status](https://ci.appveyor.com/api/projects/status/d2jnxclg20vd0o50?svg=true&branch=v1.x)](https://ci.appveyor.com/project/gabime/spdlog) [![Release](https://img.shields.io/github/release/gabime/spdlog.svg)](https://github.com/gabime/spdlog/releases/latest)\n\n## Install \n#### Header only version\nCopy the include [folder](https://github.com/gabime/spdlog/tree/v1.x/include/spdlog) to your build tree and use a C++11 compiler.\n\n#### Static lib version (recommended - much faster compile times)\n```console\n$ git clone https://github.com/gabime/spdlog.git\n$ cd spdlog && mkdir build && cd build\n$ cmake .. && make -j\n```\n      \n   see example [CMakeLists.txt](https://github.com/gabime/spdlog/blob/v1.x/example/CMakeLists.txt) on how to use.\n\n## Platforms\n * Linux, FreeBSD, OpenBSD, Solaris, AIX\n * Windows (msvc 2013+, cygwin)\n * macOS (clang 3.5+)\n * Android\n\n## Package managers:\n* Debian: `sudo apt install libspdlog-dev`\n* Homebrew: `brew install spdlog`\n* MacPorts: `sudo port install spdlog`\n* FreeBSD:  `pkg install spdlog`\n* Fedora: `dnf install spdlog`\n* Gentoo: `emerge dev-libs/spdlog`\n* Arch Linux: `pacman -S spdlog`\n* vcpkg: `vcpkg install spdlog`\n* conan: `spdlog/[>=1.4.1]`\n* conda: `conda install -c conda-forge spdlog`\n* build2: ```depends: spdlog ^1.8.2```\n\n\n## Features\n* Very fast (see [benchmarks](#benchmarks) below).\n* Headers only or compiled\n* Feature rich formatting, using the excellent [fmt](https://github.com/fmtlib/fmt) library.\n* Asynchronous mode (optional)\n* [Custom](https://github.com/gabime/spdlog/wiki/3.-Custom-formatting) formatting.\n* Multi/Single threaded loggers.\n* Various log targets:\n    * Rotating log files.\n    * Daily log files.\n    * Console logging (colors supported).\n    * syslog.\n    * Windows event log.\n    * Windows debugger (```OutputDebugString(..)```).\n    * Easily [extendable](https://github.com/gabime/spdlog/wiki/4.-Sinks#implementing-your-own-sink) with custom log targets.\n* Log filtering - log levels can be modified in runtime as well as in compile time.\n* Support for loading log levels from argv or from environment var.\n* [Backtrace](#backtrace-support) support - store debug messages in a ring buffer and display later on demand.\n \n## Usage samples\n\n#### Basic usage\n```c++\n#include \"spdlog/spdlog.h\"\n\nint main() \n{\n    spdlog::info(\"Welcome to spdlog!\");\n    spdlog::error(\"Some error message with arg: {}\", 1);\n    \n    spdlog::warn(\"Easy padding in numbers like {:08d}\", 12);\n    spdlog::critical(\"Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}\", 42);\n    spdlog::info(\"Support for floats {:03.2f}\", 1.23456);\n    spdlog::info(\"Positional args are {1} {0}..\", \"too\", \"supported\");\n    spdlog::info(\"{:<30}\", \"left aligned\");\n    \n    spdlog::set_level(spdlog::level::debug); // Set global log level to debug\n    spdlog::debug(\"This message should be displayed..\");    \n    \n    // change log pattern\n    spdlog::set_pattern(\"[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v\");\n    \n    // Compile time log levels\n    // define SPDLOG_ACTIVE_LEVEL to desired level\n    SPDLOG_TRACE(\"Some trace message with param {}\", 42);\n    SPDLOG_DEBUG(\"Some debug message\");\n}\n\n```\n---\n#### Create stdout/stderr logger object\n```c++\n#include \"spdlog/spdlog.h\"\n#include \"spdlog/sinks/stdout_color_sinks.h\"\nvoid stdout_example()\n{\n    // create color multi threaded logger\n    auto console = spdlog::stdout_color_mt(\"console\");    \n    auto err_logger = spdlog::stderr_color_mt(\"stderr\");    \n    spdlog::get(\"console\")->info(\"loggers can be retrieved from a global registry using the spdlog::get(logger_name)\");\n}\n```\n\n---\n#### Basic file logger\n```c++\n#include \"spdlog/sinks/basic_file_sink.h\"\nvoid basic_logfile_example()\n{\n    try \n    {\n        auto logger = spdlog::basic_logger_mt(\"basic_logger\", \"logs/basic-log.txt\");\n    }\n    catch (const spdlog::spdlog_ex &ex)\n    {\n        std::cout << \"Log init failed: \" << ex.what() << std::endl;\n    }\n}\n```\n---\n#### Rotating files\n```c++\n#include \"spdlog/sinks/rotating_file_sink.h\"\nvoid rotating_example()\n{\n    // Create a file rotating logger with 5mb size max and 3 rotated files\n    auto max_size = 1048576 * 5;\n    auto max_files = 3;\n    auto logger = spdlog::rotating_logger_mt(\"some_logger_name\", \"logs/rotating.txt\", max_size, max_files);\n}\n```\n\n---\n#### Daily files\n```c++\n\n#include \"spdlog/sinks/daily_file_sink.h\"\nvoid daily_example()\n{\n    // Create a daily logger - a new file is created every day on 2:30am\n    auto logger = spdlog::daily_logger_mt(\"daily_logger\", \"logs/daily.txt\", 2, 30);\n}\n\n```\n\n---\n#### Backtrace support\n```c++\n// Debug messages can be stored in a ring buffer instead of being logged immediately.\n// This is useful in order to display debug logs only when really needed (e.g. when error happens).\n// When needed, call dump_backtrace() to see them.\n\nspdlog::enable_backtrace(32); // Store the latest 32 messages in a buffer. Older messages will be dropped.\n// or my_logger->enable_backtrace(32)..\nfor(int i = 0; i < 100; i++)\n{\n  spdlog::debug(\"Backtrace message {}\", i); // not logged yet..\n}\n// e.g. if some error happened:\nspdlog::dump_backtrace(); // log them now! show the last 32 messages\n\n// or my_logger->dump_backtrace(32)..\n```\n\n---\n#### Periodic flush\n```c++\n// periodically flush all *registered* loggers every 3 seconds:\n// warning: only use if all your loggers are thread safe (\"_mt\" loggers)\nspdlog::flush_every(std::chrono::seconds(3));\n\n```\n\n---\n#### Stopwatch\n```c++\n// Stopwatch support for spdlog\n#include \"spdlog/stopwatch.h\"\nvoid stopwatch_example()\n{\n    spdlog::stopwatch sw;    \n    spdlog::debug(\"Elapsed {}\", sw);\n    spdlog::debug(\"Elapsed {:.3}\", sw);       \n}\n\n```\n\n---\n#### Log binary data in hex\n```c++\n// many types of std::container<char> types can be used.\n// ranges are supported too.\n// format flags:\n// {:X} - print in uppercase.\n// {:s} - don't separate each byte with space.\n// {:p} - don't print the position on each line start.\n// {:n} - don't split the output to lines.\n// {:a} - show ASCII if :n is not set.\n\n#include \"spdlog/fmt/bin_to_hex.h\"\n\nvoid binary_example()\n{\n    auto console = spdlog::get(\"console\");\n    std::array<char, 80> buf;\n    console->info(\"Binary example: {}\", spdlog::to_hex(buf));\n    console->info(\"Another binary example:{:n}\", spdlog::to_hex(std::begin(buf), std::begin(buf) + 10));\n    // more examples:\n    // logger->info(\"uppercase: {:X}\", spdlog::to_hex(buf));\n    // logger->info(\"uppercase, no delimiters: {:Xs}\", spdlog::to_hex(buf));\n    // logger->info(\"uppercase, no delimiters, no position info: {:Xsp}\", spdlog::to_hex(buf));\n}\n\n```\n\n---\n#### Logger with multi sinks - each with different format and log level\n```c++\n\n// create logger with 2 targets with different log levels and formats.\n// the console will show only warnings or errors, while the file will log all.\nvoid multi_sink_example()\n{\n    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();\n    console_sink->set_level(spdlog::level::warn);\n    console_sink->set_pattern(\"[multi_sink_example] [%^%l%$] %v\");\n\n    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(\"logs/multisink.txt\", true);\n    file_sink->set_level(spdlog::level::trace);\n\n    spdlog::logger logger(\"multi_sink\", {console_sink, file_sink});\n    logger.set_level(spdlog::level::debug);\n    logger.warn(\"this should appear in both console and file\");\n    logger.info(\"this message should not appear in the console, only in the file\");\n}\n```\n\n---\n#### Asynchronous logging\n```c++\n#include \"spdlog/async.h\"\n#include \"spdlog/sinks/basic_file_sink.h\"\nvoid async_example()\n{\n    // default thread pool settings can be modified *before* creating the async logger:\n    // spdlog::init_thread_pool(8192, 1); // queue with 8k items and 1 backing thread.\n    auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>(\"async_file_logger\", \"logs/async_log.txt\");\n    // alternatively:\n    // auto async_file = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>(\"async_file_logger\", \"logs/async_log.txt\");   \n}\n\n```\n\n---\n#### Asynchronous logger with multi sinks  \n```c++\n#include \"spdlog/sinks/stdout_color_sinks.h\"\n#include \"spdlog/sinks/rotating_file_sink.h\"\n\nvoid multi_sink_example2()\n{\n    spdlog::init_thread_pool(8192, 1);\n    auto stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt >();\n    auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(\"mylog.txt\", 1024*1024*10, 3);\n    std::vector<spdlog::sink_ptr> sinks {stdout_sink, rotating_sink};\n    auto logger = std::make_shared<spdlog::async_logger>(\"loggername\", sinks.begin(), sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);\n    spdlog::register_logger(logger);\n}\n```\n \n---\n#### User defined types\n```c++\n// user defined types logging by implementing operator<<\n#include \"spdlog/fmt/ostr.h\" // must be included\nstruct my_type\n{\n    int i;\n    template<typename OStream>\n    friend OStream &operator<<(OStream &os, const my_type &c)\n    {\n        return os << \"[my_type i=\" << c.i << \"]\";\n    }\n};\n\nvoid user_defined_example()\n{\n    spdlog::get(\"console\")->info(\"user defined type: {}\", my_type{14});\n}\n\n```\n\n---\n#### User defined flags in the log pattern\n```c++ \n// Log patterns can contain custom flags.\n// the following example will add new flag '%*' - which will be bound to a <my_formatter_flag> instance.\n#include \"spdlog/pattern_formatter.h\"\nclass my_formatter_flag : public spdlog::custom_flag_formatter\n{\npublic:\n    void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override\n    {\n        std::string some_txt = \"custom-flag\";\n        dest.append(some_txt.data(), some_txt.data() + some_txt.size());\n    }\n\n    std::unique_ptr<custom_flag_formatter> clone() const override\n    {\n        return spdlog::details::make_unique<my_formatter_flag>();\n    }\n};\n\nvoid custom_flags_example()\n{    \n    auto formatter = std::make_unique<spdlog::pattern_formatter>();\n    formatter->add_flag<my_formatter_flag>('*').set_pattern(\"[%n] [%*] [%^%l%$] %v\");\n    spdlog::set_formatter(std::move(formatter));\n}\n\n```\n\n---\n#### Custom error handler\n```c++\nvoid err_handler_example()\n{\n    // can be set globally or per logger(logger->set_error_handler(..))\n    spdlog::set_error_handler([](const std::string &msg) { spdlog::get(\"console\")->error(\"*** LOGGER ERROR ***: {}\", msg); });\n    spdlog::get(\"console\")->info(\"some invalid message to trigger an error {}{}{}{}\", 3);\n}\n\n```\n\n---\n#### syslog \n```c++\n#include \"spdlog/sinks/syslog_sink.h\"\nvoid syslog_example()\n{\n    std::string ident = \"spdlog-example\";\n    auto syslog_logger = spdlog::syslog_logger_mt(\"syslog\", ident, LOG_PID);\n    syslog_logger->warn(\"This is warning that will end up in syslog.\");\n}\n```\n---\n#### Android example \n```c++\n#include \"spdlog/sinks/android_sink.h\"\nvoid android_example()\n{\n    std::string tag = \"spdlog-android\";\n    auto android_logger = spdlog::android_logger_mt(\"android\", tag);\n    android_logger->critical(\"Use \\\"adb shell logcat\\\" to view this message.\");\n}\n```\n\n---\n#### Load log levels from env variable or from argv\n\n```c++\n#include \"spdlog/cfg/env.h\"\nint main (int argc, char *argv[])\n{\n    spdlog::cfg::load_env_levels();\n    // or from command line:\n    // ./example SPDLOG_LEVEL=info,mylogger=trace\n    // #include \"spdlog/cfg/argv.h\" // for loading levels from argv\n    // spdlog::cfg::load_argv_levels(argc, argv);\n}\n```\nSo then you can:\n\n```console\n$ export SPDLOG_LEVEL=info,mylogger=trace\n$ ./example\n```\n\n\n---\n#### Log file open/close event handlers\n```c++\n// You can get callbacks from spdlog before/after log file has been opened or closed. \n// This is useful for cleanup procedures or for adding someting the start/end of the log files.\nvoid file_events_example()\n{\n    // pass the spdlog::file_event_handlers to file sinks for open/close log file notifications\n    spdlog::file_event_handlers handlers;\n    handlers.before_open = [](spdlog::filename_t filename) { spdlog::info(\"Before opening {}\", filename); };\n    handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) { fputs(\"After opening\\n\", fstream); };\n    handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) { fputs(\"Before closing\\n\", fstream); };\n    handlers.after_close = [](spdlog::filename_t filename) { spdlog::info(\"After closing {}\", filename); };\n    auto my_logger = spdlog::basic_logger_st(\"some_logger\", \"logs/events-sample.txt\", true, handlers);        \n}\n```\n\n---\n#### Replace the Default Logger\n```c++\nvoid replace_default_logger_example()\n{\n    auto new_logger = spdlog::basic_logger_mt(\"new_default_logger\", \"logs/new-default-log.txt\", true);\n    spdlog::set_default_logger(new_logger);\n    spdlog::info(\"new logger log message\");\n}\n```\n\n---\n## Benchmarks\n\nBelow are some [benchmarks](https://github.com/gabime/spdlog/blob/v1.x/bench/bench.cpp) done in Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz\n\n#### Synchronous mode\n```\n[info] **************************************************************\n[info] Single thread, 1,000,000 iterations\n[info] **************************************************************\n[info] basic_st         Elapsed: 0.17 secs        5,777,626/sec\n[info] rotating_st      Elapsed: 0.18 secs        5,475,894/sec\n[info] daily_st         Elapsed: 0.20 secs        5,062,659/sec\n[info] empty_logger     Elapsed: 0.07 secs       14,127,300/sec\n[info] **************************************************************\n[info] C-string (400 bytes). Single thread, 1,000,000 iterations\n[info] **************************************************************\n[info] basic_st         Elapsed: 0.41 secs        2,412,483/sec\n[info] rotating_st      Elapsed: 0.72 secs        1,389,196/sec\n[info] daily_st         Elapsed: 0.42 secs        2,393,298/sec\n[info] null_st          Elapsed: 0.04 secs       27,446,957/sec\n[info] **************************************************************\n[info] 10 threads, competing over the same logger object, 1,000,000 iterations\n[info] **************************************************************\n[info] basic_mt         Elapsed: 0.60 secs        1,659,613/sec\n[info] rotating_mt      Elapsed: 0.62 secs        1,612,493/sec\n[info] daily_mt         Elapsed: 0.61 secs        1,638,305/sec\n[info] null_mt          Elapsed: 0.16 secs        6,272,758/sec\n```\n#### Asynchronous mode\n```\n[info] -------------------------------------------------\n[info] Messages     : 1,000,000\n[info] Threads      : 10\n[info] Queue        : 8,192 slots\n[info] Queue memory : 8,192 x 272 = 2,176 KB \n[info] -------------------------------------------------\n[info] \n[info] *********************************\n[info] Queue Overflow Policy: block\n[info] *********************************\n[info] Elapsed: 1.70784 secs     585,535/sec\n[info] Elapsed: 1.69805 secs     588,910/sec\n[info] Elapsed: 1.7026 secs      587,337/sec\n[info] \n[info] *********************************\n[info] Queue Overflow Policy: overrun\n[info] *********************************\n[info] Elapsed: 0.372816 secs    2,682,285/sec\n[info] Elapsed: 0.379758 secs    2,633,255/sec\n[info] Elapsed: 0.373532 secs    2,677,147/sec\n\n```\n\n## Documentation\nDocumentation can be found in the [wiki](https://github.com/gabime/spdlog/wiki/1.-QuickStart) pages.\n\n---\n\nThanks to [JetBrains](https://www.jetbrains.com/?from=spdlog) for donating product licenses to help develop **spdlog** <a href=\"https://www.jetbrains.com/?from=spdlog\"><img src=\"logos/jetbrains-variant-4.svg\" width=\"94\" align=\"center\" /></a>\n\n\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/cmake/ide.cmake",
    "content": "# ---------------------------------------------------------------------------------------\n# IDE support for headers\n# ---------------------------------------------------------------------------------------\nset(SPDLOG_HEADERS_DIR \"${CMAKE_CURRENT_LIST_DIR}/../include\")\n\nfile(GLOB SPDLOG_TOP_HEADERS \"${SPDLOG_HEADERS_DIR}/spdlog/*.h\")\nfile(GLOB SPDLOG_DETAILS_HEADERS \"${SPDLOG_HEADERS_DIR}/spdlog/details/*.h\")\nfile(GLOB SPDLOG_SINKS_HEADERS \"${SPDLOG_HEADERS_DIR}/spdlog/sinks/*.h\")\nfile(GLOB SPDLOG_FMT_HEADERS \"${SPDLOG_HEADERS_DIR}/spdlog/fmt/*.h\")\nfile(GLOB SPDLOG_FMT_BUNDELED_HEADERS \"${SPDLOG_HEADERS_DIR}/spdlog/fmt/bundled/*.h\")\nset(SPDLOG_ALL_HEADERS ${SPDLOG_TOP_HEADERS} ${SPDLOG_DETAILS_HEADERS} ${SPDLOG_SINKS_HEADERS} ${SPDLOG_FMT_HEADERS}\n                       ${SPDLOG_FMT_BUNDELED_HEADERS})\n\nsource_group(\"Header Files\\\\spdlog\" FILES ${SPDLOG_TOP_HEADERS})\nsource_group(\"Header Files\\\\spdlog\\\\details\" FILES ${SPDLOG_DETAILS_HEADERS})\nsource_group(\"Header Files\\\\spdlog\\\\sinks\" FILES ${SPDLOG_SINKS_HEADERS})\nsource_group(\"Header Files\\\\spdlog\\\\fmt\" FILES ${SPDLOG_FMT_HEADERS})\nsource_group(\"Header Files\\\\spdlog\\\\fmt\\\\bundled\\\\\" FILES ${SPDLOG_FMT_BUNDELED_HEADERS})\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/cmake/spdlog.pc.in",
    "content": "prefix=@CMAKE_INSTALL_PREFIX@\nexec_prefix=${prefix}\nincludedir=${prefix}/include\nlibdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@\n\nName: lib@PROJECT_NAME@\nDescription: Fast C++ logging library.\nURL: https://github.com/gabime/@PROJECT_NAME@\nVersion: @SPDLOG_VERSION@\nCFlags: -I${includedir} @PKG_CONFIG_DEFINES@\nLibs: -L${libdir} -lspdlog -pthread\nRequires: @PKG_CONFIG_REQUIRES@\n\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/cmake/spdlogCPack.cmake",
    "content": "set(CPACK_GENERATOR \"TGZ;ZIP\" CACHE STRING \"Semicolon separated list of generators\")\n\nset(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)\nset(CPACK_INSTALL_CMAKE_PROJECTS \"${CMAKE_BINARY_DIR}\" \"${PROJECT_NAME}\" ALL .)\n\nset(CPACK_PROJECT_URL \"https://github.com/gabime/spdlog\")\nset(CPACK_PACKAGE_VENDOR \"Gabi Melman\")\nset(CPACK_PACKAGE_CONTACT \"Gabi Melman <gmelman1@gmail.com>\")\nset(CPACK_PACKAGE_DESCRIPTION_SUMMARY \"Fast C++ logging library\")\nset(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})\nset(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})\nset(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})\nset(CPACK_PACKAGE_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})\nif(PROJECT_VERSION_TWEAK)\n    set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}.${PROJECT_VERSION_TWEAK})\nendif()\nset(CPACK_PACKAGE_RELOCATABLE ON CACHE BOOL \"Build relocatable package\")\n\nset(CPACK_RPM_PACKAGE_LICENSE \"MIT\")\nset(CPACK_RPM_PACKAGE_GROUP \"Development/Libraries\")\nset(CPACK_DEBIAN_PACKAGE_SECTION \"libs\")\nset(CPACK_RPM_PACKAGE_URL ${CPACK_PROJECT_URL})\nset(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${CPACK_PROJECT_URL})\nset(CPACK_RPM_PACKAGE_DESCRIPTION \"Very fast, header-only/compiled, C++ logging library.\")\nset(CPACK_DEBIAN_PACKAGE_DESCRIPTION \"Very fast, header-only/compiled, C++ logging library.\")\n\nif(CPACK_PACKAGE_NAME)\n    set(CPACK_RPM_FILE_NAME \"${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}\")\n    set(CPACK_DEBIAN_FILE_NAME \"${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}\")\nelse()\n    set(CPACK_RPM_FILE_NAME \"${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}\")\n    set(CPACK_DEBIAN_FILE_NAME \"${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}\")\n    set(CPACK_RPM_PACKAGE_NAME \"${PROJECT_NAME}\")\n    set(CPACK_DEBIAN_PACKAGE_NAME \"${PROJECT_NAME}\")\nendif()\n\nif(CPACK_RPM_PACKAGE_RELEASE)\n    set(CPACK_RPM_FILE_NAME \"${CPACK_RPM_FILE_NAME}-${CPACK_RPM_PACKAGE_RELEASE}\")\nendif()\nif(CPACK_DEBIAN_PACKAGE_RELEASE)\n    set(CPACK_DEBIAN_FILE_NAME \"${CPACK_DEBIAN_FILE_NAME}-${CPACK_DEBIAN_PACKAGE_RELEASE}\")\nendif()\n\nif(CPACK_RPM_PACKAGE_ARCHITECTURE)\n    set(CPACK_RPM_FILE_NAME \"${CPACK_RPM_FILE_NAME}.${CPACK_RPM_PACKAGE_ARCHITECTURE}\")\nendif()\nif(CPACK_DEBIAN_PACKAGE_ARCHITECTURE)\n    set(CPACK_DEBIAN_FILE_NAME \"${CPACK_DEBIAN_FILE_NAME}.${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}\")\nendif()\nset(CPACK_RPM_FILE_NAME \"${CPACK_RPM_FILE_NAME}.rpm\")\nset(CPACK_DEBIAN_FILE_NAME \"${CPACK_DEBIAN_FILE_NAME}.deb\")\n\nif(NOT CPACK_PACKAGE_RELOCATABLE)\n    # Depend on pkgconfig rpm to create the system pkgconfig folder\n    set(CPACK_RPM_PACKAGE_REQUIRES pkgconfig)\n    set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION\n        \"${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig\")\nendif()\n\ninclude(CPack)\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/cmake/spdlogConfig.cmake.in",
    "content": "# Copyright(c) 2019 spdlog authors\n# Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n@PACKAGE_INIT@\n\nfind_package(Threads REQUIRED)\n\nset(SPDLOG_FMT_EXTERNAL @SPDLOG_FMT_EXTERNAL@)\nset(SPDLOG_FMT_EXTERNAL_HO @SPDLOG_FMT_EXTERNAL_HO@)\nset(config_targets_file @config_targets_file@)\n\nif(SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO)\n    include(CMakeFindDependencyMacro)\n    find_dependency(fmt CONFIG)\nendif()\n\n\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/${config_targets_file}\")\n\ncheck_required_components(spdlog)\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/cmake/utils.cmake",
    "content": "# Get spdlog version from include/spdlog/version.h and put it in SPDLOG_VERSION\nfunction(spdlog_extract_version)\n    file(READ \"${CMAKE_CURRENT_LIST_DIR}/include/spdlog/version.h\" file_contents)\n    string(REGEX MATCH \"SPDLOG_VER_MAJOR ([0-9]+)\" _ \"${file_contents}\")\n    if(NOT CMAKE_MATCH_COUNT EQUAL 1)\n        message(FATAL_ERROR \"Could not extract major version number from spdlog/version.h\")\n    endif()\n    set(ver_major ${CMAKE_MATCH_1})\n\n    string(REGEX MATCH \"SPDLOG_VER_MINOR ([0-9]+)\" _ \"${file_contents}\")\n    if(NOT CMAKE_MATCH_COUNT EQUAL 1)\n        message(FATAL_ERROR \"Could not extract minor version number from spdlog/version.h\")\n    endif()\n\n    set(ver_minor ${CMAKE_MATCH_1})\n    string(REGEX MATCH \"SPDLOG_VER_PATCH ([0-9]+)\" _ \"${file_contents}\")\n    if(NOT CMAKE_MATCH_COUNT EQUAL 1)\n        message(FATAL_ERROR \"Could not extract patch version number from spdlog/version.h\")\n    endif()\n    set(ver_patch ${CMAKE_MATCH_1})\n\n    set(SPDLOG_VERSION_MAJOR ${ver_major} PARENT_SCOPE)\n    set(SPDLOG_VERSION_MINOR ${ver_minor} PARENT_SCOPE)\n    set(SPDLOG_VERSION_PATCH ${ver_patch} PARENT_SCOPE)\n    set(SPDLOG_VERSION \"${ver_major}.${ver_minor}.${ver_patch}\" PARENT_SCOPE)\nendfunction()\n\n# Turn on warnings on the given target\nfunction(spdlog_enable_warnings target_name)\n    if(SPDLOG_BUILD_WARNINGS)\n        if(CMAKE_CXX_COMPILER_ID STREQUAL \"MSVC\")\n            list(APPEND MSVC_OPTIONS \"/W3\")\n            if(MSVC_VERSION GREATER 1900) # Allow non fatal security warnings for msvc 2015\n                list(APPEND MSVC_OPTIONS \"/WX\")\n            endif()\n        endif()\n\n        target_compile_options(\n            ${target_name}\n            PRIVATE $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:\n                    -Wall\n                    -Wextra\n                    -Wconversion\n                    -pedantic\n                    -Werror\n                    -Wfatal-errors>\n                    $<$<CXX_COMPILER_ID:MSVC>:${MSVC_OPTIONS}>)\n    endif()\nendfunction()\n\n# Enable address sanitizer (gcc/clang only)\nfunction(spdlog_enable_sanitizer target_name)\n    if(NOT CMAKE_CXX_COMPILER_ID MATCHES \"GNU|Clang\")\n        message(FATAL_ERROR \"Sanitizer supported only for gcc/clang\")\n    endif()\n    message(STATUS \"Address sanitizer enabled\")\n    target_compile_options(${target_name} PRIVATE -fsanitize=address,undefined)\n    target_compile_options(${target_name} PRIVATE -fno-sanitize=signed-integer-overflow)\n    target_compile_options(${target_name} PRIVATE -fno-sanitize-recover=all)\n    target_compile_options(${target_name} PRIVATE -fno-omit-frame-pointer)\n    target_link_libraries(${target_name} PRIVATE -fsanitize=address,undefined -fuse-ld=gold)\nendfunction()\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/cmake/version.rc.in",
    "content": "#define APSTUDIO_READONLY_SYMBOLS\n#include <windows.h>\n#undef APSTUDIO_READONLY_SYMBOLS\n\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION @SPDLOG_VERSION_MAJOR@,@SPDLOG_VERSION_MINOR@,@SPDLOG_VERSION_PATCH@,0\n PRODUCTVERSION @SPDLOG_VERSION_MAJOR@,@SPDLOG_VERSION_MINOR@,@SPDLOG_VERSION_PATCH@,0\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x40004L\n FILETYPE 0x2L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"040904b0\"\n        BEGIN\n            VALUE \"FileDescription\", \"spdlog dll\\0\"\n            VALUE \"FileVersion\", \"@SPDLOG_VERSION@.0\\0\"\n            VALUE \"InternalName\", \"spdlog.dll\\0\"\n            VALUE \"LegalCopyright\", \"Copyright (C) spdlog\\0\"\n            VALUE \"ProductName\", \"spdlog\\0\"\n            VALUE \"ProductVersion\", \"@SPDLOG_VERSION@.0\\0\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x409, 1200\n    END\nEND\n\n\n\n\n\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/async.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n//\n// Async logging using global thread pool\n// All loggers created here share same global thread pool.\n// Each log message is pushed to a queue along with a shared pointer to the\n// logger.\n// If a logger deleted while having pending messages in the queue, it's actual\n// destruction will defer\n// until all its messages are processed by the thread pool.\n// This is because each message in the queue holds a shared_ptr to the\n// originating logger.\n\n#include <spdlog/async_logger.h>\n#include <spdlog/details/registry.h>\n#include <spdlog/details/thread_pool.h>\n\n#include <memory>\n#include <mutex>\n#include <functional>\n\nnamespace spdlog {\n\nnamespace details {\nstatic const size_t default_async_q_size = 8192;\n}\n\n// async logger factory - creates async loggers backed with thread pool.\n// if a global thread pool doesn't already exist, create it with default queue\n// size of 8192 items and single thread.\ntemplate<async_overflow_policy OverflowPolicy = async_overflow_policy::block>\nstruct async_factory_impl\n{\n    template<typename Sink, typename... SinkArgs>\n    static std::shared_ptr<async_logger> create(std::string logger_name, SinkArgs &&... args)\n    {\n        auto &registry_inst = details::registry::instance();\n\n        // create global thread pool if not already exists..\n\n        auto &mutex = registry_inst.tp_mutex();\n        std::lock_guard<std::recursive_mutex> tp_lock(mutex);\n        auto tp = registry_inst.get_tp();\n        if (tp == nullptr)\n        {\n            tp = std::make_shared<details::thread_pool>(details::default_async_q_size, 1U);\n            registry_inst.set_tp(tp);\n        }\n\n        auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);\n        auto new_logger = std::make_shared<async_logger>(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy);\n        registry_inst.initialize_logger(new_logger);\n        return new_logger;\n    }\n};\n\nusing async_factory = async_factory_impl<async_overflow_policy::block>;\nusing async_factory_nonblock = async_factory_impl<async_overflow_policy::overrun_oldest>;\n\ntemplate<typename Sink, typename... SinkArgs>\ninline std::shared_ptr<spdlog::logger> create_async(std::string logger_name, SinkArgs &&... sink_args)\n{\n    return async_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);\n}\n\ntemplate<typename Sink, typename... SinkArgs>\ninline std::shared_ptr<spdlog::logger> create_async_nb(std::string logger_name, SinkArgs &&... sink_args)\n{\n    return async_factory_nonblock::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);\n}\n\n// set global thread pool.\ninline void init_thread_pool(\n    size_t q_size, size_t thread_count, std::function<void()> on_thread_start, std::function<void()> on_thread_stop)\n{\n    auto tp = std::make_shared<details::thread_pool>(q_size, thread_count, on_thread_start, on_thread_stop);\n    details::registry::instance().set_tp(std::move(tp));\n}\n\ninline void init_thread_pool(size_t q_size, size_t thread_count, std::function<void()> on_thread_start)\n{\n    init_thread_pool(q_size, thread_count, on_thread_start, [] {});\n}\n\ninline void init_thread_pool(size_t q_size, size_t thread_count)\n{\n    init_thread_pool(\n        q_size, thread_count, [] {}, [] {});\n}\n\n// get the global thread pool.\ninline std::shared_ptr<spdlog::details::thread_pool> thread_pool()\n{\n    return details::registry::instance().get_tp();\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/async_logger-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/async_logger.h>\n#endif\n\n#include <spdlog/sinks/sink.h>\n#include <spdlog/details/thread_pool.h>\n\n#include <memory>\n#include <string>\n\nSPDLOG_INLINE spdlog::async_logger::async_logger(\n    std::string logger_name, sinks_init_list sinks_list, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)\n    : async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy)\n{}\n\nSPDLOG_INLINE spdlog::async_logger::async_logger(\n    std::string logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)\n    : async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy)\n{}\n\n// send the log message to the thread pool\nSPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg)\n{\n    if (auto pool_ptr = thread_pool_.lock())\n    {\n        pool_ptr->post_log(shared_from_this(), msg, overflow_policy_);\n    }\n    else\n    {\n        throw_spdlog_ex(\"async log: thread pool doesn't exist anymore\");\n    }\n}\n\n// send flush request to the thread pool\nSPDLOG_INLINE void spdlog::async_logger::flush_()\n{\n    if (auto pool_ptr = thread_pool_.lock())\n    {\n        pool_ptr->post_flush(shared_from_this(), overflow_policy_);\n    }\n    else\n    {\n        throw_spdlog_ex(\"async flush: thread pool doesn't exist anymore\");\n    }\n}\n\n//\n// backend functions - called from the thread pool to do the actual job\n//\nSPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg)\n{\n    for (auto &sink : sinks_)\n    {\n        if (sink->should_log(msg.level))\n        {\n            SPDLOG_TRY\n            {\n                sink->log(msg);\n            }\n            SPDLOG_LOGGER_CATCH(msg.source)\n        }\n    }\n\n    if (should_flush_(msg))\n    {\n        backend_flush_();\n    }\n}\n\nSPDLOG_INLINE void spdlog::async_logger::backend_flush_()\n{\n    for (auto &sink : sinks_)\n    {\n        SPDLOG_TRY\n        {\n            sink->flush();\n        }\n        SPDLOG_LOGGER_CATCH(source_loc())\n    }\n}\n\nSPDLOG_INLINE std::shared_ptr<spdlog::logger> spdlog::async_logger::clone(std::string new_name)\n{\n    auto cloned = std::make_shared<spdlog::async_logger>(*this);\n    cloned->name_ = std::move(new_name);\n    return cloned;\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/async_logger.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n// Fast asynchronous logger.\n// Uses pre allocated queue.\n// Creates a single back thread to pop messages from the queue and log them.\n//\n// Upon each log write the logger:\n//    1. Checks if its log level is enough to log the message\n//    2. Push a new copy of the message to a queue (or block the caller until\n//    space is available in the queue)\n// Upon destruction, logs all remaining messages in the queue before\n// destructing..\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/logger.h>\n\nnamespace spdlog {\n\n// Async overflow policy - block by default.\nenum class async_overflow_policy\n{\n    block,         // Block until message can be enqueued\n    overrun_oldest // Discard oldest message in the queue if full when trying to\n                   // add new item.\n};\n\nnamespace details {\nclass thread_pool;\n}\n\nclass SPDLOG_API async_logger final : public std::enable_shared_from_this<async_logger>, public logger\n{\n    friend class details::thread_pool;\n\npublic:\n    template<typename It>\n    async_logger(std::string logger_name, It begin, It end, std::weak_ptr<details::thread_pool> tp,\n        async_overflow_policy overflow_policy = async_overflow_policy::block)\n        : logger(std::move(logger_name), begin, end)\n        , thread_pool_(std::move(tp))\n        , overflow_policy_(overflow_policy)\n    {}\n\n    async_logger(std::string logger_name, sinks_init_list sinks_list, std::weak_ptr<details::thread_pool> tp,\n        async_overflow_policy overflow_policy = async_overflow_policy::block);\n\n    async_logger(std::string logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp,\n        async_overflow_policy overflow_policy = async_overflow_policy::block);\n\n    std::shared_ptr<logger> clone(std::string new_name) override;\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override;\n    void flush_() override;\n    void backend_sink_it_(const details::log_msg &incoming_log_msg);\n    void backend_flush_();\n\nprivate:\n    std::weak_ptr<details::thread_pool> thread_pool_;\n    async_overflow_policy overflow_policy_;\n};\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"async_logger-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/cfg/argv.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n#include <spdlog/cfg/helpers.h>\n#include <spdlog/details/registry.h>\n\n//\n// Init log levels using each argv entry that starts with \"SPDLOG_LEVEL=\"\n//\n// set all loggers to debug level:\n// example.exe \"SPDLOG_LEVEL=debug\"\n\n// set logger1 to trace level\n// example.exe \"SPDLOG_LEVEL=logger1=trace\"\n\n// turn off all logging except for logger1 and logger2:\n// example.exe \"SPDLOG_LEVEL=off,logger1=debug,logger2=info\"\n\nnamespace spdlog {\nnamespace cfg {\n\n// search for SPDLOG_LEVEL= in the args and use it to init the levels\ninline void load_argv_levels(int argc, const char **argv)\n{\n    const std::string spdlog_level_prefix = \"SPDLOG_LEVEL=\";\n    for (int i = 1; i < argc; i++)\n    {\n        std::string arg = argv[i];\n        if (arg.find(spdlog_level_prefix) == 0)\n        {\n            auto levels_string = arg.substr(spdlog_level_prefix.size());\n            helpers::load_levels(levels_string);\n        }\n    }\n}\n\ninline void load_argv_levels(int argc, char **argv)\n{\n    load_argv_levels(argc, const_cast<const char **>(argv));\n}\n\n} // namespace cfg\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/cfg/env.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n#include <spdlog/cfg/helpers.h>\n#include <spdlog/details/registry.h>\n#include <spdlog/details/os.h>\n\n//\n// Init levels and patterns from env variables SPDLOG_LEVEL\n// Inspired from Rust's \"env_logger\" crate (https://crates.io/crates/env_logger).\n// Note - fallback to \"info\" level on unrecognized levels\n//\n// Examples:\n//\n// set global level to debug:\n// export SPDLOG_LEVEL=debug\n//\n// turn off all logging except for logger1:\n// export SPDLOG_LEVEL=\"*=off,logger1=debug\"\n//\n\n// turn off all logging except for logger1 and logger2:\n// export SPDLOG_LEVEL=\"off,logger1=debug,logger2=info\"\n\nnamespace spdlog {\nnamespace cfg {\ninline void load_env_levels()\n{\n    auto env_val = details::os::getenv(\"SPDLOG_LEVEL\");\n    if (!env_val.empty())\n    {\n        helpers::load_levels(env_val);\n    }\n}\n\n} // namespace cfg\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/cfg/helpers-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/cfg/helpers.h>\n#endif\n\n#include <spdlog/spdlog.h>\n#include <spdlog/details/os.h>\n#include <spdlog/details/registry.h>\n\n#include <algorithm>\n#include <string>\n#include <utility>\n#include <sstream>\n\nnamespace spdlog {\nnamespace cfg {\nnamespace helpers {\n\n// inplace convert to lowercase\ninline std::string &to_lower_(std::string &str)\n{\n    std::transform(\n        str.begin(), str.end(), str.begin(), [](char ch) { return static_cast<char>((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch); });\n    return str;\n}\n\n// inplace trim spaces\ninline std::string &trim_(std::string &str)\n{\n    const char *spaces = \" \\n\\r\\t\";\n    str.erase(str.find_last_not_of(spaces) + 1);\n    str.erase(0, str.find_first_not_of(spaces));\n    return str;\n}\n\n// return (name,value) trimmed pair from given \"name=value\" string.\n// return empty string on missing parts\n// \"key=val\" => (\"key\", \"val\")\n// \" key  =  val \" => (\"key\", \"val\")\n// \"key=\" => (\"key\", \"\")\n// \"val\" => (\"\", \"val\")\n\ninline std::pair<std::string, std::string> extract_kv_(char sep, const std::string &str)\n{\n    auto n = str.find(sep);\n    std::string k, v;\n    if (n == std::string::npos)\n    {\n        v = str;\n    }\n    else\n    {\n        k = str.substr(0, n);\n        v = str.substr(n + 1);\n    }\n    return std::make_pair(trim_(k), trim_(v));\n}\n\n// return vector of key/value pairs from sequence of \"K1=V1,K2=V2,..\"\n// \"a=AAA,b=BBB,c=CCC,..\" => {(\"a\",\"AAA\"),(\"b\",\"BBB\"),(\"c\", \"CCC\"),...}\ninline std::unordered_map<std::string, std::string> extract_key_vals_(const std::string &str)\n{\n    std::string token;\n    std::istringstream token_stream(str);\n    std::unordered_map<std::string, std::string> rv{};\n    while (std::getline(token_stream, token, ','))\n    {\n        if (token.empty())\n        {\n            continue;\n        }\n        auto kv = extract_kv_('=', token);\n        rv[kv.first] = kv.second;\n    }\n    return rv;\n}\n\nSPDLOG_INLINE void load_levels(const std::string &input)\n{\n    if (input.empty() || input.size() > 512)\n    {\n        return;\n    }\n\n    auto key_vals = extract_key_vals_(input);\n    std::unordered_map<std::string, level::level_enum> levels;\n    level::level_enum global_level = level::info;\n    bool global_level_found = false;\n\n    for (auto &name_level : key_vals)\n    {\n        auto &logger_name = name_level.first;\n        auto level_name = to_lower_(name_level.second);\n        auto level = level::from_str(level_name);\n        // ignore unrecognized level names\n        if (level == level::off && level_name != \"off\")\n        {\n            continue;\n        }\n        if (logger_name.empty()) // no logger name indicate global level\n        {\n            global_level_found = true;\n            global_level = level;\n        }\n        else\n        {\n            levels[logger_name] = level;\n        }\n    }\n\n    details::registry::instance().set_levels(std::move(levels), global_level_found ? &global_level : nullptr);\n}\n\n} // namespace helpers\n} // namespace cfg\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/cfg/helpers.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/common.h>\n#include <unordered_map>\n\nnamespace spdlog {\nnamespace cfg {\nnamespace helpers {\n//\n// Init levels from given string\n//\n// Examples:\n//\n// set global level to debug: \"debug\"\n// turn off all logging except for logger1: \"off,logger1=debug\"\n// turn off all logging except for logger1 and logger2: \"off,logger1=debug,logger2=info\"\n//\nSPDLOG_API void load_levels(const std::string &txt);\n} // namespace helpers\n\n} // namespace cfg\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"helpers-inl.h\"\n#endif // SPDLOG_HEADER_ONLY\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/cfg/log_levels.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/common.h>\n#include <string>\n#include <unordered_map>\n\nnamespace spdlog {\nnamespace cfg {\nclass log_levels\n{\n    std::unordered_map<std::string, spdlog::level::level_enum> levels_;\n    spdlog::level::level_enum default_level_ = level::info;\n\npublic:\n    void set(const std::string &logger_name, level::level_enum lvl)\n    {\n        if (logger_name.empty())\n        {\n            default_level_ = lvl;\n        }\n        else\n        {\n            levels_[logger_name] = lvl;\n        }\n    }\n\n    void set_default(level::level_enum lvl)\n    {\n        default_level_ = lvl;\n    }\n\n    level::level_enum get(const std::string &logger_name)\n    {\n        auto it = levels_.find(logger_name);\n        return it != levels_.end() ? it->second : default_level_;\n    }\n\n    level::level_enum default_level()\n    {\n        return default_level_;\n    }\n};\n} // namespace cfg\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/common-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/common.h>\n#endif\n\n#include <algorithm>\n#include <iterator>\n\nnamespace spdlog {\nnamespace level {\n\n#if __cplusplus >= 201703L\nconstexpr\n#endif\n    static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES;\n\nstatic const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES;\n\nSPDLOG_INLINE const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT\n{\n    return level_string_views[l];\n}\n\nSPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT\n{\n    return short_level_names[l];\n}\n\nSPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT\n{\n    auto it = std::find(std::begin(level_string_views), std::end(level_string_views), name);\n    if (it != std::end(level_string_views))\n        return static_cast<level::level_enum>(it - std::begin(level_string_views));\n\n    // check also for \"warn\" and \"err\" before giving up..\n    if (name == \"warn\")\n    {\n        return level::warn;\n    }\n    if (name == \"err\")\n    {\n        return level::err;\n    }\n    return level::off;\n}\n} // namespace level\n\nSPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg)\n    : msg_(std::move(msg))\n{}\n\nSPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno)\n{\n#ifdef SPDLOG_USE_STD_FORMAT\n    msg_ = std::system_error(std::error_code(last_errno, std::generic_category()), msg).what();\n#else\n    memory_buf_t outbuf;\n    fmt::format_system_error(outbuf, last_errno, msg.c_str());\n    msg_ = fmt::to_string(outbuf);\n#endif\n}\n\nSPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT\n{\n    return msg_.c_str();\n}\n\nSPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno)\n{\n    SPDLOG_THROW(spdlog_ex(msg, last_errno));\n}\n\nSPDLOG_INLINE void throw_spdlog_ex(std::string msg)\n{\n    SPDLOG_THROW(spdlog_ex(std::move(msg)));\n}\n\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/common.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#pragma warning(disable:4275)\n#endif\n\n#include <spdlog/tweakme.h>\n#include <spdlog/details/null_mutex.h>\n\n#include <atomic>\n#include <chrono>\n#include <initializer_list>\n#include <memory>\n#include <exception>\n#include <string>\n#include <type_traits>\n#include <functional>\n#include <cstdio>\n\n#ifdef SPDLOG_USE_STD_FORMAT\n#    include <string_view>\n#endif\n\n#ifdef SPDLOG_COMPILED_LIB\n#    undef SPDLOG_HEADER_ONLY\n#    if defined(SPDLOG_SHARED_LIB)\n#        if defined(_WIN32)\n#            ifdef spdlog_EXPORTS\n#                define SPDLOG_API __declspec(dllexport)\n#            else // !spdlog_EXPORTS\n#                define SPDLOG_API __declspec(dllimport)\n#            endif\n#        else // !defined(_WIN32)\n#            define SPDLOG_API __attribute__((visibility(\"default\")))\n#        endif\n#    else // !defined(SPDLOG_SHARED_LIB)\n#        define SPDLOG_API\n#    endif\n#    define SPDLOG_INLINE\n#else // !defined(SPDLOG_COMPILED_LIB)\n#    define SPDLOG_API\n#    define SPDLOG_HEADER_ONLY\n#    define SPDLOG_INLINE inline\n#endif // #ifdef SPDLOG_COMPILED_LIB\n\n#include <spdlog/fmt/fmt.h>\n\n#if !defined(SPDLOG_USE_STD_FORMAT) && FMT_VERSION >= 80000 // backward compatibility with fmt versions older than 8\n#    define SPDLOG_FMT_RUNTIME(format_string) fmt::runtime(format_string)\n#    if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)\n#        include <spdlog/fmt/xchar.h>\n#    endif\n#else\n#    define SPDLOG_FMT_RUNTIME(format_string) format_string\n#endif\n\n// visual studio up to 2013 does not support noexcept nor constexpr\n#if defined(_MSC_VER) && (_MSC_VER < 1900)\n#    define SPDLOG_NOEXCEPT _NOEXCEPT\n#    define SPDLOG_CONSTEXPR\n#    define SPDLOG_CONSTEXPR_FUNC\n#else\n#    define SPDLOG_NOEXCEPT noexcept\n#    define SPDLOG_CONSTEXPR constexpr\n#    if __cplusplus >= 201402L\n#        define SPDLOG_CONSTEXPR_FUNC constexpr\n#    else\n#        define SPDLOG_CONSTEXPR_FUNC\n#    endif\n#endif\n\n#if defined(__GNUC__) || defined(__clang__)\n#    define SPDLOG_DEPRECATED __attribute__((deprecated))\n#elif defined(_MSC_VER)\n#    define SPDLOG_DEPRECATED __declspec(deprecated)\n#else\n#    define SPDLOG_DEPRECATED\n#endif\n\n// disable thread local on msvc 2013\n#ifndef SPDLOG_NO_TLS\n#    if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt)\n#        define SPDLOG_NO_TLS 1\n#    endif\n#endif\n\n#ifndef SPDLOG_FUNCTION\n#    define SPDLOG_FUNCTION static_cast<const char *>(__FUNCTION__)\n#endif\n\n#ifdef SPDLOG_NO_EXCEPTIONS\n#    define SPDLOG_TRY\n#    define SPDLOG_THROW(ex)                                                                                                               \\\n        do                                                                                                                                 \\\n        {                                                                                                                                  \\\n            printf(\"spdlog fatal error: %s\\n\", ex.what());                                                                                 \\\n            std::abort();                                                                                                                  \\\n        } while (0)\n#    define SPDLOG_CATCH_STD\n#else\n#    define SPDLOG_TRY try\n#    define SPDLOG_THROW(ex) throw(ex)\n#    define SPDLOG_CATCH_STD                                                                                                               \\\n        catch (const std::exception &) {}\n#endif\n\nnamespace spdlog {\n\nclass formatter;\n\nnamespace sinks {\nclass sink;\n}\n\n#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)\nusing filename_t = std::wstring;\n// allow macro expansion to occur in SPDLOG_FILENAME_T\n#    define SPDLOG_FILENAME_T_INNER(s) L##s\n#    define SPDLOG_FILENAME_T(s) SPDLOG_FILENAME_T_INNER(s)\n#else\nusing filename_t = std::string;\n#    define SPDLOG_FILENAME_T(s) s\n#endif\n\nusing log_clock = std::chrono::system_clock;\nusing sink_ptr = std::shared_ptr<sinks::sink>;\nusing sinks_init_list = std::initializer_list<sink_ptr>;\nusing err_handler = std::function<void(const std::string &err_msg)>;\n#ifdef SPDLOG_USE_STD_FORMAT\nnamespace fmt_lib = std;\n\nusing string_view_t = std::string_view;\nusing memory_buf_t = std::string;\n\ntemplate<typename... Args>\nusing format_string_t = std::string_view;\n\ntemplate<class T, class Char = char>\nstruct is_convertible_to_basic_format_string : std::integral_constant<bool, std::is_convertible<T, std::basic_string_view<Char>>::value>\n{};\n\n#    if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)\nusing wstring_view_t = std::wstring_view;\nusing wmemory_buf_t = std::wstring;\n\ntemplate<typename... Args>\nusing wformat_string_t = std::wstring_view;\n#    endif\n#    define SPDLOG_BUF_TO_STRING(x) x\n#else // use fmt lib instead of std::format\nnamespace fmt_lib = fmt;\n\nusing string_view_t = fmt::basic_string_view<char>;\nusing memory_buf_t = fmt::basic_memory_buffer<char, 250>;\n\ntemplate<typename... Args>\nusing format_string_t = fmt::format_string<Args...>;\n\ntemplate<class T>\nusing remove_cvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;\n\n// clang doesn't like SFINAE disabled constructor in std::is_convertible<> so have to repeat the condition from basic_format_string here,\n// in addition, fmt::basic_runtime<Char> is only convertible to basic_format_string<Char> but not basic_string_view<Char>\ntemplate<class T, class Char = char>\nstruct is_convertible_to_basic_format_string\n    : std::integral_constant<bool,\n          std::is_convertible<T, fmt::basic_string_view<Char>>::value || std::is_same<remove_cvref_t<T>, fmt::basic_runtime<Char>>::value>\n{};\n\n#    if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)\nusing wstring_view_t = fmt::basic_string_view<wchar_t>;\nusing wmemory_buf_t = fmt::basic_memory_buffer<wchar_t, 250>;\n\ntemplate<typename... Args>\nusing wformat_string_t = fmt::wformat_string<Args...>;\n#    endif\n#    define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x)\n#endif\n\n#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT\n#    ifndef _WIN32\n#        error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows\n#    endif // _WIN32\n#endif     // SPDLOG_WCHAR_TO_UTF8_SUPPORT\n\ntemplate<class T>\nstruct is_convertible_to_any_format_string : std::integral_constant<bool, is_convertible_to_basic_format_string<T, char>::value ||\n                                                                              is_convertible_to_basic_format_string<T, wchar_t>::value>\n{};\n\n#if defined(SPDLOG_NO_ATOMIC_LEVELS)\nusing level_t = details::null_atomic_int;\n#else\nusing level_t = std::atomic<int>;\n#endif\n\n#define SPDLOG_LEVEL_TRACE 0\n#define SPDLOG_LEVEL_DEBUG 1\n#define SPDLOG_LEVEL_INFO 2\n#define SPDLOG_LEVEL_WARN 3\n#define SPDLOG_LEVEL_ERROR 4\n#define SPDLOG_LEVEL_CRITICAL 5\n#define SPDLOG_LEVEL_OFF 6\n\n#if !defined(SPDLOG_ACTIVE_LEVEL)\n#    define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO\n#endif\n\n// Log level enum\nnamespace level {\nenum level_enum : int\n{\n    trace = SPDLOG_LEVEL_TRACE,\n    debug = SPDLOG_LEVEL_DEBUG,\n    info = SPDLOG_LEVEL_INFO,\n    warn = SPDLOG_LEVEL_WARN,\n    err = SPDLOG_LEVEL_ERROR,\n    critical = SPDLOG_LEVEL_CRITICAL,\n    off = SPDLOG_LEVEL_OFF,\n    n_levels\n};\n\n#define SPDLOG_LEVEL_NAME_TRACE spdlog::string_view_t(\"trace\", 5)\n#define SPDLOG_LEVEL_NAME_DEBUG spdlog::string_view_t(\"debug\", 5)\n#define SPDLOG_LEVEL_NAME_INFO spdlog::string_view_t(\"info\", 4)\n#define SPDLOG_LEVEL_NAME_WARNING spdlog::string_view_t(\"warning\", 7)\n#define SPDLOG_LEVEL_NAME_ERROR spdlog::string_view_t(\"error\", 5)\n#define SPDLOG_LEVEL_NAME_CRITICAL spdlog::string_view_t(\"critical\", 8)\n#define SPDLOG_LEVEL_NAME_OFF spdlog::string_view_t(\"off\", 3)\n\n#if !defined(SPDLOG_LEVEL_NAMES)\n#    define SPDLOG_LEVEL_NAMES                                                                                                             \\\n        {                                                                                                                                  \\\n            SPDLOG_LEVEL_NAME_TRACE, SPDLOG_LEVEL_NAME_DEBUG, SPDLOG_LEVEL_NAME_INFO, SPDLOG_LEVEL_NAME_WARNING, SPDLOG_LEVEL_NAME_ERROR,  \\\n                SPDLOG_LEVEL_NAME_CRITICAL, SPDLOG_LEVEL_NAME_OFF                                                                          \\\n        }\n#endif\n\n#if !defined(SPDLOG_SHORT_LEVEL_NAMES)\n\n#    define SPDLOG_SHORT_LEVEL_NAMES                                                                                                       \\\n        {                                                                                                                                  \\\n            \"T\", \"D\", \"I\", \"W\", \"E\", \"C\", \"O\"                                                                                              \\\n        }\n#endif\n\nSPDLOG_API const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;\nSPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;\nSPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT;\n\n} // namespace level\n\n//\n// Color mode used by sinks with color support.\n//\nenum class color_mode\n{\n    always,\n    automatic,\n    never\n};\n\n//\n// Pattern time - specific time getting to use for pattern_formatter.\n// local time by default\n//\nenum class pattern_time_type\n{\n    local, // log localtime\n    utc    // log utc\n};\n\n//\n// Log exception\n//\nclass SPDLOG_API spdlog_ex : public std::exception\n{\npublic:\n    explicit spdlog_ex(std::string msg);\n    spdlog_ex(const std::string &msg, int last_errno);\n    const char *what() const SPDLOG_NOEXCEPT override;\n\nprivate:\n    std::string msg_;\n};\n\n[[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno);\n[[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg);\n\nstruct source_loc\n{\n    SPDLOG_CONSTEXPR source_loc() = default;\n    SPDLOG_CONSTEXPR source_loc(const char *filename_in, int line_in, const char *funcname_in)\n        : filename{filename_in}\n        , line{line_in}\n        , funcname{funcname_in}\n    {}\n\n    SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT\n    {\n        return line == 0;\n    }\n    const char *filename{nullptr};\n    int line{0};\n    const char *funcname{nullptr};\n};\n\nstruct file_event_handlers\n{\n    std::function<void(const filename_t &filename)> before_open;\n    std::function<void(const filename_t &filename, std::FILE *file_stream)> after_open;\n    std::function<void(const filename_t &filename, std::FILE *file_stream)> before_close;\n    std::function<void(const filename_t &filename)> after_close;\n};\n\nnamespace details {\n\n// make_unique support for pre c++14\n\n#if __cplusplus >= 201402L // C++14 and beyond\nusing std::enable_if_t;\nusing std::make_unique;\n#else\ntemplate<bool B, class T = void>\nusing enable_if_t = typename std::enable_if<B, T>::type;\n\ntemplate<typename T, typename... Args>\nstd::unique_ptr<T> make_unique(Args &&... args)\n{\n    static_assert(!std::is_array<T>::value, \"arrays not supported\");\n    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));\n}\n#endif\n\n// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)\ntemplate<typename T, typename U, enable_if_t<!std::is_same<T, U>::value, int> = 0>\nconstexpr T conditional_static_cast(U value)\n{\n    return static_cast<T>(value);\n}\n\ntemplate<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>\nconstexpr T conditional_static_cast(U value)\n{\n    return value;\n}\n\n} // namespace details\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"common-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/backtracer-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/details/backtracer.h>\n#endif\nnamespace spdlog {\nnamespace details {\nSPDLOG_INLINE backtracer::backtracer(const backtracer &other)\n{\n    std::lock_guard<std::mutex> lock(other.mutex_);\n    enabled_ = other.enabled();\n    messages_ = other.messages_;\n}\n\nSPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT\n{\n    std::lock_guard<std::mutex> lock(other.mutex_);\n    enabled_ = other.enabled();\n    messages_ = std::move(other.messages_);\n}\n\nSPDLOG_INLINE backtracer &backtracer::operator=(backtracer other)\n{\n    std::lock_guard<std::mutex> lock(mutex_);\n    enabled_ = other.enabled();\n    messages_ = std::move(other.messages_);\n    return *this;\n}\n\nSPDLOG_INLINE void backtracer::enable(size_t size)\n{\n    std::lock_guard<std::mutex> lock{mutex_};\n    enabled_.store(true, std::memory_order_relaxed);\n    messages_ = circular_q<log_msg_buffer>{size};\n}\n\nSPDLOG_INLINE void backtracer::disable()\n{\n    std::lock_guard<std::mutex> lock{mutex_};\n    enabled_.store(false, std::memory_order_relaxed);\n}\n\nSPDLOG_INLINE bool backtracer::enabled() const\n{\n    return enabled_.load(std::memory_order_relaxed);\n}\n\nSPDLOG_INLINE void backtracer::push_back(const log_msg &msg)\n{\n    std::lock_guard<std::mutex> lock{mutex_};\n    messages_.push_back(log_msg_buffer{msg});\n}\n\n// pop all items in the q and apply the given fun on each of them.\nSPDLOG_INLINE void backtracer::foreach_pop(std::function<void(const details::log_msg &)> fun)\n{\n    std::lock_guard<std::mutex> lock{mutex_};\n    while (!messages_.empty())\n    {\n        auto &front_msg = messages_.front();\n        fun(front_msg);\n        messages_.pop_front();\n    }\n}\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/backtracer.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/details/log_msg_buffer.h>\n#include <spdlog/details/circular_q.h>\n\n#include <atomic>\n#include <mutex>\n#include <functional>\n\n// Store log messages in circular buffer.\n// Useful for storing debug data in case of error/warning happens.\n\nnamespace spdlog {\nnamespace details {\nclass SPDLOG_API backtracer\n{\n    mutable std::mutex mutex_;\n    std::atomic<bool> enabled_{false};\n    circular_q<log_msg_buffer> messages_;\n\npublic:\n    backtracer() = default;\n    backtracer(const backtracer &other);\n\n    backtracer(backtracer &&other) SPDLOG_NOEXCEPT;\n    backtracer &operator=(backtracer other);\n\n    void enable(size_t size);\n    void disable();\n    bool enabled() const;\n    void push_back(const log_msg &msg);\n\n    // pop all items in the q and apply the given fun on each of them.\n    void foreach_pop(std::function<void(const details::log_msg &)> fun);\n};\n\n} // namespace details\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"backtracer-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/circular_q.h",
    "content": "﻿// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n// circular q view of std::vector.\n#pragma once\n\n#include <vector>\n#include <cassert>\n\nnamespace spdlog {\nnamespace details {\ntemplate<typename T>\nclass circular_q\n{\n    size_t max_items_ = 0;\n    typename std::vector<T>::size_type head_ = 0;\n    typename std::vector<T>::size_type tail_ = 0;\n    size_t overrun_counter_ = 0;\n    std::vector<T> v_;\n\npublic:\n    using value_type = T;\n\n    // empty ctor - create a disabled queue with no elements allocated at all\n    circular_q() = default;\n\n    explicit circular_q(size_t max_items)\n        : max_items_(max_items + 1) // one item is reserved as marker for full q\n        , v_(max_items_)\n    {}\n\n    circular_q(const circular_q &) = default;\n    circular_q &operator=(const circular_q &) = default;\n\n    // move cannot be default,\n    // since we need to reset head_, tail_, etc to zero in the moved object\n    circular_q(circular_q &&other) SPDLOG_NOEXCEPT\n    {\n        copy_moveable(std::move(other));\n    }\n\n    circular_q &operator=(circular_q &&other) SPDLOG_NOEXCEPT\n    {\n        copy_moveable(std::move(other));\n        return *this;\n    }\n\n    // push back, overrun (oldest) item if no room left\n    void push_back(T &&item)\n    {\n        if (max_items_ > 0)\n        {\n            v_[tail_] = std::move(item);\n            tail_ = (tail_ + 1) % max_items_;\n\n            if (tail_ == head_) // overrun last item if full\n            {\n                head_ = (head_ + 1) % max_items_;\n                ++overrun_counter_;\n            }\n        }\n    }\n\n    // Return reference to the front item.\n    // If there are no elements in the container, the behavior is undefined.\n    const T &front() const\n    {\n        return v_[head_];\n    }\n\n    T &front()\n    {\n        return v_[head_];\n    }\n\n    // Return number of elements actually stored\n    size_t size() const\n    {\n        if (tail_ >= head_)\n        {\n            return tail_ - head_;\n        }\n        else\n        {\n            return max_items_ - (head_ - tail_);\n        }\n    }\n\n    // Return const reference to item by index.\n    // If index is out of range 0…size()-1, the behavior is undefined.\n    const T &at(size_t i) const\n    {\n        assert(i < size());\n        return v_[(head_ + i) % max_items_];\n    }\n\n    // Pop item from front.\n    // If there are no elements in the container, the behavior is undefined.\n    void pop_front()\n    {\n        head_ = (head_ + 1) % max_items_;\n    }\n\n    bool empty() const\n    {\n        return tail_ == head_;\n    }\n\n    bool full() const\n    {\n        // head is ahead of the tail by 1\n        if (max_items_ > 0)\n        {\n            return ((tail_ + 1) % max_items_) == head_;\n        }\n        return false;\n    }\n\n    size_t overrun_counter() const\n    {\n        return overrun_counter_;\n    }\n\nprivate:\n    // copy from other&& and reset it to disabled state\n    void copy_moveable(circular_q &&other) SPDLOG_NOEXCEPT\n    {\n        max_items_ = other.max_items_;\n        head_ = other.head_;\n        tail_ = other.tail_;\n        overrun_counter_ = other.overrun_counter_;\n        v_ = std::move(other.v_);\n\n        // put &&other in disabled, but valid state\n        other.max_items_ = 0;\n        other.head_ = other.tail_ = 0;\n        other.overrun_counter_ = 0;\n    }\n};\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/console_globals.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/details/null_mutex.h>\n#include <mutex>\n\nnamespace spdlog {\nnamespace details {\n\nstruct console_mutex\n{\n    using mutex_t = std::mutex;\n    static mutex_t &mutex()\n    {\n        static mutex_t s_mutex;\n        return s_mutex;\n    }\n};\n\nstruct console_nullmutex\n{\n    using mutex_t = null_mutex;\n    static mutex_t &mutex()\n    {\n        static mutex_t s_mutex;\n        return s_mutex;\n    }\n};\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/file_helper-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/details/file_helper.h>\n#endif\n\n#include <spdlog/details/os.h>\n#include <spdlog/common.h>\n\n#include <cerrno>\n#include <chrono>\n#include <cstdio>\n#include <string>\n#include <thread>\n#include <tuple>\n\nnamespace spdlog {\nnamespace details {\n\nSPDLOG_INLINE file_helper::file_helper(const file_event_handlers &event_handlers)\n    : event_handlers_(event_handlers)\n{}\n\nSPDLOG_INLINE file_helper::~file_helper()\n{\n    close();\n}\n\nSPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate)\n{\n    close();\n    filename_ = fname;\n\n    auto *mode = SPDLOG_FILENAME_T(\"ab\");\n    auto *trunc_mode = SPDLOG_FILENAME_T(\"wb\");\n\n    if (event_handlers_.before_open)\n    {\n        event_handlers_.before_open(filename_);\n    }\n    for (int tries = 0; tries < open_tries_; ++tries)\n    {\n        // create containing folder if not exists already.\n        os::create_dir(os::dir_name(fname));\n        if (truncate)\n        {\n            // Truncate by opening-and-closing a tmp file in \"wb\" mode, always\n            // opening the actual log-we-write-to in \"ab\" mode, since that\n            // interacts more politely with eternal processes that might\n            // rotate/truncate the file underneath us.\n            std::FILE *tmp;\n            if (os::fopen_s(&tmp, fname, trunc_mode))\n            {\n                continue;\n            }\n            std::fclose(tmp);\n        }\n        if (!os::fopen_s(&fd_, fname, mode))\n        {\n            if (event_handlers_.after_open)\n            {\n                event_handlers_.after_open(filename_, fd_);\n            }\n            return;\n        }\n\n        details::os::sleep_for_millis(open_interval_);\n    }\n\n    throw_spdlog_ex(\"Failed opening file \" + os::filename_to_str(filename_) + \" for writing\", errno);\n}\n\nSPDLOG_INLINE void file_helper::reopen(bool truncate)\n{\n    if (filename_.empty())\n    {\n        throw_spdlog_ex(\"Failed re opening file - was not opened before\");\n    }\n    this->open(filename_, truncate);\n}\n\nSPDLOG_INLINE void file_helper::flush()\n{\n    if (std::fflush(fd_) != 0)\n    {\n        throw_spdlog_ex(\"Failed flush to file \" + os::filename_to_str(filename_), errno);\n    }\n}\n\nSPDLOG_INLINE void file_helper::close()\n{\n    if (fd_ != nullptr)\n    {\n        if (event_handlers_.before_close)\n        {\n            event_handlers_.before_close(filename_, fd_);\n        }\n\n        std::fclose(fd_);\n        fd_ = nullptr;\n\n        if (event_handlers_.after_close)\n        {\n            event_handlers_.after_close(filename_);\n        }\n    }\n}\n\nSPDLOG_INLINE void file_helper::write(const memory_buf_t &buf)\n{\n    size_t msg_size = buf.size();\n    auto data = buf.data();\n    if (std::fwrite(data, 1, msg_size, fd_) != msg_size)\n    {\n        throw_spdlog_ex(\"Failed writing to file \" + os::filename_to_str(filename_), errno);\n    }\n}\n\nSPDLOG_INLINE size_t file_helper::size() const\n{\n    if (fd_ == nullptr)\n    {\n        throw_spdlog_ex(\"Cannot use size() on closed file \" + os::filename_to_str(filename_));\n    }\n    return os::filesize(fd_);\n}\n\nSPDLOG_INLINE const filename_t &file_helper::filename() const\n{\n    return filename_;\n}\n\n//\n// return file path and its extension:\n//\n// \"mylog.txt\" => (\"mylog\", \".txt\")\n// \"mylog\" => (\"mylog\", \"\")\n// \"mylog.\" => (\"mylog.\", \"\")\n// \"/dir1/dir2/mylog.txt\" => (\"/dir1/dir2/mylog\", \".txt\")\n//\n// the starting dot in filenames is ignored (hidden files):\n//\n// \".mylog\" => (\".mylog\". \"\")\n// \"my_folder/.mylog\" => (\"my_folder/.mylog\", \"\")\n// \"my_folder/.mylog.txt\" => (\"my_folder/.mylog\", \".txt\")\nSPDLOG_INLINE std::tuple<filename_t, filename_t> file_helper::split_by_extension(const filename_t &fname)\n{\n    auto ext_index = fname.rfind('.');\n\n    // no valid extension found - return whole path and empty string as\n    // extension\n    if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1)\n    {\n        return std::make_tuple(fname, filename_t());\n    }\n\n    // treat cases like \"/etc/rc.d/somelogfile or \"/abc/.hiddenfile\"\n    auto folder_index = fname.find_last_of(details::os::folder_seps_filename);\n    if (folder_index != filename_t::npos && folder_index >= ext_index - 1)\n    {\n        return std::make_tuple(fname, filename_t());\n    }\n\n    // finally - return a valid base and extension tuple\n    return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));\n}\n\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/file_helper.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/common.h>\n#include <tuple>\n\nnamespace spdlog {\nnamespace details {\n\n// Helper class for file sinks.\n// When failing to open a file, retry several times(5) with a delay interval(10 ms).\n// Throw spdlog_ex exception on errors.\n\nclass SPDLOG_API file_helper\n{\npublic:\n    file_helper() = default;\n    explicit file_helper(const file_event_handlers &event_handlers);\n\n    file_helper(const file_helper &) = delete;\n    file_helper &operator=(const file_helper &) = delete;\n    ~file_helper();\n\n    void open(const filename_t &fname, bool truncate = false);\n    void reopen(bool truncate);\n    void flush();\n    void close();\n    void write(const memory_buf_t &buf);\n    size_t size() const;\n    const filename_t &filename() const;\n\n    //\n    // return file path and its extension:\n    //\n    // \"mylog.txt\" => (\"mylog\", \".txt\")\n    // \"mylog\" => (\"mylog\", \"\")\n    // \"mylog.\" => (\"mylog.\", \"\")\n    // \"/dir1/dir2/mylog.txt\" => (\"/dir1/dir2/mylog\", \".txt\")\n    //\n    // the starting dot in filenames is ignored (hidden files):\n    //\n    // \".mylog\" => (\".mylog\". \"\")\n    // \"my_folder/.mylog\" => (\"my_folder/.mylog\", \"\")\n    // \"my_folder/.mylog.txt\" => (\"my_folder/.mylog\", \".txt\")\n    static std::tuple<filename_t, filename_t> split_by_extension(const filename_t &fname);\n\nprivate:\n    const int open_tries_ = 5;\n    const unsigned int open_interval_ = 10;\n    std::FILE *fd_{nullptr};\n    filename_t filename_;\n    file_event_handlers event_handlers_;\n};\n} // namespace details\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"file_helper-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/fmt_helper.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n#pragma once\n\n#include <chrono>\n#include <type_traits>\n#include <iterator>\n#include <spdlog/fmt/fmt.h>\n#include <spdlog/common.h>\n\n#ifdef SPDLOG_USE_STD_FORMAT\n#    include <charconv>\n#    include <limits>\n#endif\n\n// Some fmt helpers to efficiently format and pad ints and strings\nnamespace spdlog {\nnamespace details {\nnamespace fmt_helper {\n\ninline spdlog::string_view_t to_string_view(const memory_buf_t &buf) SPDLOG_NOEXCEPT\n{\n    return spdlog::string_view_t{buf.data(), buf.size()};\n}\n\ninline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest)\n{\n    auto *buf_ptr = view.data();\n    dest.append(buf_ptr, buf_ptr + view.size());\n}\n\n#ifdef SPDLOG_USE_STD_FORMAT\ntemplate<typename T>\ninline void append_int(T n, memory_buf_t &dest)\n{\n    // Buffer should be large enough to hold all digits (digits10 + 1) and a sign\n    SPDLOG_CONSTEXPR const auto BUF_SIZE = std::numeric_limits<T>::digits10 + 2;\n    char buf[BUF_SIZE];\n\n    auto [ptr, ec] = std::to_chars(buf, buf + BUF_SIZE, n, 10);\n    if (ec == std::errc())\n    {\n        dest.append(buf, ptr);\n    }\n    else\n    {\n        throw_spdlog_ex(\"Failed to format int\", static_cast<int>(ec));\n    }\n}\n#else\ntemplate<typename T>\ninline void append_int(T n, memory_buf_t &dest)\n{\n    fmt::format_int i(n);\n    dest.append(i.data(), i.data() + i.size());\n}\n#endif\n\ntemplate<typename T>\nSPDLOG_CONSTEXPR_FUNC unsigned int count_digits_fallback(T n)\n{\n    // taken from fmt: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/format.h#L899-L912\n    unsigned int count = 1;\n    for (;;)\n    {\n        // Integer division is slow so do it for a group of four digits instead\n        // of for every digit. The idea comes from the talk by Alexandrescu\n        // \"Three Optimization Tips for C++\". See speed-test for a comparison.\n        if (n < 10)\n            return count;\n        if (n < 100)\n            return count + 1;\n        if (n < 1000)\n            return count + 2;\n        if (n < 10000)\n            return count + 3;\n        n /= 10000u;\n        count += 4;\n    }\n}\n\ntemplate<typename T>\ninline unsigned int count_digits(T n)\n{\n    using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type;\n#ifdef SPDLOG_USE_STD_FORMAT\n    return count_digits_fallback(static_cast<count_type>(n));\n#else\n    return static_cast<unsigned int>(fmt::\n// fmt 7.0.0 renamed the internal namespace to detail.\n// See: https://github.com/fmtlib/fmt/issues/1538\n#    if FMT_VERSION < 70000\n            internal\n#    else\n            detail\n#    endif\n        ::count_digits(static_cast<count_type>(n)));\n#endif\n}\n\ninline void pad2(int n, memory_buf_t &dest)\n{\n    if (n >= 0 && n < 100) // 0-99\n    {\n        dest.push_back(static_cast<char>('0' + n / 10));\n        dest.push_back(static_cast<char>('0' + n % 10));\n    }\n    else // unlikely, but just in case, let fmt deal with it\n    {\n        fmt_lib::format_to(std::back_inserter(dest), \"{:02}\", n);\n    }\n}\n\ntemplate<typename T>\ninline void pad_uint(T n, unsigned int width, memory_buf_t &dest)\n{\n    static_assert(std::is_unsigned<T>::value, \"pad_uint must get unsigned T\");\n    for (auto digits = count_digits(n); digits < width; digits++)\n    {\n        dest.push_back('0');\n    }\n    append_int(n, dest);\n}\n\ntemplate<typename T>\ninline void pad3(T n, memory_buf_t &dest)\n{\n    static_assert(std::is_unsigned<T>::value, \"pad3 must get unsigned T\");\n    if (n < 1000)\n    {\n        dest.push_back(static_cast<char>(n / 100 + '0'));\n        n = n % 100;\n        dest.push_back(static_cast<char>((n / 10) + '0'));\n        dest.push_back(static_cast<char>((n % 10) + '0'));\n    }\n    else\n    {\n        append_int(n, dest);\n    }\n}\n\ntemplate<typename T>\ninline void pad6(T n, memory_buf_t &dest)\n{\n    pad_uint(n, 6, dest);\n}\n\ntemplate<typename T>\ninline void pad9(T n, memory_buf_t &dest)\n{\n    pad_uint(n, 9, dest);\n}\n\n// return fraction of a second of the given time_point.\n// e.g.\n// fraction<std::milliseconds>(tp) -> will return the millis part of the second\ntemplate<typename ToDuration>\ninline ToDuration time_fraction(log_clock::time_point tp)\n{\n    using std::chrono::duration_cast;\n    using std::chrono::seconds;\n    auto duration = tp.time_since_epoch();\n    auto secs = duration_cast<seconds>(duration);\n    return duration_cast<ToDuration>(duration) - duration_cast<ToDuration>(secs);\n}\n\n} // namespace fmt_helper\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/log_msg-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/details/log_msg.h>\n#endif\n\n#include <spdlog/details/os.h>\n\nnamespace spdlog {\nnamespace details {\n\nSPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time, spdlog::source_loc loc, string_view_t a_logger_name,\n    spdlog::level::level_enum lvl, spdlog::string_view_t msg)\n    : logger_name(a_logger_name)\n    , level(lvl)\n    , time(log_time)\n#ifndef SPDLOG_NO_THREAD_ID\n    , thread_id(os::thread_id())\n#endif\n    , source(loc)\n    , payload(msg)\n{}\n\nSPDLOG_INLINE log_msg::log_msg(\n    spdlog::source_loc loc, string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg)\n    : log_msg(os::now(), loc, a_logger_name, lvl, msg)\n{}\n\nSPDLOG_INLINE log_msg::log_msg(string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg)\n    : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg)\n{}\n\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/log_msg.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/common.h>\n#include <string>\n\nnamespace spdlog {\nnamespace details {\nstruct SPDLOG_API log_msg\n{\n    log_msg() = default;\n    log_msg(log_clock::time_point log_time, source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg);\n    log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg);\n    log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg);\n    log_msg(const log_msg &other) = default;\n    log_msg &operator=(const log_msg &other) = default;\n\n    string_view_t logger_name;\n    level::level_enum level{level::off};\n    log_clock::time_point time;\n    size_t thread_id{0};\n\n    // wrapping the formatted text with color (updated by pattern_formatter).\n    mutable size_t color_range_start{0};\n    mutable size_t color_range_end{0};\n\n    source_loc source;\n    string_view_t payload;\n};\n} // namespace details\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"log_msg-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/log_msg_buffer-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/details/log_msg_buffer.h>\n#endif\n\nnamespace spdlog {\nnamespace details {\n\nSPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg &orig_msg)\n    : log_msg{orig_msg}\n{\n    buffer.append(logger_name.begin(), logger_name.end());\n    buffer.append(payload.begin(), payload.end());\n    update_string_views();\n}\n\nSPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other)\n    : log_msg{other}\n{\n    buffer.append(logger_name.begin(), logger_name.end());\n    buffer.append(payload.begin(), payload.end());\n    update_string_views();\n}\n\nSPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT : log_msg{other}, buffer{std::move(other.buffer)}\n{\n    update_string_views();\n}\n\nSPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other)\n{\n    log_msg::operator=(other);\n    buffer.clear();\n    buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size());\n    update_string_views();\n    return *this;\n}\n\nSPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT\n{\n    log_msg::operator=(other);\n    buffer = std::move(other.buffer);\n    update_string_views();\n    return *this;\n}\n\nSPDLOG_INLINE void log_msg_buffer::update_string_views()\n{\n    logger_name = string_view_t{buffer.data(), logger_name.size()};\n    payload = string_view_t{buffer.data() + logger_name.size(), payload.size()};\n}\n\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/log_msg_buffer.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/details/log_msg.h>\n\nnamespace spdlog {\nnamespace details {\n\n// Extend log_msg with internal buffer to store its payload.\n// This is needed since log_msg holds string_views that points to stack data.\n\nclass SPDLOG_API log_msg_buffer : public log_msg\n{\n    memory_buf_t buffer;\n    void update_string_views();\n\npublic:\n    log_msg_buffer() = default;\n    explicit log_msg_buffer(const log_msg &orig_msg);\n    log_msg_buffer(const log_msg_buffer &other);\n    log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT;\n    log_msg_buffer &operator=(const log_msg_buffer &other);\n    log_msg_buffer &operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT;\n};\n\n} // namespace details\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"log_msg_buffer-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/mpmc_blocking_q.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n// multi producer-multi consumer blocking queue.\n// enqueue(..) - will block until room found to put the new message.\n// enqueue_nowait(..) - will return immediately with false if no room left in\n// the queue.\n// dequeue_for(..) - will block until the queue is not empty or timeout have\n// passed.\n\n#include <spdlog/details/circular_q.h>\n\n#include <condition_variable>\n#include <mutex>\n\nnamespace spdlog {\nnamespace details {\n\ntemplate<typename T>\nclass mpmc_blocking_queue\n{\npublic:\n    using item_type = T;\n    explicit mpmc_blocking_queue(size_t max_items)\n        : q_(max_items)\n    {}\n\n#ifndef __MINGW32__\n    // try to enqueue and block if no room left\n    void enqueue(T &&item)\n    {\n        {\n            std::unique_lock<std::mutex> lock(queue_mutex_);\n            pop_cv_.wait(lock, [this] { return !this->q_.full(); });\n            q_.push_back(std::move(item));\n        }\n        push_cv_.notify_one();\n    }\n\n    // enqueue immediately. overrun oldest message in the queue if no room left.\n    void enqueue_nowait(T &&item)\n    {\n        {\n            std::unique_lock<std::mutex> lock(queue_mutex_);\n            q_.push_back(std::move(item));\n        }\n        push_cv_.notify_one();\n    }\n\n    // try to dequeue item. if no item found. wait up to timeout and try again\n    // Return true, if succeeded dequeue item, false otherwise\n    bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration)\n    {\n        {\n            std::unique_lock<std::mutex> lock(queue_mutex_);\n            if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); }))\n            {\n                return false;\n            }\n            popped_item = std::move(q_.front());\n            q_.pop_front();\n        }\n        pop_cv_.notify_one();\n        return true;\n    }\n\n#else\n    // apparently mingw deadlocks if the mutex is released before cv.notify_one(),\n    // so release the mutex at the very end each function.\n\n    // try to enqueue and block if no room left\n    void enqueue(T &&item)\n    {\n        std::unique_lock<std::mutex> lock(queue_mutex_);\n        pop_cv_.wait(lock, [this] { return !this->q_.full(); });\n        q_.push_back(std::move(item));\n        push_cv_.notify_one();\n    }\n\n    // enqueue immediately. overrun oldest message in the queue if no room left.\n    void enqueue_nowait(T &&item)\n    {\n        std::unique_lock<std::mutex> lock(queue_mutex_);\n        q_.push_back(std::move(item));\n        push_cv_.notify_one();\n    }\n\n    // try to dequeue item. if no item found. wait up to timeout and try again\n    // Return true, if succeeded dequeue item, false otherwise\n    bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration)\n    {\n        std::unique_lock<std::mutex> lock(queue_mutex_);\n        if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); }))\n        {\n            return false;\n        }\n        popped_item = std::move(q_.front());\n        q_.pop_front();\n        pop_cv_.notify_one();\n        return true;\n    }\n\n#endif\n\n    size_t overrun_counter()\n    {\n        std::unique_lock<std::mutex> lock(queue_mutex_);\n        return q_.overrun_counter();\n    }\n\n    size_t size()\n    {\n        std::unique_lock<std::mutex> lock(queue_mutex_);\n        return q_.size();\n    }\n\nprivate:\n    std::mutex queue_mutex_;\n    std::condition_variable push_cv_;\n    std::condition_variable pop_cv_;\n    spdlog::details::circular_q<T> q_;\n};\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/null_mutex.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <atomic>\n#include <utility>\n// null, no cost dummy \"mutex\" and dummy \"atomic\" int\n\nnamespace spdlog {\nnamespace details {\nstruct null_mutex\n{\n    void lock() const {}\n    void unlock() const {}\n    bool try_lock() const\n    {\n        return true;\n    }\n};\n\nstruct null_atomic_int\n{\n    int value;\n    null_atomic_int() = default;\n\n    explicit null_atomic_int(int new_value)\n        : value(new_value)\n    {}\n\n    int load(std::memory_order = std::memory_order_relaxed) const\n    {\n        return value;\n    }\n\n    void store(int new_value, std::memory_order = std::memory_order_relaxed)\n    {\n        value = new_value;\n    }\n\n    int exchange(int new_value, std::memory_order = std::memory_order_relaxed)\n    {\n        std::swap(new_value, value);\n        return new_value; // return value before the call\n    }\n};\n\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/os-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/details/os.h>\n#endif\n\n#include <spdlog/common.h>\n\n#include <algorithm>\n#include <chrono>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <ctime>\n#include <string>\n#include <thread>\n#include <array>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#ifdef _WIN32\n\n#    include <io.h>      // _get_osfhandle and _isatty support\n#    include <process.h> //  _get_pid support\n#    include <spdlog/details/windows_include.h>\n\n#    ifdef __MINGW32__\n#        include <share.h>\n#    endif\n\n#    if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)\n#        include <limits>\n#    endif\n\n#    include <direct.h> // for _mkdir/_wmkdir\n\n#else // unix\n\n#    include <fcntl.h>\n#    include <unistd.h>\n\n#    ifdef __linux__\n#        include <sys/syscall.h> //Use gettid() syscall under linux to get thread id\n\n#    elif defined(_AIX)\n#        include <pthread.h> // for pthread_getthrds_np\n\n#    elif defined(__DragonFly__) || defined(__FreeBSD__)\n#        include <pthread_np.h> // for pthread_getthreadid_np\n\n#    elif defined(__NetBSD__)\n#        include <lwp.h> // for _lwp_self\n\n#    elif defined(__sun)\n#        include <thread.h> // for thr_self\n#    endif\n\n#endif // unix\n\n#ifndef __has_feature          // Clang - feature checking macros.\n#    define __has_feature(x) 0 // Compatibility with non-clang compilers.\n#endif\n\nnamespace spdlog {\nnamespace details {\nnamespace os {\n\nSPDLOG_INLINE spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT\n{\n\n#if defined __linux__ && defined SPDLOG_CLOCK_COARSE\n    timespec ts;\n    ::clock_gettime(CLOCK_REALTIME_COARSE, &ts);\n    return std::chrono::time_point<log_clock, typename log_clock::duration>(\n        std::chrono::duration_cast<typename log_clock::duration>(std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec)));\n\n#else\n    return log_clock::now();\n#endif\n}\nSPDLOG_INLINE std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT\n{\n\n#ifdef _WIN32\n    std::tm tm;\n    ::localtime_s(&tm, &time_tt);\n#else\n    std::tm tm;\n    ::localtime_r(&time_tt, &tm);\n#endif\n    return tm;\n}\n\nSPDLOG_INLINE std::tm localtime() SPDLOG_NOEXCEPT\n{\n    std::time_t now_t = ::time(nullptr);\n    return localtime(now_t);\n}\n\nSPDLOG_INLINE std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT\n{\n\n#ifdef _WIN32\n    std::tm tm;\n    ::gmtime_s(&tm, &time_tt);\n#else\n    std::tm tm;\n    ::gmtime_r(&time_tt, &tm);\n#endif\n    return tm;\n}\n\nSPDLOG_INLINE std::tm gmtime() SPDLOG_NOEXCEPT\n{\n    std::time_t now_t = ::time(nullptr);\n    return gmtime(now_t);\n}\n\n// fopen_s on non windows for writing\nSPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode)\n{\n#ifdef _WIN32\n#    ifdef SPDLOG_WCHAR_FILENAMES\n    *fp = ::_wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);\n#    else\n    *fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);\n#    endif\n#    if defined(SPDLOG_PREVENT_CHILD_FD)\n    if (*fp != nullptr)\n    {\n        auto file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(::_fileno(*fp)));\n        if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))\n        {\n            ::fclose(*fp);\n            *fp = nullptr;\n        }\n    }\n#    endif\n#else // unix\n#    if defined(SPDLOG_PREVENT_CHILD_FD)\n    const int mode_flag = mode == SPDLOG_FILENAME_T(\"ab\") ? O_APPEND : O_TRUNC;\n    const int fd = ::open((filename.c_str()), O_CREAT | O_WRONLY | O_CLOEXEC | mode_flag, mode_t(0644));\n    if (fd == -1)\n    {\n        return true;\n    }\n    *fp = ::fdopen(fd, mode.c_str());\n    if (*fp == nullptr)\n    {\n        ::close(fd);\n    }\n#    else\n    *fp = ::fopen((filename.c_str()), mode.c_str());\n#    endif\n#endif\n\n    return *fp == nullptr;\n}\n\nSPDLOG_INLINE int remove(const filename_t &filename) SPDLOG_NOEXCEPT\n{\n#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)\n    return ::_wremove(filename.c_str());\n#else\n    return std::remove(filename.c_str());\n#endif\n}\n\nSPDLOG_INLINE int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT\n{\n    return path_exists(filename) ? remove(filename) : 0;\n}\n\nSPDLOG_INLINE int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT\n{\n#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)\n    return ::_wrename(filename1.c_str(), filename2.c_str());\n#else\n    return std::rename(filename1.c_str(), filename2.c_str());\n#endif\n}\n\n// Return true if path exists (file or directory)\nSPDLOG_INLINE bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT\n{\n#ifdef _WIN32\n#    ifdef SPDLOG_WCHAR_FILENAMES\n    auto attribs = ::GetFileAttributesW(filename.c_str());\n#    else\n    auto attribs = ::GetFileAttributesA(filename.c_str());\n#    endif\n    return attribs != INVALID_FILE_ATTRIBUTES;\n#else // common linux/unix all have the stat system call\n    struct stat buffer;\n    return (::stat(filename.c_str(), &buffer) == 0);\n#endif\n}\n\n#ifdef _MSC_VER\n// avoid warning about unreachable statement at the end of filesize()\n#    pragma warning(push)\n#    pragma warning(disable : 4702)\n#endif\n\n// Return file size according to open FILE* object\nSPDLOG_INLINE size_t filesize(FILE *f)\n{\n    if (f == nullptr)\n    {\n        throw_spdlog_ex(\"Failed getting file size. fd is null\");\n    }\n#if defined(_WIN32) && !defined(__CYGWIN__)\n    int fd = ::_fileno(f);\n#    if defined(_WIN64) // 64 bits\n    __int64 ret = ::_filelengthi64(fd);\n    if (ret >= 0)\n    {\n        return static_cast<size_t>(ret);\n    }\n\n#    else // windows 32 bits\n    long ret = ::_filelength(fd);\n    if (ret >= 0)\n    {\n        return static_cast<size_t>(ret);\n    }\n#    endif\n\n#else // unix\n// OpenBSD and AIX doesn't compile with :: before the fileno(..)\n#    if defined(__OpenBSD__) || defined(_AIX)\n    int fd = fileno(f);\n#    else\n    int fd = ::fileno(f);\n#    endif\n// 64 bits(but not in osx or cygwin, where fstat64 is deprecated)\n#    if (defined(__linux__) || defined(__sun) || defined(_AIX)) && (defined(__LP64__) || defined(_LP64))\n    struct stat64 st;\n    if (::fstat64(fd, &st) == 0)\n    {\n        return static_cast<size_t>(st.st_size);\n    }\n#    else // other unix or linux 32 bits or cygwin\n    struct stat st;\n    if (::fstat(fd, &st) == 0)\n    {\n        return static_cast<size_t>(st.st_size);\n    }\n#    endif\n#endif\n    throw_spdlog_ex(\"Failed getting file size from fd\", errno);\n    return 0; // will not be reached.\n}\n\n#ifdef _MSC_VER\n#    pragma warning(pop)\n#endif\n\n// Return utc offset in minutes or throw spdlog_ex on failure\nSPDLOG_INLINE int utc_minutes_offset(const std::tm &tm)\n{\n\n#ifdef _WIN32\n#    if _WIN32_WINNT < _WIN32_WINNT_WS08\n    TIME_ZONE_INFORMATION tzinfo;\n    auto rv = ::GetTimeZoneInformation(&tzinfo);\n#    else\n    DYNAMIC_TIME_ZONE_INFORMATION tzinfo;\n    auto rv = ::GetDynamicTimeZoneInformation(&tzinfo);\n#    endif\n    if (rv == TIME_ZONE_ID_INVALID)\n        throw_spdlog_ex(\"Failed getting timezone info. \", errno);\n\n    int offset = -tzinfo.Bias;\n    if (tm.tm_isdst)\n    {\n        offset -= tzinfo.DaylightBias;\n    }\n    else\n    {\n        offset -= tzinfo.StandardBias;\n    }\n    return offset;\n#else\n\n#    if defined(sun) || defined(__sun) || defined(_AIX) || (!defined(_BSD_SOURCE) && !defined(_GNU_SOURCE))\n    // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris\n    struct helper\n    {\n        static long int calculate_gmt_offset(const std::tm &localtm = details::os::localtime(), const std::tm &gmtm = details::os::gmtime())\n        {\n            int local_year = localtm.tm_year + (1900 - 1);\n            int gmt_year = gmtm.tm_year + (1900 - 1);\n\n            long int days = (\n                // difference in day of year\n                localtm.tm_yday -\n                gmtm.tm_yday\n\n                // + intervening leap days\n                + ((local_year >> 2) - (gmt_year >> 2)) - (local_year / 100 - gmt_year / 100) +\n                ((local_year / 100 >> 2) - (gmt_year / 100 >> 2))\n\n                // + difference in years * 365 */\n                + static_cast<long int>(local_year - gmt_year) * 365);\n\n            long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour);\n            long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min);\n            long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec);\n\n            return secs;\n        }\n    };\n\n    auto offset_seconds = helper::calculate_gmt_offset(tm);\n#    else\n    auto offset_seconds = tm.tm_gmtoff;\n#    endif\n\n    return static_cast<int>(offset_seconds / 60);\n#endif\n}\n\n// Return current thread id as size_t\n// It exists because the std::this_thread::get_id() is much slower(especially\n// under VS 2013)\nSPDLOG_INLINE size_t _thread_id() SPDLOG_NOEXCEPT\n{\n#ifdef _WIN32\n    return static_cast<size_t>(::GetCurrentThreadId());\n#elif defined(__linux__)\n#    if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)\n#        define SYS_gettid __NR_gettid\n#    endif\n    return static_cast<size_t>(::syscall(SYS_gettid));\n#elif defined(_AIX)\n    struct __pthrdsinfo buf;\n    int reg_size = 0;\n    pthread_t pt = pthread_self();\n    int retval = pthread_getthrds_np(&pt, PTHRDSINFO_QUERY_TID, &buf, sizeof(buf), NULL, &reg_size);\n    int tid = (!retval) ? buf.__pi_tid : 0;\n    return static_cast<size_t>(tid);\n#elif defined(__DragonFly__) || defined(__FreeBSD__)\n    return static_cast<size_t>(::pthread_getthreadid_np());\n#elif defined(__NetBSD__)\n    return static_cast<size_t>(::_lwp_self());\n#elif defined(__OpenBSD__)\n    return static_cast<size_t>(::getthrid());\n#elif defined(__sun)\n    return static_cast<size_t>(::thr_self());\n#elif __APPLE__\n    uint64_t tid;\n    pthread_threadid_np(nullptr, &tid);\n    return static_cast<size_t>(tid);\n#else // Default to standard C++11 (other Unix)\n    return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id()));\n#endif\n}\n\n// Return current thread id as size_t (from thread local storage)\nSPDLOG_INLINE size_t thread_id() SPDLOG_NOEXCEPT\n{\n#if defined(SPDLOG_NO_TLS)\n    return _thread_id();\n#else // cache thread id in tls\n    static thread_local const size_t tid = _thread_id();\n    return tid;\n#endif\n}\n\n// This is avoid msvc issue in sleep_for that happens if the clock changes.\n// See https://github.com/gabime/spdlog/issues/609\nSPDLOG_INLINE void sleep_for_millis(unsigned int milliseconds) SPDLOG_NOEXCEPT\n{\n#if defined(_WIN32)\n    ::Sleep(milliseconds);\n#else\n    std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));\n#endif\n}\n\n// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)\n#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)\nSPDLOG_INLINE std::string filename_to_str(const filename_t &filename)\n{\n    memory_buf_t buf;\n    wstr_to_utf8buf(filename, buf);\n    return SPDLOG_BUF_TO_STRING(buf);\n}\n#else\nSPDLOG_INLINE std::string filename_to_str(const filename_t &filename)\n{\n    return filename;\n}\n#endif\n\nSPDLOG_INLINE int pid() SPDLOG_NOEXCEPT\n{\n\n#ifdef _WIN32\n    return conditional_static_cast<int>(::GetCurrentProcessId());\n#else\n    return conditional_static_cast<int>(::getpid());\n#endif\n}\n\n// Determine if the terminal supports colors\n// Based on: https://github.com/agauniyal/rang/\nSPDLOG_INLINE bool is_color_terminal() SPDLOG_NOEXCEPT\n{\n#ifdef _WIN32\n    return true;\n#else\n\n    static const bool result = []() {\n        const char *env_colorterm_p = std::getenv(\"COLORTERM\");\n        if (env_colorterm_p != nullptr)\n        {\n            return true;\n        }\n\n        static constexpr std::array<const char *, 16> terms = {{\"ansi\", \"color\", \"console\", \"cygwin\", \"gnome\", \"konsole\", \"kterm\", \"linux\",\n            \"msys\", \"putty\", \"rxvt\", \"screen\", \"vt100\", \"xterm\", \"alacritty\", \"vt102\"}};\n\n        const char *env_term_p = std::getenv(\"TERM\");\n        if (env_term_p == nullptr)\n        {\n            return false;\n        }\n\n        return std::any_of(terms.begin(), terms.end(), [&](const char *term) { return std::strstr(env_term_p, term) != nullptr; });\n    }();\n\n    return result;\n#endif\n}\n\n// Determine if the terminal attached\n// Source: https://github.com/agauniyal/rang/\nSPDLOG_INLINE bool in_terminal(FILE *file) SPDLOG_NOEXCEPT\n{\n\n#ifdef _WIN32\n    return ::_isatty(_fileno(file)) != 0;\n#else\n    return ::isatty(fileno(file)) != 0;\n#endif\n}\n\n#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)\nSPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target)\n{\n    if (wstr.size() > static_cast<size_t>((std::numeric_limits<int>::max)()) / 2 - 1)\n    {\n        throw_spdlog_ex(\"UTF-16 string is too big to be converted to UTF-8\");\n    }\n\n    int wstr_size = static_cast<int>(wstr.size());\n    if (wstr_size == 0)\n    {\n        target.resize(0);\n        return;\n    }\n\n    int result_size = static_cast<int>(target.capacity());\n    if ((wstr_size + 1) * 2 > result_size)\n    {\n        result_size = ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr_size, NULL, 0, NULL, NULL);\n    }\n\n    if (result_size > 0)\n    {\n        target.resize(result_size);\n        result_size = ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr_size, target.data(), result_size, NULL, NULL);\n\n        if (result_size > 0)\n        {\n            target.resize(result_size);\n            return;\n        }\n    }\n\n    throw_spdlog_ex(fmt_lib::format(\"WideCharToMultiByte failed. Last error: {}\", ::GetLastError()));\n}\n\nSPDLOG_INLINE void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target)\n{\n    if (str.size() > static_cast<size_t>((std::numeric_limits<int>::max)()) - 1)\n    {\n        throw_spdlog_ex(\"UTF-8 string is too big to be converted to UTF-16\");\n    }\n\n    int str_size = static_cast<int>(str.size());\n    if (str_size == 0)\n    {\n        target.resize(0);\n        return;\n    }\n\n    int result_size = static_cast<int>(target.capacity());\n    if (str_size + 1 > result_size)\n    {\n        result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, NULL, 0);\n    }\n\n    if (result_size > 0)\n    {\n        target.resize(result_size);\n        result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, target.data(), result_size);\n\n        if (result_size > 0)\n        {\n            target.resize(result_size);\n            return;\n        }\n    }\n\n    throw_spdlog_ex(fmt_lib::format(\"MultiByteToWideChar failed. Last error: {}\", ::GetLastError()));\n}\n#endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)\n\n// return true on success\nstatic SPDLOG_INLINE bool mkdir_(const filename_t &path)\n{\n#ifdef _WIN32\n#    ifdef SPDLOG_WCHAR_FILENAMES\n    return ::_wmkdir(path.c_str()) == 0;\n#    else\n    return ::_mkdir(path.c_str()) == 0;\n#    endif\n#else\n    return ::mkdir(path.c_str(), mode_t(0755)) == 0;\n#endif\n}\n\n// create the given directory - and all directories leading to it\n// return true on success or if the directory already exists\nSPDLOG_INLINE bool create_dir(const filename_t &path)\n{\n    if (path_exists(path))\n    {\n        return true;\n    }\n\n    if (path.empty())\n    {\n        return false;\n    }\n\n    size_t search_offset = 0;\n    do\n    {\n        auto token_pos = path.find_first_of(folder_seps_filename, search_offset);\n        // treat the entire path as a folder if no folder separator not found\n        if (token_pos == filename_t::npos)\n        {\n            token_pos = path.size();\n        }\n\n        auto subdir = path.substr(0, token_pos);\n\n        if (!subdir.empty() && !path_exists(subdir) && !mkdir_(subdir))\n        {\n            return false; // return error if failed creating dir\n        }\n        search_offset = token_pos + 1;\n    } while (search_offset < path.size());\n\n    return true;\n}\n\n// Return directory name from given path or empty string\n// \"abc/file\" => \"abc\"\n// \"abc/\" => \"abc\"\n// \"abc\" => \"\"\n// \"abc///\" => \"abc//\"\nSPDLOG_INLINE filename_t dir_name(const filename_t &path)\n{\n    auto pos = path.find_last_of(folder_seps_filename);\n    return pos != filename_t::npos ? path.substr(0, pos) : filename_t{};\n}\n\nstd::string SPDLOG_INLINE getenv(const char *field)\n{\n\n#if defined(_MSC_VER)\n#    if defined(__cplusplus_winrt)\n    return std::string{}; // not supported under uwp\n#    else\n    size_t len = 0;\n    char buf[128];\n    bool ok = ::getenv_s(&len, buf, sizeof(buf), field) == 0;\n    return ok ? buf : std::string{};\n#    endif\n#else // revert to getenv\n    char *buf = ::getenv(field);\n    return buf ? buf : std::string{};\n#endif\n}\n\n} // namespace os\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/os.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/common.h>\n#include <ctime> // std::time_t\n\nnamespace spdlog {\nnamespace details {\nnamespace os {\n\nSPDLOG_API spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT;\n\nSPDLOG_API std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT;\n\nSPDLOG_API std::tm localtime() SPDLOG_NOEXCEPT;\n\nSPDLOG_API std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT;\n\nSPDLOG_API std::tm gmtime() SPDLOG_NOEXCEPT;\n\n// eol definition\n#if !defined(SPDLOG_EOL)\n#    ifdef _WIN32\n#        define SPDLOG_EOL \"\\r\\n\"\n#    else\n#        define SPDLOG_EOL \"\\n\"\n#    endif\n#endif\n\nSPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;\n\n// folder separator\n#if !defined(SPDLOG_FOLDER_SEPS)\n#    ifdef _WIN32\n#        define SPDLOG_FOLDER_SEPS \"\\\\/\"\n#    else\n#        define SPDLOG_FOLDER_SEPS \"/\"\n#    endif\n#endif\n\nSPDLOG_CONSTEXPR static const char folder_seps[] = SPDLOG_FOLDER_SEPS;\nSPDLOG_CONSTEXPR static const filename_t::value_type folder_seps_filename[] = SPDLOG_FILENAME_T(SPDLOG_FOLDER_SEPS);\n\n// fopen_s on non windows for writing\nSPDLOG_API bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode);\n\n// Remove filename. return 0 on success\nSPDLOG_API int remove(const filename_t &filename) SPDLOG_NOEXCEPT;\n\n// Remove file if exists. return 0 on success\n// Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread)\nSPDLOG_API int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT;\n\nSPDLOG_API int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT;\n\n// Return if file exists.\nSPDLOG_API bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT;\n\n// Return file size according to open FILE* object\nSPDLOG_API size_t filesize(FILE *f);\n\n// Return utc offset in minutes or throw spdlog_ex on failure\nSPDLOG_API int utc_minutes_offset(const std::tm &tm = details::os::localtime());\n\n// Return current thread id as size_t\n// It exists because the std::this_thread::get_id() is much slower(especially\n// under VS 2013)\nSPDLOG_API size_t _thread_id() SPDLOG_NOEXCEPT;\n\n// Return current thread id as size_t (from thread local storage)\nSPDLOG_API size_t thread_id() SPDLOG_NOEXCEPT;\n\n// This is avoid msvc issue in sleep_for that happens if the clock changes.\n// See https://github.com/gabime/spdlog/issues/609\nSPDLOG_API void sleep_for_millis(unsigned int milliseconds) SPDLOG_NOEXCEPT;\n\nSPDLOG_API std::string filename_to_str(const filename_t &filename);\n\nSPDLOG_API int pid() SPDLOG_NOEXCEPT;\n\n// Determine if the terminal supports colors\n// Source: https://github.com/agauniyal/rang/\nSPDLOG_API bool is_color_terminal() SPDLOG_NOEXCEPT;\n\n// Determine if the terminal attached\n// Source: https://github.com/agauniyal/rang/\nSPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT;\n\n#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)\nSPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);\n\nSPDLOG_API void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target);\n#endif\n\n// Return directory name from given path or empty string\n// \"abc/file\" => \"abc\"\n// \"abc/\" => \"abc\"\n// \"abc\" => \"\"\n// \"abc///\" => \"abc//\"\nSPDLOG_API filename_t dir_name(const filename_t &path);\n\n// Create a dir from the given path.\n// Return true if succeeded or if this dir already exists.\nSPDLOG_API bool create_dir(const filename_t &path);\n\n// non thread safe, cross platform getenv/getenv_s\n// return empty string if field not found\nSPDLOG_API std::string getenv(const char *field);\n\n} // namespace os\n} // namespace details\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"os-inl.h\"\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/periodic_worker-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/details/periodic_worker.h>\n#endif\n\nnamespace spdlog {\nnamespace details {\n\nSPDLOG_INLINE periodic_worker::periodic_worker(const std::function<void()> &callback_fun, std::chrono::seconds interval)\n{\n    active_ = (interval > std::chrono::seconds::zero());\n    if (!active_)\n    {\n        return;\n    }\n\n    worker_thread_ = std::thread([this, callback_fun, interval]() {\n        for (;;)\n        {\n            std::unique_lock<std::mutex> lock(this->mutex_);\n            if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; }))\n            {\n                return; // active_ == false, so exit this thread\n            }\n            callback_fun();\n        }\n    });\n}\n\n// stop the worker thread and join it\nSPDLOG_INLINE periodic_worker::~periodic_worker()\n{\n    if (worker_thread_.joinable())\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex_);\n            active_ = false;\n        }\n        cv_.notify_one();\n        worker_thread_.join();\n    }\n}\n\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/periodic_worker.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n// periodic worker thread - periodically executes the given callback function.\n//\n// RAII over the owned thread:\n//    creates the thread on construction.\n//    stops and joins the thread on destruction (if the thread is executing a callback, wait for it to finish first).\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <chrono>\n#include <condition_variable>\n#include <functional>\n#include <mutex>\n#include <thread>\nnamespace spdlog {\nnamespace details {\n\nclass SPDLOG_API periodic_worker\n{\npublic:\n    periodic_worker(const std::function<void()> &callback_fun, std::chrono::seconds interval);\n    periodic_worker(const periodic_worker &) = delete;\n    periodic_worker &operator=(const periodic_worker &) = delete;\n    // stop the worker thread and join it\n    ~periodic_worker();\n\nprivate:\n    bool active_;\n    std::thread worker_thread_;\n    std::mutex mutex_;\n    std::condition_variable cv_;\n};\n} // namespace details\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"periodic_worker-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/registry-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/details/registry.h>\n#endif\n\n#include <spdlog/common.h>\n#include <spdlog/details/periodic_worker.h>\n#include <spdlog/logger.h>\n#include <spdlog/pattern_formatter.h>\n\n#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER\n// support for the default stdout color logger\n#    ifdef _WIN32\n#        include <spdlog/sinks/wincolor_sink.h>\n#    else\n#        include <spdlog/sinks/ansicolor_sink.h>\n#    endif\n#endif // SPDLOG_DISABLE_DEFAULT_LOGGER\n\n#include <chrono>\n#include <functional>\n#include <memory>\n#include <string>\n#include <unordered_map>\n\nnamespace spdlog {\nnamespace details {\n\nSPDLOG_INLINE registry::registry()\n    : formatter_(new pattern_formatter())\n{\n\n#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER\n    // create default logger (ansicolor_stdout_sink_mt or wincolor_stdout_sink_mt in windows).\n#    ifdef _WIN32\n    auto color_sink = std::make_shared<sinks::wincolor_stdout_sink_mt>();\n#    else\n    auto color_sink = std::make_shared<sinks::ansicolor_stdout_sink_mt>();\n#    endif\n\n    const char *default_logger_name = \"\";\n    default_logger_ = std::make_shared<spdlog::logger>(default_logger_name, std::move(color_sink));\n    loggers_[default_logger_name] = default_logger_;\n\n#endif // SPDLOG_DISABLE_DEFAULT_LOGGER\n}\n\nSPDLOG_INLINE registry::~registry() = default;\n\nSPDLOG_INLINE void registry::register_logger(std::shared_ptr<logger> new_logger)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    register_logger_(std::move(new_logger));\n}\n\nSPDLOG_INLINE void registry::initialize_logger(std::shared_ptr<logger> new_logger)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    new_logger->set_formatter(formatter_->clone());\n\n    if (err_handler_)\n    {\n        new_logger->set_error_handler(err_handler_);\n    }\n\n    // set new level according to previously configured level or default level\n    auto it = log_levels_.find(new_logger->name());\n    auto new_level = it != log_levels_.end() ? it->second : global_log_level_;\n    new_logger->set_level(new_level);\n\n    new_logger->flush_on(flush_level_);\n\n    if (backtrace_n_messages_ > 0)\n    {\n        new_logger->enable_backtrace(backtrace_n_messages_);\n    }\n\n    if (automatic_registration_)\n    {\n        register_logger_(std::move(new_logger));\n    }\n}\n\nSPDLOG_INLINE std::shared_ptr<logger> registry::get(const std::string &logger_name)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    auto found = loggers_.find(logger_name);\n    return found == loggers_.end() ? nullptr : found->second;\n}\n\nSPDLOG_INLINE std::shared_ptr<logger> registry::default_logger()\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    return default_logger_;\n}\n\n// Return raw ptr to the default logger.\n// To be used directly by the spdlog default api (e.g. spdlog::info)\n// This make the default API faster, but cannot be used concurrently with set_default_logger().\n// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another.\nSPDLOG_INLINE logger *registry::get_default_raw()\n{\n    return default_logger_.get();\n}\n\n// set default logger.\n// default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map.\nSPDLOG_INLINE void registry::set_default_logger(std::shared_ptr<logger> new_default_logger)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    // remove previous default logger from the map\n    if (default_logger_ != nullptr)\n    {\n        loggers_.erase(default_logger_->name());\n    }\n    if (new_default_logger != nullptr)\n    {\n        loggers_[new_default_logger->name()] = new_default_logger;\n    }\n    default_logger_ = std::move(new_default_logger);\n}\n\nSPDLOG_INLINE void registry::set_tp(std::shared_ptr<thread_pool> tp)\n{\n    std::lock_guard<std::recursive_mutex> lock(tp_mutex_);\n    tp_ = std::move(tp);\n}\n\nSPDLOG_INLINE std::shared_ptr<thread_pool> registry::get_tp()\n{\n    std::lock_guard<std::recursive_mutex> lock(tp_mutex_);\n    return tp_;\n}\n\n// Set global formatter. Each sink in each logger will get a clone of this object\nSPDLOG_INLINE void registry::set_formatter(std::unique_ptr<formatter> formatter)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    formatter_ = std::move(formatter);\n    for (auto &l : loggers_)\n    {\n        l.second->set_formatter(formatter_->clone());\n    }\n}\n\nSPDLOG_INLINE void registry::enable_backtrace(size_t n_messages)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    backtrace_n_messages_ = n_messages;\n\n    for (auto &l : loggers_)\n    {\n        l.second->enable_backtrace(n_messages);\n    }\n}\n\nSPDLOG_INLINE void registry::disable_backtrace()\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    backtrace_n_messages_ = 0;\n    for (auto &l : loggers_)\n    {\n        l.second->disable_backtrace();\n    }\n}\n\nSPDLOG_INLINE void registry::set_level(level::level_enum log_level)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    for (auto &l : loggers_)\n    {\n        l.second->set_level(log_level);\n    }\n    global_log_level_ = log_level;\n}\n\nSPDLOG_INLINE void registry::flush_on(level::level_enum log_level)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    for (auto &l : loggers_)\n    {\n        l.second->flush_on(log_level);\n    }\n    flush_level_ = log_level;\n}\n\nSPDLOG_INLINE void registry::flush_every(std::chrono::seconds interval)\n{\n    std::lock_guard<std::mutex> lock(flusher_mutex_);\n    auto clbk = [this]() { this->flush_all(); };\n    periodic_flusher_ = details::make_unique<periodic_worker>(clbk, interval);\n}\n\nSPDLOG_INLINE void registry::set_error_handler(err_handler handler)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    for (auto &l : loggers_)\n    {\n        l.second->set_error_handler(handler);\n    }\n    err_handler_ = std::move(handler);\n}\n\nSPDLOG_INLINE void registry::apply_all(const std::function<void(const std::shared_ptr<logger>)> &fun)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    for (auto &l : loggers_)\n    {\n        fun(l.second);\n    }\n}\n\nSPDLOG_INLINE void registry::flush_all()\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    for (auto &l : loggers_)\n    {\n        l.second->flush();\n    }\n}\n\nSPDLOG_INLINE void registry::drop(const std::string &logger_name)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    loggers_.erase(logger_name);\n    if (default_logger_ && default_logger_->name() == logger_name)\n    {\n        default_logger_.reset();\n    }\n}\n\nSPDLOG_INLINE void registry::drop_all()\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    loggers_.clear();\n    default_logger_.reset();\n}\n\n// clean all resources and threads started by the registry\nSPDLOG_INLINE void registry::shutdown()\n{\n    {\n        std::lock_guard<std::mutex> lock(flusher_mutex_);\n        periodic_flusher_.reset();\n    }\n\n    drop_all();\n\n    {\n        std::lock_guard<std::recursive_mutex> lock(tp_mutex_);\n        tp_.reset();\n    }\n}\n\nSPDLOG_INLINE std::recursive_mutex &registry::tp_mutex()\n{\n    return tp_mutex_;\n}\n\nSPDLOG_INLINE void registry::set_automatic_registration(bool automatic_registration)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    automatic_registration_ = automatic_registration;\n}\n\nSPDLOG_INLINE void registry::set_levels(log_levels levels, level::level_enum *global_level)\n{\n    std::lock_guard<std::mutex> lock(logger_map_mutex_);\n    log_levels_ = std::move(levels);\n    auto global_level_requested = global_level != nullptr;\n    global_log_level_ = global_level_requested ? *global_level : global_log_level_;\n\n    for (auto &logger : loggers_)\n    {\n        auto logger_entry = log_levels_.find(logger.first);\n        if (logger_entry != log_levels_.end())\n        {\n            logger.second->set_level(logger_entry->second);\n        }\n        else if (global_level_requested)\n        {\n            logger.second->set_level(*global_level);\n        }\n    }\n}\n\nSPDLOG_INLINE registry &registry::instance()\n{\n    static registry s_instance;\n    return s_instance;\n}\n\nSPDLOG_INLINE void registry::throw_if_exists_(const std::string &logger_name)\n{\n    if (loggers_.find(logger_name) != loggers_.end())\n    {\n        throw_spdlog_ex(\"logger with name '\" + logger_name + \"' already exists\");\n    }\n}\n\nSPDLOG_INLINE void registry::register_logger_(std::shared_ptr<logger> new_logger)\n{\n    auto logger_name = new_logger->name();\n    throw_if_exists_(logger_name);\n    loggers_[logger_name] = std::move(new_logger);\n}\n\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/registry.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n// Loggers registry of unique name->logger pointer\n// An attempt to create a logger with an already existing name will result with spdlog_ex exception.\n// If user requests a non existing logger, nullptr will be returned\n// This class is thread safe\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/common.h>\n\n#include <chrono>\n#include <functional>\n#include <memory>\n#include <string>\n#include <unordered_map>\n#include <mutex>\n\nnamespace spdlog {\nclass logger;\n\nnamespace details {\nclass thread_pool;\nclass periodic_worker;\n\nclass SPDLOG_API registry\n{\npublic:\n    using log_levels = std::unordered_map<std::string, level::level_enum>;\n    registry(const registry &) = delete;\n    registry &operator=(const registry &) = delete;\n\n    void register_logger(std::shared_ptr<logger> new_logger);\n    void initialize_logger(std::shared_ptr<logger> new_logger);\n    std::shared_ptr<logger> get(const std::string &logger_name);\n    std::shared_ptr<logger> default_logger();\n\n    // Return raw ptr to the default logger.\n    // To be used directly by the spdlog default api (e.g. spdlog::info)\n    // This make the default API faster, but cannot be used concurrently with set_default_logger().\n    // e.g do not call set_default_logger() from one thread while calling spdlog::info() from another.\n    logger *get_default_raw();\n\n    // set default logger.\n    // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map.\n    void set_default_logger(std::shared_ptr<logger> new_default_logger);\n\n    void set_tp(std::shared_ptr<thread_pool> tp);\n\n    std::shared_ptr<thread_pool> get_tp();\n\n    // Set global formatter. Each sink in each logger will get a clone of this object\n    void set_formatter(std::unique_ptr<formatter> formatter);\n\n    void enable_backtrace(size_t n_messages);\n\n    void disable_backtrace();\n\n    void set_level(level::level_enum log_level);\n\n    void flush_on(level::level_enum log_level);\n\n    void flush_every(std::chrono::seconds interval);\n\n    void set_error_handler(err_handler handler);\n\n    void apply_all(const std::function<void(const std::shared_ptr<logger>)> &fun);\n\n    void flush_all();\n\n    void drop(const std::string &logger_name);\n\n    void drop_all();\n\n    // clean all resources and threads started by the registry\n    void shutdown();\n\n    std::recursive_mutex &tp_mutex();\n\n    void set_automatic_registration(bool automatic_registration);\n\n    // set levels for all existing/future loggers. global_level can be null if should not set.\n    void set_levels(log_levels levels, level::level_enum *global_level);\n\n    static registry &instance();\n\nprivate:\n    registry();\n    ~registry();\n\n    void throw_if_exists_(const std::string &logger_name);\n    void register_logger_(std::shared_ptr<logger> new_logger);\n    bool set_level_from_cfg_(logger *logger);\n    std::mutex logger_map_mutex_, flusher_mutex_;\n    std::recursive_mutex tp_mutex_;\n    std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;\n    log_levels log_levels_;\n    std::unique_ptr<formatter> formatter_;\n    spdlog::level::level_enum global_log_level_ = level::info;\n    level::level_enum flush_level_ = level::off;\n    err_handler err_handler_;\n    std::shared_ptr<thread_pool> tp_;\n    std::unique_ptr<periodic_worker> periodic_flusher_;\n    std::shared_ptr<logger> default_logger_;\n    bool automatic_registration_ = true;\n    size_t backtrace_n_messages_ = 0;\n};\n\n} // namespace details\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"registry-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/synchronous_factory.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include \"registry.h\"\n\nnamespace spdlog {\n\n// Default logger factory-  creates synchronous loggers\nclass logger;\n\nstruct synchronous_factory\n{\n    template<typename Sink, typename... SinkArgs>\n    static std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&... args)\n    {\n        auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);\n        auto new_logger = std::make_shared<spdlog::logger>(std::move(logger_name), std::move(sink));\n        details::registry::instance().initialize_logger(new_logger);\n        return new_logger;\n    }\n};\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/tcp_client-windows.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#define WIN32_LEAN_AND_MEAN\n// tcp client helper\n#include <spdlog/common.h>\n#include <spdlog/details/os.h>\n\n#include <winsock2.h>\n#include <windows.h>\n#include <ws2tcpip.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string>\n\n#pragma comment(lib, \"Ws2_32.lib\")\n#pragma comment(lib, \"Mswsock.lib\")\n#pragma comment(lib, \"AdvApi32.lib\")\n\nnamespace spdlog {\nnamespace details {\nclass tcp_client\n{\n    SOCKET socket_ = INVALID_SOCKET;\n\n    static void init_winsock_()\n    {\n        WSADATA wsaData;\n        auto rv = WSAStartup(MAKEWORD(2, 2), &wsaData);\n        if (rv != 0)\n        {\n            throw_winsock_error_(\"WSAStartup failed\", ::WSAGetLastError());\n        }\n    }\n\n    static void throw_winsock_error_(const std::string &msg, int last_error)\n    {\n        char buf[512];\n        ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error,\n            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(char)), NULL);\n\n        throw_spdlog_ex(fmt_lib::format(\"tcp_sink - {}: {}\", msg, buf));\n    }\n\npublic:\n    tcp_client()\n    {\n        init_winsock_();\n    }\n\n    ~tcp_client()\n    {\n        close();\n        ::WSACleanup();\n    }\n\n    bool is_connected() const\n    {\n        return socket_ != INVALID_SOCKET;\n    }\n\n    void close()\n    {\n        ::closesocket(socket_);\n        socket_ = INVALID_SOCKET;\n    }\n\n    SOCKET fd() const\n    {\n        return socket_;\n    }\n\n    // try to connect or throw on failure\n    void connect(const std::string &host, int port)\n    {\n        if (is_connected())\n        {\n            close();\n        }\n        struct addrinfo hints\n        {};\n        ZeroMemory(&hints, sizeof(hints));\n\n        hints.ai_family = AF_INET;       // IPv4\n        hints.ai_socktype = SOCK_STREAM; // TCP\n        hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value\n        hints.ai_protocol = 0;\n\n        auto port_str = std::to_string(port);\n        struct addrinfo *addrinfo_result;\n        auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result);\n        int last_error = 0;\n        if (rv != 0)\n        {\n            last_error = ::WSAGetLastError();\n            WSACleanup();\n            throw_winsock_error_(\"getaddrinfo failed\", last_error);\n        }\n\n        // Try each address until we successfully connect(2).\n\n        for (auto *rp = addrinfo_result; rp != nullptr; rp = rp->ai_next)\n        {\n            socket_ = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\n            if (socket_ == INVALID_SOCKET)\n            {\n                last_error = ::WSAGetLastError();\n                WSACleanup();\n                continue;\n            }\n            if (::connect(socket_, rp->ai_addr, (int)rp->ai_addrlen) == 0)\n            {\n                break;\n            }\n            else\n            {\n                last_error = ::WSAGetLastError();\n                close();\n            }\n        }\n        ::freeaddrinfo(addrinfo_result);\n        if (socket_ == INVALID_SOCKET)\n        {\n            WSACleanup();\n            throw_winsock_error_(\"connect failed\", last_error);\n        }\n\n        // set TCP_NODELAY\n        int enable_flag = 1;\n        ::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&enable_flag), sizeof(enable_flag));\n    }\n\n    // Send exactly n_bytes of the given data.\n    // On error close the connection and throw.\n    void send(const char *data, size_t n_bytes)\n    {\n        size_t bytes_sent = 0;\n        while (bytes_sent < n_bytes)\n        {\n            const int send_flags = 0;\n            auto write_result = ::send(socket_, data + bytes_sent, (int)(n_bytes - bytes_sent), send_flags);\n            if (write_result == SOCKET_ERROR)\n            {\n                int last_error = ::WSAGetLastError();\n                close();\n                throw_winsock_error_(\"send failed\", last_error);\n            }\n\n            if (write_result == 0) // (probably should not happen but in any case..)\n            {\n                break;\n            }\n            bytes_sent += static_cast<size_t>(write_result);\n        }\n    }\n};\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/tcp_client.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifdef _WIN32\n#    error include tcp_client-windows.h instead\n#endif\n\n// tcp client helper\n#include <spdlog/common.h>\n#include <spdlog/details/os.h>\n\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <unistd.h>\n#include <netdb.h>\n#include <netinet/tcp.h>\n\n#include <string>\n\nnamespace spdlog {\nnamespace details {\nclass tcp_client\n{\n    int socket_ = -1;\n\npublic:\n    bool is_connected() const\n    {\n        return socket_ != -1;\n    }\n\n    void close()\n    {\n        if (is_connected())\n        {\n            ::close(socket_);\n            socket_ = -1;\n        }\n    }\n\n    int fd() const\n    {\n        return socket_;\n    }\n\n    ~tcp_client()\n    {\n        close();\n    }\n\n    // try to connect or throw on failure\n    void connect(const std::string &host, int port)\n    {\n        close();\n        struct addrinfo hints\n        {};\n        memset(&hints, 0, sizeof(struct addrinfo));\n        hints.ai_family = AF_INET;       // IPv4\n        hints.ai_socktype = SOCK_STREAM; // TCP\n        hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value\n        hints.ai_protocol = 0;\n\n        auto port_str = std::to_string(port);\n        struct addrinfo *addrinfo_result;\n        auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result);\n        if (rv != 0)\n        {\n            throw_spdlog_ex(fmt_lib::format(\"::getaddrinfo failed: {}\", gai_strerror(rv)));\n        }\n\n        // Try each address until we successfully connect(2).\n        int last_errno = 0;\n        for (auto *rp = addrinfo_result; rp != nullptr; rp = rp->ai_next)\n        {\n#if defined(SOCK_CLOEXEC)\n            const int flags = SOCK_CLOEXEC;\n#else\n            const int flags = 0;\n#endif\n            socket_ = ::socket(rp->ai_family, rp->ai_socktype | flags, rp->ai_protocol);\n            if (socket_ == -1)\n            {\n                last_errno = errno;\n                continue;\n            }\n            rv = ::connect(socket_, rp->ai_addr, rp->ai_addrlen);\n            if (rv == 0)\n            {\n                break;\n            }\n            last_errno = errno;\n            ::close(socket_);\n            socket_ = -1;\n        }\n        ::freeaddrinfo(addrinfo_result);\n        if (socket_ == -1)\n        {\n            throw_spdlog_ex(\"::connect failed\", last_errno);\n        }\n\n        // set TCP_NODELAY\n        int enable_flag = 1;\n        ::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&enable_flag), sizeof(enable_flag));\n\n        // prevent sigpipe on systems where MSG_NOSIGNAL is not available\n#if defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)\n        ::setsockopt(socket_, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char *>(&enable_flag), sizeof(enable_flag));\n#endif\n\n#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)\n#    error \"tcp_sink would raise SIGPIPE since niether SO_NOSIGPIPE nor MSG_NOSIGNAL are available\"\n#endif\n    }\n\n    // Send exactly n_bytes of the given data.\n    // On error close the connection and throw.\n    void send(const char *data, size_t n_bytes)\n    {\n        size_t bytes_sent = 0;\n        while (bytes_sent < n_bytes)\n        {\n#if defined(MSG_NOSIGNAL)\n            const int send_flags = MSG_NOSIGNAL;\n#else\n            const int send_flags = 0;\n#endif\n            auto write_result = ::send(socket_, data + bytes_sent, n_bytes - bytes_sent, send_flags);\n            if (write_result < 0)\n            {\n                close();\n                throw_spdlog_ex(\"write(2) failed\", errno);\n            }\n\n            if (write_result == 0) // (probably should not happen but in any case..)\n            {\n                break;\n            }\n            bytes_sent += static_cast<size_t>(write_result);\n        }\n    }\n};\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/thread_pool-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/details/thread_pool.h>\n#endif\n\n#include <spdlog/common.h>\n#include <cassert>\n\nnamespace spdlog {\nnamespace details {\n\nSPDLOG_INLINE thread_pool::thread_pool(\n    size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start, std::function<void()> on_thread_stop)\n    : q_(q_max_items)\n{\n    if (threads_n == 0 || threads_n > 1000)\n    {\n        throw_spdlog_ex(\"spdlog::thread_pool(): invalid threads_n param (valid \"\n                        \"range is 1-1000)\");\n    }\n    for (size_t i = 0; i < threads_n; i++)\n    {\n        threads_.emplace_back([this, on_thread_start, on_thread_stop] {\n            on_thread_start();\n            this->thread_pool::worker_loop_();\n            on_thread_stop();\n        });\n    }\n}\n\nSPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start)\n    : thread_pool(q_max_items, threads_n, on_thread_start, [] {})\n{}\n\nSPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n)\n    : thread_pool(\n          q_max_items, threads_n, [] {}, [] {})\n{}\n\n// message all threads to terminate gracefully join them\nSPDLOG_INLINE thread_pool::~thread_pool()\n{\n    SPDLOG_TRY\n    {\n        for (size_t i = 0; i < threads_.size(); i++)\n        {\n            post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block);\n        }\n\n        for (auto &t : threads_)\n        {\n            t.join();\n        }\n    }\n    SPDLOG_CATCH_STD\n}\n\nvoid SPDLOG_INLINE thread_pool::post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy)\n{\n    async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg);\n    post_async_msg_(std::move(async_m), overflow_policy);\n}\n\nvoid SPDLOG_INLINE thread_pool::post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy)\n{\n    post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy);\n}\n\nsize_t SPDLOG_INLINE thread_pool::overrun_counter()\n{\n    return q_.overrun_counter();\n}\n\nsize_t SPDLOG_INLINE thread_pool::queue_size()\n{\n    return q_.size();\n}\n\nvoid SPDLOG_INLINE thread_pool::post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy)\n{\n    if (overflow_policy == async_overflow_policy::block)\n    {\n        q_.enqueue(std::move(new_msg));\n    }\n    else\n    {\n        q_.enqueue_nowait(std::move(new_msg));\n    }\n}\n\nvoid SPDLOG_INLINE thread_pool::worker_loop_()\n{\n    while (process_next_msg_()) {}\n}\n\n// process next message in the queue\n// return true if this thread should still be active (while no terminate msg\n// was received)\nbool SPDLOG_INLINE thread_pool::process_next_msg_()\n{\n    async_msg incoming_async_msg;\n    bool dequeued = q_.dequeue_for(incoming_async_msg, std::chrono::seconds(10));\n    if (!dequeued)\n    {\n        return true;\n    }\n\n    switch (incoming_async_msg.msg_type)\n    {\n    case async_msg_type::log: {\n        incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg);\n        return true;\n    }\n    case async_msg_type::flush: {\n        incoming_async_msg.worker_ptr->backend_flush_();\n        return true;\n    }\n\n    case async_msg_type::terminate: {\n        return false;\n    }\n\n    default: {\n        assert(false);\n    }\n    }\n\n    return true;\n}\n\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/thread_pool.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/details/log_msg_buffer.h>\n#include <spdlog/details/mpmc_blocking_q.h>\n#include <spdlog/details/os.h>\n\n#include <chrono>\n#include <memory>\n#include <thread>\n#include <vector>\n#include <functional>\n\nnamespace spdlog {\nclass async_logger;\n\nnamespace details {\n\nusing async_logger_ptr = std::shared_ptr<spdlog::async_logger>;\n\nenum class async_msg_type\n{\n    log,\n    flush,\n    terminate\n};\n\n// Async msg to move to/from the queue\n// Movable only. should never be copied\nstruct async_msg : log_msg_buffer\n{\n    async_msg_type msg_type{async_msg_type::log};\n    async_logger_ptr worker_ptr;\n\n    async_msg() = default;\n    ~async_msg() = default;\n\n    // should only be moved in or out of the queue..\n    async_msg(const async_msg &) = delete;\n\n// support for vs2013 move\n#if defined(_MSC_VER) && _MSC_VER <= 1800\n    async_msg(async_msg &&other)\n        : log_msg_buffer(std::move(other))\n        , msg_type(other.msg_type)\n        , worker_ptr(std::move(other.worker_ptr))\n    {}\n\n    async_msg &operator=(async_msg &&other)\n    {\n        *static_cast<log_msg_buffer *>(this) = std::move(other);\n        msg_type = other.msg_type;\n        worker_ptr = std::move(other.worker_ptr);\n        return *this;\n    }\n#else // (_MSC_VER) && _MSC_VER <= 1800\n    async_msg(async_msg &&) = default;\n    async_msg &operator=(async_msg &&) = default;\n#endif\n\n    // construct from log_msg with given type\n    async_msg(async_logger_ptr &&worker, async_msg_type the_type, const details::log_msg &m)\n        : log_msg_buffer{m}\n        , msg_type{the_type}\n        , worker_ptr{std::move(worker)}\n    {}\n\n    async_msg(async_logger_ptr &&worker, async_msg_type the_type)\n        : log_msg_buffer{}\n        , msg_type{the_type}\n        , worker_ptr{std::move(worker)}\n    {}\n\n    explicit async_msg(async_msg_type the_type)\n        : async_msg{nullptr, the_type}\n    {}\n};\n\nclass SPDLOG_API thread_pool\n{\npublic:\n    using item_type = async_msg;\n    using q_type = details::mpmc_blocking_queue<item_type>;\n\n    thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start, std::function<void()> on_thread_stop);\n    thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start);\n    thread_pool(size_t q_max_items, size_t threads_n);\n\n    // message all threads to terminate gracefully and join them\n    ~thread_pool();\n\n    thread_pool(const thread_pool &) = delete;\n    thread_pool &operator=(thread_pool &&) = delete;\n\n    void post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy);\n    void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy);\n    size_t overrun_counter();\n    size_t queue_size();\n\nprivate:\n    q_type q_;\n\n    std::vector<std::thread> threads_;\n\n    void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy);\n    void worker_loop_();\n\n    // process next message in the queue\n    // return true if this thread should still be active (while no terminate msg\n    // was received)\n    bool process_next_msg_();\n};\n\n} // namespace details\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"thread_pool-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/udp_client-windows.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n// Helper RAII over winsock udp client socket.\n// Will throw on construction if socket creation failed.\n\n#include <spdlog/common.h>\n#include <spdlog/details/os.h>\n#include <spdlog/details/windows_include.h>\n#include <winsock2.h>\n#include <ws2tcpip.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string>\n\n#pragma comment(lib, \"Ws2_32.lib\")\n#pragma comment(lib, \"Mswsock.lib\")\n#pragma comment(lib, \"AdvApi32.lib\")\n\nnamespace spdlog {\nnamespace details {\nclass udp_client\n{\n    static constexpr int TX_BUFFER_SIZE = 1024 * 10;\n    SOCKET socket_ = INVALID_SOCKET;\n    sockaddr_in addr_ = {0};\n\n    static void init_winsock_()\n    {\n        WSADATA wsaData;\n        auto rv = ::WSAStartup(MAKEWORD(2, 2), &wsaData);\n        if (rv != 0)\n        {\n            throw_winsock_error_(\"WSAStartup failed\", ::WSAGetLastError());\n        }\n    }\n\n    static void throw_winsock_error_(const std::string &msg, int last_error)\n    {\n        char buf[512];\n        ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error,\n            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(char)), NULL);\n\n        throw_spdlog_ex(fmt_lib::format(\"udp_sink - {}: {}\", msg, buf));\n    }\n\n    void cleanup_()\n    {\n        if (socket_ != INVALID_SOCKET)\n        {\n            ::closesocket(socket_);\n        }\n        socket_ = INVALID_SOCKET;\n        ::WSACleanup();\n    }\n\npublic:\n    udp_client(const std::string &host, uint16_t port)\n    {\n        init_winsock_();\n\n        addr_.sin_family = PF_INET;\n        addr_.sin_port = htons(port);\n        addr_.sin_addr.s_addr = INADDR_ANY;\n        if (InetPtonA(PF_INET, host.c_str(), &addr_.sin_addr.s_addr) != 1)\n        {\n            int last_error = ::WSAGetLastError();\n            ::WSACleanup();\n            throw_winsock_error_(\"error: Invalid address!\", last_error);\n        }\n\n        socket_ = ::socket(PF_INET, SOCK_DGRAM, 0);\n        if (socket_ == INVALID_SOCKET)\n        {\n            int last_error = ::WSAGetLastError();\n            ::WSACleanup();\n            throw_winsock_error_(\"error: Create Socket failed\", last_error);\n        }\n\n        int option_value = TX_BUFFER_SIZE;\n        if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char *>(&option_value), sizeof(option_value)) < 0)\n        {\n            int last_error = ::WSAGetLastError();\n            cleanup_();\n            throw_winsock_error_(\"error: setsockopt(SO_SNDBUF) Failed!\", last_error);\n        }\n    }\n\n    ~udp_client()\n    {\n        cleanup_();\n    }\n\n    SOCKET fd() const\n    {\n        return socket_;\n    }\n\n    void send(const char *data, size_t n_bytes)\n    {\n        socklen_t tolen = sizeof(struct sockaddr);\n        if (::sendto(socket_, data, static_cast<int>(n_bytes), 0, (struct sockaddr *)&addr_, tolen) == -1)\n        {\n            throw_spdlog_ex(\"sendto(2) failed\", errno);\n        }\n    }\n};\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/udp_client.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n// Helper RAII over unix udp client socket.\n// Will throw on construction if the socket creation failed.\n\n#ifdef _WIN32\n#    error \"include udp_client-windows.h instead\"\n#endif\n\n#include <spdlog/common.h>\n#include <spdlog/details/os.h>\n\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#include <unistd.h>\n#include <netdb.h>\n#include <netinet/udp.h>\n\n#include <string>\n\nnamespace spdlog {\nnamespace details {\n\nclass udp_client\n{\n    static constexpr int TX_BUFFER_SIZE = 1024 * 10;\n    int socket_ = -1;\n    struct sockaddr_in sockAddr_;\n\n    void cleanup_()\n    {\n        if (socket_ != -1)\n        {\n            ::close(socket_);\n            socket_ = -1;\n        }\n    }\n\npublic:\n    udp_client(const std::string &host, uint16_t port)\n    {\n        socket_ = ::socket(PF_INET, SOCK_DGRAM, 0);\n        if (socket_ < 0)\n        {\n            throw_spdlog_ex(\"error: Create Socket Failed!\");\n        }\n\n        int option_value = TX_BUFFER_SIZE;\n        if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char *>(&option_value), sizeof(option_value)) < 0)\n        {\n            cleanup_();\n            throw_spdlog_ex(\"error: setsockopt(SO_SNDBUF) Failed!\");\n        }\n\n        sockAddr_.sin_family = AF_INET;\n        sockAddr_.sin_port = htons(port);\n\n        if (::inet_aton(host.c_str(), &sockAddr_.sin_addr) == 0)\n        {\n            cleanup_();\n            throw_spdlog_ex(\"error: Invalid address!\");\n        }\n\n        ::memset(sockAddr_.sin_zero, 0x00, sizeof(sockAddr_.sin_zero));\n    }\n\n    ~udp_client()\n    {\n        cleanup_();\n    }\n\n    int fd() const\n    {\n        return socket_;\n    }\n\n    // Send exactly n_bytes of the given data.\n    // On error close the connection and throw.\n    void send(const char *data, size_t n_bytes)\n    {\n        ssize_t toslen = 0;\n        socklen_t tolen = sizeof(struct sockaddr);\n        if ((toslen = ::sendto(socket_, data, n_bytes, 0, (struct sockaddr *)&sockAddr_, tolen)) == -1)\n        {\n            throw_spdlog_ex(\"sendto(2) failed\", errno);\n        }\n    }\n};\n} // namespace details\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/details/windows_include.h",
    "content": "#pragma once\n\n#ifndef NOMINMAX\n#    define NOMINMAX // prevent windows redefining min/max\n#endif\n\n#ifndef WIN32_LEAN_AND_MEAN\n#    define WIN32_LEAN_AND_MEAN\n#endif\n\n#include <windows.h>\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bin_to_hex.h",
    "content": "//\n// Copyright(c) 2015 Gabi Melman.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n//\n\n#pragma once\n\n#include <cctype>\n#include <spdlog/common.h>\n\n#if defined(__has_include) && __has_include(<version>)\n#    include <version>\n#endif\n\n#if __cpp_lib_span >= 202002L\n#    include <span>\n#endif\n\n//\n// Support for logging binary data as hex\n// format flags, any combination of the following:\n// {:X} - print in uppercase.\n// {:s} - don't separate each byte with space.\n// {:p} - don't print the position on each line start.\n// {:n} - don't split the output to lines.\n// {:a} - show ASCII if :n is not set\n\n//\n// Examples:\n//\n// std::vector<char> v(200, 0x0b);\n// logger->info(\"Some buffer {}\", spdlog::to_hex(v));\n// char buf[128];\n// logger->info(\"Some buffer {:X}\", spdlog::to_hex(std::begin(buf), std::end(buf)));\n// logger->info(\"Some buffer {:X}\", spdlog::to_hex(std::begin(buf), std::end(buf), 16));\n\nnamespace spdlog {\nnamespace details {\n\ntemplate<typename It>\nclass dump_info\n{\npublic:\n    dump_info(It range_begin, It range_end, size_t size_per_line)\n        : begin_(range_begin)\n        , end_(range_end)\n        , size_per_line_(size_per_line)\n    {}\n\n    // do not use begin() and end() to avoid collision with fmt/ranges\n    It get_begin() const\n    {\n        return begin_;\n    }\n    It get_end() const\n    {\n        return end_;\n    }\n    size_t size_per_line() const\n    {\n        return size_per_line_;\n    }\n\nprivate:\n    It begin_, end_;\n    size_t size_per_line_;\n};\n} // namespace details\n\n// create a dump_info that wraps the given container\ntemplate<typename Container>\ninline details::dump_info<typename Container::const_iterator> to_hex(const Container &container, size_t size_per_line = 32)\n{\n    static_assert(sizeof(typename Container::value_type) == 1, \"sizeof(Container::value_type) != 1\");\n    using Iter = typename Container::const_iterator;\n    return details::dump_info<Iter>(std::begin(container), std::end(container), size_per_line);\n}\n\n#if __cpp_lib_span >= 202002L\n\ntemplate<typename Value, size_t Extent>\ninline details::dump_info<typename std::span<Value, Extent>::iterator> to_hex(\n    const std::span<Value, Extent> &container, size_t size_per_line = 32)\n{\n    using Container = std::span<Value, Extent>;\n    static_assert(sizeof(typename Container::value_type) == 1, \"sizeof(Container::value_type) != 1\");\n    using Iter = typename Container::iterator;\n    return details::dump_info<Iter>(std::begin(container), std::end(container), size_per_line);\n}\n\n#endif\n\n// create dump_info from ranges\ntemplate<typename It>\ninline details::dump_info<It> to_hex(const It range_begin, const It range_end, size_t size_per_line = 32)\n{\n    return details::dump_info<It>(range_begin, range_end, size_per_line);\n}\n\n} // namespace spdlog\n\nnamespace\n#ifdef SPDLOG_USE_STD_FORMAT\n    std\n#else\n    fmt\n#endif\n{\n\ntemplate<typename T>\nstruct formatter<spdlog::details::dump_info<T>, char>\n{\n    const char delimiter = ' ';\n    bool put_newlines = true;\n    bool put_delimiters = true;\n    bool use_uppercase = false;\n    bool put_positions = true; // position on start of each line\n    bool show_ascii = false;\n\n    // parse the format string flags\n    template<typename ParseContext>\n    SPDLOG_CONSTEXPR_FUNC auto parse(ParseContext &ctx) -> decltype(ctx.begin())\n    {\n        auto it = ctx.begin();\n        while (it != ctx.end() && *it != '}')\n        {\n            switch (*it)\n            {\n            case 'X':\n                use_uppercase = true;\n                break;\n            case 's':\n                put_delimiters = false;\n                break;\n            case 'p':\n                put_positions = false;\n                break;\n            case 'n':\n                put_newlines = false;\n                show_ascii = false;\n                break;\n            case 'a':\n                if (put_newlines)\n                {\n                    show_ascii = true;\n                }\n                break;\n            }\n\n            ++it;\n        }\n        return it;\n    }\n\n    // format the given bytes range as hex\n    template<typename FormatContext, typename Container>\n    auto format(const spdlog::details::dump_info<Container> &the_range, FormatContext &ctx) -> decltype(ctx.out())\n    {\n        SPDLOG_CONSTEXPR const char *hex_upper = \"0123456789ABCDEF\";\n        SPDLOG_CONSTEXPR const char *hex_lower = \"0123456789abcdef\";\n        const char *hex_chars = use_uppercase ? hex_upper : hex_lower;\n\n#if !defined(SPDLOG_USE_STD_FORMAT) && FMT_VERSION < 60000\n        auto inserter = ctx.begin();\n#else\n        auto inserter = ctx.out();\n#endif\n\n        int size_per_line = static_cast<int>(the_range.size_per_line());\n        auto start_of_line = the_range.get_begin();\n        for (auto i = the_range.get_begin(); i != the_range.get_end(); i++)\n        {\n            auto ch = static_cast<unsigned char>(*i);\n\n            if (put_newlines && (i == the_range.get_begin() || i - start_of_line >= size_per_line))\n            {\n                if (show_ascii && i != the_range.get_begin())\n                {\n                    *inserter++ = delimiter;\n                    *inserter++ = delimiter;\n                    for (auto j = start_of_line; j < i; j++)\n                    {\n                        auto pc = static_cast<unsigned char>(*j);\n                        *inserter++ = std::isprint(pc) ? static_cast<char>(*j) : '.';\n                    }\n                }\n\n                put_newline(inserter, static_cast<size_t>(i - the_range.get_begin()));\n\n                // put first byte without delimiter in front of it\n                *inserter++ = hex_chars[(ch >> 4) & 0x0f];\n                *inserter++ = hex_chars[ch & 0x0f];\n                start_of_line = i;\n                continue;\n            }\n\n            if (put_delimiters)\n            {\n                *inserter++ = delimiter;\n            }\n\n            *inserter++ = hex_chars[(ch >> 4) & 0x0f];\n            *inserter++ = hex_chars[ch & 0x0f];\n        }\n        if (show_ascii) // add ascii to last line\n        {\n            if (the_range.get_end() - the_range.get_begin() > size_per_line)\n            {\n                auto blank_num = size_per_line - (the_range.get_end() - start_of_line);\n                while (blank_num-- > 0)\n                {\n                    *inserter++ = delimiter;\n                    *inserter++ = delimiter;\n                    if (put_delimiters)\n                    {\n                        *inserter++ = delimiter;\n                    }\n                }\n            }\n            *inserter++ = delimiter;\n            *inserter++ = delimiter;\n            for (auto j = start_of_line; j != the_range.get_end(); j++)\n            {\n                auto pc = static_cast<unsigned char>(*j);\n                *inserter++ = std::isprint(pc) ? static_cast<char>(*j) : '.';\n            }\n        }\n        return inserter;\n    }\n\n    // put newline(and position header)\n    template<typename It>\n    void put_newline(It inserter, std::size_t pos)\n    {\n#ifdef _WIN32\n        *inserter++ = '\\r';\n#endif\n        *inserter++ = '\\n';\n\n        if (put_positions)\n        {\n            spdlog::fmt_lib::format_to(inserter, \"{:04X}: \", pos);\n        }\n    }\n};\n} // namespace std\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/LICENSE.rst",
    "content": "Copyright (c) 2012 - present, Victor Zverovich\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n--- Optional exception to the license ---\n\nAs an exception, if, as a result of your compiling your source code, portions\nof this Software are embedded into a machine-executable object form of such\nsource code, you may redistribute such embedded portions in such object form\nwithout including the above copyright and permission notices.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/args.h",
    "content": "// Formatting library for C++ - dynamic format arguments\n//\n// Copyright (c) 2012 - present, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_ARGS_H_\n#define FMT_ARGS_H_\n\n#include <functional>  // std::reference_wrapper\n#include <memory>      // std::unique_ptr\n#include <vector>\n\n#include \"core.h\"\n\nFMT_BEGIN_NAMESPACE\n\nnamespace detail {\n\ntemplate <typename T> struct is_reference_wrapper : std::false_type {};\ntemplate <typename T>\nstruct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};\n\ntemplate <typename T> const T& unwrap(const T& v) { return v; }\ntemplate <typename T> const T& unwrap(const std::reference_wrapper<T>& v) {\n  return static_cast<const T&>(v);\n}\n\nclass dynamic_arg_list {\n  // Workaround for clang's -Wweak-vtables. Unlike for regular classes, for\n  // templates it doesn't complain about inability to deduce single translation\n  // unit for placing vtable. So storage_node_base is made a fake template.\n  template <typename = void> struct node {\n    virtual ~node() = default;\n    std::unique_ptr<node<>> next;\n  };\n\n  template <typename T> struct typed_node : node<> {\n    T value;\n\n    template <typename Arg>\n    FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {}\n\n    template <typename Char>\n    FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg)\n        : value(arg.data(), arg.size()) {}\n  };\n\n  std::unique_ptr<node<>> head_;\n\n public:\n  template <typename T, typename Arg> const T& push(const Arg& arg) {\n    auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));\n    auto& value = new_node->value;\n    new_node->next = std::move(head_);\n    head_ = std::move(new_node);\n    return value;\n  }\n};\n}  // namespace detail\n\n/**\n  \\rst\n  A dynamic version of `fmt::format_arg_store`.\n  It's equipped with a storage to potentially temporary objects which lifetimes\n  could be shorter than the format arguments object.\n\n  It can be implicitly converted into `~fmt::basic_format_args` for passing\n  into type-erased formatting functions such as `~fmt::vformat`.\n  \\endrst\n */\ntemplate <typename Context>\nclass dynamic_format_arg_store\n#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409\n    // Workaround a GCC template argument substitution bug.\n    : public basic_format_args<Context>\n#endif\n{\n private:\n  using char_type = typename Context::char_type;\n\n  template <typename T> struct need_copy {\n    static constexpr detail::type mapped_type =\n        detail::mapped_type_constant<T, Context>::value;\n\n    enum {\n      value = !(detail::is_reference_wrapper<T>::value ||\n                std::is_same<T, basic_string_view<char_type>>::value ||\n                std::is_same<T, detail::std_string_view<char_type>>::value ||\n                (mapped_type != detail::type::cstring_type &&\n                 mapped_type != detail::type::string_type &&\n                 mapped_type != detail::type::custom_type))\n    };\n  };\n\n  template <typename T>\n  using stored_type = conditional_t<detail::is_string<T>::value &&\n                                        !has_formatter<T, Context>::value &&\n                                        !detail::is_reference_wrapper<T>::value,\n                                    std::basic_string<char_type>, T>;\n\n  // Storage of basic_format_arg must be contiguous.\n  std::vector<basic_format_arg<Context>> data_;\n  std::vector<detail::named_arg_info<char_type>> named_info_;\n\n  // Storage of arguments not fitting into basic_format_arg must grow\n  // without relocation because items in data_ refer to it.\n  detail::dynamic_arg_list dynamic_args_;\n\n  friend class basic_format_args<Context>;\n\n  unsigned long long get_types() const {\n    return detail::is_unpacked_bit | data_.size() |\n           (named_info_.empty()\n                ? 0ULL\n                : static_cast<unsigned long long>(detail::has_named_args_bit));\n  }\n\n  const basic_format_arg<Context>* data() const {\n    return named_info_.empty() ? data_.data() : data_.data() + 1;\n  }\n\n  template <typename T> void emplace_arg(const T& arg) {\n    data_.emplace_back(detail::make_arg<Context>(arg));\n  }\n\n  template <typename T>\n  void emplace_arg(const detail::named_arg<char_type, T>& arg) {\n    if (named_info_.empty()) {\n      constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr};\n      data_.insert(data_.begin(), {zero_ptr, 0});\n    }\n    data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));\n    auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {\n      data->pop_back();\n    };\n    std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>\n        guard{&data_, pop_one};\n    named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});\n    data_[0].value_.named_args = {named_info_.data(), named_info_.size()};\n    guard.release();\n  }\n\n public:\n  constexpr dynamic_format_arg_store() = default;\n\n  /**\n    \\rst\n    Adds an argument into the dynamic store for later passing to a formatting\n    function.\n\n    Note that custom types and string types (but not string views) are copied\n    into the store dynamically allocating memory if necessary.\n\n    **Example**::\n\n      fmt::dynamic_format_arg_store<fmt::format_context> store;\n      store.push_back(42);\n      store.push_back(\"abc\");\n      store.push_back(1.5f);\n      std::string result = fmt::vformat(\"{} and {} and {}\", store);\n    \\endrst\n  */\n  template <typename T> void push_back(const T& arg) {\n    if (detail::const_check(need_copy<T>::value))\n      emplace_arg(dynamic_args_.push<stored_type<T>>(arg));\n    else\n      emplace_arg(detail::unwrap(arg));\n  }\n\n  /**\n    \\rst\n    Adds a reference to the argument into the dynamic store for later passing to\n    a formatting function.\n\n    **Example**::\n\n      fmt::dynamic_format_arg_store<fmt::format_context> store;\n      char band[] = \"Rolling Stones\";\n      store.push_back(std::cref(band));\n      band[9] = 'c'; // Changing str affects the output.\n      std::string result = fmt::vformat(\"{}\", store);\n      // result == \"Rolling Scones\"\n    \\endrst\n  */\n  template <typename T> void push_back(std::reference_wrapper<T> arg) {\n    static_assert(\n        need_copy<T>::value,\n        \"objects of built-in types and string views are always copied\");\n    emplace_arg(arg.get());\n  }\n\n  /**\n    Adds named argument into the dynamic store for later passing to a formatting\n    function. ``std::reference_wrapper`` is supported to avoid copying of the\n    argument. The name is always copied into the store.\n  */\n  template <typename T>\n  void push_back(const detail::named_arg<char_type, T>& arg) {\n    const char_type* arg_name =\n        dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();\n    if (detail::const_check(need_copy<T>::value)) {\n      emplace_arg(\n          fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));\n    } else {\n      emplace_arg(fmt::arg(arg_name, arg.value));\n    }\n  }\n\n  /** Erase all elements from the store */\n  void clear() {\n    data_.clear();\n    named_info_.clear();\n    dynamic_args_ = detail::dynamic_arg_list();\n  }\n\n  /**\n    \\rst\n    Reserves space to store at least *new_cap* arguments including\n    *new_cap_named* named arguments.\n    \\endrst\n  */\n  void reserve(size_t new_cap, size_t new_cap_named) {\n    FMT_ASSERT(new_cap >= new_cap_named,\n               \"Set of arguments includes set of named arguments\");\n    data_.reserve(new_cap);\n    named_info_.reserve(new_cap_named);\n  }\n};\n\nFMT_END_NAMESPACE\n\n#endif  // FMT_ARGS_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/chrono.h",
    "content": "﻿// Formatting library for C++ - chrono support\n//\n// Copyright (c) 2012 - present, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_CHRONO_H_\n#define FMT_CHRONO_H_\n\n#include <algorithm>\n#include <chrono>\n#include <ctime>\n#include <iterator>\n#include <locale>\n#include <ostream>\n#include <type_traits>\n\n#include \"format.h\"\n\nFMT_BEGIN_NAMESPACE\n\n// Enable tzset.\n#ifndef FMT_USE_TZSET\n// UWP doesn't provide _tzset.\n#  if FMT_HAS_INCLUDE(\"winapifamily.h\")\n#    include <winapifamily.h>\n#  endif\n#  if defined(_WIN32) && (!defined(WINAPI_FAMILY) || \\\n                          (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))\n#    define FMT_USE_TZSET 1\n#  else\n#    define FMT_USE_TZSET 0\n#  endif\n#endif\n\n// Enable safe chrono durations, unless explicitly disabled.\n#ifndef FMT_SAFE_DURATION_CAST\n#  define FMT_SAFE_DURATION_CAST 1\n#endif\n#if FMT_SAFE_DURATION_CAST\n\n// For conversion between std::chrono::durations without undefined\n// behaviour or erroneous results.\n// This is a stripped down version of duration_cast, for inclusion in fmt.\n// See https://github.com/pauldreik/safe_duration_cast\n//\n// Copyright Paul Dreik 2019\nnamespace safe_duration_cast {\n\ntemplate <typename To, typename From,\n          FMT_ENABLE_IF(!std::is_same<From, To>::value &&\n                        std::numeric_limits<From>::is_signed ==\n                            std::numeric_limits<To>::is_signed)>\nFMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {\n  ec = 0;\n  using F = std::numeric_limits<From>;\n  using T = std::numeric_limits<To>;\n  static_assert(F::is_integer, \"From must be integral\");\n  static_assert(T::is_integer, \"To must be integral\");\n\n  // A and B are both signed, or both unsigned.\n  if (detail::const_check(F::digits <= T::digits)) {\n    // From fits in To without any problem.\n  } else {\n    // From does not always fit in To, resort to a dynamic check.\n    if (from < (T::min)() || from > (T::max)()) {\n      // outside range.\n      ec = 1;\n      return {};\n    }\n  }\n  return static_cast<To>(from);\n}\n\n/**\n * converts From to To, without loss. If the dynamic value of from\n * can't be converted to To without loss, ec is set.\n */\ntemplate <typename To, typename From,\n          FMT_ENABLE_IF(!std::is_same<From, To>::value &&\n                        std::numeric_limits<From>::is_signed !=\n                            std::numeric_limits<To>::is_signed)>\nFMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {\n  ec = 0;\n  using F = std::numeric_limits<From>;\n  using T = std::numeric_limits<To>;\n  static_assert(F::is_integer, \"From must be integral\");\n  static_assert(T::is_integer, \"To must be integral\");\n\n  if (detail::const_check(F::is_signed && !T::is_signed)) {\n    // From may be negative, not allowed!\n    if (fmt::detail::is_negative(from)) {\n      ec = 1;\n      return {};\n    }\n    // From is positive. Can it always fit in To?\n    if (detail::const_check(F::digits > T::digits) &&\n        from > static_cast<From>(detail::max_value<To>())) {\n      ec = 1;\n      return {};\n    }\n  }\n\n  if (detail::const_check(!F::is_signed && T::is_signed &&\n                          F::digits >= T::digits) &&\n      from > static_cast<From>(detail::max_value<To>())) {\n    ec = 1;\n    return {};\n  }\n  return static_cast<To>(from);  // Lossless conversion.\n}\n\ntemplate <typename To, typename From,\n          FMT_ENABLE_IF(std::is_same<From, To>::value)>\nFMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {\n  ec = 0;\n  return from;\n}  // function\n\n// clang-format off\n/**\n * converts From to To if possible, otherwise ec is set.\n *\n * input                            |    output\n * ---------------------------------|---------------\n * NaN                              | NaN\n * Inf                              | Inf\n * normal, fits in output           | converted (possibly lossy)\n * normal, does not fit in output   | ec is set\n * subnormal                        | best effort\n * -Inf                             | -Inf\n */\n// clang-format on\ntemplate <typename To, typename From,\n          FMT_ENABLE_IF(!std::is_same<From, To>::value)>\nFMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {\n  ec = 0;\n  using T = std::numeric_limits<To>;\n  static_assert(std::is_floating_point<From>::value, \"From must be floating\");\n  static_assert(std::is_floating_point<To>::value, \"To must be floating\");\n\n  // catch the only happy case\n  if (std::isfinite(from)) {\n    if (from >= T::lowest() && from <= (T::max)()) {\n      return static_cast<To>(from);\n    }\n    // not within range.\n    ec = 1;\n    return {};\n  }\n\n  // nan and inf will be preserved\n  return static_cast<To>(from);\n}  // function\n\ntemplate <typename To, typename From,\n          FMT_ENABLE_IF(std::is_same<From, To>::value)>\nFMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {\n  ec = 0;\n  static_assert(std::is_floating_point<From>::value, \"From must be floating\");\n  return from;\n}\n\n/**\n * safe duration cast between integral durations\n */\ntemplate <typename To, typename FromRep, typename FromPeriod,\n          FMT_ENABLE_IF(std::is_integral<FromRep>::value),\n          FMT_ENABLE_IF(std::is_integral<typename To::rep>::value)>\nTo safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,\n                      int& ec) {\n  using From = std::chrono::duration<FromRep, FromPeriod>;\n  ec = 0;\n  // the basic idea is that we need to convert from count() in the from type\n  // to count() in the To type, by multiplying it with this:\n  struct Factor\n      : std::ratio_divide<typename From::period, typename To::period> {};\n\n  static_assert(Factor::num > 0, \"num must be positive\");\n  static_assert(Factor::den > 0, \"den must be positive\");\n\n  // the conversion is like this: multiply from.count() with Factor::num\n  // /Factor::den and convert it to To::rep, all this without\n  // overflow/underflow. let's start by finding a suitable type that can hold\n  // both To, From and Factor::num\n  using IntermediateRep =\n      typename std::common_type<typename From::rep, typename To::rep,\n                                decltype(Factor::num)>::type;\n\n  // safe conversion to IntermediateRep\n  IntermediateRep count =\n      lossless_integral_conversion<IntermediateRep>(from.count(), ec);\n  if (ec) return {};\n  // multiply with Factor::num without overflow or underflow\n  if (detail::const_check(Factor::num != 1)) {\n    const auto max1 = detail::max_value<IntermediateRep>() / Factor::num;\n    if (count > max1) {\n      ec = 1;\n      return {};\n    }\n    const auto min1 =\n        (std::numeric_limits<IntermediateRep>::min)() / Factor::num;\n    if (count < min1) {\n      ec = 1;\n      return {};\n    }\n    count *= Factor::num;\n  }\n\n  if (detail::const_check(Factor::den != 1)) count /= Factor::den;\n  auto tocount = lossless_integral_conversion<typename To::rep>(count, ec);\n  return ec ? To() : To(tocount);\n}\n\n/**\n * safe duration_cast between floating point durations\n */\ntemplate <typename To, typename FromRep, typename FromPeriod,\n          FMT_ENABLE_IF(std::is_floating_point<FromRep>::value),\n          FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)>\nTo safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,\n                      int& ec) {\n  using From = std::chrono::duration<FromRep, FromPeriod>;\n  ec = 0;\n  if (std::isnan(from.count())) {\n    // nan in, gives nan out. easy.\n    return To{std::numeric_limits<typename To::rep>::quiet_NaN()};\n  }\n  // maybe we should also check if from is denormal, and decide what to do about\n  // it.\n\n  // +-inf should be preserved.\n  if (std::isinf(from.count())) {\n    return To{from.count()};\n  }\n\n  // the basic idea is that we need to convert from count() in the from type\n  // to count() in the To type, by multiplying it with this:\n  struct Factor\n      : std::ratio_divide<typename From::period, typename To::period> {};\n\n  static_assert(Factor::num > 0, \"num must be positive\");\n  static_assert(Factor::den > 0, \"den must be positive\");\n\n  // the conversion is like this: multiply from.count() with Factor::num\n  // /Factor::den and convert it to To::rep, all this without\n  // overflow/underflow. let's start by finding a suitable type that can hold\n  // both To, From and Factor::num\n  using IntermediateRep =\n      typename std::common_type<typename From::rep, typename To::rep,\n                                decltype(Factor::num)>::type;\n\n  // force conversion of From::rep -> IntermediateRep to be safe,\n  // even if it will never happen be narrowing in this context.\n  IntermediateRep count =\n      safe_float_conversion<IntermediateRep>(from.count(), ec);\n  if (ec) {\n    return {};\n  }\n\n  // multiply with Factor::num without overflow or underflow\n  if (detail::const_check(Factor::num != 1)) {\n    constexpr auto max1 = detail::max_value<IntermediateRep>() /\n                          static_cast<IntermediateRep>(Factor::num);\n    if (count > max1) {\n      ec = 1;\n      return {};\n    }\n    constexpr auto min1 = std::numeric_limits<IntermediateRep>::lowest() /\n                          static_cast<IntermediateRep>(Factor::num);\n    if (count < min1) {\n      ec = 1;\n      return {};\n    }\n    count *= static_cast<IntermediateRep>(Factor::num);\n  }\n\n  // this can't go wrong, right? den>0 is checked earlier.\n  if (detail::const_check(Factor::den != 1)) {\n    using common_t = typename std::common_type<IntermediateRep, intmax_t>::type;\n    count /= static_cast<common_t>(Factor::den);\n  }\n\n  // convert to the to type, safely\n  using ToRep = typename To::rep;\n\n  const ToRep tocount = safe_float_conversion<ToRep>(count, ec);\n  if (ec) {\n    return {};\n  }\n  return To{tocount};\n}\n}  // namespace safe_duration_cast\n#endif\n\n// Prevents expansion of a preceding token as a function-style macro.\n// Usage: f FMT_NOMACRO()\n#define FMT_NOMACRO\n\nnamespace detail {\ntemplate <typename T = void> struct null {};\ninline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }\ninline null<> localtime_s(...) { return null<>(); }\ninline null<> gmtime_r(...) { return null<>(); }\ninline null<> gmtime_s(...) { return null<>(); }\n\ninline const std::locale& get_classic_locale() {\n  static const auto& locale = std::locale::classic();\n  return locale;\n}\n\ntemplate <typename CodeUnit> struct codecvt_result {\n  static constexpr const size_t max_size = 32;\n  CodeUnit buf[max_size];\n  CodeUnit* end;\n};\ntemplate <typename CodeUnit>\nconstexpr const size_t codecvt_result<CodeUnit>::max_size;\n\ntemplate <typename CodeUnit>\nvoid write_codecvt(codecvt_result<CodeUnit>& out, string_view in_buf,\n                   const std::locale& loc) {\n  using codecvt = std::codecvt<CodeUnit, char, std::mbstate_t>;\n#if FMT_CLANG_VERSION\n#  pragma clang diagnostic push\n#  pragma clang diagnostic ignored \"-Wdeprecated\"\n  auto& f = std::use_facet<codecvt>(loc);\n#  pragma clang diagnostic pop\n#else\n  auto& f = std::use_facet<codecvt>(loc);\n#endif\n  auto mb = std::mbstate_t();\n  const char* from_next = nullptr;\n  auto result = f.in(mb, in_buf.begin(), in_buf.end(), from_next,\n                     std::begin(out.buf), std::end(out.buf), out.end);\n  if (result != std::codecvt_base::ok)\n    FMT_THROW(format_error(\"failed to format time\"));\n}\n\ntemplate <typename OutputIt>\nauto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc)\n    -> OutputIt {\n  if (detail::is_utf8() && loc != get_classic_locale()) {\n    // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and\n    // gcc-4.\n#if FMT_MSC_VER != 0 || \\\n    (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))\n    // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5\n    // and newer.\n    using code_unit = wchar_t;\n#else\n    using code_unit = char32_t;\n#endif\n\n    using unit_t = codecvt_result<code_unit>;\n    unit_t unit;\n    write_codecvt(unit, in, loc);\n    // In UTF-8 is used one to four one-byte code units.\n    auto&& buf = basic_memory_buffer<char, unit_t::max_size * 4>();\n    for (code_unit* p = unit.buf; p != unit.end; ++p) {\n      uint32_t c = static_cast<uint32_t>(*p);\n      if (sizeof(code_unit) == 2 && c >= 0xd800 && c <= 0xdfff) {\n        // surrogate pair\n        ++p;\n        if (p == unit.end || (c & 0xfc00) != 0xd800 ||\n            (*p & 0xfc00) != 0xdc00) {\n          FMT_THROW(format_error(\"failed to format time\"));\n        }\n        c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00;\n      }\n      if (c < 0x80) {\n        buf.push_back(static_cast<char>(c));\n      } else if (c < 0x800) {\n        buf.push_back(static_cast<char>(0xc0 | (c >> 6)));\n        buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));\n      } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) {\n        buf.push_back(static_cast<char>(0xe0 | (c >> 12)));\n        buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));\n        buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));\n      } else if (c >= 0x10000 && c <= 0x10ffff) {\n        buf.push_back(static_cast<char>(0xf0 | (c >> 18)));\n        buf.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12)));\n        buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));\n        buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));\n      } else {\n        FMT_THROW(format_error(\"failed to format time\"));\n      }\n    }\n    return copy_str<char>(buf.data(), buf.data() + buf.size(), out);\n  }\n  return copy_str<char>(in.data(), in.data() + in.size(), out);\n}\n\ntemplate <typename Char, typename OutputIt,\n          FMT_ENABLE_IF(!std::is_same<Char, char>::value)>\nauto write_tm_str(OutputIt out, string_view sv, const std::locale& loc)\n    -> OutputIt {\n  codecvt_result<Char> unit;\n  write_codecvt(unit, sv, loc);\n  return copy_str<Char>(unit.buf, unit.end, out);\n}\n\ntemplate <typename Char, typename OutputIt,\n          FMT_ENABLE_IF(std::is_same<Char, char>::value)>\nauto write_tm_str(OutputIt out, string_view sv, const std::locale& loc)\n    -> OutputIt {\n  return write_encoded_tm_str(out, sv, loc);\n}\n\ntemplate <typename Char>\ninline void do_write(buffer<Char>& buf, const std::tm& time,\n                     const std::locale& loc, char format, char modifier) {\n  auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);\n  auto&& os = std::basic_ostream<Char>(&format_buf);\n  os.imbue(loc);\n  using iterator = std::ostreambuf_iterator<Char>;\n  const auto& facet = std::use_facet<std::time_put<Char, iterator>>(loc);\n  auto end = facet.put(os, os, Char(' '), &time, format, modifier);\n  if (end.failed()) FMT_THROW(format_error(\"failed to format time\"));\n}\n\ntemplate <typename Char, typename OutputIt,\n          FMT_ENABLE_IF(!std::is_same<Char, char>::value)>\nauto write(OutputIt out, const std::tm& time, const std::locale& loc,\n           char format, char modifier = 0) -> OutputIt {\n  auto&& buf = get_buffer<Char>(out);\n  do_write<Char>(buf, time, loc, format, modifier);\n  return buf.out();\n}\n\ntemplate <typename Char, typename OutputIt,\n          FMT_ENABLE_IF(std::is_same<Char, char>::value)>\nauto write(OutputIt out, const std::tm& time, const std::locale& loc,\n           char format, char modifier = 0) -> OutputIt {\n  auto&& buf = basic_memory_buffer<Char>();\n  do_write<char>(buf, time, loc, format, modifier);\n  return write_encoded_tm_str(out, string_view(buf.data(), buf.size()), loc);\n}\n\n}  // namespace detail\n\nFMT_MODULE_EXPORT_BEGIN\n\n/**\n  Converts given time since epoch as ``std::time_t`` value into calendar time,\n  expressed in local time. Unlike ``std::localtime``, this function is\n  thread-safe on most platforms.\n */\ninline std::tm localtime(std::time_t time) {\n  struct dispatcher {\n    std::time_t time_;\n    std::tm tm_;\n\n    dispatcher(std::time_t t) : time_(t) {}\n\n    bool run() {\n      using namespace fmt::detail;\n      return handle(localtime_r(&time_, &tm_));\n    }\n\n    bool handle(std::tm* tm) { return tm != nullptr; }\n\n    bool handle(detail::null<>) {\n      using namespace fmt::detail;\n      return fallback(localtime_s(&tm_, &time_));\n    }\n\n    bool fallback(int res) { return res == 0; }\n\n#if !FMT_MSC_VER\n    bool fallback(detail::null<>) {\n      using namespace fmt::detail;\n      std::tm* tm = std::localtime(&time_);\n      if (tm) tm_ = *tm;\n      return tm != nullptr;\n    }\n#endif\n  };\n  dispatcher lt(time);\n  // Too big time values may be unsupported.\n  if (!lt.run()) FMT_THROW(format_error(\"time_t value out of range\"));\n  return lt.tm_;\n}\n\ninline std::tm localtime(\n    std::chrono::time_point<std::chrono::system_clock> time_point) {\n  return localtime(std::chrono::system_clock::to_time_t(time_point));\n}\n\n/**\n  Converts given time since epoch as ``std::time_t`` value into calendar time,\n  expressed in Coordinated Universal Time (UTC). Unlike ``std::gmtime``, this\n  function is thread-safe on most platforms.\n */\ninline std::tm gmtime(std::time_t time) {\n  struct dispatcher {\n    std::time_t time_;\n    std::tm tm_;\n\n    dispatcher(std::time_t t) : time_(t) {}\n\n    bool run() {\n      using namespace fmt::detail;\n      return handle(gmtime_r(&time_, &tm_));\n    }\n\n    bool handle(std::tm* tm) { return tm != nullptr; }\n\n    bool handle(detail::null<>) {\n      using namespace fmt::detail;\n      return fallback(gmtime_s(&tm_, &time_));\n    }\n\n    bool fallback(int res) { return res == 0; }\n\n#if !FMT_MSC_VER\n    bool fallback(detail::null<>) {\n      std::tm* tm = std::gmtime(&time_);\n      if (tm) tm_ = *tm;\n      return tm != nullptr;\n    }\n#endif\n  };\n  dispatcher gt(time);\n  // Too big time values may be unsupported.\n  if (!gt.run()) FMT_THROW(format_error(\"time_t value out of range\"));\n  return gt.tm_;\n}\n\ninline std::tm gmtime(\n    std::chrono::time_point<std::chrono::system_clock> time_point) {\n  return gmtime(std::chrono::system_clock::to_time_t(time_point));\n}\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\n// Writes two-digit numbers a, b and c separated by sep to buf.\n// The method by Pavel Novikov based on\n// https://johnnylee-sde.github.io/Fast-unsigned-integer-to-time-string/.\ninline void write_digit2_separated(char* buf, unsigned a, unsigned b,\n                                   unsigned c, char sep) {\n  unsigned long long digits =\n      a | (b << 24) | (static_cast<unsigned long long>(c) << 48);\n  // Convert each value to BCD.\n  // We have x = a * 10 + b and we want to convert it to BCD y = a * 16 + b.\n  // The difference is\n  //   y - x = a * 6\n  // a can be found from x:\n  //   a = floor(x / 10)\n  // then\n  //   y = x + a * 6 = x + floor(x / 10) * 6\n  // floor(x / 10) is (x * 205) >> 11 (needs 16 bits).\n  digits += (((digits * 205) >> 11) & 0x000f00000f00000f) * 6;\n  // Put low nibbles to high bytes and high nibbles to low bytes.\n  digits = ((digits & 0x00f00000f00000f0) >> 4) |\n           ((digits & 0x000f00000f00000f) << 8);\n  auto usep = static_cast<unsigned long long>(sep);\n  // Add ASCII '0' to each digit byte and insert separators.\n  digits |= 0x3030003030003030 | (usep << 16) | (usep << 40);\n\n  constexpr const size_t len = 8;\n  if (const_check(is_big_endian())) {\n    char tmp[len];\n    memcpy(tmp, &digits, len);\n    std::reverse_copy(tmp, tmp + len, buf);\n  } else {\n    memcpy(buf, &digits, len);\n  }\n}\n\ntemplate <typename Period> FMT_CONSTEXPR inline const char* get_units() {\n  if (std::is_same<Period, std::atto>::value) return \"as\";\n  if (std::is_same<Period, std::femto>::value) return \"fs\";\n  if (std::is_same<Period, std::pico>::value) return \"ps\";\n  if (std::is_same<Period, std::nano>::value) return \"ns\";\n  if (std::is_same<Period, std::micro>::value) return \"µs\";\n  if (std::is_same<Period, std::milli>::value) return \"ms\";\n  if (std::is_same<Period, std::centi>::value) return \"cs\";\n  if (std::is_same<Period, std::deci>::value) return \"ds\";\n  if (std::is_same<Period, std::ratio<1>>::value) return \"s\";\n  if (std::is_same<Period, std::deca>::value) return \"das\";\n  if (std::is_same<Period, std::hecto>::value) return \"hs\";\n  if (std::is_same<Period, std::kilo>::value) return \"ks\";\n  if (std::is_same<Period, std::mega>::value) return \"Ms\";\n  if (std::is_same<Period, std::giga>::value) return \"Gs\";\n  if (std::is_same<Period, std::tera>::value) return \"Ts\";\n  if (std::is_same<Period, std::peta>::value) return \"Ps\";\n  if (std::is_same<Period, std::exa>::value) return \"Es\";\n  if (std::is_same<Period, std::ratio<60>>::value) return \"m\";\n  if (std::is_same<Period, std::ratio<3600>>::value) return \"h\";\n  return nullptr;\n}\n\nenum class numeric_system {\n  standard,\n  // Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale.\n  alternative\n};\n\n// Parses a put_time-like format string and invokes handler actions.\ntemplate <typename Char, typename Handler>\nFMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,\n                                              const Char* end,\n                                              Handler&& handler) {\n  auto ptr = begin;\n  while (ptr != end) {\n    auto c = *ptr;\n    if (c == '}') break;\n    if (c != '%') {\n      ++ptr;\n      continue;\n    }\n    if (begin != ptr) handler.on_text(begin, ptr);\n    ++ptr;  // consume '%'\n    if (ptr == end) FMT_THROW(format_error(\"invalid format\"));\n    c = *ptr++;\n    switch (c) {\n    case '%':\n      handler.on_text(ptr - 1, ptr);\n      break;\n    case 'n': {\n      const Char newline[] = {'\\n'};\n      handler.on_text(newline, newline + 1);\n      break;\n    }\n    case 't': {\n      const Char tab[] = {'\\t'};\n      handler.on_text(tab, tab + 1);\n      break;\n    }\n    // Year:\n    case 'Y':\n      handler.on_year(numeric_system::standard);\n      break;\n    case 'y':\n      handler.on_short_year(numeric_system::standard);\n      break;\n    case 'C':\n      handler.on_century(numeric_system::standard);\n      break;\n    case 'G':\n      handler.on_iso_week_based_year();\n      break;\n    case 'g':\n      handler.on_iso_week_based_short_year();\n      break;\n    // Day of the week:\n    case 'a':\n      handler.on_abbr_weekday();\n      break;\n    case 'A':\n      handler.on_full_weekday();\n      break;\n    case 'w':\n      handler.on_dec0_weekday(numeric_system::standard);\n      break;\n    case 'u':\n      handler.on_dec1_weekday(numeric_system::standard);\n      break;\n    // Month:\n    case 'b':\n    case 'h':\n      handler.on_abbr_month();\n      break;\n    case 'B':\n      handler.on_full_month();\n      break;\n    case 'm':\n      handler.on_dec_month(numeric_system::standard);\n      break;\n    // Day of the year/month:\n    case 'U':\n      handler.on_dec0_week_of_year(numeric_system::standard);\n      break;\n    case 'W':\n      handler.on_dec1_week_of_year(numeric_system::standard);\n      break;\n    case 'V':\n      handler.on_iso_week_of_year(numeric_system::standard);\n      break;\n    case 'j':\n      handler.on_day_of_year();\n      break;\n    case 'd':\n      handler.on_day_of_month(numeric_system::standard);\n      break;\n    case 'e':\n      handler.on_day_of_month_space(numeric_system::standard);\n      break;\n    // Hour, minute, second:\n    case 'H':\n      handler.on_24_hour(numeric_system::standard);\n      break;\n    case 'I':\n      handler.on_12_hour(numeric_system::standard);\n      break;\n    case 'M':\n      handler.on_minute(numeric_system::standard);\n      break;\n    case 'S':\n      handler.on_second(numeric_system::standard);\n      break;\n    // Other:\n    case 'c':\n      handler.on_datetime(numeric_system::standard);\n      break;\n    case 'x':\n      handler.on_loc_date(numeric_system::standard);\n      break;\n    case 'X':\n      handler.on_loc_time(numeric_system::standard);\n      break;\n    case 'D':\n      handler.on_us_date();\n      break;\n    case 'F':\n      handler.on_iso_date();\n      break;\n    case 'r':\n      handler.on_12_hour_time();\n      break;\n    case 'R':\n      handler.on_24_hour_time();\n      break;\n    case 'T':\n      handler.on_iso_time();\n      break;\n    case 'p':\n      handler.on_am_pm();\n      break;\n    case 'Q':\n      handler.on_duration_value();\n      break;\n    case 'q':\n      handler.on_duration_unit();\n      break;\n    case 'z':\n      handler.on_utc_offset();\n      break;\n    case 'Z':\n      handler.on_tz_name();\n      break;\n    // Alternative representation:\n    case 'E': {\n      if (ptr == end) FMT_THROW(format_error(\"invalid format\"));\n      c = *ptr++;\n      switch (c) {\n      case 'Y':\n        handler.on_year(numeric_system::alternative);\n        break;\n      case 'y':\n        handler.on_offset_year();\n        break;\n      case 'C':\n        handler.on_century(numeric_system::alternative);\n        break;\n      case 'c':\n        handler.on_datetime(numeric_system::alternative);\n        break;\n      case 'x':\n        handler.on_loc_date(numeric_system::alternative);\n        break;\n      case 'X':\n        handler.on_loc_time(numeric_system::alternative);\n        break;\n      default:\n        FMT_THROW(format_error(\"invalid format\"));\n      }\n      break;\n    }\n    case 'O':\n      if (ptr == end) FMT_THROW(format_error(\"invalid format\"));\n      c = *ptr++;\n      switch (c) {\n      case 'y':\n        handler.on_short_year(numeric_system::alternative);\n        break;\n      case 'm':\n        handler.on_dec_month(numeric_system::alternative);\n        break;\n      case 'U':\n        handler.on_dec0_week_of_year(numeric_system::alternative);\n        break;\n      case 'W':\n        handler.on_dec1_week_of_year(numeric_system::alternative);\n        break;\n      case 'V':\n        handler.on_iso_week_of_year(numeric_system::alternative);\n        break;\n      case 'd':\n        handler.on_day_of_month(numeric_system::alternative);\n        break;\n      case 'e':\n        handler.on_day_of_month_space(numeric_system::alternative);\n        break;\n      case 'w':\n        handler.on_dec0_weekday(numeric_system::alternative);\n        break;\n      case 'u':\n        handler.on_dec1_weekday(numeric_system::alternative);\n        break;\n      case 'H':\n        handler.on_24_hour(numeric_system::alternative);\n        break;\n      case 'I':\n        handler.on_12_hour(numeric_system::alternative);\n        break;\n      case 'M':\n        handler.on_minute(numeric_system::alternative);\n        break;\n      case 'S':\n        handler.on_second(numeric_system::alternative);\n        break;\n      default:\n        FMT_THROW(format_error(\"invalid format\"));\n      }\n      break;\n    default:\n      FMT_THROW(format_error(\"invalid format\"));\n    }\n    begin = ptr;\n  }\n  if (begin != ptr) handler.on_text(begin, ptr);\n  return ptr;\n}\n\ntemplate <typename Derived> struct null_chrono_spec_handler {\n  FMT_CONSTEXPR void unsupported() {\n    static_cast<Derived*>(this)->unsupported();\n  }\n  FMT_CONSTEXPR void on_year(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_short_year(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_offset_year() { unsupported(); }\n  FMT_CONSTEXPR void on_century(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_iso_week_based_year() { unsupported(); }\n  FMT_CONSTEXPR void on_iso_week_based_short_year() { unsupported(); }\n  FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); }\n  FMT_CONSTEXPR void on_full_weekday() { unsupported(); }\n  FMT_CONSTEXPR void on_dec0_weekday(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_dec1_weekday(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_abbr_month() { unsupported(); }\n  FMT_CONSTEXPR void on_full_month() { unsupported(); }\n  FMT_CONSTEXPR void on_dec_month(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_day_of_year() { unsupported(); }\n  FMT_CONSTEXPR void on_day_of_month(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_day_of_month_space(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_second(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_datetime(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_loc_date(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_loc_time(numeric_system) { unsupported(); }\n  FMT_CONSTEXPR void on_us_date() { unsupported(); }\n  FMT_CONSTEXPR void on_iso_date() { unsupported(); }\n  FMT_CONSTEXPR void on_12_hour_time() { unsupported(); }\n  FMT_CONSTEXPR void on_24_hour_time() { unsupported(); }\n  FMT_CONSTEXPR void on_iso_time() { unsupported(); }\n  FMT_CONSTEXPR void on_am_pm() { unsupported(); }\n  FMT_CONSTEXPR void on_duration_value() { unsupported(); }\n  FMT_CONSTEXPR void on_duration_unit() { unsupported(); }\n  FMT_CONSTEXPR void on_utc_offset() { unsupported(); }\n  FMT_CONSTEXPR void on_tz_name() { unsupported(); }\n};\n\nstruct tm_format_checker : null_chrono_spec_handler<tm_format_checker> {\n  FMT_NORETURN void unsupported() { FMT_THROW(format_error(\"no format\")); }\n\n  template <typename Char>\n  FMT_CONSTEXPR void on_text(const Char*, const Char*) {}\n  FMT_CONSTEXPR void on_year(numeric_system) {}\n  FMT_CONSTEXPR void on_short_year(numeric_system) {}\n  FMT_CONSTEXPR void on_offset_year() {}\n  FMT_CONSTEXPR void on_century(numeric_system) {}\n  FMT_CONSTEXPR void on_iso_week_based_year() {}\n  FMT_CONSTEXPR void on_iso_week_based_short_year() {}\n  FMT_CONSTEXPR void on_abbr_weekday() {}\n  FMT_CONSTEXPR void on_full_weekday() {}\n  FMT_CONSTEXPR void on_dec0_weekday(numeric_system) {}\n  FMT_CONSTEXPR void on_dec1_weekday(numeric_system) {}\n  FMT_CONSTEXPR void on_abbr_month() {}\n  FMT_CONSTEXPR void on_full_month() {}\n  FMT_CONSTEXPR void on_dec_month(numeric_system) {}\n  FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) {}\n  FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) {}\n  FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) {}\n  FMT_CONSTEXPR void on_day_of_year() {}\n  FMT_CONSTEXPR void on_day_of_month(numeric_system) {}\n  FMT_CONSTEXPR void on_day_of_month_space(numeric_system) {}\n  FMT_CONSTEXPR void on_24_hour(numeric_system) {}\n  FMT_CONSTEXPR void on_12_hour(numeric_system) {}\n  FMT_CONSTEXPR void on_minute(numeric_system) {}\n  FMT_CONSTEXPR void on_second(numeric_system) {}\n  FMT_CONSTEXPR void on_datetime(numeric_system) {}\n  FMT_CONSTEXPR void on_loc_date(numeric_system) {}\n  FMT_CONSTEXPR void on_loc_time(numeric_system) {}\n  FMT_CONSTEXPR void on_us_date() {}\n  FMT_CONSTEXPR void on_iso_date() {}\n  FMT_CONSTEXPR void on_12_hour_time() {}\n  FMT_CONSTEXPR void on_24_hour_time() {}\n  FMT_CONSTEXPR void on_iso_time() {}\n  FMT_CONSTEXPR void on_am_pm() {}\n  FMT_CONSTEXPR void on_utc_offset() {}\n  FMT_CONSTEXPR void on_tz_name() {}\n};\n\ninline const char* tm_wday_full_name(int wday) {\n  static constexpr const char* full_name_list[] = {\n      \"Sunday\",   \"Monday\", \"Tuesday\", \"Wednesday\",\n      \"Thursday\", \"Friday\", \"Saturday\"};\n  return wday >= 0 && wday <= 6 ? full_name_list[wday] : \"?\";\n}\ninline const char* tm_wday_short_name(int wday) {\n  static constexpr const char* short_name_list[] = {\"Sun\", \"Mon\", \"Tue\", \"Wed\",\n                                                    \"Thu\", \"Fri\", \"Sat\"};\n  return wday >= 0 && wday <= 6 ? short_name_list[wday] : \"???\";\n}\n\ninline const char* tm_mon_full_name(int mon) {\n  static constexpr const char* full_name_list[] = {\n      \"January\", \"February\", \"March\",     \"April\",   \"May\",      \"June\",\n      \"July\",    \"August\",   \"September\", \"October\", \"November\", \"December\"};\n  return mon >= 0 && mon <= 11 ? full_name_list[mon] : \"?\";\n}\ninline const char* tm_mon_short_name(int mon) {\n  static constexpr const char* short_name_list[] = {\n      \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n      \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\",\n  };\n  return mon >= 0 && mon <= 11 ? short_name_list[mon] : \"???\";\n}\n\ntemplate <typename T, typename = void>\nstruct has_member_data_tm_gmtoff : std::false_type {};\ntemplate <typename T>\nstruct has_member_data_tm_gmtoff<T, void_t<decltype(T::tm_gmtoff)>>\n    : std::true_type {};\n\ntemplate <typename T, typename = void>\nstruct has_member_data_tm_zone : std::false_type {};\ntemplate <typename T>\nstruct has_member_data_tm_zone<T, void_t<decltype(T::tm_zone)>>\n    : std::true_type {};\n\n#if FMT_USE_TZSET\ninline void tzset_once() {\n  static bool init = []() -> bool {\n    _tzset();\n    return true;\n  }();\n  ignore_unused(init);\n}\n#endif\n\ntemplate <typename OutputIt, typename Char> class tm_writer {\n private:\n  static constexpr int days_per_week = 7;\n\n  const std::locale& loc_;\n  const bool is_classic_;\n  OutputIt out_;\n  const std::tm& tm_;\n\n  auto tm_sec() const noexcept -> int {\n    FMT_ASSERT(tm_.tm_sec >= 0 && tm_.tm_sec <= 61, \"\");\n    return tm_.tm_sec;\n  }\n  auto tm_min() const noexcept -> int {\n    FMT_ASSERT(tm_.tm_min >= 0 && tm_.tm_min <= 59, \"\");\n    return tm_.tm_min;\n  }\n  auto tm_hour() const noexcept -> int {\n    FMT_ASSERT(tm_.tm_hour >= 0 && tm_.tm_hour <= 23, \"\");\n    return tm_.tm_hour;\n  }\n  auto tm_mday() const noexcept -> int {\n    FMT_ASSERT(tm_.tm_mday >= 1 && tm_.tm_mday <= 31, \"\");\n    return tm_.tm_mday;\n  }\n  auto tm_mon() const noexcept -> int {\n    FMT_ASSERT(tm_.tm_mon >= 0 && tm_.tm_mon <= 11, \"\");\n    return tm_.tm_mon;\n  }\n  auto tm_year() const noexcept -> long long { return 1900ll + tm_.tm_year; }\n  auto tm_wday() const noexcept -> int {\n    FMT_ASSERT(tm_.tm_wday >= 0 && tm_.tm_wday <= 6, \"\");\n    return tm_.tm_wday;\n  }\n  auto tm_yday() const noexcept -> int {\n    FMT_ASSERT(tm_.tm_yday >= 0 && tm_.tm_yday <= 365, \"\");\n    return tm_.tm_yday;\n  }\n\n  auto tm_hour12() const noexcept -> int {\n    const auto h = tm_hour();\n    const auto z = h < 12 ? h : h - 12;\n    return z == 0 ? 12 : z;\n  }\n\n  // POSIX and the C Standard are unclear or inconsistent about what %C and %y\n  // do if the year is negative or exceeds 9999. Use the convention that %C\n  // concatenated with %y yields the same output as %Y, and that %Y contains at\n  // least 4 characters, with more only if necessary.\n  auto split_year_lower(long long year) const noexcept -> int {\n    auto l = year % 100;\n    if (l < 0) l = -l;  // l in [0, 99]\n    return static_cast<int>(l);\n  }\n\n  // Algorithm:\n  // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_from_a_month_and_day_of_the_month_or_ordinal_date\n  auto iso_year_weeks(long long curr_year) const noexcept -> int {\n    const auto prev_year = curr_year - 1;\n    const auto curr_p =\n        (curr_year + curr_year / 4 - curr_year / 100 + curr_year / 400) %\n        days_per_week;\n    const auto prev_p =\n        (prev_year + prev_year / 4 - prev_year / 100 + prev_year / 400) %\n        days_per_week;\n    return 52 + ((curr_p == 4 || prev_p == 3) ? 1 : 0);\n  }\n  auto iso_week_num(int tm_yday, int tm_wday) const noexcept -> int {\n    return (tm_yday + 11 - (tm_wday == 0 ? days_per_week : tm_wday)) /\n           days_per_week;\n  }\n  auto tm_iso_week_year() const noexcept -> long long {\n    const auto year = tm_year();\n    const auto w = iso_week_num(tm_yday(), tm_wday());\n    if (w < 1) return year - 1;\n    if (w > iso_year_weeks(year)) return year + 1;\n    return year;\n  }\n  auto tm_iso_week_of_year() const noexcept -> int {\n    const auto year = tm_year();\n    const auto w = iso_week_num(tm_yday(), tm_wday());\n    if (w < 1) return iso_year_weeks(year - 1);\n    if (w > iso_year_weeks(year)) return 1;\n    return w;\n  }\n\n  void write1(int value) {\n    *out_++ = static_cast<char>('0' + to_unsigned(value) % 10);\n  }\n  void write2(int value) {\n    const char* d = digits2(to_unsigned(value) % 100);\n    *out_++ = *d++;\n    *out_++ = *d;\n  }\n\n  void write_year_extended(long long year) {\n    // At least 4 characters.\n    int width = 4;\n    if (year < 0) {\n      *out_++ = '-';\n      year = 0 - year;\n      --width;\n    }\n    uint32_or_64_or_128_t<long long> n = to_unsigned(year);\n    const int num_digits = count_digits(n);\n    if (width > num_digits) out_ = std::fill_n(out_, width - num_digits, '0');\n    out_ = format_decimal<Char>(out_, n, num_digits).end;\n  }\n  void write_year(long long year) {\n    if (year >= 0 && year < 10000) {\n      write2(static_cast<int>(year / 100));\n      write2(static_cast<int>(year % 100));\n    } else {\n      write_year_extended(year);\n    }\n  }\n\n  void write_utc_offset(long offset) {\n    if (offset < 0) {\n      *out_++ = '-';\n      offset = -offset;\n    } else {\n      *out_++ = '+';\n    }\n    offset /= 60;\n    write2(static_cast<int>(offset / 60));\n    write2(static_cast<int>(offset % 60));\n  }\n  template <typename T, FMT_ENABLE_IF(has_member_data_tm_gmtoff<T>::value)>\n  void format_utc_offset_impl(const T& tm) {\n    write_utc_offset(tm.tm_gmtoff);\n  }\n  template <typename T, FMT_ENABLE_IF(!has_member_data_tm_gmtoff<T>::value)>\n  void format_utc_offset_impl(const T& tm) {\n#if defined(_WIN32) && defined(_UCRT)\n#  if FMT_USE_TZSET\n    tzset_once();\n#  endif\n    long offset = 0;\n    _get_timezone(&offset);\n    if (tm.tm_isdst) {\n      long dstbias = 0;\n      _get_dstbias(&dstbias);\n      offset += dstbias;\n    }\n    write_utc_offset(-offset);\n#else\n    ignore_unused(tm);\n    format_localized('z');\n#endif\n  }\n\n  template <typename T, FMT_ENABLE_IF(has_member_data_tm_zone<T>::value)>\n  void format_tz_name_impl(const T& tm) {\n    if (is_classic_)\n      out_ = write_tm_str<Char>(out_, tm.tm_zone, loc_);\n    else\n      format_localized('Z');\n  }\n  template <typename T, FMT_ENABLE_IF(!has_member_data_tm_zone<T>::value)>\n  void format_tz_name_impl(const T&) {\n    format_localized('Z');\n  }\n\n  void format_localized(char format, char modifier = 0) {\n    out_ = write<Char>(out_, tm_, loc_, format, modifier);\n  }\n\n public:\n  tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm)\n      : loc_(loc),\n        is_classic_(loc_ == get_classic_locale()),\n        out_(out),\n        tm_(tm) {}\n\n  OutputIt out() const { return out_; }\n\n  FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) {\n    out_ = copy_str<Char>(begin, end, out_);\n  }\n\n  void on_abbr_weekday() {\n    if (is_classic_)\n      out_ = write(out_, tm_wday_short_name(tm_wday()));\n    else\n      format_localized('a');\n  }\n  void on_full_weekday() {\n    if (is_classic_)\n      out_ = write(out_, tm_wday_full_name(tm_wday()));\n    else\n      format_localized('A');\n  }\n  void on_dec0_weekday(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard) return write1(tm_wday());\n    format_localized('w', 'O');\n  }\n  void on_dec1_weekday(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard) {\n      auto wday = tm_wday();\n      write1(wday == 0 ? days_per_week : wday);\n    } else {\n      format_localized('u', 'O');\n    }\n  }\n\n  void on_abbr_month() {\n    if (is_classic_)\n      out_ = write(out_, tm_mon_short_name(tm_mon()));\n    else\n      format_localized('b');\n  }\n  void on_full_month() {\n    if (is_classic_)\n      out_ = write(out_, tm_mon_full_name(tm_mon()));\n    else\n      format_localized('B');\n  }\n\n  void on_datetime(numeric_system ns) {\n    if (is_classic_) {\n      on_abbr_weekday();\n      *out_++ = ' ';\n      on_abbr_month();\n      *out_++ = ' ';\n      on_day_of_month_space(numeric_system::standard);\n      *out_++ = ' ';\n      on_iso_time();\n      *out_++ = ' ';\n      on_year(numeric_system::standard);\n    } else {\n      format_localized('c', ns == numeric_system::standard ? '\\0' : 'E');\n    }\n  }\n  void on_loc_date(numeric_system ns) {\n    if (is_classic_)\n      on_us_date();\n    else\n      format_localized('x', ns == numeric_system::standard ? '\\0' : 'E');\n  }\n  void on_loc_time(numeric_system ns) {\n    if (is_classic_)\n      on_iso_time();\n    else\n      format_localized('X', ns == numeric_system::standard ? '\\0' : 'E');\n  }\n  void on_us_date() {\n    char buf[8];\n    write_digit2_separated(buf, to_unsigned(tm_mon() + 1),\n                           to_unsigned(tm_mday()),\n                           to_unsigned(split_year_lower(tm_year())), '/');\n    out_ = copy_str<Char>(std::begin(buf), std::end(buf), out_);\n  }\n  void on_iso_date() {\n    auto year = tm_year();\n    char buf[10];\n    size_t offset = 0;\n    if (year >= 0 && year < 10000) {\n      copy2(buf, digits2(to_unsigned(year / 100)));\n    } else {\n      offset = 4;\n      write_year_extended(year);\n      year = 0;\n    }\n    write_digit2_separated(buf + 2, static_cast<unsigned>(year % 100),\n                           to_unsigned(tm_mon() + 1), to_unsigned(tm_mday()),\n                           '-');\n    out_ = copy_str<Char>(std::begin(buf) + offset, std::end(buf), out_);\n  }\n\n  void on_utc_offset() { format_utc_offset_impl(tm_); }\n  void on_tz_name() { format_tz_name_impl(tm_); }\n\n  void on_year(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard)\n      return write_year(tm_year());\n    format_localized('Y', 'E');\n  }\n  void on_short_year(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard)\n      return write2(split_year_lower(tm_year()));\n    format_localized('y', 'O');\n  }\n  void on_offset_year() {\n    if (is_classic_) return write2(split_year_lower(tm_year()));\n    format_localized('y', 'E');\n  }\n\n  void on_century(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard) {\n      auto year = tm_year();\n      auto upper = year / 100;\n      if (year >= -99 && year < 0) {\n        // Zero upper on negative year.\n        *out_++ = '-';\n        *out_++ = '0';\n      } else if (upper >= 0 && upper < 100) {\n        write2(static_cast<int>(upper));\n      } else {\n        out_ = write<Char>(out_, upper);\n      }\n    } else {\n      format_localized('C', 'E');\n    }\n  }\n\n  void on_dec_month(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard)\n      return write2(tm_mon() + 1);\n    format_localized('m', 'O');\n  }\n\n  void on_dec0_week_of_year(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard)\n      return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week);\n    format_localized('U', 'O');\n  }\n  void on_dec1_week_of_year(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard) {\n      auto wday = tm_wday();\n      write2((tm_yday() + days_per_week -\n              (wday == 0 ? (days_per_week - 1) : (wday - 1))) /\n             days_per_week);\n    } else {\n      format_localized('W', 'O');\n    }\n  }\n  void on_iso_week_of_year(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard)\n      return write2(tm_iso_week_of_year());\n    format_localized('V', 'O');\n  }\n\n  void on_iso_week_based_year() { write_year(tm_iso_week_year()); }\n  void on_iso_week_based_short_year() {\n    write2(split_year_lower(tm_iso_week_year()));\n  }\n\n  void on_day_of_year() {\n    auto yday = tm_yday() + 1;\n    write1(yday / 100);\n    write2(yday % 100);\n  }\n  void on_day_of_month(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard) return write2(tm_mday());\n    format_localized('d', 'O');\n  }\n  void on_day_of_month_space(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard) {\n      auto mday = to_unsigned(tm_mday()) % 100;\n      const char* d2 = digits2(mday);\n      *out_++ = mday < 10 ? ' ' : d2[0];\n      *out_++ = d2[1];\n    } else {\n      format_localized('e', 'O');\n    }\n  }\n\n  void on_24_hour(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard) return write2(tm_hour());\n    format_localized('H', 'O');\n  }\n  void on_12_hour(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard)\n      return write2(tm_hour12());\n    format_localized('I', 'O');\n  }\n  void on_minute(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard) return write2(tm_min());\n    format_localized('M', 'O');\n  }\n  void on_second(numeric_system ns) {\n    if (is_classic_ || ns == numeric_system::standard) return write2(tm_sec());\n    format_localized('S', 'O');\n  }\n\n  void on_12_hour_time() {\n    if (is_classic_) {\n      char buf[8];\n      write_digit2_separated(buf, to_unsigned(tm_hour12()),\n                             to_unsigned(tm_min()), to_unsigned(tm_sec()), ':');\n      out_ = copy_str<Char>(std::begin(buf), std::end(buf), out_);\n      *out_++ = ' ';\n      on_am_pm();\n    } else {\n      format_localized('r');\n    }\n  }\n  void on_24_hour_time() {\n    write2(tm_hour());\n    *out_++ = ':';\n    write2(tm_min());\n  }\n  void on_iso_time() {\n    char buf[8];\n    write_digit2_separated(buf, to_unsigned(tm_hour()), to_unsigned(tm_min()),\n                           to_unsigned(tm_sec()), ':');\n    out_ = copy_str<Char>(std::begin(buf), std::end(buf), out_);\n  }\n\n  void on_am_pm() {\n    if (is_classic_) {\n      *out_++ = tm_hour() < 12 ? 'A' : 'P';\n      *out_++ = 'M';\n    } else {\n      format_localized('p');\n    }\n  }\n\n  // These apply to chrono durations but not tm.\n  void on_duration_value() {}\n  void on_duration_unit() {}\n};\n\nstruct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {\n  FMT_NORETURN void unsupported() { FMT_THROW(format_error(\"no date\")); }\n\n  template <typename Char>\n  FMT_CONSTEXPR void on_text(const Char*, const Char*) {}\n  FMT_CONSTEXPR void on_24_hour(numeric_system) {}\n  FMT_CONSTEXPR void on_12_hour(numeric_system) {}\n  FMT_CONSTEXPR void on_minute(numeric_system) {}\n  FMT_CONSTEXPR void on_second(numeric_system) {}\n  FMT_CONSTEXPR void on_12_hour_time() {}\n  FMT_CONSTEXPR void on_24_hour_time() {}\n  FMT_CONSTEXPR void on_iso_time() {}\n  FMT_CONSTEXPR void on_am_pm() {}\n  FMT_CONSTEXPR void on_duration_value() {}\n  FMT_CONSTEXPR void on_duration_unit() {}\n};\n\ntemplate <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>\ninline bool isnan(T) {\n  return false;\n}\ntemplate <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>\ninline bool isnan(T value) {\n  return std::isnan(value);\n}\n\ntemplate <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>\ninline bool isfinite(T) {\n  return true;\n}\n\n// Converts value to Int and checks that it's in the range [0, upper).\ntemplate <typename T, typename Int, FMT_ENABLE_IF(std::is_integral<T>::value)>\ninline Int to_nonnegative_int(T value, Int upper) {\n  FMT_ASSERT(value >= 0 && to_unsigned(value) <= to_unsigned(upper),\n             \"invalid value\");\n  (void)upper;\n  return static_cast<Int>(value);\n}\ntemplate <typename T, typename Int, FMT_ENABLE_IF(!std::is_integral<T>::value)>\ninline Int to_nonnegative_int(T value, Int upper) {\n  if (value < 0 || value > static_cast<T>(upper))\n    FMT_THROW(format_error(\"invalid value\"));\n  return static_cast<Int>(value);\n}\n\ntemplate <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>\ninline T mod(T x, int y) {\n  return x % static_cast<T>(y);\n}\ntemplate <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>\ninline T mod(T x, int y) {\n  return std::fmod(x, static_cast<T>(y));\n}\n\n// If T is an integral type, maps T to its unsigned counterpart, otherwise\n// leaves it unchanged (unlike std::make_unsigned).\ntemplate <typename T, bool INTEGRAL = std::is_integral<T>::value>\nstruct make_unsigned_or_unchanged {\n  using type = T;\n};\n\ntemplate <typename T> struct make_unsigned_or_unchanged<T, true> {\n  using type = typename std::make_unsigned<T>::type;\n};\n\n#if FMT_SAFE_DURATION_CAST\n// throwing version of safe_duration_cast\ntemplate <typename To, typename FromRep, typename FromPeriod>\nTo fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) {\n  int ec;\n  To to = safe_duration_cast::safe_duration_cast<To>(from, ec);\n  if (ec) FMT_THROW(format_error(\"cannot format duration\"));\n  return to;\n}\n#endif\n\ntemplate <typename Rep, typename Period,\n          FMT_ENABLE_IF(std::is_integral<Rep>::value)>\ninline std::chrono::duration<Rep, std::milli> get_milliseconds(\n    std::chrono::duration<Rep, Period> d) {\n  // this may overflow and/or the result may not fit in the\n  // target type.\n#if FMT_SAFE_DURATION_CAST\n  using CommonSecondsType =\n      typename std::common_type<decltype(d), std::chrono::seconds>::type;\n  const auto d_as_common = fmt_safe_duration_cast<CommonSecondsType>(d);\n  const auto d_as_whole_seconds =\n      fmt_safe_duration_cast<std::chrono::seconds>(d_as_common);\n  // this conversion should be nonproblematic\n  const auto diff = d_as_common - d_as_whole_seconds;\n  const auto ms =\n      fmt_safe_duration_cast<std::chrono::duration<Rep, std::milli>>(diff);\n  return ms;\n#else\n  auto s = std::chrono::duration_cast<std::chrono::seconds>(d);\n  return std::chrono::duration_cast<std::chrono::milliseconds>(d - s);\n#endif\n}\n\n// Returns the number of fractional digits in the range [0, 18] according to the\n// C++20 spec. If more than 18 fractional digits are required then returns 6 for\n// microseconds precision.\nconstexpr int count_fractional_digits(long long num, long long den, int n = 0) {\n  return num % den == 0\n             ? n\n             : (n > 18 ? 6 : count_fractional_digits(num * 10, den, n + 1));\n}\n\nconstexpr long long pow10(std::uint32_t n) {\n  return n == 0 ? 1 : 10 * pow10(n - 1);\n}\n\ntemplate <class Rep, class Period,\n          FMT_ENABLE_IF(std::numeric_limits<Rep>::is_signed)>\nconstexpr std::chrono::duration<Rep, Period> abs(\n    std::chrono::duration<Rep, Period> d) {\n  // We need to compare the duration using the count() method directly\n  // due to a compiler bug in clang-11 regarding the spaceship operator,\n  // when -Wzero-as-null-pointer-constant is enabled.\n  // In clang-12 the bug has been fixed. See\n  // https://bugs.llvm.org/show_bug.cgi?id=46235 and the reproducible example:\n  // https://www.godbolt.org/z/Knbb5joYx.\n  return d.count() >= d.zero().count() ? d : -d;\n}\n\ntemplate <class Rep, class Period,\n          FMT_ENABLE_IF(!std::numeric_limits<Rep>::is_signed)>\nconstexpr std::chrono::duration<Rep, Period> abs(\n    std::chrono::duration<Rep, Period> d) {\n  return d;\n}\n\ntemplate <typename Char, typename Rep, typename OutputIt,\n          FMT_ENABLE_IF(std::is_integral<Rep>::value)>\nOutputIt format_duration_value(OutputIt out, Rep val, int) {\n  return write<Char>(out, val);\n}\n\ntemplate <typename Char, typename Rep, typename OutputIt,\n          FMT_ENABLE_IF(std::is_floating_point<Rep>::value)>\nOutputIt format_duration_value(OutputIt out, Rep val, int precision) {\n  auto specs = basic_format_specs<Char>();\n  specs.precision = precision;\n  specs.type = precision >= 0 ? presentation_type::fixed_lower\n                              : presentation_type::general_lower;\n  return write<Char>(out, val, specs);\n}\n\ntemplate <typename Char, typename OutputIt>\nOutputIt copy_unit(string_view unit, OutputIt out, Char) {\n  return std::copy(unit.begin(), unit.end(), out);\n}\n\ntemplate <typename OutputIt>\nOutputIt copy_unit(string_view unit, OutputIt out, wchar_t) {\n  // This works when wchar_t is UTF-32 because units only contain characters\n  // that have the same representation in UTF-16 and UTF-32.\n  utf8_to_utf16 u(unit);\n  return std::copy(u.c_str(), u.c_str() + u.size(), out);\n}\n\ntemplate <typename Char, typename Period, typename OutputIt>\nOutputIt format_duration_unit(OutputIt out) {\n  if (const char* unit = get_units<Period>())\n    return copy_unit(string_view(unit), out, Char());\n  *out++ = '[';\n  out = write<Char>(out, Period::num);\n  if (const_check(Period::den != 1)) {\n    *out++ = '/';\n    out = write<Char>(out, Period::den);\n  }\n  *out++ = ']';\n  *out++ = 's';\n  return out;\n}\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4582 4583)\n#endif\n\nclass get_locale {\n private:\n  union {\n    std::locale locale_;\n  };\n  bool has_locale_ = false;\n\n public:\n  get_locale(bool localized, locale_ref loc) : has_locale_(localized) {\n    if (localized)\n      ::new (&locale_) std::locale(loc.template get<std::locale>());\n  }\n  ~get_locale() {\n    if (has_locale_) locale_.~locale();\n  }\n  operator const std::locale&() const {\n    return has_locale_ ? locale_ : get_classic_locale();\n  }\n};\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\ntemplate <typename FormatContext, typename OutputIt, typename Rep,\n          typename Period>\nstruct chrono_formatter {\n  FormatContext& context;\n  OutputIt out;\n  int precision;\n  bool localized = false;\n  // rep is unsigned to avoid overflow.\n  using rep =\n      conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int),\n                    unsigned, typename make_unsigned_or_unchanged<Rep>::type>;\n  rep val;\n  using seconds = std::chrono::duration<rep>;\n  seconds s;\n  using milliseconds = std::chrono::duration<rep, std::milli>;\n  bool negative;\n\n  using char_type = typename FormatContext::char_type;\n  using tm_writer_type = tm_writer<OutputIt, char_type>;\n\n  chrono_formatter(FormatContext& ctx, OutputIt o,\n                   std::chrono::duration<Rep, Period> d)\n      : context(ctx),\n        out(o),\n        val(static_cast<rep>(d.count())),\n        negative(false) {\n    if (d.count() < 0) {\n      val = 0 - val;\n      negative = true;\n    }\n\n    // this may overflow and/or the result may not fit in the\n    // target type.\n#if FMT_SAFE_DURATION_CAST\n    // might need checked conversion (rep!=Rep)\n    auto tmpval = std::chrono::duration<rep, Period>(val);\n    s = fmt_safe_duration_cast<seconds>(tmpval);\n#else\n    s = std::chrono::duration_cast<seconds>(\n        std::chrono::duration<rep, Period>(val));\n#endif\n  }\n\n  // returns true if nan or inf, writes to out.\n  bool handle_nan_inf() {\n    if (isfinite(val)) {\n      return false;\n    }\n    if (isnan(val)) {\n      write_nan();\n      return true;\n    }\n    // must be +-inf\n    if (val > 0) {\n      write_pinf();\n    } else {\n      write_ninf();\n    }\n    return true;\n  }\n\n  Rep hour() const { return static_cast<Rep>(mod((s.count() / 3600), 24)); }\n\n  Rep hour12() const {\n    Rep hour = static_cast<Rep>(mod((s.count() / 3600), 12));\n    return hour <= 0 ? 12 : hour;\n  }\n\n  Rep minute() const { return static_cast<Rep>(mod((s.count() / 60), 60)); }\n  Rep second() const { return static_cast<Rep>(mod(s.count(), 60)); }\n\n  std::tm time() const {\n    auto time = std::tm();\n    time.tm_hour = to_nonnegative_int(hour(), 24);\n    time.tm_min = to_nonnegative_int(minute(), 60);\n    time.tm_sec = to_nonnegative_int(second(), 60);\n    return time;\n  }\n\n  void write_sign() {\n    if (negative) {\n      *out++ = '-';\n      negative = false;\n    }\n  }\n\n  void write(Rep value, int width) {\n    write_sign();\n    if (isnan(value)) return write_nan();\n    uint32_or_64_or_128_t<int> n =\n        to_unsigned(to_nonnegative_int(value, max_value<int>()));\n    int num_digits = detail::count_digits(n);\n    if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');\n    out = format_decimal<char_type>(out, n, num_digits).end;\n  }\n\n  template <class Duration> void write_fractional_seconds(Duration d) {\n    constexpr auto num_fractional_digits =\n        count_fractional_digits(Duration::period::num, Duration::period::den);\n\n    using subsecond_precision = std::chrono::duration<\n        typename std::common_type<typename Duration::rep,\n                                  std::chrono::seconds::rep>::type,\n        std::ratio<1, detail::pow10(num_fractional_digits)>>;\n    if (std::ratio_less<typename subsecond_precision::period,\n                        std::chrono::seconds::period>::value) {\n      *out++ = '.';\n      // Don't convert long double to integer seconds to avoid overflow.\n      using sec = conditional_t<\n          std::is_same<typename Duration::rep, long double>::value,\n          std::chrono::duration<long double>, std::chrono::seconds>;\n      auto fractional = detail::abs(d) - std::chrono::duration_cast<sec>(d);\n      const auto subseconds =\n          std::chrono::treat_as_floating_point<\n              typename subsecond_precision::rep>::value\n              ? fractional.count()\n              : std::chrono::duration_cast<subsecond_precision>(fractional)\n                    .count();\n      uint32_or_64_or_128_t<long long> n =\n          to_unsigned(to_nonnegative_int(subseconds, max_value<long long>()));\n      int num_digits = detail::count_digits(n);\n      if (num_fractional_digits > num_digits)\n        out = std::fill_n(out, num_fractional_digits - num_digits, '0');\n      out = format_decimal<char_type>(out, n, num_digits).end;\n    }\n  }\n\n  void write_nan() { std::copy_n(\"nan\", 3, out); }\n  void write_pinf() { std::copy_n(\"inf\", 3, out); }\n  void write_ninf() { std::copy_n(\"-inf\", 4, out); }\n\n  template <typename Callback, typename... Args>\n  void format_tm(const tm& time, Callback cb, Args... args) {\n    if (isnan(val)) return write_nan();\n    get_locale loc(localized, context.locale());\n    auto w = tm_writer_type(loc, out, time);\n    (w.*cb)(args...);\n    out = w.out();\n  }\n\n  void on_text(const char_type* begin, const char_type* end) {\n    std::copy(begin, end, out);\n  }\n\n  // These are not implemented because durations don't have date information.\n  void on_abbr_weekday() {}\n  void on_full_weekday() {}\n  void on_dec0_weekday(numeric_system) {}\n  void on_dec1_weekday(numeric_system) {}\n  void on_abbr_month() {}\n  void on_full_month() {}\n  void on_datetime(numeric_system) {}\n  void on_loc_date(numeric_system) {}\n  void on_loc_time(numeric_system) {}\n  void on_us_date() {}\n  void on_iso_date() {}\n  void on_utc_offset() {}\n  void on_tz_name() {}\n  void on_year(numeric_system) {}\n  void on_short_year(numeric_system) {}\n  void on_offset_year() {}\n  void on_century(numeric_system) {}\n  void on_iso_week_based_year() {}\n  void on_iso_week_based_short_year() {}\n  void on_dec_month(numeric_system) {}\n  void on_dec0_week_of_year(numeric_system) {}\n  void on_dec1_week_of_year(numeric_system) {}\n  void on_iso_week_of_year(numeric_system) {}\n  void on_day_of_year() {}\n  void on_day_of_month(numeric_system) {}\n  void on_day_of_month_space(numeric_system) {}\n\n  void on_24_hour(numeric_system ns) {\n    if (handle_nan_inf()) return;\n\n    if (ns == numeric_system::standard) return write(hour(), 2);\n    auto time = tm();\n    time.tm_hour = to_nonnegative_int(hour(), 24);\n    format_tm(time, &tm_writer_type::on_24_hour, ns);\n  }\n\n  void on_12_hour(numeric_system ns) {\n    if (handle_nan_inf()) return;\n\n    if (ns == numeric_system::standard) return write(hour12(), 2);\n    auto time = tm();\n    time.tm_hour = to_nonnegative_int(hour12(), 12);\n    format_tm(time, &tm_writer_type::on_12_hour, ns);\n  }\n\n  void on_minute(numeric_system ns) {\n    if (handle_nan_inf()) return;\n\n    if (ns == numeric_system::standard) return write(minute(), 2);\n    auto time = tm();\n    time.tm_min = to_nonnegative_int(minute(), 60);\n    format_tm(time, &tm_writer_type::on_minute, ns);\n  }\n\n  void on_second(numeric_system ns) {\n    if (handle_nan_inf()) return;\n\n    if (ns == numeric_system::standard) {\n      write(second(), 2);\n      write_fractional_seconds(std::chrono::duration<rep, Period>{val});\n      return;\n    }\n    auto time = tm();\n    time.tm_sec = to_nonnegative_int(second(), 60);\n    format_tm(time, &tm_writer_type::on_second, ns);\n  }\n\n  void on_12_hour_time() {\n    if (handle_nan_inf()) return;\n    format_tm(time(), &tm_writer_type::on_12_hour_time);\n  }\n\n  void on_24_hour_time() {\n    if (handle_nan_inf()) {\n      *out++ = ':';\n      handle_nan_inf();\n      return;\n    }\n\n    write(hour(), 2);\n    *out++ = ':';\n    write(minute(), 2);\n  }\n\n  void on_iso_time() {\n    on_24_hour_time();\n    *out++ = ':';\n    if (handle_nan_inf()) return;\n    on_second(numeric_system::standard);\n  }\n\n  void on_am_pm() {\n    if (handle_nan_inf()) return;\n    format_tm(time(), &tm_writer_type::on_am_pm);\n  }\n\n  void on_duration_value() {\n    if (handle_nan_inf()) return;\n    write_sign();\n    out = format_duration_value<char_type>(out, val, precision);\n  }\n\n  void on_duration_unit() {\n    out = format_duration_unit<char_type, Period>(out);\n  }\n};\n\nFMT_END_DETAIL_NAMESPACE\n\n#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907\nusing weekday = std::chrono::weekday;\n#else\n// A fallback version of weekday.\nclass weekday {\n private:\n  unsigned char value;\n\n public:\n  weekday() = default;\n  explicit constexpr weekday(unsigned wd) noexcept\n      : value(static_cast<unsigned char>(wd != 7 ? wd : 0)) {}\n  constexpr unsigned c_encoding() const noexcept { return value; }\n};\n\nclass year_month_day {};\n#endif\n\n// A rudimentary weekday formatter.\ntemplate <typename Char> struct formatter<weekday, Char> {\n private:\n  bool localized = false;\n\n public:\n  FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)\n      -> decltype(ctx.begin()) {\n    auto begin = ctx.begin(), end = ctx.end();\n    if (begin != end && *begin == 'L') {\n      ++begin;\n      localized = true;\n    }\n    return begin;\n  }\n\n  template <typename FormatContext>\n  auto format(weekday wd, FormatContext& ctx) const -> decltype(ctx.out()) {\n    auto time = std::tm();\n    time.tm_wday = static_cast<int>(wd.c_encoding());\n    detail::get_locale loc(localized, ctx.locale());\n    auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);\n    w.on_abbr_weekday();\n    return w.out();\n  }\n};\n\ntemplate <typename Rep, typename Period, typename Char>\nstruct formatter<std::chrono::duration<Rep, Period>, Char> {\n private:\n  basic_format_specs<Char> specs;\n  int precision = -1;\n  using arg_ref_type = detail::arg_ref<Char>;\n  arg_ref_type width_ref;\n  arg_ref_type precision_ref;\n  bool localized = false;\n  basic_string_view<Char> format_str;\n  using duration = std::chrono::duration<Rep, Period>;\n\n  struct spec_handler {\n    formatter& f;\n    basic_format_parse_context<Char>& context;\n    basic_string_view<Char> format_str;\n\n    template <typename Id> FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) {\n      context.check_arg_id(arg_id);\n      return arg_ref_type(arg_id);\n    }\n\n    FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view<Char> arg_id) {\n      context.check_arg_id(arg_id);\n      return arg_ref_type(arg_id);\n    }\n\n    FMT_CONSTEXPR arg_ref_type make_arg_ref(detail::auto_id) {\n      return arg_ref_type(context.next_arg_id());\n    }\n\n    void on_error(const char* msg) { FMT_THROW(format_error(msg)); }\n    FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) {\n      f.specs.fill = fill;\n    }\n    FMT_CONSTEXPR void on_align(align_t align) { f.specs.align = align; }\n    FMT_CONSTEXPR void on_width(int width) { f.specs.width = width; }\n    FMT_CONSTEXPR void on_precision(int _precision) {\n      f.precision = _precision;\n    }\n    FMT_CONSTEXPR void end_precision() {}\n\n    template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {\n      f.width_ref = make_arg_ref(arg_id);\n    }\n\n    template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {\n      f.precision_ref = make_arg_ref(arg_id);\n    }\n  };\n\n  using iterator = typename basic_format_parse_context<Char>::iterator;\n  struct parse_range {\n    iterator begin;\n    iterator end;\n  };\n\n  FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context<Char>& ctx) {\n    auto begin = ctx.begin(), end = ctx.end();\n    if (begin == end || *begin == '}') return {begin, begin};\n    spec_handler handler{*this, ctx, format_str};\n    begin = detail::parse_align(begin, end, handler);\n    if (begin == end) return {begin, begin};\n    begin = detail::parse_width(begin, end, handler);\n    if (begin == end) return {begin, begin};\n    if (*begin == '.') {\n      if (std::is_floating_point<Rep>::value)\n        begin = detail::parse_precision(begin, end, handler);\n      else\n        handler.on_error(\"precision not allowed for this argument type\");\n    }\n    if (begin != end && *begin == 'L') {\n      ++begin;\n      localized = true;\n    }\n    end = detail::parse_chrono_format(begin, end,\n                                      detail::chrono_format_checker());\n    return {begin, end};\n  }\n\n public:\n  FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)\n      -> decltype(ctx.begin()) {\n    auto range = do_parse(ctx);\n    format_str = basic_string_view<Char>(\n        &*range.begin, detail::to_unsigned(range.end - range.begin));\n    return range.end;\n  }\n\n  template <typename FormatContext>\n  auto format(const duration& d, FormatContext& ctx) const\n      -> decltype(ctx.out()) {\n    auto specs_copy = specs;\n    auto precision_copy = precision;\n    auto begin = format_str.begin(), end = format_str.end();\n    // As a possible future optimization, we could avoid extra copying if width\n    // is not specified.\n    basic_memory_buffer<Char> buf;\n    auto out = std::back_inserter(buf);\n    detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width,\n                                                       width_ref, ctx);\n    detail::handle_dynamic_spec<detail::precision_checker>(precision_copy,\n                                                           precision_ref, ctx);\n    if (begin == end || *begin == '}') {\n      out = detail::format_duration_value<Char>(out, d.count(), precision_copy);\n      detail::format_duration_unit<Char, Period>(out);\n    } else {\n      detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f(\n          ctx, out, d);\n      f.precision = precision_copy;\n      f.localized = localized;\n      detail::parse_chrono_format(begin, end, f);\n    }\n    return detail::write(\n        ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy);\n  }\n};\n\ntemplate <typename Char, typename Duration>\nstruct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,\n                 Char> : formatter<std::tm, Char> {\n  FMT_CONSTEXPR formatter() {\n    this->do_parse(default_specs,\n                   default_specs + sizeof(default_specs) / sizeof(Char));\n  }\n\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    return this->do_parse(ctx.begin(), ctx.end(), true);\n  }\n\n  template <typename FormatContext>\n  auto format(std::chrono::time_point<std::chrono::system_clock> val,\n              FormatContext& ctx) const -> decltype(ctx.out()) {\n    return formatter<std::tm, Char>::format(localtime(val), ctx);\n  }\n\n  static constexpr const Char default_specs[] = {'%', 'F', ' ', '%', 'T'};\n};\n\ntemplate <typename Char, typename Duration>\nconstexpr const Char\n    formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,\n              Char>::default_specs[];\n\ntemplate <typename Char> struct formatter<std::tm, Char> {\n private:\n  enum class spec {\n    unknown,\n    year_month_day,\n    hh_mm_ss,\n  };\n  spec spec_ = spec::unknown;\n  basic_string_view<Char> specs;\n\n protected:\n  template <typename It>\n  FMT_CONSTEXPR auto do_parse(It begin, It end, bool with_default = false)\n      -> It {\n    if (begin != end && *begin == ':') ++begin;\n    end = detail::parse_chrono_format(begin, end, detail::tm_format_checker());\n    if (!with_default || end != begin)\n      specs = {begin, detail::to_unsigned(end - begin)};\n    // basic_string_view<>::compare isn't constexpr before C++17.\n    if (specs.size() == 2 && specs[0] == Char('%')) {\n      if (specs[1] == Char('F'))\n        spec_ = spec::year_month_day;\n      else if (specs[1] == Char('T'))\n        spec_ = spec::hh_mm_ss;\n    }\n    return end;\n  }\n\n public:\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    return this->do_parse(ctx.begin(), ctx.end());\n  }\n\n  template <typename FormatContext>\n  auto format(const std::tm& tm, FormatContext& ctx) const\n      -> decltype(ctx.out()) {\n    const auto loc_ref = ctx.locale();\n    detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref);\n    auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), tm);\n    if (spec_ == spec::year_month_day)\n      w.on_iso_date();\n    else if (spec_ == spec::hh_mm_ss)\n      w.on_iso_time();\n    else\n      detail::parse_chrono_format(specs.begin(), specs.end(), w);\n    return w.out();\n  }\n};\n\nFMT_MODULE_EXPORT_END\nFMT_END_NAMESPACE\n\n#endif  // FMT_CHRONO_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/color.h",
    "content": "// Formatting library for C++ - color support\n//\n// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_COLOR_H_\n#define FMT_COLOR_H_\n\n#include \"format.h\"\n\n// __declspec(deprecated) is broken in some MSVC versions.\n#if FMT_MSC_VER\n#  define FMT_DEPRECATED_NONMSVC\n#else\n#  define FMT_DEPRECATED_NONMSVC FMT_DEPRECATED\n#endif\n\nFMT_BEGIN_NAMESPACE\nFMT_MODULE_EXPORT_BEGIN\n\nenum class color : uint32_t {\n  alice_blue = 0xF0F8FF,               // rgb(240,248,255)\n  antique_white = 0xFAEBD7,            // rgb(250,235,215)\n  aqua = 0x00FFFF,                     // rgb(0,255,255)\n  aquamarine = 0x7FFFD4,               // rgb(127,255,212)\n  azure = 0xF0FFFF,                    // rgb(240,255,255)\n  beige = 0xF5F5DC,                    // rgb(245,245,220)\n  bisque = 0xFFE4C4,                   // rgb(255,228,196)\n  black = 0x000000,                    // rgb(0,0,0)\n  blanched_almond = 0xFFEBCD,          // rgb(255,235,205)\n  blue = 0x0000FF,                     // rgb(0,0,255)\n  blue_violet = 0x8A2BE2,              // rgb(138,43,226)\n  brown = 0xA52A2A,                    // rgb(165,42,42)\n  burly_wood = 0xDEB887,               // rgb(222,184,135)\n  cadet_blue = 0x5F9EA0,               // rgb(95,158,160)\n  chartreuse = 0x7FFF00,               // rgb(127,255,0)\n  chocolate = 0xD2691E,                // rgb(210,105,30)\n  coral = 0xFF7F50,                    // rgb(255,127,80)\n  cornflower_blue = 0x6495ED,          // rgb(100,149,237)\n  cornsilk = 0xFFF8DC,                 // rgb(255,248,220)\n  crimson = 0xDC143C,                  // rgb(220,20,60)\n  cyan = 0x00FFFF,                     // rgb(0,255,255)\n  dark_blue = 0x00008B,                // rgb(0,0,139)\n  dark_cyan = 0x008B8B,                // rgb(0,139,139)\n  dark_golden_rod = 0xB8860B,          // rgb(184,134,11)\n  dark_gray = 0xA9A9A9,                // rgb(169,169,169)\n  dark_green = 0x006400,               // rgb(0,100,0)\n  dark_khaki = 0xBDB76B,               // rgb(189,183,107)\n  dark_magenta = 0x8B008B,             // rgb(139,0,139)\n  dark_olive_green = 0x556B2F,         // rgb(85,107,47)\n  dark_orange = 0xFF8C00,              // rgb(255,140,0)\n  dark_orchid = 0x9932CC,              // rgb(153,50,204)\n  dark_red = 0x8B0000,                 // rgb(139,0,0)\n  dark_salmon = 0xE9967A,              // rgb(233,150,122)\n  dark_sea_green = 0x8FBC8F,           // rgb(143,188,143)\n  dark_slate_blue = 0x483D8B,          // rgb(72,61,139)\n  dark_slate_gray = 0x2F4F4F,          // rgb(47,79,79)\n  dark_turquoise = 0x00CED1,           // rgb(0,206,209)\n  dark_violet = 0x9400D3,              // rgb(148,0,211)\n  deep_pink = 0xFF1493,                // rgb(255,20,147)\n  deep_sky_blue = 0x00BFFF,            // rgb(0,191,255)\n  dim_gray = 0x696969,                 // rgb(105,105,105)\n  dodger_blue = 0x1E90FF,              // rgb(30,144,255)\n  fire_brick = 0xB22222,               // rgb(178,34,34)\n  floral_white = 0xFFFAF0,             // rgb(255,250,240)\n  forest_green = 0x228B22,             // rgb(34,139,34)\n  fuchsia = 0xFF00FF,                  // rgb(255,0,255)\n  gainsboro = 0xDCDCDC,                // rgb(220,220,220)\n  ghost_white = 0xF8F8FF,              // rgb(248,248,255)\n  gold = 0xFFD700,                     // rgb(255,215,0)\n  golden_rod = 0xDAA520,               // rgb(218,165,32)\n  gray = 0x808080,                     // rgb(128,128,128)\n  green = 0x008000,                    // rgb(0,128,0)\n  green_yellow = 0xADFF2F,             // rgb(173,255,47)\n  honey_dew = 0xF0FFF0,                // rgb(240,255,240)\n  hot_pink = 0xFF69B4,                 // rgb(255,105,180)\n  indian_red = 0xCD5C5C,               // rgb(205,92,92)\n  indigo = 0x4B0082,                   // rgb(75,0,130)\n  ivory = 0xFFFFF0,                    // rgb(255,255,240)\n  khaki = 0xF0E68C,                    // rgb(240,230,140)\n  lavender = 0xE6E6FA,                 // rgb(230,230,250)\n  lavender_blush = 0xFFF0F5,           // rgb(255,240,245)\n  lawn_green = 0x7CFC00,               // rgb(124,252,0)\n  lemon_chiffon = 0xFFFACD,            // rgb(255,250,205)\n  light_blue = 0xADD8E6,               // rgb(173,216,230)\n  light_coral = 0xF08080,              // rgb(240,128,128)\n  light_cyan = 0xE0FFFF,               // rgb(224,255,255)\n  light_golden_rod_yellow = 0xFAFAD2,  // rgb(250,250,210)\n  light_gray = 0xD3D3D3,               // rgb(211,211,211)\n  light_green = 0x90EE90,              // rgb(144,238,144)\n  light_pink = 0xFFB6C1,               // rgb(255,182,193)\n  light_salmon = 0xFFA07A,             // rgb(255,160,122)\n  light_sea_green = 0x20B2AA,          // rgb(32,178,170)\n  light_sky_blue = 0x87CEFA,           // rgb(135,206,250)\n  light_slate_gray = 0x778899,         // rgb(119,136,153)\n  light_steel_blue = 0xB0C4DE,         // rgb(176,196,222)\n  light_yellow = 0xFFFFE0,             // rgb(255,255,224)\n  lime = 0x00FF00,                     // rgb(0,255,0)\n  lime_green = 0x32CD32,               // rgb(50,205,50)\n  linen = 0xFAF0E6,                    // rgb(250,240,230)\n  magenta = 0xFF00FF,                  // rgb(255,0,255)\n  maroon = 0x800000,                   // rgb(128,0,0)\n  medium_aquamarine = 0x66CDAA,        // rgb(102,205,170)\n  medium_blue = 0x0000CD,              // rgb(0,0,205)\n  medium_orchid = 0xBA55D3,            // rgb(186,85,211)\n  medium_purple = 0x9370DB,            // rgb(147,112,219)\n  medium_sea_green = 0x3CB371,         // rgb(60,179,113)\n  medium_slate_blue = 0x7B68EE,        // rgb(123,104,238)\n  medium_spring_green = 0x00FA9A,      // rgb(0,250,154)\n  medium_turquoise = 0x48D1CC,         // rgb(72,209,204)\n  medium_violet_red = 0xC71585,        // rgb(199,21,133)\n  midnight_blue = 0x191970,            // rgb(25,25,112)\n  mint_cream = 0xF5FFFA,               // rgb(245,255,250)\n  misty_rose = 0xFFE4E1,               // rgb(255,228,225)\n  moccasin = 0xFFE4B5,                 // rgb(255,228,181)\n  navajo_white = 0xFFDEAD,             // rgb(255,222,173)\n  navy = 0x000080,                     // rgb(0,0,128)\n  old_lace = 0xFDF5E6,                 // rgb(253,245,230)\n  olive = 0x808000,                    // rgb(128,128,0)\n  olive_drab = 0x6B8E23,               // rgb(107,142,35)\n  orange = 0xFFA500,                   // rgb(255,165,0)\n  orange_red = 0xFF4500,               // rgb(255,69,0)\n  orchid = 0xDA70D6,                   // rgb(218,112,214)\n  pale_golden_rod = 0xEEE8AA,          // rgb(238,232,170)\n  pale_green = 0x98FB98,               // rgb(152,251,152)\n  pale_turquoise = 0xAFEEEE,           // rgb(175,238,238)\n  pale_violet_red = 0xDB7093,          // rgb(219,112,147)\n  papaya_whip = 0xFFEFD5,              // rgb(255,239,213)\n  peach_puff = 0xFFDAB9,               // rgb(255,218,185)\n  peru = 0xCD853F,                     // rgb(205,133,63)\n  pink = 0xFFC0CB,                     // rgb(255,192,203)\n  plum = 0xDDA0DD,                     // rgb(221,160,221)\n  powder_blue = 0xB0E0E6,              // rgb(176,224,230)\n  purple = 0x800080,                   // rgb(128,0,128)\n  rebecca_purple = 0x663399,           // rgb(102,51,153)\n  red = 0xFF0000,                      // rgb(255,0,0)\n  rosy_brown = 0xBC8F8F,               // rgb(188,143,143)\n  royal_blue = 0x4169E1,               // rgb(65,105,225)\n  saddle_brown = 0x8B4513,             // rgb(139,69,19)\n  salmon = 0xFA8072,                   // rgb(250,128,114)\n  sandy_brown = 0xF4A460,              // rgb(244,164,96)\n  sea_green = 0x2E8B57,                // rgb(46,139,87)\n  sea_shell = 0xFFF5EE,                // rgb(255,245,238)\n  sienna = 0xA0522D,                   // rgb(160,82,45)\n  silver = 0xC0C0C0,                   // rgb(192,192,192)\n  sky_blue = 0x87CEEB,                 // rgb(135,206,235)\n  slate_blue = 0x6A5ACD,               // rgb(106,90,205)\n  slate_gray = 0x708090,               // rgb(112,128,144)\n  snow = 0xFFFAFA,                     // rgb(255,250,250)\n  spring_green = 0x00FF7F,             // rgb(0,255,127)\n  steel_blue = 0x4682B4,               // rgb(70,130,180)\n  tan = 0xD2B48C,                      // rgb(210,180,140)\n  teal = 0x008080,                     // rgb(0,128,128)\n  thistle = 0xD8BFD8,                  // rgb(216,191,216)\n  tomato = 0xFF6347,                   // rgb(255,99,71)\n  turquoise = 0x40E0D0,                // rgb(64,224,208)\n  violet = 0xEE82EE,                   // rgb(238,130,238)\n  wheat = 0xF5DEB3,                    // rgb(245,222,179)\n  white = 0xFFFFFF,                    // rgb(255,255,255)\n  white_smoke = 0xF5F5F5,              // rgb(245,245,245)\n  yellow = 0xFFFF00,                   // rgb(255,255,0)\n  yellow_green = 0x9ACD32              // rgb(154,205,50)\n};                                     // enum class color\n\nenum class terminal_color : uint8_t {\n  black = 30,\n  red,\n  green,\n  yellow,\n  blue,\n  magenta,\n  cyan,\n  white,\n  bright_black = 90,\n  bright_red,\n  bright_green,\n  bright_yellow,\n  bright_blue,\n  bright_magenta,\n  bright_cyan,\n  bright_white\n};\n\nenum class emphasis : uint8_t {\n  bold = 1,\n  faint = 1 << 1,\n  italic = 1 << 2,\n  underline = 1 << 3,\n  blink = 1 << 4,\n  reverse = 1 << 5,\n  conceal = 1 << 6,\n  strikethrough = 1 << 7,\n};\n\n// rgb is a struct for red, green and blue colors.\n// Using the name \"rgb\" makes some editors show the color in a tooltip.\nstruct rgb {\n  FMT_CONSTEXPR rgb() : r(0), g(0), b(0) {}\n  FMT_CONSTEXPR rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {}\n  FMT_CONSTEXPR rgb(uint32_t hex)\n      : r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {}\n  FMT_CONSTEXPR rgb(color hex)\n      : r((uint32_t(hex) >> 16) & 0xFF),\n        g((uint32_t(hex) >> 8) & 0xFF),\n        b(uint32_t(hex) & 0xFF) {}\n  uint8_t r;\n  uint8_t g;\n  uint8_t b;\n};\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\n// color is a struct of either a rgb color or a terminal color.\nstruct color_type {\n  FMT_CONSTEXPR color_type() FMT_NOEXCEPT : is_rgb(), value{} {}\n  FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT : is_rgb(true),\n                                                           value{} {\n    value.rgb_color = static_cast<uint32_t>(rgb_color);\n  }\n  FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT : is_rgb(true), value{} {\n    value.rgb_color = (static_cast<uint32_t>(rgb_color.r) << 16) |\n                      (static_cast<uint32_t>(rgb_color.g) << 8) | rgb_color.b;\n  }\n  FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(),\n                                                                     value{} {\n    value.term_color = static_cast<uint8_t>(term_color);\n  }\n  bool is_rgb;\n  union color_union {\n    uint8_t term_color;\n    uint32_t rgb_color;\n  } value;\n};\n\nFMT_END_DETAIL_NAMESPACE\n\n/** A text style consisting of foreground and background colors and emphasis. */\nclass text_style {\n public:\n  FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT\n      : set_foreground_color(),\n        set_background_color(),\n        ems(em) {}\n\n  FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) {\n    if (!set_foreground_color) {\n      set_foreground_color = rhs.set_foreground_color;\n      foreground_color = rhs.foreground_color;\n    } else if (rhs.set_foreground_color) {\n      if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)\n        FMT_THROW(format_error(\"can't OR a terminal color\"));\n      foreground_color.value.rgb_color |= rhs.foreground_color.value.rgb_color;\n    }\n\n    if (!set_background_color) {\n      set_background_color = rhs.set_background_color;\n      background_color = rhs.background_color;\n    } else if (rhs.set_background_color) {\n      if (!background_color.is_rgb || !rhs.background_color.is_rgb)\n        FMT_THROW(format_error(\"can't OR a terminal color\"));\n      background_color.value.rgb_color |= rhs.background_color.value.rgb_color;\n    }\n\n    ems = static_cast<emphasis>(static_cast<uint8_t>(ems) |\n                                static_cast<uint8_t>(rhs.ems));\n    return *this;\n  }\n\n  friend FMT_CONSTEXPR text_style operator|(text_style lhs,\n                                            const text_style& rhs) {\n    return lhs |= rhs;\n  }\n\n  FMT_DEPRECATED_NONMSVC FMT_CONSTEXPR text_style& operator&=(\n      const text_style& rhs) {\n    return and_assign(rhs);\n  }\n\n  FMT_DEPRECATED_NONMSVC friend FMT_CONSTEXPR text_style\n  operator&(text_style lhs, const text_style& rhs) {\n    return lhs.and_assign(rhs);\n  }\n\n  FMT_CONSTEXPR bool has_foreground() const FMT_NOEXCEPT {\n    return set_foreground_color;\n  }\n  FMT_CONSTEXPR bool has_background() const FMT_NOEXCEPT {\n    return set_background_color;\n  }\n  FMT_CONSTEXPR bool has_emphasis() const FMT_NOEXCEPT {\n    return static_cast<uint8_t>(ems) != 0;\n  }\n  FMT_CONSTEXPR detail::color_type get_foreground() const FMT_NOEXCEPT {\n    FMT_ASSERT(has_foreground(), \"no foreground specified for this style\");\n    return foreground_color;\n  }\n  FMT_CONSTEXPR detail::color_type get_background() const FMT_NOEXCEPT {\n    FMT_ASSERT(has_background(), \"no background specified for this style\");\n    return background_color;\n  }\n  FMT_CONSTEXPR emphasis get_emphasis() const FMT_NOEXCEPT {\n    FMT_ASSERT(has_emphasis(), \"no emphasis specified for this style\");\n    return ems;\n  }\n\n private:\n  FMT_CONSTEXPR text_style(bool is_foreground,\n                           detail::color_type text_color) FMT_NOEXCEPT\n      : set_foreground_color(),\n        set_background_color(),\n        ems() {\n    if (is_foreground) {\n      foreground_color = text_color;\n      set_foreground_color = true;\n    } else {\n      background_color = text_color;\n      set_background_color = true;\n    }\n  }\n\n  // DEPRECATED!\n  FMT_CONSTEXPR text_style& and_assign(const text_style& rhs) {\n    if (!set_foreground_color) {\n      set_foreground_color = rhs.set_foreground_color;\n      foreground_color = rhs.foreground_color;\n    } else if (rhs.set_foreground_color) {\n      if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)\n        FMT_THROW(format_error(\"can't AND a terminal color\"));\n      foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color;\n    }\n\n    if (!set_background_color) {\n      set_background_color = rhs.set_background_color;\n      background_color = rhs.background_color;\n    } else if (rhs.set_background_color) {\n      if (!background_color.is_rgb || !rhs.background_color.is_rgb)\n        FMT_THROW(format_error(\"can't AND a terminal color\"));\n      background_color.value.rgb_color &= rhs.background_color.value.rgb_color;\n    }\n\n    ems = static_cast<emphasis>(static_cast<uint8_t>(ems) &\n                                static_cast<uint8_t>(rhs.ems));\n    return *this;\n  }\n\n  friend FMT_CONSTEXPR_DECL text_style fg(detail::color_type foreground)\n      FMT_NOEXCEPT;\n\n  friend FMT_CONSTEXPR_DECL text_style bg(detail::color_type background)\n      FMT_NOEXCEPT;\n\n  detail::color_type foreground_color;\n  detail::color_type background_color;\n  bool set_foreground_color;\n  bool set_background_color;\n  emphasis ems;\n};\n\n/** Creates a text style from the foreground (text) color. */\nFMT_CONSTEXPR inline text_style fg(detail::color_type foreground) FMT_NOEXCEPT {\n  return text_style(true, foreground);\n}\n\n/** Creates a text style from the background color. */\nFMT_CONSTEXPR inline text_style bg(detail::color_type background) FMT_NOEXCEPT {\n  return text_style(false, background);\n}\n\nFMT_CONSTEXPR inline text_style operator|(emphasis lhs,\n                                          emphasis rhs) FMT_NOEXCEPT {\n  return text_style(lhs) | rhs;\n}\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\ntemplate <typename Char> struct ansi_color_escape {\n  FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,\n                                  const char* esc) FMT_NOEXCEPT {\n    // If we have a terminal color, we need to output another escape code\n    // sequence.\n    if (!text_color.is_rgb) {\n      bool is_background = esc == string_view(\"\\x1b[48;2;\");\n      uint32_t value = text_color.value.term_color;\n      // Background ASCII codes are the same as the foreground ones but with\n      // 10 more.\n      if (is_background) value += 10u;\n\n      size_t index = 0;\n      buffer[index++] = static_cast<Char>('\\x1b');\n      buffer[index++] = static_cast<Char>('[');\n\n      if (value >= 100u) {\n        buffer[index++] = static_cast<Char>('1');\n        value %= 100u;\n      }\n      buffer[index++] = static_cast<Char>('0' + value / 10u);\n      buffer[index++] = static_cast<Char>('0' + value % 10u);\n\n      buffer[index++] = static_cast<Char>('m');\n      buffer[index++] = static_cast<Char>('\\0');\n      return;\n    }\n\n    for (int i = 0; i < 7; i++) {\n      buffer[i] = static_cast<Char>(esc[i]);\n    }\n    rgb color(text_color.value.rgb_color);\n    to_esc(color.r, buffer + 7, ';');\n    to_esc(color.g, buffer + 11, ';');\n    to_esc(color.b, buffer + 15, 'm');\n    buffer[19] = static_cast<Char>(0);\n  }\n  FMT_CONSTEXPR ansi_color_escape(emphasis em) FMT_NOEXCEPT {\n    uint8_t em_codes[num_emphases] = {};\n    if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1;\n    if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2;\n    if (has_emphasis(em, emphasis::italic)) em_codes[2] = 3;\n    if (has_emphasis(em, emphasis::underline)) em_codes[3] = 4;\n    if (has_emphasis(em, emphasis::blink)) em_codes[4] = 5;\n    if (has_emphasis(em, emphasis::reverse)) em_codes[5] = 7;\n    if (has_emphasis(em, emphasis::conceal)) em_codes[6] = 8;\n    if (has_emphasis(em, emphasis::strikethrough)) em_codes[7] = 9;\n\n    size_t index = 0;\n    for (size_t i = 0; i < num_emphases; ++i) {\n      if (!em_codes[i]) continue;\n      buffer[index++] = static_cast<Char>('\\x1b');\n      buffer[index++] = static_cast<Char>('[');\n      buffer[index++] = static_cast<Char>('0' + em_codes[i]);\n      buffer[index++] = static_cast<Char>('m');\n    }\n    buffer[index++] = static_cast<Char>(0);\n  }\n  FMT_CONSTEXPR operator const Char*() const FMT_NOEXCEPT { return buffer; }\n\n  FMT_CONSTEXPR const Char* begin() const FMT_NOEXCEPT { return buffer; }\n  FMT_CONSTEXPR_CHAR_TRAITS const Char* end() const FMT_NOEXCEPT {\n    return buffer + std::char_traits<Char>::length(buffer);\n  }\n\n private:\n  static constexpr size_t num_emphases = 8;\n  Char buffer[7u + 3u * num_emphases + 1u];\n\n  static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,\n                                   char delimiter) FMT_NOEXCEPT {\n    out[0] = static_cast<Char>('0' + c / 100);\n    out[1] = static_cast<Char>('0' + c / 10 % 10);\n    out[2] = static_cast<Char>('0' + c % 10);\n    out[3] = static_cast<Char>(delimiter);\n  }\n  static FMT_CONSTEXPR bool has_emphasis(emphasis em,\n                                         emphasis mask) FMT_NOEXCEPT {\n    return static_cast<uint8_t>(em) & static_cast<uint8_t>(mask);\n  }\n};\n\ntemplate <typename Char>\nFMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(\n    detail::color_type foreground) FMT_NOEXCEPT {\n  return ansi_color_escape<Char>(foreground, \"\\x1b[38;2;\");\n}\n\ntemplate <typename Char>\nFMT_CONSTEXPR ansi_color_escape<Char> make_background_color(\n    detail::color_type background) FMT_NOEXCEPT {\n  return ansi_color_escape<Char>(background, \"\\x1b[48;2;\");\n}\n\ntemplate <typename Char>\nFMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) FMT_NOEXCEPT {\n  return ansi_color_escape<Char>(em);\n}\n\ntemplate <typename Char>\ninline void fputs(const Char* chars, FILE* stream) FMT_NOEXCEPT {\n  std::fputs(chars, stream);\n}\n\ntemplate <>\ninline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT {\n  std::fputws(chars, stream);\n}\n\ntemplate <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT {\n  fputs(\"\\x1b[0m\", stream);\n}\n\ntemplate <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {\n  fputs(L\"\\x1b[0m\", stream);\n}\n\ntemplate <typename Char>\ninline void reset_color(buffer<Char>& buffer) FMT_NOEXCEPT {\n  auto reset_color = string_view(\"\\x1b[0m\");\n  buffer.append(reset_color.begin(), reset_color.end());\n}\n\ntemplate <typename Char>\nvoid vformat_to(buffer<Char>& buf, const text_style& ts,\n                basic_string_view<Char> format_str,\n                basic_format_args<buffer_context<type_identity_t<Char>>> args) {\n  bool has_style = false;\n  if (ts.has_emphasis()) {\n    has_style = true;\n    auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());\n    buf.append(emphasis.begin(), emphasis.end());\n  }\n  if (ts.has_foreground()) {\n    has_style = true;\n    auto foreground = detail::make_foreground_color<Char>(ts.get_foreground());\n    buf.append(foreground.begin(), foreground.end());\n  }\n  if (ts.has_background()) {\n    has_style = true;\n    auto background = detail::make_background_color<Char>(ts.get_background());\n    buf.append(background.begin(), background.end());\n  }\n  detail::vformat_to(buf, format_str, args, {});\n  if (has_style) detail::reset_color<Char>(buf);\n}\n\nFMT_END_DETAIL_NAMESPACE\n\ntemplate <typename S, typename Char = char_t<S>>\nvoid vprint(std::FILE* f, const text_style& ts, const S& format,\n            basic_format_args<buffer_context<type_identity_t<Char>>> args) {\n  basic_memory_buffer<Char> buf;\n  detail::vformat_to(buf, ts, to_string_view(format), args);\n  buf.push_back(Char(0));\n  detail::fputs(buf.data(), f);\n}\n\n/**\n  \\rst\n  Formats a string and prints it to the specified file stream using ANSI\n  escape sequences to specify text formatting.\n\n  **Example**::\n\n    fmt::print(fmt::emphasis::bold | fg(fmt::color::red),\n               \"Elapsed time: {0:.2f} seconds\", 1.23);\n  \\endrst\n */\ntemplate <typename S, typename... Args,\n          FMT_ENABLE_IF(detail::is_string<S>::value)>\nvoid print(std::FILE* f, const text_style& ts, const S& format_str,\n           const Args&... args) {\n  vprint(f, ts, format_str,\n         fmt::make_args_checked<Args...>(format_str, args...));\n}\n\n/**\n  \\rst\n  Formats a string and prints it to stdout using ANSI escape sequences to\n  specify text formatting.\n\n  **Example**::\n\n    fmt::print(fmt::emphasis::bold | fg(fmt::color::red),\n               \"Elapsed time: {0:.2f} seconds\", 1.23);\n  \\endrst\n */\ntemplate <typename S, typename... Args,\n          FMT_ENABLE_IF(detail::is_string<S>::value)>\nvoid print(const text_style& ts, const S& format_str, const Args&... args) {\n  return print(stdout, ts, format_str, args...);\n}\n\ntemplate <typename S, typename Char = char_t<S>>\ninline std::basic_string<Char> vformat(\n    const text_style& ts, const S& format_str,\n    basic_format_args<buffer_context<type_identity_t<Char>>> args) {\n  basic_memory_buffer<Char> buf;\n  detail::vformat_to(buf, ts, to_string_view(format_str), args);\n  return fmt::to_string(buf);\n}\n\n/**\n  \\rst\n  Formats arguments and returns the result as a string using ANSI\n  escape sequences to specify text formatting.\n\n  **Example**::\n\n    #include <fmt/color.h>\n    std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),\n                                      \"The answer is {}\", 42);\n  \\endrst\n*/\ntemplate <typename S, typename... Args, typename Char = char_t<S>>\ninline std::basic_string<Char> format(const text_style& ts, const S& format_str,\n                                      const Args&... args) {\n  return fmt::vformat(ts, to_string_view(format_str),\n                      fmt::make_args_checked<Args...>(format_str, args...));\n}\n\n/**\n  Formats a string with the given text_style and writes the output to ``out``.\n */\ntemplate <typename OutputIt, typename Char,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>\nOutputIt vformat_to(\n    OutputIt out, const text_style& ts, basic_string_view<Char> format_str,\n    basic_format_args<buffer_context<type_identity_t<Char>>> args) {\n  auto&& buf = detail::get_buffer<Char>(out);\n  detail::vformat_to(buf, ts, format_str, args);\n  return detail::get_iterator(buf);\n}\n\n/**\n  \\rst\n  Formats arguments with the given text_style, writes the result to the output\n  iterator ``out`` and returns the iterator past the end of the output range.\n\n  **Example**::\n\n    std::vector<char> out;\n    fmt::format_to(std::back_inserter(out),\n                   fmt::emphasis::bold | fg(fmt::color::red), \"{}\", 42);\n  \\endrst\n*/\ntemplate <typename OutputIt, typename S, typename... Args,\n          bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value&&\n              detail::is_string<S>::value>\ninline auto format_to(OutputIt out, const text_style& ts, const S& format_str,\n                      Args&&... args) ->\n    typename std::enable_if<enable, OutputIt>::type {\n  return vformat_to(out, ts, to_string_view(format_str),\n                    fmt::make_args_checked<Args...>(format_str, args...));\n}\n\nFMT_MODULE_EXPORT_END\nFMT_END_NAMESPACE\n\n#endif  // FMT_COLOR_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/compile.h",
    "content": "// Formatting library for C++ - experimental format string compilation\n//\n// Copyright (c) 2012 - present, Victor Zverovich and fmt contributors\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_COMPILE_H_\n#define FMT_COMPILE_H_\n\n#include \"format.h\"\n\nFMT_BEGIN_NAMESPACE\nnamespace detail {\n\n// An output iterator that counts the number of objects written to it and\n// discards them.\nclass counting_iterator {\n private:\n  size_t count_;\n\n public:\n  using iterator_category = std::output_iterator_tag;\n  using difference_type = std::ptrdiff_t;\n  using pointer = void;\n  using reference = void;\n  using _Unchecked_type = counting_iterator;  // Mark iterator as checked.\n\n  struct value_type {\n    template <typename T> void operator=(const T&) {}\n  };\n\n  counting_iterator() : count_(0) {}\n\n  size_t count() const { return count_; }\n\n  counting_iterator& operator++() {\n    ++count_;\n    return *this;\n  }\n  counting_iterator operator++(int) {\n    auto it = *this;\n    ++*this;\n    return it;\n  }\n\n  friend counting_iterator operator+(counting_iterator it, difference_type n) {\n    it.count_ += static_cast<size_t>(n);\n    return it;\n  }\n\n  value_type operator*() const { return {}; }\n};\n\ntemplate <typename Char, typename InputIt>\ninline counting_iterator copy_str(InputIt begin, InputIt end,\n                                  counting_iterator it) {\n  return it + (end - begin);\n}\n\ntemplate <typename OutputIt> class truncating_iterator_base {\n protected:\n  OutputIt out_;\n  size_t limit_;\n  size_t count_ = 0;\n\n  truncating_iterator_base() : out_(), limit_(0) {}\n\n  truncating_iterator_base(OutputIt out, size_t limit)\n      : out_(out), limit_(limit) {}\n\n public:\n  using iterator_category = std::output_iterator_tag;\n  using value_type = typename std::iterator_traits<OutputIt>::value_type;\n  using difference_type = std::ptrdiff_t;\n  using pointer = void;\n  using reference = void;\n  using _Unchecked_type =\n      truncating_iterator_base;  // Mark iterator as checked.\n\n  OutputIt base() const { return out_; }\n  size_t count() const { return count_; }\n};\n\n// An output iterator that truncates the output and counts the number of objects\n// written to it.\ntemplate <typename OutputIt,\n          typename Enable = typename std::is_void<\n              typename std::iterator_traits<OutputIt>::value_type>::type>\nclass truncating_iterator;\n\ntemplate <typename OutputIt>\nclass truncating_iterator<OutputIt, std::false_type>\n    : public truncating_iterator_base<OutputIt> {\n  mutable typename truncating_iterator_base<OutputIt>::value_type blackhole_;\n\n public:\n  using value_type = typename truncating_iterator_base<OutputIt>::value_type;\n\n  truncating_iterator() = default;\n\n  truncating_iterator(OutputIt out, size_t limit)\n      : truncating_iterator_base<OutputIt>(out, limit) {}\n\n  truncating_iterator& operator++() {\n    if (this->count_++ < this->limit_) ++this->out_;\n    return *this;\n  }\n\n  truncating_iterator operator++(int) {\n    auto it = *this;\n    ++*this;\n    return it;\n  }\n\n  value_type& operator*() const {\n    return this->count_ < this->limit_ ? *this->out_ : blackhole_;\n  }\n};\n\ntemplate <typename OutputIt>\nclass truncating_iterator<OutputIt, std::true_type>\n    : public truncating_iterator_base<OutputIt> {\n public:\n  truncating_iterator() = default;\n\n  truncating_iterator(OutputIt out, size_t limit)\n      : truncating_iterator_base<OutputIt>(out, limit) {}\n\n  template <typename T> truncating_iterator& operator=(T val) {\n    if (this->count_++ < this->limit_) *this->out_++ = val;\n    return *this;\n  }\n\n  truncating_iterator& operator++() { return *this; }\n  truncating_iterator& operator++(int) { return *this; }\n  truncating_iterator& operator*() { return *this; }\n};\n\n// A compile-time string which is compiled into fast formatting code.\nclass compiled_string {};\n\ntemplate <typename S>\nstruct is_compiled_string : std::is_base_of<compiled_string, S> {};\n\n/**\n  \\rst\n  Converts a string literal *s* into a format string that will be parsed at\n  compile time and converted into efficient formatting code. Requires C++17\n  ``constexpr if`` compiler support.\n\n  **Example**::\n\n    // Converts 42 into std::string using the most efficient method and no\n    // runtime format string processing.\n    std::string s = fmt::format(FMT_COMPILE(\"{}\"), 42);\n  \\endrst\n */\n#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)\n#  define FMT_COMPILE(s) \\\n    FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit)\n#else\n#  define FMT_COMPILE(s) FMT_STRING(s)\n#endif\n\n#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\ntemplate <typename Char, size_t N,\n          fmt::detail_exported::fixed_string<Char, N> Str>\nstruct udl_compiled_string : compiled_string {\n  using char_type = Char;\n  constexpr operator basic_string_view<char_type>() const {\n    return {Str.data, N - 1};\n  }\n};\n#endif\n\ntemplate <typename T, typename... Tail>\nconst T& first(const T& value, const Tail&...) {\n  return value;\n}\n\n#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)\ntemplate <typename... Args> struct type_list {};\n\n// Returns a reference to the argument at index N from [first, rest...].\ntemplate <int N, typename T, typename... Args>\nconstexpr const auto& get([[maybe_unused]] const T& first,\n                          [[maybe_unused]] const Args&... rest) {\n  static_assert(N < 1 + sizeof...(Args), \"index is out of bounds\");\n  if constexpr (N == 0)\n    return first;\n  else\n    return detail::get<N - 1>(rest...);\n}\n\ntemplate <typename Char, typename... Args>\nconstexpr int get_arg_index_by_name(basic_string_view<Char> name,\n                                    type_list<Args...>) {\n  return get_arg_index_by_name<Args...>(name);\n}\n\ntemplate <int N, typename> struct get_type_impl;\n\ntemplate <int N, typename... Args> struct get_type_impl<N, type_list<Args...>> {\n  using type =\n      remove_cvref_t<decltype(detail::get<N>(std::declval<Args>()...))>;\n};\n\ntemplate <int N, typename T>\nusing get_type = typename get_type_impl<N, T>::type;\n\ntemplate <typename T> struct is_compiled_format : std::false_type {};\n\ntemplate <typename Char> struct text {\n  basic_string_view<Char> data;\n  using char_type = Char;\n\n  template <typename OutputIt, typename... Args>\n  constexpr OutputIt format(OutputIt out, const Args&...) const {\n    return write<Char>(out, data);\n  }\n};\n\ntemplate <typename Char>\nstruct is_compiled_format<text<Char>> : std::true_type {};\n\ntemplate <typename Char>\nconstexpr text<Char> make_text(basic_string_view<Char> s, size_t pos,\n                               size_t size) {\n  return {{&s[pos], size}};\n}\n\ntemplate <typename Char> struct code_unit {\n  Char value;\n  using char_type = Char;\n\n  template <typename OutputIt, typename... Args>\n  constexpr OutputIt format(OutputIt out, const Args&...) const {\n    return write<Char>(out, value);\n  }\n};\n\n// This ensures that the argument type is convertible to `const T&`.\ntemplate <typename T, int N, typename... Args>\nconstexpr const T& get_arg_checked(const Args&... args) {\n  const auto& arg = detail::get<N>(args...);\n  if constexpr (detail::is_named_arg<remove_cvref_t<decltype(arg)>>()) {\n    return arg.value;\n  } else {\n    return arg;\n  }\n}\n\ntemplate <typename Char>\nstruct is_compiled_format<code_unit<Char>> : std::true_type {};\n\n// A replacement field that refers to argument N.\ntemplate <typename Char, typename T, int N> struct field {\n  using char_type = Char;\n\n  template <typename OutputIt, typename... Args>\n  constexpr OutputIt format(OutputIt out, const Args&... args) const {\n    return write<Char>(out, get_arg_checked<T, N>(args...));\n  }\n};\n\ntemplate <typename Char, typename T, int N>\nstruct is_compiled_format<field<Char, T, N>> : std::true_type {};\n\n// A replacement field that refers to argument with name.\ntemplate <typename Char> struct runtime_named_field {\n  using char_type = Char;\n  basic_string_view<Char> name;\n\n  template <typename OutputIt, typename T>\n  constexpr static bool try_format_argument(\n      OutputIt& out,\n      // [[maybe_unused]] due to unused-but-set-parameter warning in GCC 7,8,9\n      [[maybe_unused]] basic_string_view<Char> arg_name, const T& arg) {\n    if constexpr (is_named_arg<typename std::remove_cv<T>::type>::value) {\n      if (arg_name == arg.name) {\n        out = write<Char>(out, arg.value);\n        return true;\n      }\n    }\n    return false;\n  }\n\n  template <typename OutputIt, typename... Args>\n  constexpr OutputIt format(OutputIt out, const Args&... args) const {\n    bool found = (try_format_argument(out, name, args) || ...);\n    if (!found) {\n      FMT_THROW(format_error(\"argument with specified name is not found\"));\n    }\n    return out;\n  }\n};\n\ntemplate <typename Char>\nstruct is_compiled_format<runtime_named_field<Char>> : std::true_type {};\n\n// A replacement field that refers to argument N and has format specifiers.\ntemplate <typename Char, typename T, int N> struct spec_field {\n  using char_type = Char;\n  formatter<T, Char> fmt;\n\n  template <typename OutputIt, typename... Args>\n  constexpr FMT_INLINE OutputIt format(OutputIt out,\n                                       const Args&... args) const {\n    const auto& vargs =\n        fmt::make_format_args<basic_format_context<OutputIt, Char>>(args...);\n    basic_format_context<OutputIt, Char> ctx(out, vargs);\n    return fmt.format(get_arg_checked<T, N>(args...), ctx);\n  }\n};\n\ntemplate <typename Char, typename T, int N>\nstruct is_compiled_format<spec_field<Char, T, N>> : std::true_type {};\n\ntemplate <typename L, typename R> struct concat {\n  L lhs;\n  R rhs;\n  using char_type = typename L::char_type;\n\n  template <typename OutputIt, typename... Args>\n  constexpr OutputIt format(OutputIt out, const Args&... args) const {\n    out = lhs.format(out, args...);\n    return rhs.format(out, args...);\n  }\n};\n\ntemplate <typename L, typename R>\nstruct is_compiled_format<concat<L, R>> : std::true_type {};\n\ntemplate <typename L, typename R>\nconstexpr concat<L, R> make_concat(L lhs, R rhs) {\n  return {lhs, rhs};\n}\n\nstruct unknown_format {};\n\ntemplate <typename Char>\nconstexpr size_t parse_text(basic_string_view<Char> str, size_t pos) {\n  for (size_t size = str.size(); pos != size; ++pos) {\n    if (str[pos] == '{' || str[pos] == '}') break;\n  }\n  return pos;\n}\n\ntemplate <typename Args, size_t POS, int ID, typename S>\nconstexpr auto compile_format_string(S format_str);\n\ntemplate <typename Args, size_t POS, int ID, typename T, typename S>\nconstexpr auto parse_tail(T head, S format_str) {\n  if constexpr (POS !=\n                basic_string_view<typename S::char_type>(format_str).size()) {\n    constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);\n    if constexpr (std::is_same<remove_cvref_t<decltype(tail)>,\n                               unknown_format>())\n      return tail;\n    else\n      return make_concat(head, tail);\n  } else {\n    return head;\n  }\n}\n\ntemplate <typename T, typename Char> struct parse_specs_result {\n  formatter<T, Char> fmt;\n  size_t end;\n  int next_arg_id;\n};\n\nconstexpr int manual_indexing_id = -1;\n\ntemplate <typename T, typename Char>\nconstexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,\n                                                  size_t pos, int next_arg_id) {\n  str.remove_prefix(pos);\n  auto ctx = basic_format_parse_context<Char>(str, {}, next_arg_id);\n  auto f = formatter<T, Char>();\n  auto end = f.parse(ctx);\n  return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1,\n          next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()};\n}\n\ntemplate <typename Char> struct arg_id_handler {\n  arg_ref<Char> arg_id;\n\n  constexpr int operator()() {\n    FMT_ASSERT(false, \"handler cannot be used with automatic indexing\");\n    return 0;\n  }\n  constexpr int operator()(int id) {\n    arg_id = arg_ref<Char>(id);\n    return 0;\n  }\n  constexpr int operator()(basic_string_view<Char> id) {\n    arg_id = arg_ref<Char>(id);\n    return 0;\n  }\n\n  constexpr void on_error(const char* message) {\n    FMT_THROW(format_error(message));\n  }\n};\n\ntemplate <typename Char> struct parse_arg_id_result {\n  arg_ref<Char> arg_id;\n  const Char* arg_id_end;\n};\n\ntemplate <int ID, typename Char>\nconstexpr auto parse_arg_id(const Char* begin, const Char* end) {\n  auto handler = arg_id_handler<Char>{arg_ref<Char>{}};\n  auto arg_id_end = parse_arg_id(begin, end, handler);\n  return parse_arg_id_result<Char>{handler.arg_id, arg_id_end};\n}\n\ntemplate <typename T, typename Enable = void> struct field_type {\n  using type = remove_cvref_t<T>;\n};\n\ntemplate <typename T>\nstruct field_type<T, enable_if_t<detail::is_named_arg<T>::value>> {\n  using type = remove_cvref_t<decltype(T::value)>;\n};\n\ntemplate <typename T, typename Args, size_t END_POS, int ARG_INDEX, int NEXT_ID,\n          typename S>\nconstexpr auto parse_replacement_field_then_tail(S format_str) {\n  using char_type = typename S::char_type;\n  constexpr auto str = basic_string_view<char_type>(format_str);\n  constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type();\n  if constexpr (c == '}') {\n    return parse_tail<Args, END_POS + 1, NEXT_ID>(\n        field<char_type, typename field_type<T>::type, ARG_INDEX>(),\n        format_str);\n  } else if constexpr (c == ':') {\n    constexpr auto result = parse_specs<typename field_type<T>::type>(\n        str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID);\n    return parse_tail<Args, result.end, result.next_arg_id>(\n        spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{\n            result.fmt},\n        format_str);\n  }\n}\n\n// Compiles a non-empty format string and returns the compiled representation\n// or unknown_format() on unrecognized input.\ntemplate <typename Args, size_t POS, int ID, typename S>\nconstexpr auto compile_format_string(S format_str) {\n  using char_type = typename S::char_type;\n  constexpr auto str = basic_string_view<char_type>(format_str);\n  if constexpr (str[POS] == '{') {\n    if constexpr (POS + 1 == str.size())\n      FMT_THROW(format_error(\"unmatched '{' in format string\"));\n    if constexpr (str[POS + 1] == '{') {\n      return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);\n    } else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') {\n      static_assert(ID != manual_indexing_id,\n                    \"cannot switch from manual to automatic argument indexing\");\n      constexpr auto next_id =\n          ID != manual_indexing_id ? ID + 1 : manual_indexing_id;\n      return parse_replacement_field_then_tail<get_type<ID, Args>, Args,\n                                               POS + 1, ID, next_id>(\n          format_str);\n    } else {\n      constexpr auto arg_id_result =\n          parse_arg_id<ID>(str.data() + POS + 1, str.data() + str.size());\n      constexpr auto arg_id_end_pos = arg_id_result.arg_id_end - str.data();\n      constexpr char_type c =\n          arg_id_end_pos != str.size() ? str[arg_id_end_pos] : char_type();\n      static_assert(c == '}' || c == ':', \"missing '}' in format string\");\n      if constexpr (arg_id_result.arg_id.kind == arg_id_kind::index) {\n        static_assert(\n            ID == manual_indexing_id || ID == 0,\n            \"cannot switch from automatic to manual argument indexing\");\n        constexpr auto arg_index = arg_id_result.arg_id.val.index;\n        return parse_replacement_field_then_tail<get_type<arg_index, Args>,\n                                                 Args, arg_id_end_pos,\n                                                 arg_index, manual_indexing_id>(\n            format_str);\n      } else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) {\n        constexpr auto arg_index =\n            get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{});\n        if constexpr (arg_index != invalid_arg_index) {\n          constexpr auto next_id =\n              ID != manual_indexing_id ? ID + 1 : manual_indexing_id;\n          return parse_replacement_field_then_tail<\n              decltype(get_type<arg_index, Args>::value), Args, arg_id_end_pos,\n              arg_index, next_id>(format_str);\n        } else {\n          if constexpr (c == '}') {\n            return parse_tail<Args, arg_id_end_pos + 1, ID>(\n                runtime_named_field<char_type>{arg_id_result.arg_id.val.name},\n                format_str);\n          } else if constexpr (c == ':') {\n            return unknown_format();  // no type info for specs parsing\n          }\n        }\n      }\n    }\n  } else if constexpr (str[POS] == '}') {\n    if constexpr (POS + 1 == str.size())\n      FMT_THROW(format_error(\"unmatched '}' in format string\"));\n    return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);\n  } else {\n    constexpr auto end = parse_text(str, POS + 1);\n    if constexpr (end - POS > 1) {\n      return parse_tail<Args, end, ID>(make_text(str, POS, end - POS),\n                                       format_str);\n    } else {\n      return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]},\n                                       format_str);\n    }\n  }\n}\n\ntemplate <typename... Args, typename S,\n          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>\nconstexpr auto compile(S format_str) {\n  constexpr auto str = basic_string_view<typename S::char_type>(format_str);\n  if constexpr (str.size() == 0) {\n    return detail::make_text(str, 0, 0);\n  } else {\n    constexpr auto result =\n        detail::compile_format_string<detail::type_list<Args...>, 0, 0>(\n            format_str);\n    return result;\n  }\n}\n#endif  // defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)\n}  // namespace detail\n\nFMT_MODULE_EXPORT_BEGIN\n\n#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)\n\ntemplate <typename CompiledFormat, typename... Args,\n          typename Char = typename CompiledFormat::char_type,\n          FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>\nFMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf,\n                                          const Args&... args) {\n  auto s = std::basic_string<Char>();\n  cf.format(std::back_inserter(s), args...);\n  return s;\n}\n\ntemplate <typename OutputIt, typename CompiledFormat, typename... Args,\n          FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>\nconstexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf,\n                                        const Args&... args) {\n  return cf.format(out, args...);\n}\n\ntemplate <typename S, typename... Args,\n          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>\nFMT_INLINE std::basic_string<typename S::char_type> format(const S&,\n                                                           Args&&... args) {\n  if constexpr (std::is_same<typename S::char_type, char>::value) {\n    constexpr auto str = basic_string_view<typename S::char_type>(S());\n    if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') {\n      const auto& first = detail::first(args...);\n      if constexpr (detail::is_named_arg<\n                        remove_cvref_t<decltype(first)>>::value) {\n        return fmt::to_string(first.value);\n      } else {\n        return fmt::to_string(first);\n      }\n    }\n  }\n  constexpr auto compiled = detail::compile<Args...>(S());\n  if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,\n                             detail::unknown_format>()) {\n    return format(static_cast<basic_string_view<typename S::char_type>>(S()),\n                  std::forward<Args>(args)...);\n  } else {\n    return format(compiled, std::forward<Args>(args)...);\n  }\n}\n\ntemplate <typename OutputIt, typename S, typename... Args,\n          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>\nFMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) {\n  constexpr auto compiled = detail::compile<Args...>(S());\n  if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,\n                             detail::unknown_format>()) {\n    return format_to(out,\n                     static_cast<basic_string_view<typename S::char_type>>(S()),\n                     std::forward<Args>(args)...);\n  } else {\n    return format_to(out, compiled, std::forward<Args>(args)...);\n  }\n}\n#endif\n\ntemplate <typename OutputIt, typename S, typename... Args,\n          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>\nformat_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,\n                                         const S& format_str, Args&&... args) {\n  auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), format_str,\n                      std::forward<Args>(args)...);\n  return {it.base(), it.count()};\n}\n\ntemplate <typename S, typename... Args,\n          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>\nsize_t formatted_size(const S& format_str, const Args&... args) {\n  return format_to(detail::counting_iterator(), format_str, args...).count();\n}\n\ntemplate <typename S, typename... Args,\n          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>\nvoid print(std::FILE* f, const S& format_str, const Args&... args) {\n  memory_buffer buffer;\n  format_to(std::back_inserter(buffer), format_str, args...);\n  detail::print(f, {buffer.data(), buffer.size()});\n}\n\ntemplate <typename S, typename... Args,\n          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>\nvoid print(const S& format_str, const Args&... args) {\n  print(stdout, format_str, args...);\n}\n\n#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\ninline namespace literals {\ntemplate <detail_exported::fixed_string Str>\nconstexpr detail::udl_compiled_string<\n    remove_cvref_t<decltype(Str.data[0])>,\n    sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str>\noperator\"\"_cf() {\n  return {};\n}\n}  // namespace literals\n#endif\n\nFMT_MODULE_EXPORT_END\nFMT_END_NAMESPACE\n\n#endif  // FMT_COMPILE_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/core.h",
    "content": "// Formatting library for C++ - the core API for char/UTF-8\n//\n// Copyright (c) 2012 - present, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_CORE_H_\n#define FMT_CORE_H_\n\n#include <cstddef>  // std::byte\n#include <cstdio>   // std::FILE\n#include <cstring>\n#include <iterator>\n#include <limits>\n#include <string>\n#include <type_traits>\n\n// The fmt library version in the form major * 10000 + minor * 100 + patch.\n#define FMT_VERSION 80101\n\n#if defined(__clang__) && !defined(__ibmxl__)\n#  define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)\n#else\n#  define FMT_CLANG_VERSION 0\n#endif\n\n#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && \\\n    !defined(__NVCOMPILER)\n#  define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#else\n#  define FMT_GCC_VERSION 0\n#endif\n\n#ifndef FMT_GCC_PRAGMA\n// Workaround _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884.\n#  if FMT_GCC_VERSION >= 504\n#    define FMT_GCC_PRAGMA(arg) _Pragma(arg)\n#  else\n#    define FMT_GCC_PRAGMA(arg)\n#  endif\n#endif\n\n#ifdef __ICL\n#  define FMT_ICC_VERSION __ICL\n#elif defined(__INTEL_COMPILER)\n#  define FMT_ICC_VERSION __INTEL_COMPILER\n#else\n#  define FMT_ICC_VERSION 0\n#endif\n\n#ifdef __NVCC__\n#  define FMT_NVCC __NVCC__\n#else\n#  define FMT_NVCC 0\n#endif\n\n#ifdef _MSC_VER\n#  define FMT_MSC_VER _MSC_VER\n#  define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__))\n#else\n#  define FMT_MSC_VER 0\n#  define FMT_MSC_WARNING(...)\n#endif\n\n#ifdef __has_feature\n#  define FMT_HAS_FEATURE(x) __has_feature(x)\n#else\n#  define FMT_HAS_FEATURE(x) 0\n#endif\n\n#if defined(__has_include) &&                             \\\n    (!defined(__INTELLISENSE__) || FMT_MSC_VER > 1900) && \\\n    (!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1600)\n#  define FMT_HAS_INCLUDE(x) __has_include(x)\n#else\n#  define FMT_HAS_INCLUDE(x) 0\n#endif\n\n#ifdef __has_cpp_attribute\n#  define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)\n#else\n#  define FMT_HAS_CPP_ATTRIBUTE(x) 0\n#endif\n\n#ifdef _MSVC_LANG\n#  define FMT_CPLUSPLUS _MSVC_LANG\n#else\n#  define FMT_CPLUSPLUS __cplusplus\n#endif\n\n#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \\\n  (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute))\n\n#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \\\n  (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute))\n\n// Check if relaxed C++14 constexpr is supported.\n// GCC doesn't allow throw in constexpr until version 6 (bug 67371).\n#ifndef FMT_USE_CONSTEXPR\n#  define FMT_USE_CONSTEXPR                                           \\\n    (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1912 || \\\n     (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) &&           \\\n        !FMT_NVCC && !FMT_ICC_VERSION\n#endif\n#if FMT_USE_CONSTEXPR\n#  define FMT_CONSTEXPR constexpr\n#  define FMT_CONSTEXPR_DECL constexpr\n#else\n#  define FMT_CONSTEXPR\n#  define FMT_CONSTEXPR_DECL\n#endif\n\n#if ((__cplusplus >= 202002L) &&                              \\\n     (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE > 9)) || \\\n    (__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002)\n#  define FMT_CONSTEXPR20 constexpr\n#else\n#  define FMT_CONSTEXPR20\n#endif\n\n// Check if constexpr std::char_traits<>::compare,length is supported.\n#if defined(__GLIBCXX__)\n#  if __cplusplus >= 201703L && defined(_GLIBCXX_RELEASE) && \\\n      _GLIBCXX_RELEASE >= 7  // GCC 7+ libstdc++ has _GLIBCXX_RELEASE.\n#    define FMT_CONSTEXPR_CHAR_TRAITS constexpr\n#  endif\n#elif defined(_LIBCPP_VERSION) && __cplusplus >= 201703L && \\\n    _LIBCPP_VERSION >= 4000\n#  define FMT_CONSTEXPR_CHAR_TRAITS constexpr\n#elif FMT_MSC_VER >= 1914 && _MSVC_LANG >= 201703L\n#  define FMT_CONSTEXPR_CHAR_TRAITS constexpr\n#endif\n#ifndef FMT_CONSTEXPR_CHAR_TRAITS\n#  define FMT_CONSTEXPR_CHAR_TRAITS\n#endif\n\n// Check if exceptions are disabled.\n#ifndef FMT_EXCEPTIONS\n#  if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \\\n      FMT_MSC_VER && !_HAS_EXCEPTIONS\n#    define FMT_EXCEPTIONS 0\n#  else\n#    define FMT_EXCEPTIONS 1\n#  endif\n#endif\n\n// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).\n#ifndef FMT_USE_NOEXCEPT\n#  define FMT_USE_NOEXCEPT 0\n#endif\n\n#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \\\n    FMT_GCC_VERSION >= 408 || FMT_MSC_VER >= 1900\n#  define FMT_DETECTED_NOEXCEPT noexcept\n#  define FMT_HAS_CXX11_NOEXCEPT 1\n#else\n#  define FMT_DETECTED_NOEXCEPT throw()\n#  define FMT_HAS_CXX11_NOEXCEPT 0\n#endif\n\n#ifndef FMT_NOEXCEPT\n#  if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT\n#    define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT\n#  else\n#    define FMT_NOEXCEPT\n#  endif\n#endif\n\n// [[noreturn]] is disabled on MSVC and NVCC because of bogus unreachable code\n// warnings.\n#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \\\n    !FMT_NVCC\n#  define FMT_NORETURN [[noreturn]]\n#else\n#  define FMT_NORETURN\n#endif\n\n#if __cplusplus == 201103L || __cplusplus == 201402L\n#  if defined(__INTEL_COMPILER) || defined(__PGI)\n#    define FMT_FALLTHROUGH\n#  elif defined(__clang__)\n#    define FMT_FALLTHROUGH [[clang::fallthrough]]\n#  elif FMT_GCC_VERSION >= 700 && \\\n      (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)\n#    define FMT_FALLTHROUGH [[gnu::fallthrough]]\n#  else\n#    define FMT_FALLTHROUGH\n#  endif\n#elif FMT_HAS_CPP17_ATTRIBUTE(fallthrough)\n#  define FMT_FALLTHROUGH [[fallthrough]]\n#else\n#  define FMT_FALLTHROUGH\n#endif\n\n#ifndef FMT_NODISCARD\n#  if FMT_HAS_CPP17_ATTRIBUTE(nodiscard)\n#    define FMT_NODISCARD [[nodiscard]]\n#  else\n#    define FMT_NODISCARD\n#  endif\n#endif\n\n#ifndef FMT_USE_FLOAT\n#  define FMT_USE_FLOAT 1\n#endif\n#ifndef FMT_USE_DOUBLE\n#  define FMT_USE_DOUBLE 1\n#endif\n#ifndef FMT_USE_LONG_DOUBLE\n#  define FMT_USE_LONG_DOUBLE 1\n#endif\n\n#ifndef FMT_INLINE\n#  if FMT_GCC_VERSION || FMT_CLANG_VERSION\n#    define FMT_INLINE inline __attribute__((always_inline))\n#  else\n#    define FMT_INLINE inline\n#  endif\n#endif\n\n#ifndef FMT_DEPRECATED\n#  if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900\n#    define FMT_DEPRECATED [[deprecated]]\n#  else\n#    if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)\n#      define FMT_DEPRECATED __attribute__((deprecated))\n#    elif FMT_MSC_VER\n#      define FMT_DEPRECATED __declspec(deprecated)\n#    else\n#      define FMT_DEPRECATED /* deprecated */\n#    endif\n#  endif\n#endif\n\n#ifndef FMT_BEGIN_NAMESPACE\n#  define FMT_BEGIN_NAMESPACE \\\n    namespace fmt {           \\\n    inline namespace v8 {\n#  define FMT_END_NAMESPACE \\\n    }                       \\\n    }\n#endif\n\n#ifndef FMT_MODULE_EXPORT\n#  define FMT_MODULE_EXPORT\n#  define FMT_MODULE_EXPORT_BEGIN\n#  define FMT_MODULE_EXPORT_END\n#  define FMT_BEGIN_DETAIL_NAMESPACE namespace detail {\n#  define FMT_END_DETAIL_NAMESPACE }\n#endif\n\n#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)\n#  define FMT_CLASS_API FMT_MSC_WARNING(suppress : 4275)\n#  ifdef FMT_EXPORT\n#    define FMT_API __declspec(dllexport)\n#  elif defined(FMT_SHARED)\n#    define FMT_API __declspec(dllimport)\n#  endif\n#else\n#  define FMT_CLASS_API\n#  if defined(FMT_EXPORT) || defined(FMT_SHARED)\n#    if defined(__GNUC__) || defined(__clang__)\n#      define FMT_API __attribute__((visibility(\"default\")))\n#    endif\n#  endif\n#endif\n#ifndef FMT_API\n#  define FMT_API\n#endif\n\n// libc++ supports string_view in pre-c++17.\n#if (FMT_HAS_INCLUDE(<string_view>) &&                       \\\n     (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \\\n    (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)\n#  include <string_view>\n#  define FMT_USE_STRING_VIEW\n#elif FMT_HAS_INCLUDE(\"experimental/string_view\") && __cplusplus >= 201402L\n#  include <experimental/string_view>\n#  define FMT_USE_EXPERIMENTAL_STRING_VIEW\n#endif\n\n#ifndef FMT_UNICODE\n#  define FMT_UNICODE !FMT_MSC_VER\n#endif\n\n#ifndef FMT_CONSTEVAL\n#  if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) &&      \\\n       __cplusplus > 201703L && !defined(__apple_build_version__)) || \\\n      (defined(__cpp_consteval) &&                                    \\\n       (!FMT_MSC_VER || _MSC_FULL_VER >= 193030704))\n// consteval is broken in MSVC before VS2022 and Apple clang 13.\n#    define FMT_CONSTEVAL consteval\n#    define FMT_HAS_CONSTEVAL\n#  else\n#    define FMT_CONSTEVAL\n#  endif\n#endif\n\n#ifndef FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\n#  if defined(__cpp_nontype_template_args) &&                \\\n      ((FMT_GCC_VERSION >= 903 && __cplusplus >= 201709L) || \\\n       __cpp_nontype_template_args >= 201911L)\n#    define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 1\n#  else\n#    define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 0\n#  endif\n#endif\n\n// Enable minimal optimizations for more compact code in debug mode.\nFMT_GCC_PRAGMA(\"GCC push_options\")\n#ifndef __OPTIMIZE__\nFMT_GCC_PRAGMA(\"GCC optimize(\\\"Og\\\")\")\n#endif\n\nFMT_BEGIN_NAMESPACE\nFMT_MODULE_EXPORT_BEGIN\n\n// Implementations of enable_if_t and other metafunctions for older systems.\ntemplate <bool B, typename T = void>\nusing enable_if_t = typename std::enable_if<B, T>::type;\ntemplate <bool B, typename T, typename F>\nusing conditional_t = typename std::conditional<B, T, F>::type;\ntemplate <bool B> using bool_constant = std::integral_constant<bool, B>;\ntemplate <typename T>\nusing remove_reference_t = typename std::remove_reference<T>::type;\ntemplate <typename T>\nusing remove_const_t = typename std::remove_const<T>::type;\ntemplate <typename T>\nusing remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;\ntemplate <typename T> struct type_identity { using type = T; };\ntemplate <typename T> using type_identity_t = typename type_identity<T>::type;\n\nstruct monostate {\n  constexpr monostate() {}\n};\n\n// An enable_if helper to be used in template parameters which results in much\n// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed\n// to workaround a bug in MSVC 2019 (see #1140 and #1186).\n#ifdef FMT_DOC\n#  define FMT_ENABLE_IF(...)\n#else\n#  define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0\n#endif\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\n// Suppress \"unused variable\" warnings with the method described in\n// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.\n// (void)var does not work on many Intel compilers.\ntemplate <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}\n\nconstexpr FMT_INLINE auto is_constant_evaluated(bool default_value = false)\n    FMT_NOEXCEPT -> bool {\n#ifdef __cpp_lib_is_constant_evaluated\n  ignore_unused(default_value);\n  return std::is_constant_evaluated();\n#else\n  return default_value;\n#endif\n}\n\n// A function to suppress \"conditional expression is constant\" warnings.\ntemplate <typename T> constexpr FMT_INLINE auto const_check(T value) -> T {\n  return value;\n}\n\nFMT_NORETURN FMT_API void assert_fail(const char* file, int line,\n                                      const char* message);\n\n#ifndef FMT_ASSERT\n#  ifdef NDEBUG\n// FMT_ASSERT is not empty to avoid -Werror=empty-body.\n#    define FMT_ASSERT(condition, message) \\\n      ::fmt::detail::ignore_unused((condition), (message))\n#  else\n#    define FMT_ASSERT(condition, message)                                    \\\n      ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \\\n           ? (void)0                                                          \\\n           : ::fmt::detail::assert_fail(__FILE__, __LINE__, (message)))\n#  endif\n#endif\n\n#ifdef __cpp_lib_byte\nusing byte = std::byte;\n#else\nenum class byte : unsigned char {};\n#endif\n\n#if defined(FMT_USE_STRING_VIEW)\ntemplate <typename Char> using std_string_view = std::basic_string_view<Char>;\n#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)\ntemplate <typename Char>\nusing std_string_view = std::experimental::basic_string_view<Char>;\n#else\ntemplate <typename T> struct std_string_view {};\n#endif\n\n#ifdef FMT_USE_INT128\n// Do nothing.\n#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \\\n    !(FMT_CLANG_VERSION && FMT_MSC_VER)\n#  define FMT_USE_INT128 1\nusing int128_t = __int128_t;\nusing uint128_t = __uint128_t;\ntemplate <typename T> inline auto convert_for_visit(T value) -> T {\n  return value;\n}\n#else\n#  define FMT_USE_INT128 0\n#endif\n#if !FMT_USE_INT128\nenum class int128_t {};\nenum class uint128_t {};\n// Reduce template instantiations.\ntemplate <typename T> inline auto convert_for_visit(T) -> monostate {\n  return {};\n}\n#endif\n\n// Casts a nonnegative integer to unsigned.\ntemplate <typename Int>\nFMT_CONSTEXPR auto to_unsigned(Int value) ->\n    typename std::make_unsigned<Int>::type {\n  FMT_ASSERT(value >= 0, \"negative value\");\n  return static_cast<typename std::make_unsigned<Int>::type>(value);\n}\n\nFMT_MSC_WARNING(suppress : 4566) constexpr unsigned char micro[] = \"\\u00B5\";\n\nconstexpr auto is_utf8() -> bool {\n  // Avoid buggy sign extensions in MSVC's constant evaluation mode.\n  // https://developercommunity.visualstudio.com/t/C-difference-in-behavior-for-unsigned/1233612\n  using uchar = unsigned char;\n  return FMT_UNICODE || (sizeof(micro) == 3 && uchar(micro[0]) == 0xC2 &&\n                         uchar(micro[1]) == 0xB5);\n}\nFMT_END_DETAIL_NAMESPACE\n\n/**\n  An implementation of ``std::basic_string_view`` for pre-C++17. It provides a\n  subset of the API. ``fmt::basic_string_view`` is used for format strings even\n  if ``std::string_view`` is available to prevent issues when a library is\n  compiled with a different ``-std`` option than the client code (which is not\n  recommended).\n */\ntemplate <typename Char> class basic_string_view {\n private:\n  const Char* data_;\n  size_t size_;\n\n public:\n  using value_type = Char;\n  using iterator = const Char*;\n\n  constexpr basic_string_view() FMT_NOEXCEPT : data_(nullptr), size_(0) {}\n\n  /** Constructs a string reference object from a C string and a size. */\n  constexpr basic_string_view(const Char* s, size_t count) FMT_NOEXCEPT\n      : data_(s),\n        size_(count) {}\n\n  /**\n    \\rst\n    Constructs a string reference object from a C string computing\n    the size with ``std::char_traits<Char>::length``.\n    \\endrst\n   */\n  FMT_CONSTEXPR_CHAR_TRAITS\n  FMT_INLINE\n  basic_string_view(const Char* s)\n      : data_(s),\n        size_(detail::const_check(std::is_same<Char, char>::value &&\n                                  !detail::is_constant_evaluated(true))\n                  ? std::strlen(reinterpret_cast<const char*>(s))\n                  : std::char_traits<Char>::length(s)) {}\n\n  /** Constructs a string reference from a ``std::basic_string`` object. */\n  template <typename Traits, typename Alloc>\n  FMT_CONSTEXPR basic_string_view(\n      const std::basic_string<Char, Traits, Alloc>& s) FMT_NOEXCEPT\n      : data_(s.data()),\n        size_(s.size()) {}\n\n  template <typename S, FMT_ENABLE_IF(std::is_same<\n                                      S, detail::std_string_view<Char>>::value)>\n  FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()),\n                                                      size_(s.size()) {}\n\n  /** Returns a pointer to the string data. */\n  constexpr auto data() const FMT_NOEXCEPT -> const Char* { return data_; }\n\n  /** Returns the string size. */\n  constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; }\n\n  constexpr auto begin() const FMT_NOEXCEPT -> iterator { return data_; }\n  constexpr auto end() const FMT_NOEXCEPT -> iterator { return data_ + size_; }\n\n  constexpr auto operator[](size_t pos) const FMT_NOEXCEPT -> const Char& {\n    return data_[pos];\n  }\n\n  FMT_CONSTEXPR void remove_prefix(size_t n) FMT_NOEXCEPT {\n    data_ += n;\n    size_ -= n;\n  }\n\n  // Lexicographically compare this string reference to other.\n  FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int {\n    size_t str_size = size_ < other.size_ ? size_ : other.size_;\n    int result = std::char_traits<Char>::compare(data_, other.data_, str_size);\n    if (result == 0)\n      result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);\n    return result;\n  }\n\n  FMT_CONSTEXPR_CHAR_TRAITS friend auto operator==(basic_string_view lhs,\n                                                   basic_string_view rhs)\n      -> bool {\n    return lhs.compare(rhs) == 0;\n  }\n  friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool {\n    return lhs.compare(rhs) != 0;\n  }\n  friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool {\n    return lhs.compare(rhs) < 0;\n  }\n  friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool {\n    return lhs.compare(rhs) <= 0;\n  }\n  friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool {\n    return lhs.compare(rhs) > 0;\n  }\n  friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool {\n    return lhs.compare(rhs) >= 0;\n  }\n};\n\nusing string_view = basic_string_view<char>;\n\n/** Specifies if ``T`` is a character type. Can be specialized by users. */\ntemplate <typename T> struct is_char : std::false_type {};\ntemplate <> struct is_char<char> : std::true_type {};\n\n// Returns a string view of `s`.\ntemplate <typename Char, FMT_ENABLE_IF(is_char<Char>::value)>\nFMT_INLINE auto to_string_view(const Char* s) -> basic_string_view<Char> {\n  return s;\n}\ntemplate <typename Char, typename Traits, typename Alloc>\ninline auto to_string_view(const std::basic_string<Char, Traits, Alloc>& s)\n    -> basic_string_view<Char> {\n  return s;\n}\ntemplate <typename Char>\nconstexpr auto to_string_view(basic_string_view<Char> s)\n    -> basic_string_view<Char> {\n  return s;\n}\ntemplate <typename Char,\n          FMT_ENABLE_IF(!std::is_empty<detail::std_string_view<Char>>::value)>\ninline auto to_string_view(detail::std_string_view<Char> s)\n    -> basic_string_view<Char> {\n  return s;\n}\n\n// A base class for compile-time strings. It is defined in the fmt namespace to\n// make formatting functions visible via ADL, e.g. format(FMT_STRING(\"{}\"), 42).\nstruct compile_string {};\n\ntemplate <typename S>\nstruct is_compile_string : std::is_base_of<compile_string, S> {};\n\ntemplate <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>\nconstexpr auto to_string_view(const S& s)\n    -> basic_string_view<typename S::char_type> {\n  return basic_string_view<typename S::char_type>(s);\n}\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\nvoid to_string_view(...);\nusing fmt::to_string_view;\n\n// Specifies whether S is a string type convertible to fmt::basic_string_view.\n// It should be a constexpr function but MSVC 2017 fails to compile it in\n// enable_if and MSVC 2015 fails to compile it as an alias template.\ntemplate <typename S>\nstruct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))> {\n};\n\ntemplate <typename S, typename = void> struct char_t_impl {};\ntemplate <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> {\n  using result = decltype(to_string_view(std::declval<S>()));\n  using type = typename result::value_type;\n};\n\n// Reports a compile-time error if S is not a valid format string.\ntemplate <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>\nFMT_INLINE void check_format_string(const S&) {\n#ifdef FMT_ENFORCE_COMPILE_STRING\n  static_assert(is_compile_string<S>::value,\n                \"FMT_ENFORCE_COMPILE_STRING requires all format strings to use \"\n                \"FMT_STRING.\");\n#endif\n}\ntemplate <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>\nvoid check_format_string(S);\n\nFMT_NORETURN FMT_API void throw_format_error(const char* message);\n\nstruct error_handler {\n  constexpr error_handler() = default;\n  constexpr error_handler(const error_handler&) = default;\n\n  // This function is intentionally not constexpr to give a compile-time error.\n  FMT_NORETURN FMT_API void on_error(const char* message);\n};\nFMT_END_DETAIL_NAMESPACE\n\n/** String's character type. */\ntemplate <typename S> using char_t = typename detail::char_t_impl<S>::type;\n\n/**\n  \\rst\n  Parsing context consisting of a format string range being parsed and an\n  argument counter for automatic indexing.\n  You can use the ``format_parse_context`` type alias for ``char`` instead.\n  \\endrst\n */\ntemplate <typename Char, typename ErrorHandler = detail::error_handler>\nclass basic_format_parse_context : private ErrorHandler {\n private:\n  basic_string_view<Char> format_str_;\n  int next_arg_id_;\n\n public:\n  using char_type = Char;\n  using iterator = typename basic_string_view<Char>::iterator;\n\n  explicit constexpr basic_format_parse_context(\n      basic_string_view<Char> format_str, ErrorHandler eh = {},\n      int next_arg_id = 0)\n      : ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {}\n\n  /**\n    Returns an iterator to the beginning of the format string range being\n    parsed.\n   */\n  constexpr auto begin() const FMT_NOEXCEPT -> iterator {\n    return format_str_.begin();\n  }\n\n  /**\n    Returns an iterator past the end of the format string range being parsed.\n   */\n  constexpr auto end() const FMT_NOEXCEPT -> iterator {\n    return format_str_.end();\n  }\n\n  /** Advances the begin iterator to ``it``. */\n  FMT_CONSTEXPR void advance_to(iterator it) {\n    format_str_.remove_prefix(detail::to_unsigned(it - begin()));\n  }\n\n  /**\n    Reports an error if using the manual argument indexing; otherwise returns\n    the next argument index and switches to the automatic indexing.\n   */\n  FMT_CONSTEXPR auto next_arg_id() -> int {\n    // Don't check if the argument id is valid to avoid overhead and because it\n    // will be checked during formatting anyway.\n    if (next_arg_id_ >= 0) return next_arg_id_++;\n    on_error(\"cannot switch from manual to automatic argument indexing\");\n    return 0;\n  }\n\n  /**\n    Reports an error if using the automatic argument indexing; otherwise\n    switches to the manual indexing.\n   */\n  FMT_CONSTEXPR void check_arg_id(int) {\n    if (next_arg_id_ > 0)\n      on_error(\"cannot switch from automatic to manual argument indexing\");\n    else\n      next_arg_id_ = -1;\n  }\n\n  FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {}\n\n  FMT_CONSTEXPR void on_error(const char* message) {\n    ErrorHandler::on_error(message);\n  }\n\n  constexpr auto error_handler() const -> ErrorHandler { return *this; }\n};\n\nusing format_parse_context = basic_format_parse_context<char>;\n\ntemplate <typename Context> class basic_format_arg;\ntemplate <typename Context> class basic_format_args;\ntemplate <typename Context> class dynamic_format_arg_store;\n\n// A formatter for objects of type T.\ntemplate <typename T, typename Char = char, typename Enable = void>\nstruct formatter {\n  // A deleted default constructor indicates a disabled formatter.\n  formatter() = delete;\n};\n\n// Specifies if T has an enabled formatter specialization. A type can be\n// formattable even if it doesn't have a formatter e.g. via a conversion.\ntemplate <typename T, typename Context>\nusing has_formatter =\n    std::is_constructible<typename Context::template formatter_type<T>>;\n\n// Checks whether T is a container with contiguous storage.\ntemplate <typename T> struct is_contiguous : std::false_type {};\ntemplate <typename Char>\nstruct is_contiguous<std::basic_string<Char>> : std::true_type {};\n\nclass appender;\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\ntemplate <typename Context, typename T>\nconstexpr auto has_const_formatter_impl(T*)\n    -> decltype(typename Context::template formatter_type<T>().format(\n                    std::declval<const T&>(), std::declval<Context&>()),\n                true) {\n  return true;\n}\ntemplate <typename Context>\nconstexpr auto has_const_formatter_impl(...) -> bool {\n  return false;\n}\ntemplate <typename T, typename Context>\nconstexpr auto has_const_formatter() -> bool {\n  return has_const_formatter_impl<Context>(static_cast<T*>(nullptr));\n}\n\n// Extracts a reference to the container from back_insert_iterator.\ntemplate <typename Container>\ninline auto get_container(std::back_insert_iterator<Container> it)\n    -> Container& {\n  using bi_iterator = std::back_insert_iterator<Container>;\n  struct accessor : bi_iterator {\n    accessor(bi_iterator iter) : bi_iterator(iter) {}\n    using bi_iterator::container;\n  };\n  return *accessor(it).container;\n}\n\ntemplate <typename Char, typename InputIt, typename OutputIt>\nFMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out)\n    -> OutputIt {\n  while (begin != end) *out++ = static_cast<Char>(*begin++);\n  return out;\n}\n\ntemplate <typename Char, typename T, typename U,\n          FMT_ENABLE_IF(\n              std::is_same<remove_const_t<T>, U>::value&& is_char<U>::value)>\nFMT_CONSTEXPR auto copy_str(T* begin, T* end, U* out) -> U* {\n  if (is_constant_evaluated()) return copy_str<Char, T*, U*>(begin, end, out);\n  auto size = to_unsigned(end - begin);\n  memcpy(out, begin, size * sizeof(U));\n  return out + size;\n}\n\n/**\n  \\rst\n  A contiguous memory buffer with an optional growing ability. It is an internal\n  class and shouldn't be used directly, only via `~fmt::basic_memory_buffer`.\n  \\endrst\n */\ntemplate <typename T> class buffer {\n private:\n  T* ptr_;\n  size_t size_;\n  size_t capacity_;\n\n protected:\n  // Don't initialize ptr_ since it is not accessed to save a few cycles.\n  FMT_MSC_WARNING(suppress : 26495)\n  buffer(size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}\n\n  FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0,\n                         size_t cap = 0) FMT_NOEXCEPT : ptr_(p),\n                                                        size_(sz),\n                                                        capacity_(cap) {}\n\n  FMT_CONSTEXPR20 ~buffer() = default;\n  buffer(buffer&&) = default;\n\n  /** Sets the buffer data and capacity. */\n  FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) FMT_NOEXCEPT {\n    ptr_ = buf_data;\n    capacity_ = buf_capacity;\n  }\n\n  /** Increases the buffer capacity to hold at least *capacity* elements. */\n  virtual FMT_CONSTEXPR20 void grow(size_t capacity) = 0;\n\n public:\n  using value_type = T;\n  using const_reference = const T&;\n\n  buffer(const buffer&) = delete;\n  void operator=(const buffer&) = delete;\n\n  auto begin() FMT_NOEXCEPT -> T* { return ptr_; }\n  auto end() FMT_NOEXCEPT -> T* { return ptr_ + size_; }\n\n  auto begin() const FMT_NOEXCEPT -> const T* { return ptr_; }\n  auto end() const FMT_NOEXCEPT -> const T* { return ptr_ + size_; }\n\n  /** Returns the size of this buffer. */\n  constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; }\n\n  /** Returns the capacity of this buffer. */\n  constexpr auto capacity() const FMT_NOEXCEPT -> size_t { return capacity_; }\n\n  /** Returns a pointer to the buffer data. */\n  FMT_CONSTEXPR auto data() FMT_NOEXCEPT -> T* { return ptr_; }\n\n  /** Returns a pointer to the buffer data. */\n  FMT_CONSTEXPR auto data() const FMT_NOEXCEPT -> const T* { return ptr_; }\n\n  /** Clears this buffer. */\n  void clear() { size_ = 0; }\n\n  // Tries resizing the buffer to contain *count* elements. If T is a POD type\n  // the new elements may not be initialized.\n  FMT_CONSTEXPR20 void try_resize(size_t count) {\n    try_reserve(count);\n    size_ = count <= capacity_ ? count : capacity_;\n  }\n\n  // Tries increasing the buffer capacity to *new_capacity*. It can increase the\n  // capacity by a smaller amount than requested but guarantees there is space\n  // for at least one additional element either by increasing the capacity or by\n  // flushing the buffer if it is full.\n  FMT_CONSTEXPR20 void try_reserve(size_t new_capacity) {\n    if (new_capacity > capacity_) grow(new_capacity);\n  }\n\n  FMT_CONSTEXPR20 void push_back(const T& value) {\n    try_reserve(size_ + 1);\n    ptr_[size_++] = value;\n  }\n\n  /** Appends data to the end of the buffer. */\n  template <typename U> void append(const U* begin, const U* end);\n\n  template <typename I> FMT_CONSTEXPR auto operator[](I index) -> T& {\n    return ptr_[index];\n  }\n  template <typename I>\n  FMT_CONSTEXPR auto operator[](I index) const -> const T& {\n    return ptr_[index];\n  }\n};\n\nstruct buffer_traits {\n  explicit buffer_traits(size_t) {}\n  auto count() const -> size_t { return 0; }\n  auto limit(size_t size) -> size_t { return size; }\n};\n\nclass fixed_buffer_traits {\n private:\n  size_t count_ = 0;\n  size_t limit_;\n\n public:\n  explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}\n  auto count() const -> size_t { return count_; }\n  auto limit(size_t size) -> size_t {\n    size_t n = limit_ > count_ ? limit_ - count_ : 0;\n    count_ += size;\n    return size < n ? size : n;\n  }\n};\n\n// A buffer that writes to an output iterator when flushed.\ntemplate <typename OutputIt, typename T, typename Traits = buffer_traits>\nclass iterator_buffer final : public Traits, public buffer<T> {\n private:\n  OutputIt out_;\n  enum { buffer_size = 256 };\n  T data_[buffer_size];\n\n protected:\n  FMT_CONSTEXPR20 void grow(size_t) override {\n    if (this->size() == buffer_size) flush();\n  }\n\n  void flush() {\n    auto size = this->size();\n    this->clear();\n    out_ = copy_str<T>(data_, data_ + this->limit(size), out_);\n  }\n\n public:\n  explicit iterator_buffer(OutputIt out, size_t n = buffer_size)\n      : Traits(n), buffer<T>(data_, 0, buffer_size), out_(out) {}\n  iterator_buffer(iterator_buffer&& other)\n      : Traits(other), buffer<T>(data_, 0, buffer_size), out_(other.out_) {}\n  ~iterator_buffer() { flush(); }\n\n  auto out() -> OutputIt {\n    flush();\n    return out_;\n  }\n  auto count() const -> size_t { return Traits::count() + this->size(); }\n};\n\ntemplate <typename T>\nclass iterator_buffer<T*, T, fixed_buffer_traits> final\n    : public fixed_buffer_traits,\n      public buffer<T> {\n private:\n  T* out_;\n  enum { buffer_size = 256 };\n  T data_[buffer_size];\n\n protected:\n  FMT_CONSTEXPR20 void grow(size_t) override {\n    if (this->size() == this->capacity()) flush();\n  }\n\n  void flush() {\n    size_t n = this->limit(this->size());\n    if (this->data() == out_) {\n      out_ += n;\n      this->set(data_, buffer_size);\n    }\n    this->clear();\n  }\n\n public:\n  explicit iterator_buffer(T* out, size_t n = buffer_size)\n      : fixed_buffer_traits(n), buffer<T>(out, 0, n), out_(out) {}\n  iterator_buffer(iterator_buffer&& other)\n      : fixed_buffer_traits(other),\n        buffer<T>(std::move(other)),\n        out_(other.out_) {\n    if (this->data() != out_) {\n      this->set(data_, buffer_size);\n      this->clear();\n    }\n  }\n  ~iterator_buffer() { flush(); }\n\n  auto out() -> T* {\n    flush();\n    return out_;\n  }\n  auto count() const -> size_t {\n    return fixed_buffer_traits::count() + this->size();\n  }\n};\n\ntemplate <typename T> class iterator_buffer<T*, T> final : public buffer<T> {\n protected:\n  FMT_CONSTEXPR20 void grow(size_t) override {}\n\n public:\n  explicit iterator_buffer(T* out, size_t = 0) : buffer<T>(out, 0, ~size_t()) {}\n\n  auto out() -> T* { return &*this->end(); }\n};\n\n// A buffer that writes to a container with the contiguous storage.\ntemplate <typename Container>\nclass iterator_buffer<std::back_insert_iterator<Container>,\n                      enable_if_t<is_contiguous<Container>::value,\n                                  typename Container::value_type>>\n    final : public buffer<typename Container::value_type> {\n private:\n  Container& container_;\n\n protected:\n  FMT_CONSTEXPR20 void grow(size_t capacity) override {\n    container_.resize(capacity);\n    this->set(&container_[0], capacity);\n  }\n\n public:\n  explicit iterator_buffer(Container& c)\n      : buffer<typename Container::value_type>(c.size()), container_(c) {}\n  explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0)\n      : iterator_buffer(get_container(out)) {}\n  auto out() -> std::back_insert_iterator<Container> {\n    return std::back_inserter(container_);\n  }\n};\n\n// A buffer that counts the number of code units written discarding the output.\ntemplate <typename T = char> class counting_buffer final : public buffer<T> {\n private:\n  enum { buffer_size = 256 };\n  T data_[buffer_size];\n  size_t count_ = 0;\n\n protected:\n  FMT_CONSTEXPR20 void grow(size_t) override {\n    if (this->size() != buffer_size) return;\n    count_ += this->size();\n    this->clear();\n  }\n\n public:\n  counting_buffer() : buffer<T>(data_, 0, buffer_size) {}\n\n  auto count() -> size_t { return count_ + this->size(); }\n};\n\ntemplate <typename T>\nusing buffer_appender = conditional_t<std::is_same<T, char>::value, appender,\n                                      std::back_insert_iterator<buffer<T>>>;\n\n// Maps an output iterator to a buffer.\ntemplate <typename T, typename OutputIt>\nauto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> {\n  return iterator_buffer<OutputIt, T>(out);\n}\n\ntemplate <typename Buffer>\nauto get_iterator(Buffer& buf) -> decltype(buf.out()) {\n  return buf.out();\n}\ntemplate <typename T> auto get_iterator(buffer<T>& buf) -> buffer_appender<T> {\n  return buffer_appender<T>(buf);\n}\n\ntemplate <typename T, typename Char = char, typename Enable = void>\nstruct fallback_formatter {\n  fallback_formatter() = delete;\n};\n\n// Specifies if T has an enabled fallback_formatter specialization.\ntemplate <typename T, typename Char>\nusing has_fallback_formatter =\n    std::is_constructible<fallback_formatter<T, Char>>;\n\nstruct view {};\n\ntemplate <typename Char, typename T> struct named_arg : view {\n  const Char* name;\n  const T& value;\n  named_arg(const Char* n, const T& v) : name(n), value(v) {}\n};\n\ntemplate <typename Char> struct named_arg_info {\n  const Char* name;\n  int id;\n};\n\ntemplate <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>\nstruct arg_data {\n  // args_[0].named_args points to named_args_ to avoid bloating format_args.\n  // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.\n  T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];\n  named_arg_info<Char> named_args_[NUM_NAMED_ARGS];\n\n  template <typename... U>\n  arg_data(const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {}\n  arg_data(const arg_data& other) = delete;\n  auto args() const -> const T* { return args_ + 1; }\n  auto named_args() -> named_arg_info<Char>* { return named_args_; }\n};\n\ntemplate <typename T, typename Char, size_t NUM_ARGS>\nstruct arg_data<T, Char, NUM_ARGS, 0> {\n  // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.\n  T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];\n\n  template <typename... U>\n  FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {}\n  FMT_CONSTEXPR FMT_INLINE auto args() const -> const T* { return args_; }\n  FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t {\n    return nullptr;\n  }\n};\n\ntemplate <typename Char>\ninline void init_named_args(named_arg_info<Char>*, int, int) {}\n\ntemplate <typename T> struct is_named_arg : std::false_type {};\ntemplate <typename T> struct is_statically_named_arg : std::false_type {};\n\ntemplate <typename T, typename Char>\nstruct is_named_arg<named_arg<Char, T>> : std::true_type {};\n\ntemplate <typename Char, typename T, typename... Tail,\n          FMT_ENABLE_IF(!is_named_arg<T>::value)>\nvoid init_named_args(named_arg_info<Char>* named_args, int arg_count,\n                     int named_arg_count, const T&, const Tail&... args) {\n  init_named_args(named_args, arg_count + 1, named_arg_count, args...);\n}\n\ntemplate <typename Char, typename T, typename... Tail,\n          FMT_ENABLE_IF(is_named_arg<T>::value)>\nvoid init_named_args(named_arg_info<Char>* named_args, int arg_count,\n                     int named_arg_count, const T& arg, const Tail&... args) {\n  named_args[named_arg_count++] = {arg.name, arg_count};\n  init_named_args(named_args, arg_count + 1, named_arg_count, args...);\n}\n\ntemplate <typename... Args>\nFMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int,\n                                              const Args&...) {}\n\ntemplate <bool B = false> constexpr auto count() -> size_t { return B ? 1 : 0; }\ntemplate <bool B1, bool B2, bool... Tail> constexpr auto count() -> size_t {\n  return (B1 ? 1 : 0) + count<B2, Tail...>();\n}\n\ntemplate <typename... Args> constexpr auto count_named_args() -> size_t {\n  return count<is_named_arg<Args>::value...>();\n}\n\ntemplate <typename... Args>\nconstexpr auto count_statically_named_args() -> size_t {\n  return count<is_statically_named_arg<Args>::value...>();\n}\n\nenum class type {\n  none_type,\n  // Integer types should go first,\n  int_type,\n  uint_type,\n  long_long_type,\n  ulong_long_type,\n  int128_type,\n  uint128_type,\n  bool_type,\n  char_type,\n  last_integer_type = char_type,\n  // followed by floating-point types.\n  float_type,\n  double_type,\n  long_double_type,\n  last_numeric_type = long_double_type,\n  cstring_type,\n  string_type,\n  pointer_type,\n  custom_type\n};\n\n// Maps core type T to the corresponding type enum constant.\ntemplate <typename T, typename Char>\nstruct type_constant : std::integral_constant<type, type::custom_type> {};\n\n#define FMT_TYPE_CONSTANT(Type, constant) \\\n  template <typename Char>                \\\n  struct type_constant<Type, Char>        \\\n      : std::integral_constant<type, type::constant> {}\n\nFMT_TYPE_CONSTANT(int, int_type);\nFMT_TYPE_CONSTANT(unsigned, uint_type);\nFMT_TYPE_CONSTANT(long long, long_long_type);\nFMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);\nFMT_TYPE_CONSTANT(int128_t, int128_type);\nFMT_TYPE_CONSTANT(uint128_t, uint128_type);\nFMT_TYPE_CONSTANT(bool, bool_type);\nFMT_TYPE_CONSTANT(Char, char_type);\nFMT_TYPE_CONSTANT(float, float_type);\nFMT_TYPE_CONSTANT(double, double_type);\nFMT_TYPE_CONSTANT(long double, long_double_type);\nFMT_TYPE_CONSTANT(const Char*, cstring_type);\nFMT_TYPE_CONSTANT(basic_string_view<Char>, string_type);\nFMT_TYPE_CONSTANT(const void*, pointer_type);\n\nconstexpr bool is_integral_type(type t) {\n  return t > type::none_type && t <= type::last_integer_type;\n}\n\nconstexpr bool is_arithmetic_type(type t) {\n  return t > type::none_type && t <= type::last_numeric_type;\n}\n\nstruct unformattable {};\nstruct unformattable_char : unformattable {};\nstruct unformattable_const : unformattable {};\nstruct unformattable_pointer : unformattable {};\n\ntemplate <typename Char> struct string_value {\n  const Char* data;\n  size_t size;\n};\n\ntemplate <typename Char> struct named_arg_value {\n  const named_arg_info<Char>* data;\n  size_t size;\n};\n\ntemplate <typename Context> struct custom_value {\n  using parse_context = typename Context::parse_context_type;\n  void* value;\n  void (*format)(void* arg, parse_context& parse_ctx, Context& ctx);\n};\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4582 4583)\n#endif\n\n// A formatting argument value.\ntemplate <typename Context> class value {\n public:\n  using char_type = typename Context::char_type;\n\n  union {\n    monostate no_value;\n    int int_value;\n    unsigned uint_value;\n    long long long_long_value;\n    unsigned long long ulong_long_value;\n    int128_t int128_value;\n    uint128_t uint128_value;\n    bool bool_value;\n    char_type char_value;\n    float float_value;\n    double double_value;\n    long double long_double_value;\n    const void* pointer;\n    string_value<char_type> string;\n    custom_value<Context> custom;\n    named_arg_value<char_type> named_args;\n  };\n\n  constexpr FMT_INLINE value() : no_value() {}\n  constexpr FMT_INLINE value(int val) : int_value(val) {}\n  constexpr FMT_INLINE value(unsigned val) : uint_value(val) {}\n  constexpr FMT_INLINE value(long long val) : long_long_value(val) {}\n  constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {}\n  FMT_INLINE value(int128_t val) : int128_value(val) {}\n  FMT_INLINE value(uint128_t val) : uint128_value(val) {}\n  constexpr FMT_INLINE value(float val) : float_value(val) {}\n  constexpr FMT_INLINE value(double val) : double_value(val) {}\n  FMT_INLINE value(long double val) : long_double_value(val) {}\n  constexpr FMT_INLINE value(bool val) : bool_value(val) {}\n  constexpr FMT_INLINE value(char_type val) : char_value(val) {}\n  FMT_CONSTEXPR FMT_INLINE value(const char_type* val) {\n    string.data = val;\n    if (is_constant_evaluated()) string.size = {};\n  }\n  FMT_CONSTEXPR FMT_INLINE value(basic_string_view<char_type> val) {\n    string.data = val.data();\n    string.size = val.size();\n  }\n  FMT_INLINE value(const void* val) : pointer(val) {}\n  FMT_INLINE value(const named_arg_info<char_type>* args, size_t size)\n      : named_args{args, size} {}\n\n  template <typename T> FMT_CONSTEXPR FMT_INLINE value(T& val) {\n    using value_type = remove_cvref_t<T>;\n    custom.value = const_cast<value_type*>(&val);\n    // Get the formatter type through the context to allow different contexts\n    // have different extension points, e.g. `formatter<T>` for `format` and\n    // `printf_formatter<T>` for `printf`.\n    custom.format = format_custom_arg<\n        value_type,\n        conditional_t<has_formatter<value_type, Context>::value,\n                      typename Context::template formatter_type<value_type>,\n                      fallback_formatter<value_type, char_type>>>;\n  }\n  value(unformattable);\n  value(unformattable_char);\n  value(unformattable_const);\n  value(unformattable_pointer);\n\n private:\n  // Formats an argument of a custom type, such as a user-defined class.\n  template <typename T, typename Formatter>\n  static void format_custom_arg(void* arg,\n                                typename Context::parse_context_type& parse_ctx,\n                                Context& ctx) {\n    auto f = Formatter();\n    parse_ctx.advance_to(f.parse(parse_ctx));\n    using qualified_type =\n        conditional_t<has_const_formatter<T, Context>(), const T, T>;\n    ctx.advance_to(f.format(*static_cast<qualified_type*>(arg), ctx));\n  }\n};\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\ntemplate <typename Context, typename T>\nFMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context>;\n\n// To minimize the number of types we need to deal with, long is translated\n// either to int or to long long depending on its size.\nenum { long_short = sizeof(long) == sizeof(int) };\nusing long_type = conditional_t<long_short, int, long long>;\nusing ulong_type = conditional_t<long_short, unsigned, unsigned long long>;\n\n// Maps formatting arguments to core types.\n// arg_mapper reports errors by returning unformattable instead of using\n// static_assert because it's used in the is_formattable trait.\ntemplate <typename Context> struct arg_mapper {\n  using char_type = typename Context::char_type;\n\n  FMT_CONSTEXPR FMT_INLINE auto map(signed char val) -> int { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(unsigned char val) -> unsigned {\n    return val;\n  }\n  FMT_CONSTEXPR FMT_INLINE auto map(short val) -> int { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(unsigned short val) -> unsigned {\n    return val;\n  }\n  FMT_CONSTEXPR FMT_INLINE auto map(int val) -> int { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(unsigned val) -> unsigned { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(long val) -> long_type { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(unsigned long val) -> ulong_type {\n    return val;\n  }\n  FMT_CONSTEXPR FMT_INLINE auto map(long long val) -> long long { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(unsigned long long val)\n      -> unsigned long long {\n    return val;\n  }\n  FMT_CONSTEXPR FMT_INLINE auto map(int128_t val) -> int128_t { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(uint128_t val) -> uint128_t { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; }\n\n  template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value ||\n                                      std::is_same<T, char_type>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type {\n    return val;\n  }\n  template <typename T, enable_if_t<(std::is_same<T, wchar_t>::value ||\n#ifdef __cpp_char8_t\n                                     std::is_same<T, char8_t>::value ||\n#endif\n                                     std::is_same<T, char16_t>::value ||\n                                     std::is_same<T, char32_t>::value) &&\n                                        !std::is_same<T, char_type>::value,\n                                    int> = 0>\n  FMT_CONSTEXPR FMT_INLINE auto map(T) -> unformattable_char {\n    return {};\n  }\n\n  FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(long double val) -> long double {\n    return val;\n  }\n\n  FMT_CONSTEXPR FMT_INLINE auto map(char_type* val) -> const char_type* {\n    return val;\n  }\n  FMT_CONSTEXPR FMT_INLINE auto map(const char_type* val) -> const char_type* {\n    return val;\n  }\n  template <typename T,\n            FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&\n                          std::is_same<char_type, char_t<T>>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto map(const T& val)\n      -> basic_string_view<char_type> {\n    return to_string_view(val);\n  }\n  template <typename T,\n            FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&\n                          !std::is_same<char_type, char_t<T>>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto map(const T&) -> unformattable_char {\n    return {};\n  }\n  template <typename T,\n            FMT_ENABLE_IF(\n                std::is_constructible<basic_string_view<char_type>, T>::value &&\n                !is_string<T>::value && !has_formatter<T, Context>::value &&\n                !has_fallback_formatter<T, char_type>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto map(const T& val)\n      -> basic_string_view<char_type> {\n    return basic_string_view<char_type>(val);\n  }\n  template <\n      typename T,\n      FMT_ENABLE_IF(\n          std::is_constructible<std_string_view<char_type>, T>::value &&\n          !std::is_constructible<basic_string_view<char_type>, T>::value &&\n          !is_string<T>::value && !has_formatter<T, Context>::value &&\n          !has_fallback_formatter<T, char_type>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto map(const T& val)\n      -> basic_string_view<char_type> {\n    return std_string_view<char_type>(val);\n  }\n\n  using cstring_result = conditional_t<std::is_same<char_type, char>::value,\n                                       const char*, unformattable_pointer>;\n\n  FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const signed char* val)\n      -> cstring_result {\n    return map(reinterpret_cast<const char*>(val));\n  }\n  FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const unsigned char* val)\n      -> cstring_result {\n    return map(reinterpret_cast<const char*>(val));\n  }\n  FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(signed char* val)\n      -> cstring_result {\n    return map(reinterpret_cast<const char*>(val));\n  }\n  FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(unsigned char* val)\n      -> cstring_result {\n    return map(reinterpret_cast<const char*>(val));\n  }\n\n  FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; }\n  FMT_CONSTEXPR FMT_INLINE auto map(const void* val) -> const void* {\n    return val;\n  }\n  FMT_CONSTEXPR FMT_INLINE auto map(std::nullptr_t val) -> const void* {\n    return val;\n  }\n\n  // We use SFINAE instead of a const T* parameter to avoid conflicting with\n  // the C array overload.\n  template <\n      typename T,\n      FMT_ENABLE_IF(\n          std::is_member_pointer<T>::value ||\n          std::is_function<typename std::remove_pointer<T>::type>::value ||\n          (std::is_convertible<const T&, const void*>::value &&\n           !std::is_convertible<const T&, const char_type*>::value))>\n  FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer {\n    return {};\n  }\n\n  template <typename T, std::size_t N,\n            FMT_ENABLE_IF(!std::is_same<T, wchar_t>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto map(const T (&values)[N]) -> const T (&)[N] {\n    return values;\n  }\n\n  template <typename T,\n            FMT_ENABLE_IF(\n                std::is_enum<T>::value&& std::is_convertible<T, int>::value &&\n                !has_formatter<T, Context>::value &&\n                !has_fallback_formatter<T, char_type>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto map(const T& val)\n      -> decltype(std::declval<arg_mapper>().map(\n          static_cast<typename std::underlying_type<T>::type>(val))) {\n    return map(static_cast<typename std::underlying_type<T>::type>(val));\n  }\n\n  FMT_CONSTEXPR FMT_INLINE auto map(detail::byte val) -> unsigned {\n    return map(static_cast<unsigned char>(val));\n  }\n\n  template <typename T, typename U = remove_cvref_t<T>>\n  struct formattable\n      : bool_constant<has_const_formatter<U, Context>() ||\n                      !std::is_const<remove_reference_t<T>>::value ||\n                      has_fallback_formatter<U, char_type>::value> {};\n\n#if FMT_MSC_VER != 0 && FMT_MSC_VER < 1910\n  // Workaround a bug in MSVC.\n  template <typename T> FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& {\n    return val;\n  }\n#else\n  template <typename T, FMT_ENABLE_IF(formattable<T>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& {\n    return val;\n  }\n  template <typename T, FMT_ENABLE_IF(!formattable<T>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto do_map(T&&) -> unformattable_const {\n    return {};\n  }\n#endif\n\n  template <typename T, typename U = remove_cvref_t<T>,\n            FMT_ENABLE_IF(!is_string<U>::value && !is_char<U>::value &&\n                          !std::is_array<U>::value &&\n                          (has_formatter<U, Context>::value ||\n                           has_fallback_formatter<U, char_type>::value))>\n  FMT_CONSTEXPR FMT_INLINE auto map(T&& val)\n      -> decltype(this->do_map(std::forward<T>(val))) {\n    return do_map(std::forward<T>(val));\n  }\n\n  template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>\n  FMT_CONSTEXPR FMT_INLINE auto map(const T& named_arg)\n      -> decltype(std::declval<arg_mapper>().map(named_arg.value)) {\n    return map(named_arg.value);\n  }\n\n  auto map(...) -> unformattable { return {}; }\n};\n\n// A type constant after applying arg_mapper<Context>.\ntemplate <typename T, typename Context>\nusing mapped_type_constant =\n    type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())),\n                  typename Context::char_type>;\n\nenum { packed_arg_bits = 4 };\n// Maximum number of arguments with packed types.\nenum { max_packed_args = 62 / packed_arg_bits };\nenum : unsigned long long { is_unpacked_bit = 1ULL << 63 };\nenum : unsigned long long { has_named_args_bit = 1ULL << 62 };\n\nFMT_END_DETAIL_NAMESPACE\n\n// An output iterator that appends to a buffer.\n// It is used to reduce symbol sizes for the common case.\nclass appender : public std::back_insert_iterator<detail::buffer<char>> {\n  using base = std::back_insert_iterator<detail::buffer<char>>;\n\n  template <typename T>\n  friend auto get_buffer(appender out) -> detail::buffer<char>& {\n    return detail::get_container(out);\n  }\n\n public:\n  using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator;\n  appender(base it) FMT_NOEXCEPT : base(it) {}\n  using _Unchecked_type = appender;  // Mark iterator as checked.\n\n  auto operator++() FMT_NOEXCEPT -> appender& { return *this; }\n\n  auto operator++(int) FMT_NOEXCEPT -> appender { return *this; }\n};\n\n// A formatting argument. It is a trivially copyable/constructible type to\n// allow storage in basic_memory_buffer.\ntemplate <typename Context> class basic_format_arg {\n private:\n  detail::value<Context> value_;\n  detail::type type_;\n\n  template <typename ContextType, typename T>\n  friend FMT_CONSTEXPR auto detail::make_arg(const T& value)\n      -> basic_format_arg<ContextType>;\n\n  template <typename Visitor, typename Ctx>\n  friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis,\n                                             const basic_format_arg<Ctx>& arg)\n      -> decltype(vis(0));\n\n  friend class basic_format_args<Context>;\n  friend class dynamic_format_arg_store<Context>;\n\n  using char_type = typename Context::char_type;\n\n  template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>\n  friend struct detail::arg_data;\n\n  basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size)\n      : value_(args, size) {}\n\n public:\n  class handle {\n   public:\n    explicit handle(detail::custom_value<Context> custom) : custom_(custom) {}\n\n    void format(typename Context::parse_context_type& parse_ctx,\n                Context& ctx) const {\n      custom_.format(custom_.value, parse_ctx, ctx);\n    }\n\n   private:\n    detail::custom_value<Context> custom_;\n  };\n\n  constexpr basic_format_arg() : type_(detail::type::none_type) {}\n\n  constexpr explicit operator bool() const FMT_NOEXCEPT {\n    return type_ != detail::type::none_type;\n  }\n\n  auto type() const -> detail::type { return type_; }\n\n  auto is_integral() const -> bool { return detail::is_integral_type(type_); }\n  auto is_arithmetic() const -> bool {\n    return detail::is_arithmetic_type(type_);\n  }\n};\n\n/**\n  \\rst\n  Visits an argument dispatching to the appropriate visit method based on\n  the argument type. For example, if the argument type is ``double`` then\n  ``vis(value)`` will be called with the value of type ``double``.\n  \\endrst\n */\ntemplate <typename Visitor, typename Context>\nFMT_CONSTEXPR FMT_INLINE auto visit_format_arg(\n    Visitor&& vis, const basic_format_arg<Context>& arg) -> decltype(vis(0)) {\n  switch (arg.type_) {\n  case detail::type::none_type:\n    break;\n  case detail::type::int_type:\n    return vis(arg.value_.int_value);\n  case detail::type::uint_type:\n    return vis(arg.value_.uint_value);\n  case detail::type::long_long_type:\n    return vis(arg.value_.long_long_value);\n  case detail::type::ulong_long_type:\n    return vis(arg.value_.ulong_long_value);\n  case detail::type::int128_type:\n    return vis(detail::convert_for_visit(arg.value_.int128_value));\n  case detail::type::uint128_type:\n    return vis(detail::convert_for_visit(arg.value_.uint128_value));\n  case detail::type::bool_type:\n    return vis(arg.value_.bool_value);\n  case detail::type::char_type:\n    return vis(arg.value_.char_value);\n  case detail::type::float_type:\n    return vis(arg.value_.float_value);\n  case detail::type::double_type:\n    return vis(arg.value_.double_value);\n  case detail::type::long_double_type:\n    return vis(arg.value_.long_double_value);\n  case detail::type::cstring_type:\n    return vis(arg.value_.string.data);\n  case detail::type::string_type:\n    using sv = basic_string_view<typename Context::char_type>;\n    return vis(sv(arg.value_.string.data, arg.value_.string.size));\n  case detail::type::pointer_type:\n    return vis(arg.value_.pointer);\n  case detail::type::custom_type:\n    return vis(typename basic_format_arg<Context>::handle(arg.value_.custom));\n  }\n  return vis(monostate());\n}\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\ntemplate <typename Char, typename InputIt>\nauto copy_str(InputIt begin, InputIt end, appender out) -> appender {\n  get_container(out).append(begin, end);\n  return out;\n}\n\n#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500\n// A workaround for gcc 4.8 to make void_t work in a SFINAE context.\ntemplate <typename... Ts> struct void_t_impl { using type = void; };\ntemplate <typename... Ts>\nusing void_t = typename detail::void_t_impl<Ts...>::type;\n#else\ntemplate <typename...> using void_t = void;\n#endif\n\ntemplate <typename It, typename T, typename Enable = void>\nstruct is_output_iterator : std::false_type {};\n\ntemplate <typename It, typename T>\nstruct is_output_iterator<\n    It, T,\n    void_t<typename std::iterator_traits<It>::iterator_category,\n           decltype(*std::declval<It>() = std::declval<T>())>>\n    : std::true_type {};\n\ntemplate <typename OutputIt>\nstruct is_back_insert_iterator : std::false_type {};\ntemplate <typename Container>\nstruct is_back_insert_iterator<std::back_insert_iterator<Container>>\n    : std::true_type {};\n\ntemplate <typename OutputIt>\nstruct is_contiguous_back_insert_iterator : std::false_type {};\ntemplate <typename Container>\nstruct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>\n    : is_contiguous<Container> {};\ntemplate <>\nstruct is_contiguous_back_insert_iterator<appender> : std::true_type {};\n\n// A type-erased reference to an std::locale to avoid heavy <locale> include.\nclass locale_ref {\n private:\n  const void* locale_;  // A type-erased pointer to std::locale.\n\n public:\n  constexpr locale_ref() : locale_(nullptr) {}\n  template <typename Locale> explicit locale_ref(const Locale& loc);\n\n  explicit operator bool() const FMT_NOEXCEPT { return locale_ != nullptr; }\n\n  template <typename Locale> auto get() const -> Locale;\n};\n\ntemplate <typename> constexpr auto encode_types() -> unsigned long long {\n  return 0;\n}\n\ntemplate <typename Context, typename Arg, typename... Args>\nconstexpr auto encode_types() -> unsigned long long {\n  return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) |\n         (encode_types<Context, Args...>() << packed_arg_bits);\n}\n\ntemplate <typename Context, typename T>\nFMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context> {\n  basic_format_arg<Context> arg;\n  arg.type_ = mapped_type_constant<T, Context>::value;\n  arg.value_ = arg_mapper<Context>().map(value);\n  return arg;\n}\n\n// The type template parameter is there to avoid an ODR violation when using\n// a fallback formatter in one translation unit and an implicit conversion in\n// another (not recommended).\ntemplate <bool IS_PACKED, typename Context, type, typename T,\n          FMT_ENABLE_IF(IS_PACKED)>\nFMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {\n  const auto& arg = arg_mapper<Context>().map(std::forward<T>(val));\n\n  constexpr bool formattable_char =\n      !std::is_same<decltype(arg), const unformattable_char&>::value;\n  static_assert(formattable_char, \"Mixing character types is disallowed.\");\n\n  constexpr bool formattable_const =\n      !std::is_same<decltype(arg), const unformattable_const&>::value;\n  static_assert(formattable_const, \"Cannot format a const argument.\");\n\n  // Formatting of arbitrary pointers is disallowed. If you want to output\n  // a pointer cast it to \"void *\" or \"const void *\". In particular, this\n  // forbids formatting of \"[const] volatile char *\" which is printed as bool\n  // by iostreams.\n  constexpr bool formattable_pointer =\n      !std::is_same<decltype(arg), const unformattable_pointer&>::value;\n  static_assert(formattable_pointer,\n                \"Formatting of non-void pointers is disallowed.\");\n\n  constexpr bool formattable =\n      !std::is_same<decltype(arg), const unformattable&>::value;\n  static_assert(\n      formattable,\n      \"Cannot format an argument. To make type T formattable provide a \"\n      \"formatter<T> specialization: https://fmt.dev/latest/api.html#udt\");\n  return {arg};\n}\n\ntemplate <bool IS_PACKED, typename Context, type, typename T,\n          FMT_ENABLE_IF(!IS_PACKED)>\ninline auto make_arg(const T& value) -> basic_format_arg<Context> {\n  return make_arg<Context>(value);\n}\nFMT_END_DETAIL_NAMESPACE\n\n// Formatting context.\ntemplate <typename OutputIt, typename Char> class basic_format_context {\n public:\n  /** The character type for the output. */\n  using char_type = Char;\n\n private:\n  OutputIt out_;\n  basic_format_args<basic_format_context> args_;\n  detail::locale_ref loc_;\n\n public:\n  using iterator = OutputIt;\n  using format_arg = basic_format_arg<basic_format_context>;\n  using parse_context_type = basic_format_parse_context<Char>;\n  template <typename T> using formatter_type = formatter<T, char_type>;\n\n  basic_format_context(basic_format_context&&) = default;\n  basic_format_context(const basic_format_context&) = delete;\n  void operator=(const basic_format_context&) = delete;\n  /**\n   Constructs a ``basic_format_context`` object. References to the arguments are\n   stored in the object so make sure they have appropriate lifetimes.\n   */\n  constexpr basic_format_context(\n      OutputIt out, basic_format_args<basic_format_context> ctx_args,\n      detail::locale_ref loc = detail::locale_ref())\n      : out_(out), args_(ctx_args), loc_(loc) {}\n\n  constexpr auto arg(int id) const -> format_arg { return args_.get(id); }\n  FMT_CONSTEXPR auto arg(basic_string_view<char_type> name) -> format_arg {\n    return args_.get(name);\n  }\n  FMT_CONSTEXPR auto arg_id(basic_string_view<char_type> name) -> int {\n    return args_.get_id(name);\n  }\n  auto args() const -> const basic_format_args<basic_format_context>& {\n    return args_;\n  }\n\n  FMT_CONSTEXPR auto error_handler() -> detail::error_handler { return {}; }\n  void on_error(const char* message) { error_handler().on_error(message); }\n\n  // Returns an iterator to the beginning of the output range.\n  FMT_CONSTEXPR auto out() -> iterator { return out_; }\n\n  // Advances the begin iterator to ``it``.\n  void advance_to(iterator it) {\n    if (!detail::is_back_insert_iterator<iterator>()) out_ = it;\n  }\n\n  FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; }\n};\n\ntemplate <typename Char>\nusing buffer_context =\n    basic_format_context<detail::buffer_appender<Char>, Char>;\nusing format_context = buffer_context<char>;\n\n// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164.\n#define FMT_BUFFER_CONTEXT(Char) \\\n  basic_format_context<detail::buffer_appender<Char>, Char>\n\ntemplate <typename T, typename Char = char>\nusing is_formattable = bool_constant<\n    !std::is_base_of<detail::unformattable,\n                     decltype(detail::arg_mapper<buffer_context<Char>>().map(\n                         std::declval<T>()))>::value &&\n    !detail::has_fallback_formatter<T, Char>::value>;\n\n/**\n  \\rst\n  An array of references to arguments. It can be implicitly converted into\n  `~fmt::basic_format_args` for passing into type-erased formatting functions\n  such as `~fmt::vformat`.\n  \\endrst\n */\ntemplate <typename Context, typename... Args>\nclass format_arg_store\n#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409\n    // Workaround a GCC template argument substitution bug.\n    : public basic_format_args<Context>\n#endif\n{\n private:\n  static const size_t num_args = sizeof...(Args);\n  static const size_t num_named_args = detail::count_named_args<Args...>();\n  static const bool is_packed = num_args <= detail::max_packed_args;\n\n  using value_type = conditional_t<is_packed, detail::value<Context>,\n                                   basic_format_arg<Context>>;\n\n  detail::arg_data<value_type, typename Context::char_type, num_args,\n                   num_named_args>\n      data_;\n\n  friend class basic_format_args<Context>;\n\n  static constexpr unsigned long long desc =\n      (is_packed ? detail::encode_types<Context, Args...>()\n                 : detail::is_unpacked_bit | num_args) |\n      (num_named_args != 0\n           ? static_cast<unsigned long long>(detail::has_named_args_bit)\n           : 0);\n\n public:\n  template <typename... T>\n  FMT_CONSTEXPR FMT_INLINE format_arg_store(T&&... args)\n      :\n#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409\n        basic_format_args<Context>(*this),\n#endif\n        data_{detail::make_arg<\n            is_packed, Context,\n            detail::mapped_type_constant<remove_cvref_t<T>, Context>::value>(\n            std::forward<T>(args))...} {\n    detail::init_named_args(data_.named_args(), 0, 0, args...);\n  }\n};\n\n/**\n  \\rst\n  Constructs a `~fmt::format_arg_store` object that contains references to\n  arguments and can be implicitly converted to `~fmt::format_args`. `Context`\n  can be omitted in which case it defaults to `~fmt::context`.\n  See `~fmt::arg` for lifetime considerations.\n  \\endrst\n */\ntemplate <typename Context = format_context, typename... Args>\nconstexpr auto make_format_args(Args&&... args)\n    -> format_arg_store<Context, remove_cvref_t<Args>...> {\n  return {std::forward<Args>(args)...};\n}\n\n/**\n  \\rst\n  Returns a named argument to be used in a formatting function.\n  It should only be used in a call to a formatting function or\n  `dynamic_format_arg_store::push_back`.\n\n  **Example**::\n\n    fmt::print(\"Elapsed time: {s:.2f} seconds\", fmt::arg(\"s\", 1.23));\n  \\endrst\n */\ntemplate <typename Char, typename T>\ninline auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T> {\n  static_assert(!detail::is_named_arg<T>(), \"nested named arguments\");\n  return {name, arg};\n}\n\n/**\n  \\rst\n  A view of a collection of formatting arguments. To avoid lifetime issues it\n  should only be used as a parameter type in type-erased functions such as\n  ``vformat``::\n\n    void vlog(string_view format_str, format_args args);  // OK\n    format_args args = make_format_args(42);  // Error: dangling reference\n  \\endrst\n */\ntemplate <typename Context> class basic_format_args {\n public:\n  using size_type = int;\n  using format_arg = basic_format_arg<Context>;\n\n private:\n  // A descriptor that contains information about formatting arguments.\n  // If the number of arguments is less or equal to max_packed_args then\n  // argument types are passed in the descriptor. This reduces binary code size\n  // per formatting function call.\n  unsigned long long desc_;\n  union {\n    // If is_packed() returns true then argument values are stored in values_;\n    // otherwise they are stored in args_. This is done to improve cache\n    // locality and reduce compiled code size since storing larger objects\n    // may require more code (at least on x86-64) even if the same amount of\n    // data is actually copied to stack. It saves ~10% on the bloat test.\n    const detail::value<Context>* values_;\n    const format_arg* args_;\n  };\n\n  constexpr auto is_packed() const -> bool {\n    return (desc_ & detail::is_unpacked_bit) == 0;\n  }\n  auto has_named_args() const -> bool {\n    return (desc_ & detail::has_named_args_bit) != 0;\n  }\n\n  FMT_CONSTEXPR auto type(int index) const -> detail::type {\n    int shift = index * detail::packed_arg_bits;\n    unsigned int mask = (1 << detail::packed_arg_bits) - 1;\n    return static_cast<detail::type>((desc_ >> shift) & mask);\n  }\n\n  constexpr FMT_INLINE basic_format_args(unsigned long long desc,\n                                         const detail::value<Context>* values)\n      : desc_(desc), values_(values) {}\n  constexpr basic_format_args(unsigned long long desc, const format_arg* args)\n      : desc_(desc), args_(args) {}\n\n public:\n  constexpr basic_format_args() : desc_(0), args_(nullptr) {}\n\n  /**\n   \\rst\n   Constructs a `basic_format_args` object from `~fmt::format_arg_store`.\n   \\endrst\n   */\n  template <typename... Args>\n  constexpr FMT_INLINE basic_format_args(\n      const format_arg_store<Context, Args...>& store)\n      : basic_format_args(format_arg_store<Context, Args...>::desc,\n                          store.data_.args()) {}\n\n  /**\n   \\rst\n   Constructs a `basic_format_args` object from\n   `~fmt::dynamic_format_arg_store`.\n   \\endrst\n   */\n  constexpr FMT_INLINE basic_format_args(\n      const dynamic_format_arg_store<Context>& store)\n      : basic_format_args(store.get_types(), store.data()) {}\n\n  /**\n   \\rst\n   Constructs a `basic_format_args` object from a dynamic set of arguments.\n   \\endrst\n   */\n  constexpr basic_format_args(const format_arg* args, int count)\n      : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count),\n                          args) {}\n\n  /** Returns the argument with the specified id. */\n  FMT_CONSTEXPR auto get(int id) const -> format_arg {\n    format_arg arg;\n    if (!is_packed()) {\n      if (id < max_size()) arg = args_[id];\n      return arg;\n    }\n    if (id >= detail::max_packed_args) return arg;\n    arg.type_ = type(id);\n    if (arg.type_ == detail::type::none_type) return arg;\n    arg.value_ = values_[id];\n    return arg;\n  }\n\n  template <typename Char>\n  auto get(basic_string_view<Char> name) const -> format_arg {\n    int id = get_id(name);\n    return id >= 0 ? get(id) : format_arg();\n  }\n\n  template <typename Char>\n  auto get_id(basic_string_view<Char> name) const -> int {\n    if (!has_named_args()) return -1;\n    const auto& named_args =\n        (is_packed() ? values_[-1] : args_[-1].value_).named_args;\n    for (size_t i = 0; i < named_args.size; ++i) {\n      if (named_args.data[i].name == name) return named_args.data[i].id;\n    }\n    return -1;\n  }\n\n  auto max_size() const -> int {\n    unsigned long long max_packed = detail::max_packed_args;\n    return static_cast<int>(is_packed() ? max_packed\n                                        : desc_ & ~detail::is_unpacked_bit);\n  }\n};\n\n/** An alias to ``basic_format_args<format_context>``. */\n// A separate type would result in shorter symbols but break ABI compatibility\n// between clang and gcc on ARM (#1919).\nusing format_args = basic_format_args<format_context>;\n\n// We cannot use enum classes as bit fields because of a gcc bug\n// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.\nnamespace align {\nenum type { none, left, right, center, numeric };\n}\nusing align_t = align::type;\nnamespace sign {\nenum type { none, minus, plus, space };\n}\nusing sign_t = sign::type;\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\n// Workaround an array initialization issue in gcc 4.8.\ntemplate <typename Char> struct fill_t {\n private:\n  enum { max_size = 4 };\n  Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)};\n  unsigned char size_ = 1;\n\n public:\n  FMT_CONSTEXPR void operator=(basic_string_view<Char> s) {\n    auto size = s.size();\n    if (size > max_size) return throw_format_error(\"invalid fill\");\n    for (size_t i = 0; i < size; ++i) data_[i] = s[i];\n    size_ = static_cast<unsigned char>(size);\n  }\n\n  constexpr auto size() const -> size_t { return size_; }\n  constexpr auto data() const -> const Char* { return data_; }\n\n  FMT_CONSTEXPR auto operator[](size_t index) -> Char& { return data_[index]; }\n  FMT_CONSTEXPR auto operator[](size_t index) const -> const Char& {\n    return data_[index];\n  }\n};\nFMT_END_DETAIL_NAMESPACE\n\nenum class presentation_type : unsigned char {\n  none,\n  // Integer types should go first,\n  dec,             // 'd'\n  oct,             // 'o'\n  hex_lower,       // 'x'\n  hex_upper,       // 'X'\n  bin_lower,       // 'b'\n  bin_upper,       // 'B'\n  hexfloat_lower,  // 'a'\n  hexfloat_upper,  // 'A'\n  exp_lower,       // 'e'\n  exp_upper,       // 'E'\n  fixed_lower,     // 'f'\n  fixed_upper,     // 'F'\n  general_lower,   // 'g'\n  general_upper,   // 'G'\n  chr,             // 'c'\n  string,          // 's'\n  pointer          // 'p'\n};\n\n// Format specifiers for built-in and string types.\ntemplate <typename Char> struct basic_format_specs {\n  int width;\n  int precision;\n  presentation_type type;\n  align_t align : 4;\n  sign_t sign : 3;\n  bool alt : 1;  // Alternate form ('#').\n  bool localized : 1;\n  detail::fill_t<Char> fill;\n\n  constexpr basic_format_specs()\n      : width(0),\n        precision(-1),\n        type(presentation_type::none),\n        align(align::none),\n        sign(sign::none),\n        alt(false),\n        localized(false) {}\n};\n\nusing format_specs = basic_format_specs<char>;\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\nenum class arg_id_kind { none, index, name };\n\n// An argument reference.\ntemplate <typename Char> struct arg_ref {\n  FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {}\n\n  FMT_CONSTEXPR explicit arg_ref(int index)\n      : kind(arg_id_kind::index), val(index) {}\n  FMT_CONSTEXPR explicit arg_ref(basic_string_view<Char> name)\n      : kind(arg_id_kind::name), val(name) {}\n\n  FMT_CONSTEXPR auto operator=(int idx) -> arg_ref& {\n    kind = arg_id_kind::index;\n    val.index = idx;\n    return *this;\n  }\n\n  arg_id_kind kind;\n  union value {\n    FMT_CONSTEXPR value(int id = 0) : index{id} {}\n    FMT_CONSTEXPR value(basic_string_view<Char> n) : name(n) {}\n\n    int index;\n    basic_string_view<Char> name;\n  } val;\n};\n\n// Format specifiers with width and precision resolved at formatting rather\n// than parsing time to allow re-using the same parsed specifiers with\n// different sets of arguments (precompilation of format strings).\ntemplate <typename Char>\nstruct dynamic_format_specs : basic_format_specs<Char> {\n  arg_ref<Char> width_ref;\n  arg_ref<Char> precision_ref;\n};\n\nstruct auto_id {};\n\n// A format specifier handler that sets fields in basic_format_specs.\ntemplate <typename Char> class specs_setter {\n protected:\n  basic_format_specs<Char>& specs_;\n\n public:\n  explicit FMT_CONSTEXPR specs_setter(basic_format_specs<Char>& specs)\n      : specs_(specs) {}\n\n  FMT_CONSTEXPR specs_setter(const specs_setter& other)\n      : specs_(other.specs_) {}\n\n  FMT_CONSTEXPR void on_align(align_t align) { specs_.align = align; }\n  FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) {\n    specs_.fill = fill;\n  }\n  FMT_CONSTEXPR void on_sign(sign_t s) { specs_.sign = s; }\n  FMT_CONSTEXPR void on_hash() { specs_.alt = true; }\n  FMT_CONSTEXPR void on_localized() { specs_.localized = true; }\n\n  FMT_CONSTEXPR void on_zero() {\n    if (specs_.align == align::none) specs_.align = align::numeric;\n    specs_.fill[0] = Char('0');\n  }\n\n  FMT_CONSTEXPR void on_width(int width) { specs_.width = width; }\n  FMT_CONSTEXPR void on_precision(int precision) {\n    specs_.precision = precision;\n  }\n  FMT_CONSTEXPR void end_precision() {}\n\n  FMT_CONSTEXPR void on_type(presentation_type type) { specs_.type = type; }\n};\n\n// Format spec handler that saves references to arguments representing dynamic\n// width and precision to be resolved at formatting time.\ntemplate <typename ParseContext>\nclass dynamic_specs_handler\n    : public specs_setter<typename ParseContext::char_type> {\n public:\n  using char_type = typename ParseContext::char_type;\n\n  FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs<char_type>& specs,\n                                      ParseContext& ctx)\n      : specs_setter<char_type>(specs), specs_(specs), context_(ctx) {}\n\n  FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler& other)\n      : specs_setter<char_type>(other),\n        specs_(other.specs_),\n        context_(other.context_) {}\n\n  template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {\n    specs_.width_ref = make_arg_ref(arg_id);\n  }\n\n  template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {\n    specs_.precision_ref = make_arg_ref(arg_id);\n  }\n\n  FMT_CONSTEXPR void on_error(const char* message) {\n    context_.on_error(message);\n  }\n\n private:\n  dynamic_format_specs<char_type>& specs_;\n  ParseContext& context_;\n\n  using arg_ref_type = arg_ref<char_type>;\n\n  FMT_CONSTEXPR auto make_arg_ref(int arg_id) -> arg_ref_type {\n    context_.check_arg_id(arg_id);\n    return arg_ref_type(arg_id);\n  }\n\n  FMT_CONSTEXPR auto make_arg_ref(auto_id) -> arg_ref_type {\n    return arg_ref_type(context_.next_arg_id());\n  }\n\n  FMT_CONSTEXPR auto make_arg_ref(basic_string_view<char_type> arg_id)\n      -> arg_ref_type {\n    context_.check_arg_id(arg_id);\n    basic_string_view<char_type> format_str(\n        context_.begin(), to_unsigned(context_.end() - context_.begin()));\n    return arg_ref_type(arg_id);\n  }\n};\n\ntemplate <typename Char> constexpr bool is_ascii_letter(Char c) {\n  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');\n}\n\n// Converts a character to ASCII. Returns a number > 127 on conversion failure.\ntemplate <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>\nconstexpr auto to_ascii(Char value) -> Char {\n  return value;\n}\ntemplate <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)>\nconstexpr auto to_ascii(Char value) ->\n    typename std::underlying_type<Char>::type {\n  return value;\n}\n\ntemplate <typename Char>\nFMT_CONSTEXPR auto code_point_length(const Char* begin) -> int {\n  if (const_check(sizeof(Char) != 1)) return 1;\n  auto lengths =\n      \"\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\0\\0\\0\\0\\0\\0\\0\\0\\2\\2\\2\\2\\3\\3\\4\";\n  int len = lengths[static_cast<unsigned char>(*begin) >> 3];\n\n  // Compute the pointer to the next character early so that the next\n  // iteration can start working on the next character. Neither Clang\n  // nor GCC figure out this reordering on their own.\n  return len + !len;\n}\n\n// Return the result via the out param to workaround gcc bug 77539.\ntemplate <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>\nFMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool {\n  for (out = first; out != last; ++out) {\n    if (*out == value) return true;\n  }\n  return false;\n}\n\ntemplate <>\ninline auto find<false, char>(const char* first, const char* last, char value,\n                              const char*& out) -> bool {\n  out = static_cast<const char*>(\n      std::memchr(first, value, to_unsigned(last - first)));\n  return out != nullptr;\n}\n\n// Parses the range [begin, end) as an unsigned integer. This function assumes\n// that the range is non-empty and the first character is a digit.\ntemplate <typename Char>\nFMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end,\n                                         int error_value) noexcept -> int {\n  FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', \"\");\n  unsigned value = 0, prev = 0;\n  auto p = begin;\n  do {\n    prev = value;\n    value = value * 10 + unsigned(*p - '0');\n    ++p;\n  } while (p != end && '0' <= *p && *p <= '9');\n  auto num_digits = p - begin;\n  begin = p;\n  if (num_digits <= std::numeric_limits<int>::digits10)\n    return static_cast<int>(value);\n  // Check for overflow.\n  const unsigned max = to_unsigned((std::numeric_limits<int>::max)());\n  return num_digits == std::numeric_limits<int>::digits10 + 1 &&\n                 prev * 10ull + unsigned(p[-1] - '0') <= max\n             ? static_cast<int>(value)\n             : error_value;\n}\n\n// Parses fill and alignment.\ntemplate <typename Char, typename Handler>\nFMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,\n                               Handler&& handler) -> const Char* {\n  FMT_ASSERT(begin != end, \"\");\n  auto align = align::none;\n  auto p = begin + code_point_length(begin);\n  if (p >= end) p = begin;\n  for (;;) {\n    switch (to_ascii(*p)) {\n    case '<':\n      align = align::left;\n      break;\n    case '>':\n      align = align::right;\n      break;\n    case '^':\n      align = align::center;\n      break;\n    default:\n      break;\n    }\n    if (align != align::none) {\n      if (p != begin) {\n        auto c = *begin;\n        if (c == '{')\n          return handler.on_error(\"invalid fill character '{'\"), begin;\n        handler.on_fill(basic_string_view<Char>(begin, to_unsigned(p - begin)));\n        begin = p + 1;\n      } else\n        ++begin;\n      handler.on_align(align);\n      break;\n    } else if (p == begin) {\n      break;\n    }\n    p = begin;\n  }\n  return begin;\n}\n\ntemplate <typename Char> FMT_CONSTEXPR bool is_name_start(Char c) {\n  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;\n}\n\ntemplate <typename Char, typename IDHandler>\nFMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end,\n                                   IDHandler&& handler) -> const Char* {\n  FMT_ASSERT(begin != end, \"\");\n  Char c = *begin;\n  if (c >= '0' && c <= '9') {\n    int index = 0;\n    if (c != '0')\n      index =\n          parse_nonnegative_int(begin, end, (std::numeric_limits<int>::max)());\n    else\n      ++begin;\n    if (begin == end || (*begin != '}' && *begin != ':'))\n      handler.on_error(\"invalid format string\");\n    else\n      handler(index);\n    return begin;\n  }\n  if (!is_name_start(c)) {\n    handler.on_error(\"invalid format string\");\n    return begin;\n  }\n  auto it = begin;\n  do {\n    ++it;\n  } while (it != end && (is_name_start(c = *it) || ('0' <= c && c <= '9')));\n  handler(basic_string_view<Char>(begin, to_unsigned(it - begin)));\n  return it;\n}\n\ntemplate <typename Char, typename IDHandler>\nFMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char* begin, const Char* end,\n                                           IDHandler&& handler) -> const Char* {\n  Char c = *begin;\n  if (c != '}' && c != ':') return do_parse_arg_id(begin, end, handler);\n  handler();\n  return begin;\n}\n\ntemplate <typename Char, typename Handler>\nFMT_CONSTEXPR auto parse_width(const Char* begin, const Char* end,\n                               Handler&& handler) -> const Char* {\n  using detail::auto_id;\n  struct width_adapter {\n    Handler& handler;\n\n    FMT_CONSTEXPR void operator()() { handler.on_dynamic_width(auto_id()); }\n    FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_width(id); }\n    FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {\n      handler.on_dynamic_width(id);\n    }\n    FMT_CONSTEXPR void on_error(const char* message) {\n      if (message) handler.on_error(message);\n    }\n  };\n\n  FMT_ASSERT(begin != end, \"\");\n  if ('0' <= *begin && *begin <= '9') {\n    int width = parse_nonnegative_int(begin, end, -1);\n    if (width != -1)\n      handler.on_width(width);\n    else\n      handler.on_error(\"number is too big\");\n  } else if (*begin == '{') {\n    ++begin;\n    if (begin != end) begin = parse_arg_id(begin, end, width_adapter{handler});\n    if (begin == end || *begin != '}')\n      return handler.on_error(\"invalid format string\"), begin;\n    ++begin;\n  }\n  return begin;\n}\n\ntemplate <typename Char, typename Handler>\nFMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end,\n                                   Handler&& handler) -> const Char* {\n  using detail::auto_id;\n  struct precision_adapter {\n    Handler& handler;\n\n    FMT_CONSTEXPR void operator()() { handler.on_dynamic_precision(auto_id()); }\n    FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_precision(id); }\n    FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {\n      handler.on_dynamic_precision(id);\n    }\n    FMT_CONSTEXPR void on_error(const char* message) {\n      if (message) handler.on_error(message);\n    }\n  };\n\n  ++begin;\n  auto c = begin != end ? *begin : Char();\n  if ('0' <= c && c <= '9') {\n    auto precision = parse_nonnegative_int(begin, end, -1);\n    if (precision != -1)\n      handler.on_precision(precision);\n    else\n      handler.on_error(\"number is too big\");\n  } else if (c == '{') {\n    ++begin;\n    if (begin != end)\n      begin = parse_arg_id(begin, end, precision_adapter{handler});\n    if (begin == end || *begin++ != '}')\n      return handler.on_error(\"invalid format string\"), begin;\n  } else {\n    return handler.on_error(\"missing precision specifier\"), begin;\n  }\n  handler.end_precision();\n  return begin;\n}\n\ntemplate <typename Char>\nFMT_CONSTEXPR auto parse_presentation_type(Char type) -> presentation_type {\n  switch (to_ascii(type)) {\n  case 'd':\n    return presentation_type::dec;\n  case 'o':\n    return presentation_type::oct;\n  case 'x':\n    return presentation_type::hex_lower;\n  case 'X':\n    return presentation_type::hex_upper;\n  case 'b':\n    return presentation_type::bin_lower;\n  case 'B':\n    return presentation_type::bin_upper;\n  case 'a':\n    return presentation_type::hexfloat_lower;\n  case 'A':\n    return presentation_type::hexfloat_upper;\n  case 'e':\n    return presentation_type::exp_lower;\n  case 'E':\n    return presentation_type::exp_upper;\n  case 'f':\n    return presentation_type::fixed_lower;\n  case 'F':\n    return presentation_type::fixed_upper;\n  case 'g':\n    return presentation_type::general_lower;\n  case 'G':\n    return presentation_type::general_upper;\n  case 'c':\n    return presentation_type::chr;\n  case 's':\n    return presentation_type::string;\n  case 'p':\n    return presentation_type::pointer;\n  default:\n    return presentation_type::none;\n  }\n}\n\n// Parses standard format specifiers and sends notifications about parsed\n// components to handler.\ntemplate <typename Char, typename SpecHandler>\nFMT_CONSTEXPR FMT_INLINE auto parse_format_specs(const Char* begin,\n                                                 const Char* end,\n                                                 SpecHandler&& handler)\n    -> const Char* {\n  if (1 < end - begin && begin[1] == '}' && is_ascii_letter(*begin) &&\n      *begin != 'L') {\n    presentation_type type = parse_presentation_type(*begin++);\n    if (type == presentation_type::none)\n      handler.on_error(\"invalid type specifier\");\n    handler.on_type(type);\n    return begin;\n  }\n\n  if (begin == end) return begin;\n\n  begin = parse_align(begin, end, handler);\n  if (begin == end) return begin;\n\n  // Parse sign.\n  switch (to_ascii(*begin)) {\n  case '+':\n    handler.on_sign(sign::plus);\n    ++begin;\n    break;\n  case '-':\n    handler.on_sign(sign::minus);\n    ++begin;\n    break;\n  case ' ':\n    handler.on_sign(sign::space);\n    ++begin;\n    break;\n  default:\n    break;\n  }\n  if (begin == end) return begin;\n\n  if (*begin == '#') {\n    handler.on_hash();\n    if (++begin == end) return begin;\n  }\n\n  // Parse zero flag.\n  if (*begin == '0') {\n    handler.on_zero();\n    if (++begin == end) return begin;\n  }\n\n  begin = parse_width(begin, end, handler);\n  if (begin == end) return begin;\n\n  // Parse precision.\n  if (*begin == '.') {\n    begin = parse_precision(begin, end, handler);\n    if (begin == end) return begin;\n  }\n\n  if (*begin == 'L') {\n    handler.on_localized();\n    ++begin;\n  }\n\n  // Parse type.\n  if (begin != end && *begin != '}') {\n    presentation_type type = parse_presentation_type(*begin++);\n    if (type == presentation_type::none)\n      handler.on_error(\"invalid type specifier\");\n    handler.on_type(type);\n  }\n  return begin;\n}\n\ntemplate <typename Char, typename Handler>\nFMT_CONSTEXPR auto parse_replacement_field(const Char* begin, const Char* end,\n                                           Handler&& handler) -> const Char* {\n  struct id_adapter {\n    Handler& handler;\n    int arg_id;\n\n    FMT_CONSTEXPR void operator()() { arg_id = handler.on_arg_id(); }\n    FMT_CONSTEXPR void operator()(int id) { arg_id = handler.on_arg_id(id); }\n    FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {\n      arg_id = handler.on_arg_id(id);\n    }\n    FMT_CONSTEXPR void on_error(const char* message) {\n      if (message) handler.on_error(message);\n    }\n  };\n\n  ++begin;\n  if (begin == end) return handler.on_error(\"invalid format string\"), end;\n  if (*begin == '}') {\n    handler.on_replacement_field(handler.on_arg_id(), begin);\n  } else if (*begin == '{') {\n    handler.on_text(begin, begin + 1);\n  } else {\n    auto adapter = id_adapter{handler, 0};\n    begin = parse_arg_id(begin, end, adapter);\n    Char c = begin != end ? *begin : Char();\n    if (c == '}') {\n      handler.on_replacement_field(adapter.arg_id, begin);\n    } else if (c == ':') {\n      begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);\n      if (begin == end || *begin != '}')\n        return handler.on_error(\"unknown format specifier\"), end;\n    } else {\n      return handler.on_error(\"missing '}' in format string\"), end;\n    }\n  }\n  return begin + 1;\n}\n\ntemplate <bool IS_CONSTEXPR, typename Char, typename Handler>\nFMT_CONSTEXPR FMT_INLINE void parse_format_string(\n    basic_string_view<Char> format_str, Handler&& handler) {\n  // Workaround a name-lookup bug in MSVC's modules implementation.\n  using detail::find;\n\n  auto begin = format_str.data();\n  auto end = begin + format_str.size();\n  if (end - begin < 32) {\n    // Use a simple loop instead of memchr for small strings.\n    const Char* p = begin;\n    while (p != end) {\n      auto c = *p++;\n      if (c == '{') {\n        handler.on_text(begin, p - 1);\n        begin = p = parse_replacement_field(p - 1, end, handler);\n      } else if (c == '}') {\n        if (p == end || *p != '}')\n          return handler.on_error(\"unmatched '}' in format string\");\n        handler.on_text(begin, p);\n        begin = ++p;\n      }\n    }\n    handler.on_text(begin, end);\n    return;\n  }\n  struct writer {\n    FMT_CONSTEXPR void operator()(const Char* pbegin, const Char* pend) {\n      if (pbegin == pend) return;\n      for (;;) {\n        const Char* p = nullptr;\n        if (!find<IS_CONSTEXPR>(pbegin, pend, Char('}'), p))\n          return handler_.on_text(pbegin, pend);\n        ++p;\n        if (p == pend || *p != '}')\n          return handler_.on_error(\"unmatched '}' in format string\");\n        handler_.on_text(pbegin, p);\n        pbegin = p + 1;\n      }\n    }\n    Handler& handler_;\n  } write{handler};\n  while (begin != end) {\n    // Doing two passes with memchr (one for '{' and another for '}') is up to\n    // 2.5x faster than the naive one-pass implementation on big format strings.\n    const Char* p = begin;\n    if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, Char('{'), p))\n      return write(begin, end);\n    write(begin, p);\n    begin = parse_replacement_field(p, end, handler);\n  }\n}\n\ntemplate <typename T, typename ParseContext>\nFMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx)\n    -> decltype(ctx.begin()) {\n  using char_type = typename ParseContext::char_type;\n  using context = buffer_context<char_type>;\n  using mapped_type = conditional_t<\n      mapped_type_constant<T, context>::value != type::custom_type,\n      decltype(arg_mapper<context>().map(std::declval<const T&>())), T>;\n  auto f = conditional_t<has_formatter<mapped_type, context>::value,\n                         formatter<mapped_type, char_type>,\n                         fallback_formatter<T, char_type>>();\n  return f.parse(ctx);\n}\n\n// A parse context with extra argument id checks. It is only used at compile\n// time because adding checks at runtime would introduce substantial overhead\n// and would be redundant since argument ids are checked when arguments are\n// retrieved anyway.\ntemplate <typename Char, typename ErrorHandler = error_handler>\nclass compile_parse_context\n    : public basic_format_parse_context<Char, ErrorHandler> {\n private:\n  int num_args_;\n  using base = basic_format_parse_context<Char, ErrorHandler>;\n\n public:\n  explicit FMT_CONSTEXPR compile_parse_context(\n      basic_string_view<Char> format_str,\n      int num_args = (std::numeric_limits<int>::max)(), ErrorHandler eh = {})\n      : base(format_str, eh), num_args_(num_args) {}\n\n  FMT_CONSTEXPR auto next_arg_id() -> int {\n    int id = base::next_arg_id();\n    if (id >= num_args_) this->on_error(\"argument not found\");\n    return id;\n  }\n\n  FMT_CONSTEXPR void check_arg_id(int id) {\n    base::check_arg_id(id);\n    if (id >= num_args_) this->on_error(\"argument not found\");\n  }\n  using base::check_arg_id;\n};\n\ntemplate <typename ErrorHandler>\nFMT_CONSTEXPR void check_int_type_spec(presentation_type type,\n                                       ErrorHandler&& eh) {\n  if (type > presentation_type::bin_upper && type != presentation_type::chr)\n    eh.on_error(\"invalid type specifier\");\n}\n\n// Checks char specs and returns true if the type spec is char (and not int).\ntemplate <typename Char, typename ErrorHandler = error_handler>\nFMT_CONSTEXPR auto check_char_specs(const basic_format_specs<Char>& specs,\n                                    ErrorHandler&& eh = {}) -> bool {\n  if (specs.type != presentation_type::none &&\n      specs.type != presentation_type::chr) {\n    check_int_type_spec(specs.type, eh);\n    return false;\n  }\n  if (specs.align == align::numeric || specs.sign != sign::none || specs.alt)\n    eh.on_error(\"invalid format specifier for char\");\n  return true;\n}\n\n// A floating-point presentation format.\nenum class float_format : unsigned char {\n  general,  // General: exponent notation or fixed point based on magnitude.\n  exp,      // Exponent notation with the default precision of 6, e.g. 1.2e-3.\n  fixed,    // Fixed point with the default precision of 6, e.g. 0.0012.\n  hex\n};\n\nstruct float_specs {\n  int precision;\n  float_format format : 8;\n  sign_t sign : 8;\n  bool upper : 1;\n  bool locale : 1;\n  bool binary32 : 1;\n  bool fallback : 1;\n  bool showpoint : 1;\n};\n\ntemplate <typename ErrorHandler = error_handler, typename Char>\nFMT_CONSTEXPR auto parse_float_type_spec(const basic_format_specs<Char>& specs,\n                                         ErrorHandler&& eh = {})\n    -> float_specs {\n  auto result = float_specs();\n  result.showpoint = specs.alt;\n  result.locale = specs.localized;\n  switch (specs.type) {\n  case presentation_type::none:\n    result.format = float_format::general;\n    break;\n  case presentation_type::general_upper:\n    result.upper = true;\n    FMT_FALLTHROUGH;\n  case presentation_type::general_lower:\n    result.format = float_format::general;\n    break;\n  case presentation_type::exp_upper:\n    result.upper = true;\n    FMT_FALLTHROUGH;\n  case presentation_type::exp_lower:\n    result.format = float_format::exp;\n    result.showpoint |= specs.precision != 0;\n    break;\n  case presentation_type::fixed_upper:\n    result.upper = true;\n    FMT_FALLTHROUGH;\n  case presentation_type::fixed_lower:\n    result.format = float_format::fixed;\n    result.showpoint |= specs.precision != 0;\n    break;\n  case presentation_type::hexfloat_upper:\n    result.upper = true;\n    FMT_FALLTHROUGH;\n  case presentation_type::hexfloat_lower:\n    result.format = float_format::hex;\n    break;\n  default:\n    eh.on_error(\"invalid type specifier\");\n    break;\n  }\n  return result;\n}\n\ntemplate <typename ErrorHandler = error_handler>\nFMT_CONSTEXPR auto check_cstring_type_spec(presentation_type type,\n                                           ErrorHandler&& eh = {}) -> bool {\n  if (type == presentation_type::none || type == presentation_type::string)\n    return true;\n  if (type != presentation_type::pointer) eh.on_error(\"invalid type specifier\");\n  return false;\n}\n\ntemplate <typename ErrorHandler = error_handler>\nFMT_CONSTEXPR void check_string_type_spec(presentation_type type,\n                                          ErrorHandler&& eh = {}) {\n  if (type != presentation_type::none && type != presentation_type::string)\n    eh.on_error(\"invalid type specifier\");\n}\n\ntemplate <typename ErrorHandler>\nFMT_CONSTEXPR void check_pointer_type_spec(presentation_type type,\n                                           ErrorHandler&& eh) {\n  if (type != presentation_type::none && type != presentation_type::pointer)\n    eh.on_error(\"invalid type specifier\");\n}\n\n// A parse_format_specs handler that checks if specifiers are consistent with\n// the argument type.\ntemplate <typename Handler> class specs_checker : public Handler {\n private:\n  detail::type arg_type_;\n\n  FMT_CONSTEXPR void require_numeric_argument() {\n    if (!is_arithmetic_type(arg_type_))\n      this->on_error(\"format specifier requires numeric argument\");\n  }\n\n public:\n  FMT_CONSTEXPR specs_checker(const Handler& handler, detail::type arg_type)\n      : Handler(handler), arg_type_(arg_type) {}\n\n  FMT_CONSTEXPR void on_align(align_t align) {\n    if (align == align::numeric) require_numeric_argument();\n    Handler::on_align(align);\n  }\n\n  FMT_CONSTEXPR void on_sign(sign_t s) {\n    require_numeric_argument();\n    if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&\n        arg_type_ != type::long_long_type && arg_type_ != type::char_type) {\n      this->on_error(\"format specifier requires signed argument\");\n    }\n    Handler::on_sign(s);\n  }\n\n  FMT_CONSTEXPR void on_hash() {\n    require_numeric_argument();\n    Handler::on_hash();\n  }\n\n  FMT_CONSTEXPR void on_localized() {\n    require_numeric_argument();\n    Handler::on_localized();\n  }\n\n  FMT_CONSTEXPR void on_zero() {\n    require_numeric_argument();\n    Handler::on_zero();\n  }\n\n  FMT_CONSTEXPR void end_precision() {\n    if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type)\n      this->on_error(\"precision not allowed for this argument type\");\n  }\n};\n\nconstexpr int invalid_arg_index = -1;\n\n#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\ntemplate <int N, typename T, typename... Args, typename Char>\nconstexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int {\n  if constexpr (detail::is_statically_named_arg<T>()) {\n    if (name == T::name) return N;\n  }\n  if constexpr (sizeof...(Args) > 0)\n    return get_arg_index_by_name<N + 1, Args...>(name);\n  (void)name;  // Workaround an MSVC bug about \"unused\" parameter.\n  return invalid_arg_index;\n}\n#endif\n\ntemplate <typename... Args, typename Char>\nFMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int {\n#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\n  if constexpr (sizeof...(Args) > 0)\n    return get_arg_index_by_name<0, Args...>(name);\n#endif\n  (void)name;\n  return invalid_arg_index;\n}\n\ntemplate <typename Char, typename ErrorHandler, typename... Args>\nclass format_string_checker {\n private:\n  using parse_context_type = compile_parse_context<Char, ErrorHandler>;\n  enum { num_args = sizeof...(Args) };\n\n  // Format specifier parsing function.\n  using parse_func = const Char* (*)(parse_context_type&);\n\n  parse_context_type context_;\n  parse_func parse_funcs_[num_args > 0 ? num_args : 1];\n\n public:\n  explicit FMT_CONSTEXPR format_string_checker(\n      basic_string_view<Char> format_str, ErrorHandler eh)\n      : context_(format_str, num_args, eh),\n        parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}\n\n  FMT_CONSTEXPR void on_text(const Char*, const Char*) {}\n\n  FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); }\n  FMT_CONSTEXPR auto on_arg_id(int id) -> int {\n    return context_.check_arg_id(id), id;\n  }\n  FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {\n#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\n    auto index = get_arg_index_by_name<Args...>(id);\n    if (index == invalid_arg_index) on_error(\"named argument is not found\");\n    return context_.check_arg_id(index), index;\n#else\n    (void)id;\n    on_error(\"compile-time checks for named arguments require C++20 support\");\n    return 0;\n#endif\n  }\n\n  FMT_CONSTEXPR void on_replacement_field(int, const Char*) {}\n\n  FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*)\n      -> const Char* {\n    context_.advance_to(context_.begin() + (begin - &*context_.begin()));\n    // id >= 0 check is a workaround for gcc 10 bug (#2065).\n    return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin;\n  }\n\n  FMT_CONSTEXPR void on_error(const char* message) {\n    context_.on_error(message);\n  }\n};\n\ntemplate <typename... Args, typename S,\n          enable_if_t<(is_compile_string<S>::value), int>>\nvoid check_format_string(S format_str) {\n  FMT_CONSTEXPR auto s = to_string_view(format_str);\n  using checker = format_string_checker<typename S::char_type, error_handler,\n                                        remove_cvref_t<Args>...>;\n  FMT_CONSTEXPR bool invalid_format =\n      (parse_format_string<true>(s, checker(s, {})), true);\n  ignore_unused(invalid_format);\n}\n\ntemplate <typename Char>\nvoid vformat_to(\n    buffer<Char>& buf, basic_string_view<Char> fmt,\n    basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args,\n    locale_ref loc = {});\n\nFMT_API void vprint_mojibake(std::FILE*, string_view, format_args);\n#ifndef _WIN32\ninline void vprint_mojibake(std::FILE*, string_view, format_args) {}\n#endif\nFMT_END_DETAIL_NAMESPACE\n\n// A formatter specialization for the core types corresponding to detail::type\n// constants.\ntemplate <typename T, typename Char>\nstruct formatter<T, Char,\n                 enable_if_t<detail::type_constant<T, Char>::value !=\n                             detail::type::custom_type>> {\n private:\n  detail::dynamic_format_specs<Char> specs_;\n\n public:\n  // Parses format specifiers stopping either at the end of the range or at the\n  // terminating '}'.\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    auto begin = ctx.begin(), end = ctx.end();\n    if (begin == end) return begin;\n    using handler_type = detail::dynamic_specs_handler<ParseContext>;\n    auto type = detail::type_constant<T, Char>::value;\n    auto checker =\n        detail::specs_checker<handler_type>(handler_type(specs_, ctx), type);\n    auto it = detail::parse_format_specs(begin, end, checker);\n    auto eh = ctx.error_handler();\n    switch (type) {\n    case detail::type::none_type:\n      FMT_ASSERT(false, \"invalid argument type\");\n      break;\n    case detail::type::bool_type:\n      if (specs_.type == presentation_type::none ||\n          specs_.type == presentation_type::string) {\n        break;\n      }\n      FMT_FALLTHROUGH;\n    case detail::type::int_type:\n    case detail::type::uint_type:\n    case detail::type::long_long_type:\n    case detail::type::ulong_long_type:\n    case detail::type::int128_type:\n    case detail::type::uint128_type:\n      detail::check_int_type_spec(specs_.type, eh);\n      break;\n    case detail::type::char_type:\n      detail::check_char_specs(specs_, eh);\n      break;\n    case detail::type::float_type:\n      if (detail::const_check(FMT_USE_FLOAT))\n        detail::parse_float_type_spec(specs_, eh);\n      else\n        FMT_ASSERT(false, \"float support disabled\");\n      break;\n    case detail::type::double_type:\n      if (detail::const_check(FMT_USE_DOUBLE))\n        detail::parse_float_type_spec(specs_, eh);\n      else\n        FMT_ASSERT(false, \"double support disabled\");\n      break;\n    case detail::type::long_double_type:\n      if (detail::const_check(FMT_USE_LONG_DOUBLE))\n        detail::parse_float_type_spec(specs_, eh);\n      else\n        FMT_ASSERT(false, \"long double support disabled\");\n      break;\n    case detail::type::cstring_type:\n      detail::check_cstring_type_spec(specs_.type, eh);\n      break;\n    case detail::type::string_type:\n      detail::check_string_type_spec(specs_.type, eh);\n      break;\n    case detail::type::pointer_type:\n      detail::check_pointer_type_spec(specs_.type, eh);\n      break;\n    case detail::type::custom_type:\n      // Custom format specifiers are checked in parse functions of\n      // formatter specializations.\n      break;\n    }\n    return it;\n  }\n\n  template <typename FormatContext>\n  FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const\n      -> decltype(ctx.out());\n};\n\ntemplate <typename Char> struct basic_runtime { basic_string_view<Char> str; };\n\n/** A compile-time format string. */\ntemplate <typename Char, typename... Args> class basic_format_string {\n private:\n  basic_string_view<Char> str_;\n\n public:\n  template <typename S,\n            FMT_ENABLE_IF(\n                std::is_convertible<const S&, basic_string_view<Char>>::value)>\n  FMT_CONSTEVAL FMT_INLINE basic_format_string(const S& s) : str_(s) {\n    static_assert(\n        detail::count<\n            (std::is_base_of<detail::view, remove_reference_t<Args>>::value &&\n             std::is_reference<Args>::value)...>() == 0,\n        \"passing views as lvalues is disallowed\");\n    auto sv = basic_string_view<Char>(str_);\n#ifdef FMT_HAS_CONSTEVAL\n    if constexpr (detail::count_named_args<Args...>() ==\n                  detail::count_statically_named_args<Args...>()) {\n      using checker = detail::format_string_checker<Char, detail::error_handler,\n                                                    remove_cvref_t<Args>...>;\n      detail::parse_format_string<true>(sv, checker(sv, {}));\n    }\n#else\n    detail::check_format_string<Args...>(s);\n#endif\n  }\n  basic_format_string(basic_runtime<Char> r) : str_(r.str) {}\n\n  FMT_INLINE operator basic_string_view<Char>() const { return str_; }\n};\n\n#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409\n// Workaround broken conversion on older gcc.\ntemplate <typename... Args> using format_string = string_view;\ntemplate <typename S> auto runtime(const S& s) -> basic_string_view<char_t<S>> {\n  return s;\n}\n#else\ntemplate <typename... Args>\nusing format_string = basic_format_string<char, type_identity_t<Args>...>;\n/**\n  \\rst\n  Creates a runtime format string.\n\n  **Example**::\n\n    // Check format string at runtime instead of compile-time.\n    fmt::print(fmt::runtime(\"{:d}\"), \"I am not a number\");\n  \\endrst\n */\ntemplate <typename S> auto runtime(const S& s) -> basic_runtime<char_t<S>> {\n  return {{s}};\n}\n#endif\n\nFMT_API auto vformat(string_view fmt, format_args args) -> std::string;\n\n/**\n  \\rst\n  Formats ``args`` according to specifications in ``fmt`` and returns the result\n  as a string.\n\n  **Example**::\n\n    #include <fmt/core.h>\n    std::string message = fmt::format(\"The answer is {}.\", 42);\n  \\endrst\n*/\ntemplate <typename... T>\nFMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args)\n    -> std::string {\n  return vformat(fmt, fmt::make_format_args(args...));\n}\n\n/** Formats a string and writes the output to ``out``. */\ntemplate <typename OutputIt,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>\nauto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt {\n  using detail::get_buffer;\n  auto&& buf = get_buffer<char>(out);\n  detail::vformat_to(buf, fmt, args, {});\n  return detail::get_iterator(buf);\n}\n\n/**\n \\rst\n Formats ``args`` according to specifications in ``fmt``, writes the result to\n the output iterator ``out`` and returns the iterator past the end of the output\n range. `format_to` does not append a terminating null character.\n\n **Example**::\n\n   auto out = std::vector<char>();\n   fmt::format_to(std::back_inserter(out), \"{}\", 42);\n \\endrst\n */\ntemplate <typename OutputIt, typename... T,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>\nFMT_INLINE auto format_to(OutputIt out, format_string<T...> fmt, T&&... args)\n    -> OutputIt {\n  return vformat_to(out, fmt, fmt::make_format_args(args...));\n}\n\ntemplate <typename OutputIt> struct format_to_n_result {\n  /** Iterator past the end of the output range. */\n  OutputIt out;\n  /** Total (not truncated) output size. */\n  size_t size;\n};\n\ntemplate <typename OutputIt, typename... T,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>\nauto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args)\n    -> format_to_n_result<OutputIt> {\n  using traits = detail::fixed_buffer_traits;\n  auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);\n  detail::vformat_to(buf, fmt, args, {});\n  return {buf.out(), buf.count()};\n}\n\n/**\n  \\rst\n  Formats ``args`` according to specifications in ``fmt``, writes up to ``n``\n  characters of the result to the output iterator ``out`` and returns the total\n  (not truncated) output size and the iterator past the end of the output range.\n  `format_to_n` does not append a terminating null character.\n  \\endrst\n */\ntemplate <typename OutputIt, typename... T,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>\nFMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt,\n                            T&&... args) -> format_to_n_result<OutputIt> {\n  return vformat_to_n(out, n, fmt, fmt::make_format_args(args...));\n}\n\n/** Returns the number of chars in the output of ``format(fmt, args...)``. */\ntemplate <typename... T>\nFMT_NODISCARD FMT_INLINE auto formatted_size(format_string<T...> fmt,\n                                             T&&... args) -> size_t {\n  auto buf = detail::counting_buffer<>();\n  detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...), {});\n  return buf.count();\n}\n\nFMT_API void vprint(string_view fmt, format_args args);\nFMT_API void vprint(std::FILE* f, string_view fmt, format_args args);\n\n/**\n  \\rst\n  Formats ``args`` according to specifications in ``fmt`` and writes the output\n  to ``stdout``.\n\n  **Example**::\n\n    fmt::print(\"Elapsed time: {0:.2f} seconds\", 1.23);\n  \\endrst\n */\ntemplate <typename... T>\nFMT_INLINE void print(format_string<T...> fmt, T&&... args) {\n  const auto& vargs = fmt::make_format_args(args...);\n  return detail::is_utf8() ? vprint(fmt, vargs)\n                           : detail::vprint_mojibake(stdout, fmt, vargs);\n}\n\n/**\n  \\rst\n  Formats ``args`` according to specifications in ``fmt`` and writes the\n  output to the file ``f``.\n\n  **Example**::\n\n    fmt::print(stderr, \"Don't {}!\", \"panic\");\n  \\endrst\n */\ntemplate <typename... T>\nFMT_INLINE void print(std::FILE* f, format_string<T...> fmt, T&&... args) {\n  const auto& vargs = fmt::make_format_args(args...);\n  return detail::is_utf8() ? vprint(f, fmt, vargs)\n                           : detail::vprint_mojibake(f, fmt, vargs);\n}\n\nFMT_MODULE_EXPORT_END\nFMT_GCC_PRAGMA(\"GCC pop_options\")\nFMT_END_NAMESPACE\n\n#ifdef FMT_HEADER_ONLY\n#  include \"format.h\"\n#endif\n#endif  // FMT_CORE_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/fmt.license.rst",
    "content": "Copyright (c) 2012 - present, Victor Zverovich\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n--- Optional exception to the license ---\n\nAs an exception, if, as a result of your compiling your source code, portions\nof this Software are embedded into a machine-executable object form of such\nsource code, you may redistribute such embedded portions in such object form\nwithout including the above copyright and permission notices.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/format-inl.h",
    "content": "// Formatting library for C++ - implementation\n//\n// Copyright (c) 2012 - 2016, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_FORMAT_INL_H_\n#define FMT_FORMAT_INL_H_\n\n#include <algorithm>\n#include <cctype>\n#include <cerrno>  // errno\n#include <climits>\n#include <cmath>\n#include <cstdarg>\n#include <cstring>  // std::memmove\n#include <cwchar>\n#include <exception>\n\n#ifndef FMT_STATIC_THOUSANDS_SEPARATOR\n#  include <locale>\n#endif\n\n#ifdef _WIN32\n#  include <io.h>  // _isatty\n#endif\n\n#include \"format.h\"\n\nFMT_BEGIN_NAMESPACE\nnamespace detail {\n\nFMT_FUNC void assert_fail(const char* file, int line, const char* message) {\n  // Use unchecked std::fprintf to avoid triggering another assertion when\n  // writing to stderr fails\n  std::fprintf(stderr, \"%s:%d: assertion failed: %s\", file, line, message);\n  // Chosen instead of std::abort to satisfy Clang in CUDA mode during device\n  // code pass.\n  std::terminate();\n}\n\nFMT_FUNC void throw_format_error(const char* message) {\n  FMT_THROW(format_error(message));\n}\n\n#ifndef _MSC_VER\n#  define FMT_SNPRINTF snprintf\n#else  // _MSC_VER\ninline int fmt_snprintf(char* buffer, size_t size, const char* format, ...) {\n  va_list args;\n  va_start(args, format);\n  int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);\n  va_end(args);\n  return result;\n}\n#  define FMT_SNPRINTF fmt_snprintf\n#endif  // _MSC_VER\n\nFMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,\n                                string_view message) FMT_NOEXCEPT {\n  // Report error code making sure that the output fits into\n  // inline_buffer_size to avoid dynamic memory allocation and potential\n  // bad_alloc.\n  out.try_resize(0);\n  static const char SEP[] = \": \";\n  static const char ERROR_STR[] = \"error \";\n  // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.\n  size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;\n  auto abs_value = static_cast<uint32_or_64_or_128_t<int>>(error_code);\n  if (detail::is_negative(error_code)) {\n    abs_value = 0 - abs_value;\n    ++error_code_size;\n  }\n  error_code_size += detail::to_unsigned(detail::count_digits(abs_value));\n  auto it = buffer_appender<char>(out);\n  if (message.size() <= inline_buffer_size - error_code_size)\n    format_to(it, FMT_STRING(\"{}{}\"), message, SEP);\n  format_to(it, FMT_STRING(\"{}{}\"), ERROR_STR, error_code);\n  FMT_ASSERT(out.size() <= inline_buffer_size, \"\");\n}\n\nFMT_FUNC void report_error(format_func func, int error_code,\n                           const char* message) FMT_NOEXCEPT {\n  memory_buffer full_message;\n  func(full_message, error_code, message);\n  // Don't use fwrite_fully because the latter may throw.\n  if (std::fwrite(full_message.data(), full_message.size(), 1, stderr) > 0)\n    std::fputc('\\n', stderr);\n}\n\n// A wrapper around fwrite that throws on error.\ninline void fwrite_fully(const void* ptr, size_t size, size_t count,\n                         FILE* stream) {\n  size_t written = std::fwrite(ptr, size, count, stream);\n  if (written < count) FMT_THROW(system_error(errno, \"cannot write to file\"));\n}\n\n#ifndef FMT_STATIC_THOUSANDS_SEPARATOR\ntemplate <typename Locale>\nlocale_ref::locale_ref(const Locale& loc) : locale_(&loc) {\n  static_assert(std::is_same<Locale, std::locale>::value, \"\");\n}\n\ntemplate <typename Locale> Locale locale_ref::get() const {\n  static_assert(std::is_same<Locale, std::locale>::value, \"\");\n  return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale();\n}\n\ntemplate <typename Char>\nFMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> {\n  auto& facet = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>());\n  auto grouping = facet.grouping();\n  auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep();\n  return {std::move(grouping), thousands_sep};\n}\ntemplate <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) {\n  return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())\n      .decimal_point();\n}\n#else\ntemplate <typename Char>\nFMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> {\n  return {\"\\03\", FMT_STATIC_THOUSANDS_SEPARATOR};\n}\ntemplate <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {\n  return '.';\n}\n#endif\n}  // namespace detail\n\n#if !FMT_MSC_VER\nFMT_API FMT_FUNC format_error::~format_error() FMT_NOEXCEPT = default;\n#endif\n\nFMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str,\n                                         format_args args) {\n  auto ec = std::error_code(error_code, std::generic_category());\n  return std::system_error(ec, vformat(format_str, args));\n}\n\nnamespace detail {\n\ntemplate <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) {\n  // fallback_uintptr is always stored in little endian.\n  int i = static_cast<int>(sizeof(void*)) - 1;\n  while (i > 0 && n.value[i] == 0) --i;\n  auto char_digits = std::numeric_limits<unsigned char>::digits / 4;\n  return i >= 0 ? i * char_digits + count_digits<4, unsigned>(n.value[i]) : 1;\n}\n\n// log10(2) = 0x0.4d104d427de7fbcc...\nstatic constexpr uint64_t log10_2_significand = 0x4d104d427de7fbcc;\n\ntemplate <typename T = void> struct basic_impl_data {\n  // Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.\n  // These are generated by support/compute-powers.py.\n  static constexpr uint64_t pow10_significands[87] = {\n      0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,\n      0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,\n      0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,\n      0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,\n      0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,\n      0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,\n      0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,\n      0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,\n      0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,\n      0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,\n      0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,\n      0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,\n      0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,\n      0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,\n      0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,\n      0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,\n      0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,\n      0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,\n      0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,\n      0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,\n      0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,\n      0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,\n      0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,\n      0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,\n      0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,\n      0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,\n      0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,\n      0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,\n      0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,\n  };\n\n#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wnarrowing\"\n#endif\n  // Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding\n  // to significands above.\n  static constexpr int16_t pow10_exponents[87] = {\n      -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,\n      -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,  -688, -661,\n      -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,  -422,  -396, -369,\n      -343,  -316,  -289,  -263,  -236,  -210,  -183,  -157,  -130,  -103, -77,\n      -50,   -24,   3,     30,    56,    83,    109,   136,   162,   189,  216,\n      242,   269,   295,   322,   348,   375,   402,   428,   455,   481,  508,\n      534,   561,   588,   614,   641,   667,   694,   720,   747,   774,  800,\n      827,   853,   880,   907,   933,   960,   986,   1013,  1039,  1066};\n#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409\n#  pragma GCC diagnostic pop\n#endif\n\n  static constexpr uint64_t power_of_10_64[20] = {\n      1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL),\n      10000000000000000000ULL};\n};\n\n// This is a struct rather than an alias to avoid shadowing warnings in gcc.\nstruct impl_data : basic_impl_data<> {};\n\n#if __cplusplus < 201703L\ntemplate <typename T>\nconstexpr uint64_t basic_impl_data<T>::pow10_significands[];\ntemplate <typename T> constexpr int16_t basic_impl_data<T>::pow10_exponents[];\ntemplate <typename T> constexpr uint64_t basic_impl_data<T>::power_of_10_64[];\n#endif\n\ntemplate <typename T> struct bits {\n  static FMT_CONSTEXPR_DECL const int value =\n      static_cast<int>(sizeof(T) * std::numeric_limits<unsigned char>::digits);\n};\n\n// Returns the number of significand bits in Float excluding the implicit bit.\ntemplate <typename Float> constexpr int num_significand_bits() {\n  // Subtract 1 to account for an implicit most significant bit in the\n  // normalized form.\n  return std::numeric_limits<Float>::digits - 1;\n}\n\n// A floating-point number f * pow(2, e).\nstruct fp {\n  uint64_t f;\n  int e;\n\n  static constexpr const int num_significand_bits = bits<decltype(f)>::value;\n\n  constexpr fp() : f(0), e(0) {}\n  constexpr fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}\n\n  // Constructs fp from an IEEE754 floating-point number. It is a template to\n  // prevent compile errors on systems where n is not IEEE754.\n  template <typename Float> explicit FMT_CONSTEXPR fp(Float n) { assign(n); }\n\n  template <typename Float>\n  using is_supported = bool_constant<sizeof(Float) == sizeof(uint64_t) ||\n                                     sizeof(Float) == sizeof(uint32_t)>;\n\n  // Assigns d to this and return true iff predecessor is closer than successor.\n  template <typename Float, FMT_ENABLE_IF(is_supported<Float>::value)>\n  FMT_CONSTEXPR bool assign(Float n) {\n    // Assume float is in the format [sign][exponent][significand].\n    const int num_float_significand_bits =\n        detail::num_significand_bits<Float>();\n    const uint64_t implicit_bit = 1ULL << num_float_significand_bits;\n    const uint64_t significand_mask = implicit_bit - 1;\n    constexpr bool is_double = sizeof(Float) == sizeof(uint64_t);\n    auto u = bit_cast<conditional_t<is_double, uint64_t, uint32_t>>(n);\n    f = u & significand_mask;\n    const uint64_t exponent_mask = (~0ULL >> 1) & ~significand_mask;\n    int biased_e =\n        static_cast<int>((u & exponent_mask) >> num_float_significand_bits);\n    // The predecessor is closer if n is a normalized power of 2 (f == 0) other\n    // than the smallest normalized number (biased_e > 1).\n    bool is_predecessor_closer = f == 0 && biased_e > 1;\n    if (biased_e != 0)\n      f += implicit_bit;\n    else\n      biased_e = 1;  // Subnormals use biased exponent 1 (min exponent).\n    const int exponent_bias = std::numeric_limits<Float>::max_exponent - 1;\n    e = biased_e - exponent_bias - num_float_significand_bits;\n    return is_predecessor_closer;\n  }\n\n  template <typename Float, FMT_ENABLE_IF(!is_supported<Float>::value)>\n  bool assign(Float) {\n    FMT_ASSERT(false, \"\");\n    return false;\n  }\n};\n\n// Normalizes the value converted from double and multiplied by (1 << SHIFT).\ntemplate <int SHIFT = 0> FMT_CONSTEXPR fp normalize(fp value) {\n  // Handle subnormals.\n  const uint64_t implicit_bit = 1ULL << num_significand_bits<double>();\n  const auto shifted_implicit_bit = implicit_bit << SHIFT;\n  while ((value.f & shifted_implicit_bit) == 0) {\n    value.f <<= 1;\n    --value.e;\n  }\n  // Subtract 1 to account for hidden bit.\n  const auto offset =\n      fp::num_significand_bits - num_significand_bits<double>() - SHIFT - 1;\n  value.f <<= offset;\n  value.e -= offset;\n  return value;\n}\n\ninline bool operator==(fp x, fp y) { return x.f == y.f && x.e == y.e; }\n\n// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.\nFMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {\n#if FMT_USE_INT128\n  auto product = static_cast<__uint128_t>(lhs) * rhs;\n  auto f = static_cast<uint64_t>(product >> 64);\n  return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;\n#else\n  // Multiply 32-bit parts of significands.\n  uint64_t mask = (1ULL << 32) - 1;\n  uint64_t a = lhs >> 32, b = lhs & mask;\n  uint64_t c = rhs >> 32, d = rhs & mask;\n  uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;\n  // Compute mid 64-bit of result and round.\n  uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);\n  return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);\n#endif\n}\n\nFMT_CONSTEXPR inline fp operator*(fp x, fp y) {\n  return {multiply(x.f, y.f), x.e + y.e + 64};\n}\n\n// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its\n// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`.\nFMT_CONSTEXPR inline fp get_cached_power(int min_exponent,\n                                         int& pow10_exponent) {\n  const int shift = 32;\n  const auto significand = static_cast<int64_t>(log10_2_significand);\n  int index = static_cast<int>(\n      ((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) +\n       ((int64_t(1) << shift) - 1))  // ceil\n      >> 32                          // arithmetic shift\n  );\n  // Decimal exponent of the first (smallest) cached power of 10.\n  const int first_dec_exp = -348;\n  // Difference between 2 consecutive decimal exponents in cached powers of 10.\n  const int dec_exp_step = 8;\n  index = (index - first_dec_exp - 1) / dec_exp_step + 1;\n  pow10_exponent = first_dec_exp + index * dec_exp_step;\n  return {impl_data::pow10_significands[index],\n          impl_data::pow10_exponents[index]};\n}\n\n// A simple accumulator to hold the sums of terms in bigint::square if uint128_t\n// is not available.\nstruct accumulator {\n  uint64_t lower;\n  uint64_t upper;\n\n  constexpr accumulator() : lower(0), upper(0) {}\n  constexpr explicit operator uint32_t() const {\n    return static_cast<uint32_t>(lower);\n  }\n\n  FMT_CONSTEXPR void operator+=(uint64_t n) {\n    lower += n;\n    if (lower < n) ++upper;\n  }\n  FMT_CONSTEXPR void operator>>=(int shift) {\n    FMT_ASSERT(shift == 32, \"\");\n    (void)shift;\n    lower = (upper << 32) | (lower >> 32);\n    upper >>= 32;\n  }\n};\n\nclass bigint {\n private:\n  // A bigint is stored as an array of bigits (big digits), with bigit at index\n  // 0 being the least significant one.\n  using bigit = uint32_t;\n  using double_bigit = uint64_t;\n  enum { bigits_capacity = 32 };\n  basic_memory_buffer<bigit, bigits_capacity> bigits_;\n  int exp_;\n\n  FMT_CONSTEXPR20 bigit operator[](int index) const {\n    return bigits_[to_unsigned(index)];\n  }\n  FMT_CONSTEXPR20 bigit& operator[](int index) {\n    return bigits_[to_unsigned(index)];\n  }\n\n  static FMT_CONSTEXPR_DECL const int bigit_bits = bits<bigit>::value;\n\n  friend struct formatter<bigint>;\n\n  FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) {\n    auto result = static_cast<double_bigit>((*this)[index]) - other - borrow;\n    (*this)[index] = static_cast<bigit>(result);\n    borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1));\n  }\n\n  FMT_CONSTEXPR20 void remove_leading_zeros() {\n    int num_bigits = static_cast<int>(bigits_.size()) - 1;\n    while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits;\n    bigits_.resize(to_unsigned(num_bigits + 1));\n  }\n\n  // Computes *this -= other assuming aligned bigints and *this >= other.\n  FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) {\n    FMT_ASSERT(other.exp_ >= exp_, \"unaligned bigints\");\n    FMT_ASSERT(compare(*this, other) >= 0, \"\");\n    bigit borrow = 0;\n    int i = other.exp_ - exp_;\n    for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j)\n      subtract_bigits(i, other.bigits_[j], borrow);\n    while (borrow > 0) subtract_bigits(i, 0, borrow);\n    remove_leading_zeros();\n  }\n\n  FMT_CONSTEXPR20 void multiply(uint32_t value) {\n    const double_bigit wide_value = value;\n    bigit carry = 0;\n    for (size_t i = 0, n = bigits_.size(); i < n; ++i) {\n      double_bigit result = bigits_[i] * wide_value + carry;\n      bigits_[i] = static_cast<bigit>(result);\n      carry = static_cast<bigit>(result >> bigit_bits);\n    }\n    if (carry != 0) bigits_.push_back(carry);\n  }\n\n  FMT_CONSTEXPR20 void multiply(uint64_t value) {\n    const bigit mask = ~bigit(0);\n    const double_bigit lower = value & mask;\n    const double_bigit upper = value >> bigit_bits;\n    double_bigit carry = 0;\n    for (size_t i = 0, n = bigits_.size(); i < n; ++i) {\n      double_bigit result = bigits_[i] * lower + (carry & mask);\n      carry =\n          bigits_[i] * upper + (result >> bigit_bits) + (carry >> bigit_bits);\n      bigits_[i] = static_cast<bigit>(result);\n    }\n    while (carry != 0) {\n      bigits_.push_back(carry & mask);\n      carry >>= bigit_bits;\n    }\n  }\n\n public:\n  FMT_CONSTEXPR20 bigint() : exp_(0) {}\n  explicit bigint(uint64_t n) { assign(n); }\n  FMT_CONSTEXPR20 ~bigint() {\n    FMT_ASSERT(bigits_.capacity() <= bigits_capacity, \"\");\n  }\n\n  bigint(const bigint&) = delete;\n  void operator=(const bigint&) = delete;\n\n  FMT_CONSTEXPR20 void assign(const bigint& other) {\n    auto size = other.bigits_.size();\n    bigits_.resize(size);\n    auto data = other.bigits_.data();\n    std::copy(data, data + size, make_checked(bigits_.data(), size));\n    exp_ = other.exp_;\n  }\n\n  FMT_CONSTEXPR20 void assign(uint64_t n) {\n    size_t num_bigits = 0;\n    do {\n      bigits_[num_bigits++] = n & ~bigit(0);\n      n >>= bigit_bits;\n    } while (n != 0);\n    bigits_.resize(num_bigits);\n    exp_ = 0;\n  }\n\n  FMT_CONSTEXPR20 int num_bigits() const {\n    return static_cast<int>(bigits_.size()) + exp_;\n  }\n\n  FMT_NOINLINE FMT_CONSTEXPR20 bigint& operator<<=(int shift) {\n    FMT_ASSERT(shift >= 0, \"\");\n    exp_ += shift / bigit_bits;\n    shift %= bigit_bits;\n    if (shift == 0) return *this;\n    bigit carry = 0;\n    for (size_t i = 0, n = bigits_.size(); i < n; ++i) {\n      bigit c = bigits_[i] >> (bigit_bits - shift);\n      bigits_[i] = (bigits_[i] << shift) + carry;\n      carry = c;\n    }\n    if (carry != 0) bigits_.push_back(carry);\n    return *this;\n  }\n\n  template <typename Int> FMT_CONSTEXPR20 bigint& operator*=(Int value) {\n    FMT_ASSERT(value > 0, \"\");\n    multiply(uint32_or_64_or_128_t<Int>(value));\n    return *this;\n  }\n\n  friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) {\n    int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();\n    if (num_lhs_bigits != num_rhs_bigits)\n      return num_lhs_bigits > num_rhs_bigits ? 1 : -1;\n    int i = static_cast<int>(lhs.bigits_.size()) - 1;\n    int j = static_cast<int>(rhs.bigits_.size()) - 1;\n    int end = i - j;\n    if (end < 0) end = 0;\n    for (; i >= end; --i, --j) {\n      bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j];\n      if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1;\n    }\n    if (i != j) return i > j ? 1 : -1;\n    return 0;\n  }\n\n  // Returns compare(lhs1 + lhs2, rhs).\n  friend FMT_CONSTEXPR20 int add_compare(const bigint& lhs1, const bigint& lhs2,\n                                         const bigint& rhs) {\n    int max_lhs_bigits = (std::max)(lhs1.num_bigits(), lhs2.num_bigits());\n    int num_rhs_bigits = rhs.num_bigits();\n    if (max_lhs_bigits + 1 < num_rhs_bigits) return -1;\n    if (max_lhs_bigits > num_rhs_bigits) return 1;\n    auto get_bigit = [](const bigint& n, int i) -> bigit {\n      return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0;\n    };\n    double_bigit borrow = 0;\n    int min_exp = (std::min)((std::min)(lhs1.exp_, lhs2.exp_), rhs.exp_);\n    for (int i = num_rhs_bigits - 1; i >= min_exp; --i) {\n      double_bigit sum =\n          static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i);\n      bigit rhs_bigit = get_bigit(rhs, i);\n      if (sum > rhs_bigit + borrow) return 1;\n      borrow = rhs_bigit + borrow - sum;\n      if (borrow > 1) return -1;\n      borrow <<= bigit_bits;\n    }\n    return borrow != 0 ? -1 : 0;\n  }\n\n  // Assigns pow(10, exp) to this bigint.\n  FMT_CONSTEXPR20 void assign_pow10(int exp) {\n    FMT_ASSERT(exp >= 0, \"\");\n    if (exp == 0) return assign(1);\n    // Find the top bit.\n    int bitmask = 1;\n    while (exp >= bitmask) bitmask <<= 1;\n    bitmask >>= 1;\n    // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by\n    // repeated squaring and multiplication.\n    assign(5);\n    bitmask >>= 1;\n    while (bitmask != 0) {\n      square();\n      if ((exp & bitmask) != 0) *this *= 5;\n      bitmask >>= 1;\n    }\n    *this <<= exp;  // Multiply by pow(2, exp) by shifting.\n  }\n\n  FMT_CONSTEXPR20 void square() {\n    int num_bigits = static_cast<int>(bigits_.size());\n    int num_result_bigits = 2 * num_bigits;\n    basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_));\n    bigits_.resize(to_unsigned(num_result_bigits));\n    using accumulator_t = conditional_t<FMT_USE_INT128, uint128_t, accumulator>;\n    auto sum = accumulator_t();\n    for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) {\n      // Compute bigit at position bigit_index of the result by adding\n      // cross-product terms n[i] * n[j] such that i + j == bigit_index.\n      for (int i = 0, j = bigit_index; j >= 0; ++i, --j) {\n        // Most terms are multiplied twice which can be optimized in the future.\n        sum += static_cast<double_bigit>(n[i]) * n[j];\n      }\n      (*this)[bigit_index] = static_cast<bigit>(sum);\n      sum >>= bits<bigit>::value;  // Compute the carry.\n    }\n    // Do the same for the top half.\n    for (int bigit_index = num_bigits; bigit_index < num_result_bigits;\n         ++bigit_index) {\n      for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;)\n        sum += static_cast<double_bigit>(n[i++]) * n[j--];\n      (*this)[bigit_index] = static_cast<bigit>(sum);\n      sum >>= bits<bigit>::value;\n    }\n    remove_leading_zeros();\n    exp_ *= 2;\n  }\n\n  // If this bigint has a bigger exponent than other, adds trailing zero to make\n  // exponents equal. This simplifies some operations such as subtraction.\n  FMT_CONSTEXPR20 void align(const bigint& other) {\n    int exp_difference = exp_ - other.exp_;\n    if (exp_difference <= 0) return;\n    int num_bigits = static_cast<int>(bigits_.size());\n    bigits_.resize(to_unsigned(num_bigits + exp_difference));\n    for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)\n      bigits_[j] = bigits_[i];\n    std::uninitialized_fill_n(bigits_.data(), exp_difference, 0);\n    exp_ -= exp_difference;\n  }\n\n  // Divides this bignum by divisor, assigning the remainder to this and\n  // returning the quotient.\n  FMT_CONSTEXPR20 int divmod_assign(const bigint& divisor) {\n    FMT_ASSERT(this != &divisor, \"\");\n    if (compare(*this, divisor) < 0) return 0;\n    FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, \"\");\n    align(divisor);\n    int quotient = 0;\n    do {\n      subtract_aligned(divisor);\n      ++quotient;\n    } while (compare(*this, divisor) >= 0);\n    return quotient;\n  }\n};\n\nenum class round_direction { unknown, up, down };\n\n// Given the divisor (normally a power of 10), the remainder = v % divisor for\n// some number v and the error, returns whether v should be rounded up, down, or\n// whether the rounding direction can't be determined due to error.\n// error should be less than divisor / 2.\nFMT_CONSTEXPR inline round_direction get_round_direction(uint64_t divisor,\n                                                         uint64_t remainder,\n                                                         uint64_t error) {\n  FMT_ASSERT(remainder < divisor, \"\");  // divisor - remainder won't overflow.\n  FMT_ASSERT(error < divisor, \"\");      // divisor - error won't overflow.\n  FMT_ASSERT(error < divisor - error, \"\");  // error * 2 won't overflow.\n  // Round down if (remainder + error) * 2 <= divisor.\n  if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2)\n    return round_direction::down;\n  // Round up if (remainder - error) * 2 >= divisor.\n  if (remainder >= error &&\n      remainder - error >= divisor - (remainder - error)) {\n    return round_direction::up;\n  }\n  return round_direction::unknown;\n}\n\nnamespace digits {\nenum result {\n  more,  // Generate more digits.\n  done,  // Done generating digits.\n  error  // Digit generation cancelled due to an error.\n};\n}\n\nstruct gen_digits_handler {\n  char* buf;\n  int size;\n  int precision;\n  int exp10;\n  bool fixed;\n\n  FMT_CONSTEXPR digits::result on_digit(char digit, uint64_t divisor,\n                                        uint64_t remainder, uint64_t error,\n                                        bool integral) {\n    FMT_ASSERT(remainder < divisor, \"\");\n    buf[size++] = digit;\n    if (!integral && error >= remainder) return digits::error;\n    if (size < precision) return digits::more;\n    if (!integral) {\n      // Check if error * 2 < divisor with overflow prevention.\n      // The check is not needed for the integral part because error = 1\n      // and divisor > (1 << 32) there.\n      if (error >= divisor || error >= divisor - error) return digits::error;\n    } else {\n      FMT_ASSERT(error == 1 && divisor > 2, \"\");\n    }\n    auto dir = get_round_direction(divisor, remainder, error);\n    if (dir != round_direction::up)\n      return dir == round_direction::down ? digits::done : digits::error;\n    ++buf[size - 1];\n    for (int i = size - 1; i > 0 && buf[i] > '9'; --i) {\n      buf[i] = '0';\n      ++buf[i - 1];\n    }\n    if (buf[0] > '9') {\n      buf[0] = '1';\n      if (fixed)\n        buf[size++] = '0';\n      else\n        ++exp10;\n    }\n    return digits::done;\n  }\n};\n\n// Generates output using the Grisu digit-gen algorithm.\n// error: the size of the region (lower, upper) outside of which numbers\n// definitely do not round to value (Delta in Grisu3).\nFMT_INLINE FMT_CONSTEXPR20 digits::result grisu_gen_digits(\n    fp value, uint64_t error, int& exp, gen_digits_handler& handler) {\n  const fp one(1ULL << -value.e, value.e);\n  // The integral part of scaled value (p1 in Grisu) = value / one. It cannot be\n  // zero because it contains a product of two 64-bit numbers with MSB set (due\n  // to normalization) - 1, shifted right by at most 60 bits.\n  auto integral = static_cast<uint32_t>(value.f >> -one.e);\n  FMT_ASSERT(integral != 0, \"\");\n  FMT_ASSERT(integral == value.f >> -one.e, \"\");\n  // The fractional part of scaled value (p2 in Grisu) c = value % one.\n  uint64_t fractional = value.f & (one.f - 1);\n  exp = count_digits(integral);  // kappa in Grisu.\n  // Non-fixed formats require at least one digit and no precision adjustment.\n  if (handler.fixed) {\n    // Adjust fixed precision by exponent because it is relative to decimal\n    // point.\n    int precision_offset = exp + handler.exp10;\n    if (precision_offset > 0 &&\n        handler.precision > max_value<int>() - precision_offset) {\n      FMT_THROW(format_error(\"number is too big\"));\n    }\n    handler.precision += precision_offset;\n    // Check if precision is satisfied just by leading zeros, e.g.\n    // format(\"{:.2f}\", 0.001) gives \"0.00\" without generating any digits.\n    if (handler.precision <= 0) {\n      if (handler.precision < 0) return digits::done;\n      // Divide by 10 to prevent overflow.\n      uint64_t divisor = impl_data::power_of_10_64[exp - 1] << -one.e;\n      auto dir = get_round_direction(divisor, value.f / 10, error * 10);\n      if (dir == round_direction::unknown) return digits::error;\n      handler.buf[handler.size++] = dir == round_direction::up ? '1' : '0';\n      return digits::done;\n    }\n  }\n  // Generate digits for the integral part. This can produce up to 10 digits.\n  do {\n    uint32_t digit = 0;\n    auto divmod_integral = [&](uint32_t divisor) {\n      digit = integral / divisor;\n      integral %= divisor;\n    };\n    // This optimization by Milo Yip reduces the number of integer divisions by\n    // one per iteration.\n    switch (exp) {\n    case 10:\n      divmod_integral(1000000000);\n      break;\n    case 9:\n      divmod_integral(100000000);\n      break;\n    case 8:\n      divmod_integral(10000000);\n      break;\n    case 7:\n      divmod_integral(1000000);\n      break;\n    case 6:\n      divmod_integral(100000);\n      break;\n    case 5:\n      divmod_integral(10000);\n      break;\n    case 4:\n      divmod_integral(1000);\n      break;\n    case 3:\n      divmod_integral(100);\n      break;\n    case 2:\n      divmod_integral(10);\n      break;\n    case 1:\n      digit = integral;\n      integral = 0;\n      break;\n    default:\n      FMT_ASSERT(false, \"invalid number of digits\");\n    }\n    --exp;\n    auto remainder = (static_cast<uint64_t>(integral) << -one.e) + fractional;\n    auto result = handler.on_digit(static_cast<char>('0' + digit),\n                                   impl_data::power_of_10_64[exp] << -one.e,\n                                   remainder, error, true);\n    if (result != digits::more) return result;\n  } while (exp > 0);\n  // Generate digits for the fractional part.\n  for (;;) {\n    fractional *= 10;\n    error *= 10;\n    char digit = static_cast<char>('0' + (fractional >> -one.e));\n    fractional &= one.f - 1;\n    --exp;\n    auto result = handler.on_digit(digit, one.f, fractional, error, false);\n    if (result != digits::more) return result;\n  }\n}\n\n// A 128-bit integer type used internally,\nstruct uint128_wrapper {\n  uint128_wrapper() = default;\n\n#if FMT_USE_INT128\n  uint128_t internal_;\n\n  constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT\n      : internal_{static_cast<uint128_t>(low) |\n                  (static_cast<uint128_t>(high) << 64)} {}\n\n  constexpr uint128_wrapper(uint128_t u) : internal_{u} {}\n\n  constexpr uint64_t high() const FMT_NOEXCEPT {\n    return uint64_t(internal_ >> 64);\n  }\n  constexpr uint64_t low() const FMT_NOEXCEPT { return uint64_t(internal_); }\n\n  uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT {\n    internal_ += n;\n    return *this;\n  }\n#else\n  uint64_t high_;\n  uint64_t low_;\n\n  constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT\n      : high_{high},\n        low_{low} {}\n\n  constexpr uint64_t high() const FMT_NOEXCEPT { return high_; }\n  constexpr uint64_t low() const FMT_NOEXCEPT { return low_; }\n\n  uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT {\n#  if defined(_MSC_VER) && defined(_M_X64)\n    unsigned char carry = _addcarry_u64(0, low_, n, &low_);\n    _addcarry_u64(carry, high_, 0, &high_);\n    return *this;\n#  else\n    uint64_t sum = low_ + n;\n    high_ += (sum < low_ ? 1 : 0);\n    low_ = sum;\n    return *this;\n#  endif\n  }\n#endif\n};\n\n// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox.\nnamespace dragonbox {\n// Computes 128-bit result of multiplication of two 64-bit unsigned integers.\ninline uint128_wrapper umul128(uint64_t x, uint64_t y) FMT_NOEXCEPT {\n#if FMT_USE_INT128\n  return static_cast<uint128_t>(x) * static_cast<uint128_t>(y);\n#elif defined(_MSC_VER) && defined(_M_X64)\n  uint128_wrapper result;\n  result.low_ = _umul128(x, y, &result.high_);\n  return result;\n#else\n  const uint64_t mask = (uint64_t(1) << 32) - uint64_t(1);\n\n  uint64_t a = x >> 32;\n  uint64_t b = x & mask;\n  uint64_t c = y >> 32;\n  uint64_t d = y & mask;\n\n  uint64_t ac = a * c;\n  uint64_t bc = b * c;\n  uint64_t ad = a * d;\n  uint64_t bd = b * d;\n\n  uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask);\n\n  return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),\n          (intermediate << 32) + (bd & mask)};\n#endif\n}\n\n// Computes upper 64 bits of multiplication of two 64-bit unsigned integers.\ninline uint64_t umul128_upper64(uint64_t x, uint64_t y) FMT_NOEXCEPT {\n#if FMT_USE_INT128\n  auto p = static_cast<uint128_t>(x) * static_cast<uint128_t>(y);\n  return static_cast<uint64_t>(p >> 64);\n#elif defined(_MSC_VER) && defined(_M_X64)\n  return __umulh(x, y);\n#else\n  return umul128(x, y).high();\n#endif\n}\n\n// Computes upper 64 bits of multiplication of a 64-bit unsigned integer and a\n// 128-bit unsigned integer.\ninline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT {\n  uint128_wrapper g0 = umul128(x, y.high());\n  g0 += umul128_upper64(x, y.low());\n  return g0.high();\n}\n\n// Computes upper 32 bits of multiplication of a 32-bit unsigned integer and a\n// 64-bit unsigned integer.\ninline uint32_t umul96_upper32(uint32_t x, uint64_t y) FMT_NOEXCEPT {\n  return static_cast<uint32_t>(umul128_upper64(x, y));\n}\n\n// Computes middle 64 bits of multiplication of a 64-bit unsigned integer and a\n// 128-bit unsigned integer.\ninline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT {\n  uint64_t g01 = x * y.high();\n  uint64_t g10 = umul128_upper64(x, y.low());\n  return g01 + g10;\n}\n\n// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a\n// 64-bit unsigned integer.\ninline uint64_t umul96_lower64(uint32_t x, uint64_t y) FMT_NOEXCEPT {\n  return x * y;\n}\n\n// Computes floor(log10(pow(2, e))) for e in [-1700, 1700] using the method from\n// https://fmt.dev/papers/Grisu-Exact.pdf#page=5, section 3.4.\ninline int floor_log10_pow2(int e) FMT_NOEXCEPT {\n  FMT_ASSERT(e <= 1700 && e >= -1700, \"too large exponent\");\n  const int shift = 22;\n  return (e * static_cast<int>(log10_2_significand >> (64 - shift))) >> shift;\n}\n\n// Various fast log computations.\ninline int floor_log2_pow10(int e) FMT_NOEXCEPT {\n  FMT_ASSERT(e <= 1233 && e >= -1233, \"too large exponent\");\n  const uint64_t log2_10_integer_part = 3;\n  const uint64_t log2_10_fractional_digits = 0x5269e12f346e2bf9;\n  const int shift_amount = 19;\n  return (e * static_cast<int>(\n                  (log2_10_integer_part << shift_amount) |\n                  (log2_10_fractional_digits >> (64 - shift_amount)))) >>\n         shift_amount;\n}\ninline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT {\n  FMT_ASSERT(e <= 1700 && e >= -1700, \"too large exponent\");\n  const uint64_t log10_4_over_3_fractional_digits = 0x1ffbfc2bbc780375;\n  const int shift_amount = 22;\n  return (e * static_cast<int>(log10_2_significand >> (64 - shift_amount)) -\n          static_cast<int>(log10_4_over_3_fractional_digits >>\n                           (64 - shift_amount))) >>\n         shift_amount;\n}\n\n// Returns true iff x is divisible by pow(2, exp).\ninline bool divisible_by_power_of_2(uint32_t x, int exp) FMT_NOEXCEPT {\n  FMT_ASSERT(exp >= 1, \"\");\n  FMT_ASSERT(x != 0, \"\");\n#ifdef FMT_BUILTIN_CTZ\n  return FMT_BUILTIN_CTZ(x) >= exp;\n#else\n  return exp < num_bits<uint32_t>() && x == ((x >> exp) << exp);\n#endif\n}\ninline bool divisible_by_power_of_2(uint64_t x, int exp) FMT_NOEXCEPT {\n  FMT_ASSERT(exp >= 1, \"\");\n  FMT_ASSERT(x != 0, \"\");\n#ifdef FMT_BUILTIN_CTZLL\n  return FMT_BUILTIN_CTZLL(x) >= exp;\n#else\n  return exp < num_bits<uint64_t>() && x == ((x >> exp) << exp);\n#endif\n}\n\n// Table entry type for divisibility test.\ntemplate <typename T> struct divtest_table_entry {\n  T mod_inv;\n  T max_quotient;\n};\n\n// Returns true iff x is divisible by pow(5, exp).\ninline bool divisible_by_power_of_5(uint32_t x, int exp) FMT_NOEXCEPT {\n  FMT_ASSERT(exp <= 10, \"too large exponent\");\n  static constexpr const divtest_table_entry<uint32_t> divtest_table[] = {\n      {0x00000001, 0xffffffff}, {0xcccccccd, 0x33333333},\n      {0xc28f5c29, 0x0a3d70a3}, {0x26e978d5, 0x020c49ba},\n      {0x3afb7e91, 0x0068db8b}, {0x0bcbe61d, 0x0014f8b5},\n      {0x68c26139, 0x000431bd}, {0xae8d46a5, 0x0000d6bf},\n      {0x22e90e21, 0x00002af3}, {0x3a2e9c6d, 0x00000897},\n      {0x3ed61f49, 0x000001b7}};\n  return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient;\n}\ninline bool divisible_by_power_of_5(uint64_t x, int exp) FMT_NOEXCEPT {\n  FMT_ASSERT(exp <= 23, \"too large exponent\");\n  static constexpr const divtest_table_entry<uint64_t> divtest_table[] = {\n      {0x0000000000000001, 0xffffffffffffffff},\n      {0xcccccccccccccccd, 0x3333333333333333},\n      {0x8f5c28f5c28f5c29, 0x0a3d70a3d70a3d70},\n      {0x1cac083126e978d5, 0x020c49ba5e353f7c},\n      {0xd288ce703afb7e91, 0x0068db8bac710cb2},\n      {0x5d4e8fb00bcbe61d, 0x0014f8b588e368f0},\n      {0x790fb65668c26139, 0x000431bde82d7b63},\n      {0xe5032477ae8d46a5, 0x0000d6bf94d5e57a},\n      {0xc767074b22e90e21, 0x00002af31dc46118},\n      {0x8e47ce423a2e9c6d, 0x0000089705f4136b},\n      {0x4fa7f60d3ed61f49, 0x000001b7cdfd9d7b},\n      {0x0fee64690c913975, 0x00000057f5ff85e5},\n      {0x3662e0e1cf503eb1, 0x000000119799812d},\n      {0xa47a2cf9f6433fbd, 0x0000000384b84d09},\n      {0x54186f653140a659, 0x00000000b424dc35},\n      {0x7738164770402145, 0x0000000024075f3d},\n      {0xe4a4d1417cd9a041, 0x000000000734aca5},\n      {0xc75429d9e5c5200d, 0x000000000170ef54},\n      {0xc1773b91fac10669, 0x000000000049c977},\n      {0x26b172506559ce15, 0x00000000000ec1e4},\n      {0xd489e3a9addec2d1, 0x000000000002f394},\n      {0x90e860bb892c8d5d, 0x000000000000971d},\n      {0x502e79bf1b6f4f79, 0x0000000000001e39},\n      {0xdcd618596be30fe5, 0x000000000000060b}};\n  return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient;\n}\n\n// Replaces n by floor(n / pow(5, N)) returning true if and only if n is\n// divisible by pow(5, N).\n// Precondition: n <= 2 * pow(5, N + 1).\ntemplate <int N>\nbool check_divisibility_and_divide_by_pow5(uint32_t& n) FMT_NOEXCEPT {\n  static constexpr struct {\n    uint32_t magic_number;\n    int bits_for_comparison;\n    uint32_t threshold;\n    int shift_amount;\n  } infos[] = {{0xcccd, 16, 0x3333, 18}, {0xa429, 8, 0x0a, 20}};\n  constexpr auto info = infos[N - 1];\n  n *= info.magic_number;\n  const uint32_t comparison_mask = (1u << info.bits_for_comparison) - 1;\n  bool result = (n & comparison_mask) <= info.threshold;\n  n >>= info.shift_amount;\n  return result;\n}\n\n// Computes floor(n / pow(10, N)) for small n and N.\n// Precondition: n <= pow(10, N + 1).\ntemplate <int N> uint32_t small_division_by_pow10(uint32_t n) FMT_NOEXCEPT {\n  static constexpr struct {\n    uint32_t magic_number;\n    int shift_amount;\n    uint32_t divisor_times_10;\n  } infos[] = {{0xcccd, 19, 100}, {0xa3d8, 22, 1000}};\n  constexpr auto info = infos[N - 1];\n  FMT_ASSERT(n <= info.divisor_times_10, \"n is too large\");\n  return n * info.magic_number >> info.shift_amount;\n}\n\n// Computes floor(n / 10^(kappa + 1)) (float)\ninline uint32_t divide_by_10_to_kappa_plus_1(uint32_t n) FMT_NOEXCEPT {\n  return n / float_info<float>::big_divisor;\n}\n// Computes floor(n / 10^(kappa + 1)) (double)\ninline uint64_t divide_by_10_to_kappa_plus_1(uint64_t n) FMT_NOEXCEPT {\n  return umul128_upper64(n, 0x83126e978d4fdf3c) >> 9;\n}\n\n// Various subroutines using pow10 cache\ntemplate <class T> struct cache_accessor;\n\ntemplate <> struct cache_accessor<float> {\n  using carrier_uint = float_info<float>::carrier_uint;\n  using cache_entry_type = uint64_t;\n\n  static uint64_t get_cached_power(int k) FMT_NOEXCEPT {\n    FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::max_k,\n               \"k is out of range\");\n    static constexpr const uint64_t pow10_significands[] = {\n        0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f,\n        0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb,\n        0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28,\n        0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb,\n        0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a,\n        0xe69594bec44de15c, 0x901d7cf73ab0acda, 0xb424dc35095cd810,\n        0xe12e13424bb40e14, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff,\n        0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd,\n        0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424,\n        0xd1b71758e219652c, 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b,\n        0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000,\n        0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000,\n        0xc350000000000000, 0xf424000000000000, 0x9896800000000000,\n        0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000,\n        0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000,\n        0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000,\n        0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000,\n        0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000,\n        0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0,\n        0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940984,\n        0xa18f07d736b90be5, 0xc9f2c9cd04674ede, 0xfc6f7c4045812296,\n        0x9dc5ada82b70b59d, 0xc5371912364ce305, 0xf684df56c3e01bc6,\n        0x9a130b963a6c115c, 0xc097ce7bc90715b3, 0xf0bdc21abb48db20,\n        0x96769950b50d88f4, 0xbc143fa4e250eb31, 0xeb194f8e1ae525fd,\n        0x92efd1b8d0cf37be, 0xb7abc627050305ad, 0xe596b7b0c643c719,\n        0x8f7e32ce7bea5c6f, 0xb35dbf821ae4f38b, 0xe0352f62a19e306e};\n    return pow10_significands[k - float_info<float>::min_k];\n  }\n\n  static carrier_uint compute_mul(carrier_uint u,\n                                  const cache_entry_type& cache) FMT_NOEXCEPT {\n    return umul96_upper32(u, cache);\n  }\n\n  static uint32_t compute_delta(const cache_entry_type& cache,\n                                int beta_minus_1) FMT_NOEXCEPT {\n    return static_cast<uint32_t>(cache >> (64 - 1 - beta_minus_1));\n  }\n\n  static bool compute_mul_parity(carrier_uint two_f,\n                                 const cache_entry_type& cache,\n                                 int beta_minus_1) FMT_NOEXCEPT {\n    FMT_ASSERT(beta_minus_1 >= 1, \"\");\n    FMT_ASSERT(beta_minus_1 < 64, \"\");\n\n    return ((umul96_lower64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0;\n  }\n\n  static carrier_uint compute_left_endpoint_for_shorter_interval_case(\n      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {\n    return static_cast<carrier_uint>(\n        (cache - (cache >> (float_info<float>::significand_bits + 2))) >>\n        (64 - float_info<float>::significand_bits - 1 - beta_minus_1));\n  }\n\n  static carrier_uint compute_right_endpoint_for_shorter_interval_case(\n      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {\n    return static_cast<carrier_uint>(\n        (cache + (cache >> (float_info<float>::significand_bits + 1))) >>\n        (64 - float_info<float>::significand_bits - 1 - beta_minus_1));\n  }\n\n  static carrier_uint compute_round_up_for_shorter_interval_case(\n      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {\n    return (static_cast<carrier_uint>(\n                cache >>\n                (64 - float_info<float>::significand_bits - 2 - beta_minus_1)) +\n            1) /\n           2;\n  }\n};\n\ntemplate <> struct cache_accessor<double> {\n  using carrier_uint = float_info<double>::carrier_uint;\n  using cache_entry_type = uint128_wrapper;\n\n  static uint128_wrapper get_cached_power(int k) FMT_NOEXCEPT {\n    FMT_ASSERT(k >= float_info<double>::min_k && k <= float_info<double>::max_k,\n               \"k is out of range\");\n\n    static constexpr const uint128_wrapper pow10_significands[] = {\n#if FMT_USE_FULL_CACHE_DRAGONBOX\n      {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},\n      {0x9faacf3df73609b1, 0x77b191618c54e9ad},\n      {0xc795830d75038c1d, 0xd59df5b9ef6a2418},\n      {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e},\n      {0x9becce62836ac577, 0x4ee367f9430aec33},\n      {0xc2e801fb244576d5, 0x229c41f793cda740},\n      {0xf3a20279ed56d48a, 0x6b43527578c11110},\n      {0x9845418c345644d6, 0x830a13896b78aaaa},\n      {0xbe5691ef416bd60c, 0x23cc986bc656d554},\n      {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9},\n      {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa},\n      {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54},\n      {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69},\n      {0x91376c36d99995be, 0x23100809b9c21fa2},\n      {0xb58547448ffffb2d, 0xabd40a0c2832a78b},\n      {0xe2e69915b3fff9f9, 0x16c90c8f323f516d},\n      {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4},\n      {0xb1442798f49ffb4a, 0x99cd11cfdf41779d},\n      {0xdd95317f31c7fa1d, 0x40405643d711d584},\n      {0x8a7d3eef7f1cfc52, 0x482835ea666b2573},\n      {0xad1c8eab5ee43b66, 0xda3243650005eed0},\n      {0xd863b256369d4a40, 0x90bed43e40076a83},\n      {0x873e4f75e2224e68, 0x5a7744a6e804a292},\n      {0xa90de3535aaae202, 0x711515d0a205cb37},\n      {0xd3515c2831559a83, 0x0d5a5b44ca873e04},\n      {0x8412d9991ed58091, 0xe858790afe9486c3},\n      {0xa5178fff668ae0b6, 0x626e974dbe39a873},\n      {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},\n      {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a},\n      {0xa139029f6a239f72, 0x1c1fffc1ebc44e81},\n      {0xc987434744ac874e, 0xa327ffb266b56221},\n      {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9},\n      {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa},\n      {0xc4ce17b399107c22, 0xcb550fb4384d21d4},\n      {0xf6019da07f549b2b, 0x7e2a53a146606a49},\n      {0x99c102844f94e0fb, 0x2eda7444cbfc426e},\n      {0xc0314325637a1939, 0xfa911155fefb5309},\n      {0xf03d93eebc589f88, 0x793555ab7eba27cb},\n      {0x96267c7535b763b5, 0x4bc1558b2f3458df},\n      {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17},\n      {0xea9c227723ee8bcb, 0x465e15a979c1cadd},\n      {0x92a1958a7675175f, 0x0bfacd89ec191eca},\n      {0xb749faed14125d36, 0xcef980ec671f667c},\n      {0xe51c79a85916f484, 0x82b7e12780e7401b},\n      {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811},\n      {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16},\n      {0xdfbdcece67006ac9, 0x67a791e093e1d49b},\n      {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1},\n      {0xaecc49914078536d, 0x58fae9f773886e19},\n      {0xda7f5bf590966848, 0xaf39a475506a899f},\n      {0x888f99797a5e012d, 0x6d8406c952429604},\n      {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84},\n      {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65},\n      {0x855c3be0a17fcd26, 0x5cf2eea09a550680},\n      {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f},\n      {0xd0601d8efc57b08b, 0xf13b94daf124da27},\n      {0x823c12795db6ce57, 0x76c53d08d6b70859},\n      {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f},\n      {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a},\n      {0xfe5d54150b090b02, 0xd3f93b35435d7c4d},\n      {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0},\n      {0xc6b8e9b0709f109a, 0x359ab6419ca1091c},\n      {0xf867241c8cc6d4c0, 0xc30163d203c94b63},\n      {0x9b407691d7fc44f8, 0x79e0de63425dcf1e},\n      {0xc21094364dfb5636, 0x985915fc12f542e5},\n      {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e},\n      {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43},\n      {0xbd8430bd08277231, 0x50c6ff782a838354},\n      {0xece53cec4a314ebd, 0xa4f8bf5635246429},\n      {0x940f4613ae5ed136, 0x871b7795e136be9a},\n      {0xb913179899f68584, 0x28e2557b59846e40},\n      {0xe757dd7ec07426e5, 0x331aeada2fe589d0},\n      {0x9096ea6f3848984f, 0x3ff0d2c85def7622},\n      {0xb4bca50b065abe63, 0x0fed077a756b53aa},\n      {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895},\n      {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d},\n      {0xb080392cc4349dec, 0xbd8d794d96aacfb4},\n      {0xdca04777f541c567, 0xecf0d7a0fc5583a1},\n      {0x89e42caaf9491b60, 0xf41686c49db57245},\n      {0xac5d37d5b79b6239, 0x311c2875c522ced6},\n      {0xd77485cb25823ac7, 0x7d633293366b828c},\n      {0x86a8d39ef77164bc, 0xae5dff9c02033198},\n      {0xa8530886b54dbdeb, 0xd9f57f830283fdfd},\n      {0xd267caa862a12d66, 0xd072df63c324fd7c},\n      {0x8380dea93da4bc60, 0x4247cb9e59f71e6e},\n      {0xa46116538d0deb78, 0x52d9be85f074e609},\n      {0xcd795be870516656, 0x67902e276c921f8c},\n      {0x806bd9714632dff6, 0x00ba1cd8a3db53b7},\n      {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5},\n      {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce},\n      {0xfad2a4b13d1b5d6c, 0x796b805720085f82},\n      {0x9cc3a6eec6311a63, 0xcbe3303674053bb1},\n      {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d},\n      {0xf4f1b4d515acb93b, 0xee92fb5515482d45},\n      {0x991711052d8bf3c5, 0x751bdd152d4d1c4b},\n      {0xbf5cd54678eef0b6, 0xd262d45a78a0635e},\n      {0xef340a98172aace4, 0x86fb897116c87c35},\n      {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1},\n      {0xbae0a846d2195712, 0x8974836059cca10a},\n      {0xe998d258869facd7, 0x2bd1a438703fc94c},\n      {0x91ff83775423cc06, 0x7b6306a34627ddd0},\n      {0xb67f6455292cbf08, 0x1a3bc84c17b1d543},\n      {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94},\n      {0x8e938662882af53e, 0x547eb47b7282ee9d},\n      {0xb23867fb2a35b28d, 0xe99e619a4f23aa44},\n      {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5},\n      {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05},\n      {0xae0b158b4738705e, 0x9624ab50b148d446},\n      {0xd98ddaee19068c76, 0x3badd624dd9b0958},\n      {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7},\n      {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d},\n      {0xd47487cc8470652b, 0x7647c32000696720},\n      {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074},\n      {0xa5fb0a17c777cf09, 0xf468107100525891},\n      {0xcf79cc9db955c2cc, 0x7182148d4066eeb5},\n      {0x81ac1fe293d599bf, 0xc6f14cd848405531},\n      {0xa21727db38cb002f, 0xb8ada00e5a506a7d},\n      {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d},\n      {0xfd442e4688bd304a, 0x908f4a166d1da664},\n      {0x9e4a9cec15763e2e, 0x9a598e4e043287ff},\n      {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe},\n      {0xf7549530e188c128, 0xd12bee59e68ef47d},\n      {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf},\n      {0xc13a148e3032d6e7, 0xe36a52363c1faf02},\n      {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2},\n      {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba},\n      {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8},\n      {0xebdf661791d60f56, 0x111b495b3464ad22},\n      {0x936b9fcebb25c995, 0xcab10dd900beec35},\n      {0xb84687c269ef3bfb, 0x3d5d514f40eea743},\n      {0xe65829b3046b0afa, 0x0cb4a5a3112a5113},\n      {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac},\n      {0xb3f4e093db73a093, 0x59ed216765690f57},\n      {0xe0f218b8d25088b8, 0x306869c13ec3532d},\n      {0x8c974f7383725573, 0x1e414218c73a13fc},\n      {0xafbd2350644eeacf, 0xe5d1929ef90898fb},\n      {0xdbac6c247d62a583, 0xdf45f746b74abf3a},\n      {0x894bc396ce5da772, 0x6b8bba8c328eb784},\n      {0xab9eb47c81f5114f, 0x066ea92f3f326565},\n      {0xd686619ba27255a2, 0xc80a537b0efefebe},\n      {0x8613fd0145877585, 0xbd06742ce95f5f37},\n      {0xa798fc4196e952e7, 0x2c48113823b73705},\n      {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6},\n      {0x82ef85133de648c4, 0x9a984d73dbe722fc},\n      {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb},\n      {0xcc963fee10b7d1b3, 0x318df905079926a9},\n      {0xffbbcfe994e5c61f, 0xfdf17746497f7053},\n      {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634},\n      {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1},\n      {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1},\n      {0x9c1661a651213e2d, 0x06bea10ca65c084f},\n      {0xc31bfa0fe5698db8, 0x486e494fcff30a63},\n      {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb},\n      {0x986ddb5c6b3a76b7, 0xf89629465a75e01d},\n      {0xbe89523386091465, 0xf6bbb397f1135824},\n      {0xee2ba6c0678b597f, 0x746aa07ded582e2d},\n      {0x94db483840b717ef, 0xa8c2a44eb4571cdd},\n      {0xba121a4650e4ddeb, 0x92f34d62616ce414},\n      {0xe896a0d7e51e1566, 0x77b020baf9c81d18},\n      {0x915e2486ef32cd60, 0x0ace1474dc1d122f},\n      {0xb5b5ada8aaff80b8, 0x0d819992132456bb},\n      {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a},\n      {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2},\n      {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3},\n      {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf},\n      {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c},\n      {0xad4ab7112eb3929d, 0x86c16c98d2c953c7},\n      {0xd89d64d57a607744, 0xe871c7bf077ba8b8},\n      {0x87625f056c7c4a8b, 0x11471cd764ad4973},\n      {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0},\n      {0xd389b47879823479, 0x4aff1d108d4ec2c4},\n      {0x843610cb4bf160cb, 0xcedf722a585139bb},\n      {0xa54394fe1eedb8fe, 0xc2974eb4ee658829},\n      {0xce947a3da6a9273e, 0x733d226229feea33},\n      {0x811ccc668829b887, 0x0806357d5a3f5260},\n      {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8},\n      {0xc9bcff6034c13052, 0xfc89b393dd02f0b6},\n      {0xfc2c3f3841f17c67, 0xbbac2078d443ace3},\n      {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e},\n      {0xc5029163f384a931, 0x0a9e795e65d4df12},\n      {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6},\n      {0x99ea0196163fa42e, 0x504bced1bf8e4e46},\n      {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7},\n      {0xf07da27a82c37088, 0x5d767327bb4e5a4d},\n      {0x964e858c91ba2655, 0x3a6a07f8d510f870},\n      {0xbbe226efb628afea, 0x890489f70a55368c},\n      {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f},\n      {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e},\n      {0xb77ada0617e3bbcb, 0x09ce6ebb40173745},\n      {0xe55990879ddcaabd, 0xcc420a6a101d0516},\n      {0x8f57fa54c2a9eab6, 0x9fa946824a12232e},\n      {0xb32df8e9f3546564, 0x47939822dc96abfa},\n      {0xdff9772470297ebd, 0x59787e2b93bc56f8},\n      {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b},\n      {0xaefae51477a06b03, 0xede622920b6b23f2},\n      {0xdab99e59958885c4, 0xe95fab368e45ecee},\n      {0x88b402f7fd75539b, 0x11dbcb0218ebb415},\n      {0xaae103b5fcd2a881, 0xd652bdc29f26a11a},\n      {0xd59944a37c0752a2, 0x4be76d3346f04960},\n      {0x857fcae62d8493a5, 0x6f70a4400c562ddc},\n      {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953},\n      {0xd097ad07a71f26b2, 0x7e2000a41346a7a8},\n      {0x825ecc24c873782f, 0x8ed400668c0c28c9},\n      {0xa2f67f2dfa90563b, 0x728900802f0f32fb},\n      {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba},\n      {0xfea126b7d78186bc, 0xe2f610c84987bfa9},\n      {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca},\n      {0xc6ede63fa05d3143, 0x91503d1c79720dbc},\n      {0xf8a95fcf88747d94, 0x75a44c6397ce912b},\n      {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb},\n      {0xc24452da229b021b, 0xfbe85badce996169},\n      {0xf2d56790ab41c2a2, 0xfae27299423fb9c4},\n      {0x97c560ba6b0919a5, 0xdccd879fc967d41b},\n      {0xbdb6b8e905cb600f, 0x5400e987bbc1c921},\n      {0xed246723473e3813, 0x290123e9aab23b69},\n      {0x9436c0760c86e30b, 0xf9a0b6720aaf6522},\n      {0xb94470938fa89bce, 0xf808e40e8d5b3e6a},\n      {0xe7958cb87392c2c2, 0xb60b1d1230b20e05},\n      {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3},\n      {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4},\n      {0xe2280b6c20dd5232, 0x25c6da63c38de1b1},\n      {0x8d590723948a535f, 0x579c487e5a38ad0f},\n      {0xb0af48ec79ace837, 0x2d835a9df0c6d852},\n      {0xdcdb1b2798182244, 0xf8e431456cf88e66},\n      {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900},\n      {0xac8b2d36eed2dac5, 0xe272467e3d222f40},\n      {0xd7adf884aa879177, 0x5b0ed81dcc6abb10},\n      {0x86ccbb52ea94baea, 0x98e947129fc2b4ea},\n      {0xa87fea27a539e9a5, 0x3f2398d747b36225},\n      {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae},\n      {0x83a3eeeef9153e89, 0x1953cf68300424ad},\n      {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8},\n      {0xcdb02555653131b6, 0x3792f412cb06794e},\n      {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1},\n      {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5},\n      {0xc8de047564d20a8b, 0xf245825a5a445276},\n      {0xfb158592be068d2e, 0xeed6e2f0f0d56713},\n      {0x9ced737bb6c4183d, 0x55464dd69685606c},\n      {0xc428d05aa4751e4c, 0xaa97e14c3c26b887},\n      {0xf53304714d9265df, 0xd53dd99f4b3066a9},\n      {0x993fe2c6d07b7fab, 0xe546a8038efe402a},\n      {0xbf8fdb78849a5f96, 0xde98520472bdd034},\n      {0xef73d256a5c0f77c, 0x963e66858f6d4441},\n      {0x95a8637627989aad, 0xdde7001379a44aa9},\n      {0xbb127c53b17ec159, 0x5560c018580d5d53},\n      {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7},\n      {0x9226712162ab070d, 0xcab3961304ca70e9},\n      {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23},\n      {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b},\n      {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243},\n      {0xb267ed1940f1c61c, 0x55f038b237591ed4},\n      {0xdf01e85f912e37a3, 0x6b6c46dec52f6689},\n      {0x8b61313bbabce2c6, 0x2323ac4b3b3da016},\n      {0xae397d8aa96c1b77, 0xabec975e0a0d081b},\n      {0xd9c7dced53c72255, 0x96e7bd358c904a22},\n      {0x881cea14545c7575, 0x7e50d64177da2e55},\n      {0xaa242499697392d2, 0xdde50bd1d5d0b9ea},\n      {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865},\n      {0x84ec3c97da624ab4, 0xbd5af13bef0b113f},\n      {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f},\n      {0xcfb11ead453994ba, 0x67de18eda5814af3},\n      {0x81ceb32c4b43fcf4, 0x80eacf948770ced8},\n      {0xa2425ff75e14fc31, 0xa1258379a94d028e},\n      {0xcad2f7f5359a3b3e, 0x096ee45813a04331},\n      {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd},\n      {0x9e74d1b791e07e48, 0x775ea264cf55347e},\n      {0xc612062576589dda, 0x95364afe032a819e},\n      {0xf79687aed3eec551, 0x3a83ddbd83f52205},\n      {0x9abe14cd44753b52, 0xc4926a9672793543},\n      {0xc16d9a0095928a27, 0x75b7053c0f178294},\n      {0xf1c90080baf72cb1, 0x5324c68b12dd6339},\n      {0x971da05074da7bee, 0xd3f6fc16ebca5e04},\n      {0xbce5086492111aea, 0x88f4bb1ca6bcf585},\n      {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6},\n      {0x9392ee8e921d5d07, 0x3aff322e62439fd0},\n      {0xb877aa3236a4b449, 0x09befeb9fad487c3},\n      {0xe69594bec44de15b, 0x4c2ebe687989a9b4},\n      {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11},\n      {0xb424dc35095cd80f, 0x538484c19ef38c95},\n      {0xe12e13424bb40e13, 0x2865a5f206b06fba},\n      {0x8cbccc096f5088cb, 0xf93f87b7442e45d4},\n      {0xafebff0bcb24aafe, 0xf78f69a51539d749},\n      {0xdbe6fecebdedd5be, 0xb573440e5a884d1c},\n      {0x89705f4136b4a597, 0x31680a88f8953031},\n      {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e},\n      {0xd6bf94d5e57a42bc, 0x3d32907604691b4d},\n      {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110},\n      {0xa7c5ac471b478423, 0x0fcf80dc33721d54},\n      {0xd1b71758e219652b, 0xd3c36113404ea4a9},\n      {0x83126e978d4fdf3b, 0x645a1cac083126ea},\n      {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4},\n      {0xcccccccccccccccc, 0xcccccccccccccccd},\n      {0x8000000000000000, 0x0000000000000000},\n      {0xa000000000000000, 0x0000000000000000},\n      {0xc800000000000000, 0x0000000000000000},\n      {0xfa00000000000000, 0x0000000000000000},\n      {0x9c40000000000000, 0x0000000000000000},\n      {0xc350000000000000, 0x0000000000000000},\n      {0xf424000000000000, 0x0000000000000000},\n      {0x9896800000000000, 0x0000000000000000},\n      {0xbebc200000000000, 0x0000000000000000},\n      {0xee6b280000000000, 0x0000000000000000},\n      {0x9502f90000000000, 0x0000000000000000},\n      {0xba43b74000000000, 0x0000000000000000},\n      {0xe8d4a51000000000, 0x0000000000000000},\n      {0x9184e72a00000000, 0x0000000000000000},\n      {0xb5e620f480000000, 0x0000000000000000},\n      {0xe35fa931a0000000, 0x0000000000000000},\n      {0x8e1bc9bf04000000, 0x0000000000000000},\n      {0xb1a2bc2ec5000000, 0x0000000000000000},\n      {0xde0b6b3a76400000, 0x0000000000000000},\n      {0x8ac7230489e80000, 0x0000000000000000},\n      {0xad78ebc5ac620000, 0x0000000000000000},\n      {0xd8d726b7177a8000, 0x0000000000000000},\n      {0x878678326eac9000, 0x0000000000000000},\n      {0xa968163f0a57b400, 0x0000000000000000},\n      {0xd3c21bcecceda100, 0x0000000000000000},\n      {0x84595161401484a0, 0x0000000000000000},\n      {0xa56fa5b99019a5c8, 0x0000000000000000},\n      {0xcecb8f27f4200f3a, 0x0000000000000000},\n      {0x813f3978f8940984, 0x4000000000000000},\n      {0xa18f07d736b90be5, 0x5000000000000000},\n      {0xc9f2c9cd04674ede, 0xa400000000000000},\n      {0xfc6f7c4045812296, 0x4d00000000000000},\n      {0x9dc5ada82b70b59d, 0xf020000000000000},\n      {0xc5371912364ce305, 0x6c28000000000000},\n      {0xf684df56c3e01bc6, 0xc732000000000000},\n      {0x9a130b963a6c115c, 0x3c7f400000000000},\n      {0xc097ce7bc90715b3, 0x4b9f100000000000},\n      {0xf0bdc21abb48db20, 0x1e86d40000000000},\n      {0x96769950b50d88f4, 0x1314448000000000},\n      {0xbc143fa4e250eb31, 0x17d955a000000000},\n      {0xeb194f8e1ae525fd, 0x5dcfab0800000000},\n      {0x92efd1b8d0cf37be, 0x5aa1cae500000000},\n      {0xb7abc627050305ad, 0xf14a3d9e40000000},\n      {0xe596b7b0c643c719, 0x6d9ccd05d0000000},\n      {0x8f7e32ce7bea5c6f, 0xe4820023a2000000},\n      {0xb35dbf821ae4f38b, 0xdda2802c8a800000},\n      {0xe0352f62a19e306e, 0xd50b2037ad200000},\n      {0x8c213d9da502de45, 0x4526f422cc340000},\n      {0xaf298d050e4395d6, 0x9670b12b7f410000},\n      {0xdaf3f04651d47b4c, 0x3c0cdd765f114000},\n      {0x88d8762bf324cd0f, 0xa5880a69fb6ac800},\n      {0xab0e93b6efee0053, 0x8eea0d047a457a00},\n      {0xd5d238a4abe98068, 0x72a4904598d6d880},\n      {0x85a36366eb71f041, 0x47a6da2b7f864750},\n      {0xa70c3c40a64e6c51, 0x999090b65f67d924},\n      {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d},\n      {0x82818f1281ed449f, 0xbff8f10e7a8921a4},\n      {0xa321f2d7226895c7, 0xaff72d52192b6a0d},\n      {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490},\n      {0xfee50b7025c36a08, 0x02f236d04753d5b4},\n      {0x9f4f2726179a2245, 0x01d762422c946590},\n      {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5},\n      {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2},\n      {0x9b934c3b330c8577, 0x63cc55f49f88eb2f},\n      {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb},\n      {0xf316271c7fc3908a, 0x8bef464e3945ef7a},\n      {0x97edd871cfda3a56, 0x97758bf0e3cbb5ac},\n      {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317},\n      {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd},\n      {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a},\n      {0xb975d6b6ee39e436, 0xb3e2fd538e122b44},\n      {0xe7d34c64a9c85d44, 0x60dbbca87196b616},\n      {0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd},\n      {0xb51d13aea4a488dd, 0x6babab6398bdbe41},\n      {0xe264589a4dcdab14, 0xc696963c7eed2dd1},\n      {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2},\n      {0xb0de65388cc8ada8, 0x3b25a55f43294bcb},\n      {0xdd15fe86affad912, 0x49ef0eb713f39ebe},\n      {0x8a2dbf142dfcc7ab, 0x6e3569326c784337},\n      {0xacb92ed9397bf996, 0x49c2c37f07965404},\n      {0xd7e77a8f87daf7fb, 0xdc33745ec97be906},\n      {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3},\n      {0xa8acd7c0222311bc, 0xc40832ea0d68ce0c},\n      {0xd2d80db02aabd62b, 0xf50a3fa490c30190},\n      {0x83c7088e1aab65db, 0x792667c6da79e0fa},\n      {0xa4b8cab1a1563f52, 0x577001b891185938},\n      {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86},\n      {0x80b05e5ac60b6178, 0x544f8158315b05b4},\n      {0xa0dc75f1778e39d6, 0x696361ae3db1c721},\n      {0xc913936dd571c84c, 0x03bc3a19cd1e38e9},\n      {0xfb5878494ace3a5f, 0x04ab48a04065c723},\n      {0x9d174b2dcec0e47b, 0x62eb0d64283f9c76},\n      {0xc45d1df942711d9a, 0x3ba5d0bd324f8394},\n      {0xf5746577930d6500, 0xca8f44ec7ee36479},\n      {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb},\n      {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e},\n      {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e},\n      {0x95d04aee3b80ece5, 0xbba1f1d158724a12},\n      {0xbb445da9ca61281f, 0x2a8a6e45ae8edc97},\n      {0xea1575143cf97226, 0xf52d09d71a3293bd},\n      {0x924d692ca61be758, 0x593c2626705f9c56},\n      {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c},\n      {0xe498f455c38b997a, 0x0b6dfb9c0f956447},\n      {0x8edf98b59a373fec, 0x4724bd4189bd5eac},\n      {0xb2977ee300c50fe7, 0x58edec91ec2cb657},\n      {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed},\n      {0x8b865b215899f46c, 0xbd79e0d20082ee74},\n      {0xae67f1e9aec07187, 0xecd8590680a3aa11},\n      {0xda01ee641a708de9, 0xe80e6f4820cc9495},\n      {0x884134fe908658b2, 0x3109058d147fdcdd},\n      {0xaa51823e34a7eede, 0xbd4b46f0599fd415},\n      {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a},\n      {0x850fadc09923329e, 0x03e2cf6bc604ddb0},\n      {0xa6539930bf6bff45, 0x84db8346b786151c},\n      {0xcfe87f7cef46ff16, 0xe612641865679a63},\n      {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e},\n      {0xa26da3999aef7749, 0xe3be5e330f38f09d},\n      {0xcb090c8001ab551c, 0x5cadf5bfd3072cc5},\n      {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6},\n      {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa},\n      {0xc646d63501a1511d, 0xb281e1fd541501b8},\n      {0xf7d88bc24209a565, 0x1f225a7ca91a4226},\n      {0x9ae757596946075f, 0x3375788de9b06958},\n      {0xc1a12d2fc3978937, 0x0052d6b1641c83ae},\n      {0xf209787bb47d6b84, 0xc0678c5dbd23a49a},\n      {0x9745eb4d50ce6332, 0xf840b7ba963646e0},\n      {0xbd176620a501fbff, 0xb650e5a93bc3d898},\n      {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe},\n      {0x93ba47c980e98cdf, 0xc66f336c36b10137},\n      {0xb8a8d9bbe123f017, 0xb80b0047445d4184},\n      {0xe6d3102ad96cec1d, 0xa60dc059157491e5},\n      {0x9043ea1ac7e41392, 0x87c89837ad68db2f},\n      {0xb454e4a179dd1877, 0x29babe4598c311fb},\n      {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a},\n      {0x8ce2529e2734bb1d, 0x1899e4a65f58660c},\n      {0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f},\n      {0xdc21a1171d42645d, 0x76707543f4fa1f73},\n      {0x899504ae72497eba, 0x6a06494a791c53a8},\n      {0xabfa45da0edbde69, 0x0487db9d17636892},\n      {0xd6f8d7509292d603, 0x45a9d2845d3c42b6},\n      {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2},\n      {0xa7f26836f282b732, 0x8e6cac7768d7141e},\n      {0xd1ef0244af2364ff, 0x3207d795430cd926},\n      {0x8335616aed761f1f, 0x7f44e6bd49e807b8},\n      {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6},\n      {0xcd036837130890a1, 0x36dba887c37a8c0f},\n      {0x802221226be55a64, 0xc2494954da2c9789},\n      {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c},\n      {0xc83553c5c8965d3d, 0x6f92829494e5acc7},\n      {0xfa42a8b73abbf48c, 0xcb772339ba1f17f9},\n      {0x9c69a97284b578d7, 0xff2a760414536efb},\n      {0xc38413cf25e2d70d, 0xfef5138519684aba},\n      {0xf46518c2ef5b8cd1, 0x7eb258665fc25d69},\n      {0x98bf2f79d5993802, 0xef2f773ffbd97a61},\n      {0xbeeefb584aff8603, 0xaafb550ffacfd8fa},\n      {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38},\n      {0x952ab45cfa97a0b2, 0xdd945a747bf26183},\n      {0xba756174393d88df, 0x94f971119aeef9e4},\n      {0xe912b9d1478ceb17, 0x7a37cd5601aab85d},\n      {0x91abb422ccb812ee, 0xac62e055c10ab33a},\n      {0xb616a12b7fe617aa, 0x577b986b314d6009},\n      {0xe39c49765fdf9d94, 0xed5a7e85fda0b80b},\n      {0x8e41ade9fbebc27d, 0x14588f13be847307},\n      {0xb1d219647ae6b31c, 0x596eb2d8ae258fc8},\n      {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb},\n      {0x8aec23d680043bee, 0x25de7bb9480d5854},\n      {0xada72ccc20054ae9, 0xaf561aa79a10ae6a},\n      {0xd910f7ff28069da4, 0x1b2ba1518094da04},\n      {0x87aa9aff79042286, 0x90fb44d2f05d0842},\n      {0xa99541bf57452b28, 0x353a1607ac744a53},\n      {0xd3fa922f2d1675f2, 0x42889b8997915ce8},\n      {0x847c9b5d7c2e09b7, 0x69956135febada11},\n      {0xa59bc234db398c25, 0x43fab9837e699095},\n      {0xcf02b2c21207ef2e, 0x94f967e45e03f4bb},\n      {0x8161afb94b44f57d, 0x1d1be0eebac278f5},\n      {0xa1ba1ba79e1632dc, 0x6462d92a69731732},\n      {0xca28a291859bbf93, 0x7d7b8f7503cfdcfe},\n      {0xfcb2cb35e702af78, 0x5cda735244c3d43e},\n      {0x9defbf01b061adab, 0x3a0888136afa64a7},\n      {0xc56baec21c7a1916, 0x088aaa1845b8fdd0},\n      {0xf6c69a72a3989f5b, 0x8aad549e57273d45},\n      {0x9a3c2087a63f6399, 0x36ac54e2f678864b},\n      {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd},\n      {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5},\n      {0x969eb7c47859e743, 0x9f644ae5a4b1b325},\n      {0xbc4665b596706114, 0x873d5d9f0dde1fee},\n      {0xeb57ff22fc0c7959, 0xa90cb506d155a7ea},\n      {0x9316ff75dd87cbd8, 0x09a7f12442d588f2},\n      {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb2f},\n      {0xe5d3ef282a242e81, 0x8f1668c8a86da5fa},\n      {0x8fa475791a569d10, 0xf96e017d694487bc},\n      {0xb38d92d760ec4455, 0x37c981dcc395a9ac},\n      {0xe070f78d3927556a, 0x85bbe253f47b1417},\n      {0x8c469ab843b89562, 0x93956d7478ccec8e},\n      {0xaf58416654a6babb, 0x387ac8d1970027b2},\n      {0xdb2e51bfe9d0696a, 0x06997b05fcc0319e},\n      {0x88fcf317f22241e2, 0x441fece3bdf81f03},\n      {0xab3c2fddeeaad25a, 0xd527e81cad7626c3},\n      {0xd60b3bd56a5586f1, 0x8a71e223d8d3b074},\n      {0x85c7056562757456, 0xf6872d5667844e49},\n      {0xa738c6bebb12d16c, 0xb428f8ac016561db},\n      {0xd106f86e69d785c7, 0xe13336d701beba52},\n      {0x82a45b450226b39c, 0xecc0024661173473},\n      {0xa34d721642b06084, 0x27f002d7f95d0190},\n      {0xcc20ce9bd35c78a5, 0x31ec038df7b441f4},\n      {0xff290242c83396ce, 0x7e67047175a15271},\n      {0x9f79a169bd203e41, 0x0f0062c6e984d386},\n      {0xc75809c42c684dd1, 0x52c07b78a3e60868},\n      {0xf92e0c3537826145, 0xa7709a56ccdf8a82},\n      {0x9bbcc7a142b17ccb, 0x88a66076400bb691},\n      {0xc2abf989935ddbfe, 0x6acff893d00ea435},\n      {0xf356f7ebf83552fe, 0x0583f6b8c4124d43},\n      {0x98165af37b2153de, 0xc3727a337a8b704a},\n      {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c},\n      {0xeda2ee1c7064130c, 0x1162def06f79df73},\n      {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8},\n      {0xb9a74a0637ce2ee1, 0x6d953e2bd7173692},\n      {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437},\n      {0x910ab1d4db9914a0, 0x1d9c9892400a22a2},\n      {0xb54d5e4a127f59c8, 0x2503beb6d00cab4b},\n      {0xe2a0b5dc971f303a, 0x2e44ae64840fd61d},\n      {0x8da471a9de737e24, 0x5ceaecfed289e5d2},\n      {0xb10d8e1456105dad, 0x7425a83e872c5f47},\n      {0xdd50f1996b947518, 0xd12f124e28f77719},\n      {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f},\n      {0xace73cbfdc0bfb7b, 0x636cc64d1001550b},\n      {0xd8210befd30efa5a, 0x3c47f7e05401aa4e},\n      {0x8714a775e3e95c78, 0x65acfaec34810a71},\n      {0xa8d9d1535ce3b396, 0x7f1839a741a14d0d},\n      {0xd31045a8341ca07c, 0x1ede48111209a050},\n      {0x83ea2b892091e44d, 0x934aed0aab460432},\n      {0xa4e4b66b68b65d60, 0xf81da84d5617853f},\n      {0xce1de40642e3f4b9, 0x36251260ab9d668e},\n      {0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019},\n      {0xa1075a24e4421730, 0xb24cf65b8612f81f},\n      {0xc94930ae1d529cfc, 0xdee033f26797b627},\n      {0xfb9b7cd9a4a7443c, 0x169840ef017da3b1},\n      {0x9d412e0806e88aa5, 0x8e1f289560ee864e},\n      {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2},\n      {0xf5b5d7ec8acb58a2, 0xae10af696774b1db},\n      {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29},\n      {0xbff610b0cc6edd3f, 0x17fd090a58d32af3},\n      {0xeff394dcff8a948e, 0xddfc4b4cef07f5b0},\n      {0x95f83d0a1fb69cd9, 0x4abdaf101564f98e},\n      {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1},\n      {0xea53df5fd18d5513, 0x84c86189216dc5ed},\n      {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4},\n      {0xb7118682dbb66a77, 0x3fbc8c33221dc2a1},\n      {0xe4d5e82392a40515, 0x0fabaf3feaa5334a},\n      {0x8f05b1163ba6832d, 0x29cb4d87f2a7400e},\n      {0xb2c71d5bca9023f8, 0x743e20e9ef511012},\n      {0xdf78e4b2bd342cf6, 0x914da9246b255416},\n      {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e},\n      {0xae9672aba3d0c320, 0xa184ac2473b529b1},\n      {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e},\n      {0x8865899617fb1871, 0x7e2fa67c7a658892},\n      {0xaa7eebfb9df9de8d, 0xddbb901b98feeab7},\n      {0xd51ea6fa85785631, 0x552a74227f3ea565},\n      {0x8533285c936b35de, 0xd53a88958f87275f},\n      {0xa67ff273b8460356, 0x8a892abaf368f137},\n      {0xd01fef10a657842c, 0x2d2b7569b0432d85},\n      {0x8213f56a67f6b29b, 0x9c3b29620e29fc73},\n      {0xa298f2c501f45f42, 0x8349f3ba91b47b8f},\n      {0xcb3f2f7642717713, 0x241c70a936219a73},\n      {0xfe0efb53d30dd4d7, 0xed238cd383aa0110},\n      {0x9ec95d1463e8a506, 0xf4363804324a40aa},\n      {0xc67bb4597ce2ce48, 0xb143c6053edcd0d5},\n      {0xf81aa16fdc1b81da, 0xdd94b7868e94050a},\n      {0x9b10a4e5e9913128, 0xca7cf2b4191c8326},\n      {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0},\n      {0xf24a01a73cf2dccf, 0xbc633b39673c8cec},\n      {0x976e41088617ca01, 0xd5be0503e085d813},\n      {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18},\n      {0xec9c459d51852ba2, 0xddf8e7d60ed1219e},\n      {0x93e1ab8252f33b45, 0xcabb90e5c942b503},\n      {0xb8da1662e7b00a17, 0x3d6a751f3b936243},\n      {0xe7109bfba19c0c9d, 0x0cc512670a783ad4},\n      {0x906a617d450187e2, 0x27fb2b80668b24c5},\n      {0xb484f9dc9641e9da, 0xb1f9f660802dedf6},\n      {0xe1a63853bbd26451, 0x5e7873f8a0396973},\n      {0x8d07e33455637eb2, 0xdb0b487b6423e1e8},\n      {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62},\n      {0xdc5c5301c56b75f7, 0x7641a140cc7810fb},\n      {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d},\n      {0xac2820d9623bf429, 0x546345fa9fbdcd44},\n      {0xd732290fbacaf133, 0xa97c177947ad4095},\n      {0x867f59a9d4bed6c0, 0x49ed8eabcccc485d},\n      {0xa81f301449ee8c70, 0x5c68f256bfff5a74},\n      {0xd226fc195c6a2f8c, 0x73832eec6fff3111},\n      {0x83585d8fd9c25db7, 0xc831fd53c5ff7eab},\n      {0xa42e74f3d032f525, 0xba3e7ca8b77f5e55},\n      {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb},\n      {0x80444b5e7aa7cf85, 0x7980d163cf5b81b3},\n      {0xa0555e361951c366, 0xd7e105bcc332621f},\n      {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7},\n      {0xfa856334878fc150, 0xb14f98f6f0feb951},\n      {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3},\n      {0xc3b8358109e84f07, 0x0a862f80ec4700c8},\n      {0xf4a642e14c6262c8, 0xcd27bb612758c0fa},\n      {0x98e7e9cccfbd7dbd, 0x8038d51cb897789c},\n      {0xbf21e44003acdd2c, 0xe0470a63e6bd56c3},\n      {0xeeea5d5004981478, 0x1858ccfce06cac74},\n      {0x95527a5202df0ccb, 0x0f37801e0c43ebc8},\n      {0xbaa718e68396cffd, 0xd30560258f54e6ba},\n      {0xe950df20247c83fd, 0x47c6b82ef32a2069},\n      {0x91d28b7416cdd27e, 0x4cdc331d57fa5441},\n      {0xb6472e511c81471d, 0xe0133fe4adf8e952},\n      {0xe3d8f9e563a198e5, 0x58180fddd97723a6},\n      {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648},\n      {0xb201833b35d63f73, 0x2cd2cc6551e513da},\n      {0xde81e40a034bcf4f, 0xf8077f7ea65e58d1},\n      {0x8b112e86420f6191, 0xfb04afaf27faf782},\n      {0xadd57a27d29339f6, 0x79c5db9af1f9b563},\n      {0xd94ad8b1c7380874, 0x18375281ae7822bc},\n      {0x87cec76f1c830548, 0x8f2293910d0b15b5},\n      {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb22},\n      {0xd433179d9c8cb841, 0x5fa60692a46151eb},\n      {0x849feec281d7f328, 0xdbc7c41ba6bcd333},\n      {0xa5c7ea73224deff3, 0x12b9b522906c0800},\n      {0xcf39e50feae16bef, 0xd768226b34870a00},\n      {0x81842f29f2cce375, 0xe6a1158300d46640},\n      {0xa1e53af46f801c53, 0x60495ae3c1097fd0},\n      {0xca5e89b18b602368, 0x385bb19cb14bdfc4},\n      {0xfcf62c1dee382c42, 0x46729e03dd9ed7b5},\n      {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d1},\n      {0xc5a05277621be293, 0xc7098b7305241885},\n      { 0xf70867153aa2db38,\n        0xb8cbee4fc66d1ea7 }\n#else\n      {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},\n      {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},\n      {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f},\n      {0x86a8d39ef77164bc, 0xae5dff9c02033198},\n      {0xd98ddaee19068c76, 0x3badd624dd9b0958},\n      {0xafbd2350644eeacf, 0xe5d1929ef90898fb},\n      {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2},\n      {0xe55990879ddcaabd, 0xcc420a6a101d0516},\n      {0xb94470938fa89bce, 0xf808e40e8d5b3e6a},\n      {0x95a8637627989aad, 0xdde7001379a44aa9},\n      {0xf1c90080baf72cb1, 0x5324c68b12dd6339},\n      {0xc350000000000000, 0x0000000000000000},\n      {0x9dc5ada82b70b59d, 0xf020000000000000},\n      {0xfee50b7025c36a08, 0x02f236d04753d5b4},\n      {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86},\n      {0xa6539930bf6bff45, 0x84db8346b786151c},\n      {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2},\n      {0xd910f7ff28069da4, 0x1b2ba1518094da04},\n      {0xaf58416654a6babb, 0x387ac8d1970027b2},\n      {0x8da471a9de737e24, 0x5ceaecfed289e5d2},\n      {0xe4d5e82392a40515, 0x0fabaf3feaa5334a},\n      {0xb8da1662e7b00a17, 0x3d6a751f3b936243},\n      { 0x95527a5202df0ccb,\n        0x0f37801e0c43ebc8 }\n#endif\n    };\n\n#if FMT_USE_FULL_CACHE_DRAGONBOX\n    return pow10_significands[k - float_info<double>::min_k];\n#else\n    static constexpr const uint64_t powers_of_5_64[] = {\n        0x0000000000000001, 0x0000000000000005, 0x0000000000000019,\n        0x000000000000007d, 0x0000000000000271, 0x0000000000000c35,\n        0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1,\n        0x00000000001dcd65, 0x00000000009502f9, 0x0000000002e90edd,\n        0x000000000e8d4a51, 0x0000000048c27395, 0x000000016bcc41e9,\n        0x000000071afd498d, 0x0000002386f26fc1, 0x000000b1a2bc2ec5,\n        0x000003782dace9d9, 0x00001158e460913d, 0x000056bc75e2d631,\n        0x0001b1ae4d6e2ef5, 0x000878678326eac9, 0x002a5a058fc295ed,\n        0x00d3c21bcecceda1, 0x0422ca8b0a00a425, 0x14adf4b7320334b9};\n\n    static constexpr const uint32_t pow10_recovery_errors[] = {\n        0x50001400, 0x54044100, 0x54014555, 0x55954415, 0x54115555, 0x00000001,\n        0x50000000, 0x00104000, 0x54010004, 0x05004001, 0x55555544, 0x41545555,\n        0x54040551, 0x15445545, 0x51555514, 0x10000015, 0x00101100, 0x01100015,\n        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04450514, 0x45414110,\n        0x55555145, 0x50544050, 0x15040155, 0x11054140, 0x50111514, 0x11451454,\n        0x00400541, 0x00000000, 0x55555450, 0x10056551, 0x10054011, 0x55551014,\n        0x69514555, 0x05151109, 0x00155555};\n\n    static const int compression_ratio = 27;\n\n    // Compute base index.\n    int cache_index = (k - float_info<double>::min_k) / compression_ratio;\n    int kb = cache_index * compression_ratio + float_info<double>::min_k;\n    int offset = k - kb;\n\n    // Get base cache.\n    uint128_wrapper base_cache = pow10_significands[cache_index];\n    if (offset == 0) return base_cache;\n\n    // Compute the required amount of bit-shift.\n    int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset;\n    FMT_ASSERT(alpha > 0 && alpha < 64, \"shifting error detected\");\n\n    // Try to recover the real cache.\n    uint64_t pow5 = powers_of_5_64[offset];\n    uint128_wrapper recovered_cache = umul128(base_cache.high(), pow5);\n    uint128_wrapper middle_low =\n        umul128(base_cache.low() - (kb < 0 ? 1u : 0u), pow5);\n\n    recovered_cache += middle_low.high();\n\n    uint64_t high_to_middle = recovered_cache.high() << (64 - alpha);\n    uint64_t middle_to_low = recovered_cache.low() << (64 - alpha);\n\n    recovered_cache =\n        uint128_wrapper{(recovered_cache.low() >> alpha) | high_to_middle,\n                        ((middle_low.low() >> alpha) | middle_to_low)};\n\n    if (kb < 0) recovered_cache += 1;\n\n    // Get error.\n    int error_idx = (k - float_info<double>::min_k) / 16;\n    uint32_t error = (pow10_recovery_errors[error_idx] >>\n                      ((k - float_info<double>::min_k) % 16) * 2) &\n                     0x3;\n\n    // Add the error back.\n    FMT_ASSERT(recovered_cache.low() + error >= recovered_cache.low(), \"\");\n    return {recovered_cache.high(), recovered_cache.low() + error};\n#endif\n  }\n\n  static carrier_uint compute_mul(carrier_uint u,\n                                  const cache_entry_type& cache) FMT_NOEXCEPT {\n    return umul192_upper64(u, cache);\n  }\n\n  static uint32_t compute_delta(cache_entry_type const& cache,\n                                int beta_minus_1) FMT_NOEXCEPT {\n    return static_cast<uint32_t>(cache.high() >> (64 - 1 - beta_minus_1));\n  }\n\n  static bool compute_mul_parity(carrier_uint two_f,\n                                 const cache_entry_type& cache,\n                                 int beta_minus_1) FMT_NOEXCEPT {\n    FMT_ASSERT(beta_minus_1 >= 1, \"\");\n    FMT_ASSERT(beta_minus_1 < 64, \"\");\n\n    return ((umul192_middle64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0;\n  }\n\n  static carrier_uint compute_left_endpoint_for_shorter_interval_case(\n      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {\n    return (cache.high() -\n            (cache.high() >> (float_info<double>::significand_bits + 2))) >>\n           (64 - float_info<double>::significand_bits - 1 - beta_minus_1);\n  }\n\n  static carrier_uint compute_right_endpoint_for_shorter_interval_case(\n      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {\n    return (cache.high() +\n            (cache.high() >> (float_info<double>::significand_bits + 1))) >>\n           (64 - float_info<double>::significand_bits - 1 - beta_minus_1);\n  }\n\n  static carrier_uint compute_round_up_for_shorter_interval_case(\n      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {\n    return ((cache.high() >>\n             (64 - float_info<double>::significand_bits - 2 - beta_minus_1)) +\n            1) /\n           2;\n  }\n};\n\n// Various integer checks\ntemplate <class T>\nbool is_left_endpoint_integer_shorter_interval(int exponent) FMT_NOEXCEPT {\n  return exponent >=\n             float_info<\n                 T>::case_shorter_interval_left_endpoint_lower_threshold &&\n         exponent <=\n             float_info<T>::case_shorter_interval_left_endpoint_upper_threshold;\n}\ntemplate <class T>\nbool is_endpoint_integer(typename float_info<T>::carrier_uint two_f,\n                         int exponent, int minus_k) FMT_NOEXCEPT {\n  if (exponent < float_info<T>::case_fc_pm_half_lower_threshold) return false;\n  // For k >= 0.\n  if (exponent <= float_info<T>::case_fc_pm_half_upper_threshold) return true;\n  // For k < 0.\n  if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false;\n  return divisible_by_power_of_5(two_f, minus_k);\n}\n\ntemplate <class T>\nbool is_center_integer(typename float_info<T>::carrier_uint two_f, int exponent,\n                       int minus_k) FMT_NOEXCEPT {\n  // Exponent for 5 is negative.\n  if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false;\n  if (exponent > float_info<T>::case_fc_upper_threshold)\n    return divisible_by_power_of_5(two_f, minus_k);\n  // Both exponents are nonnegative.\n  if (exponent >= float_info<T>::case_fc_lower_threshold) return true;\n  // Exponent for 2 is negative.\n  return divisible_by_power_of_2(two_f, minus_k - exponent + 1);\n}\n\n// Remove trailing zeros from n and return the number of zeros removed (float)\nFMT_INLINE int remove_trailing_zeros(uint32_t& n) FMT_NOEXCEPT {\n#ifdef FMT_BUILTIN_CTZ\n  int t = FMT_BUILTIN_CTZ(n);\n#else\n  int t = ctz(n);\n#endif\n  if (t > float_info<float>::max_trailing_zeros)\n    t = float_info<float>::max_trailing_zeros;\n\n  const uint32_t mod_inv1 = 0xcccccccd;\n  const uint32_t max_quotient1 = 0x33333333;\n  const uint32_t mod_inv2 = 0xc28f5c29;\n  const uint32_t max_quotient2 = 0x0a3d70a3;\n\n  int s = 0;\n  for (; s < t - 1; s += 2) {\n    if (n * mod_inv2 > max_quotient2) break;\n    n *= mod_inv2;\n  }\n  if (s < t && n * mod_inv1 <= max_quotient1) {\n    n *= mod_inv1;\n    ++s;\n  }\n  n >>= s;\n  return s;\n}\n\n// Removes trailing zeros and returns the number of zeros removed (double)\nFMT_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT {\n#ifdef FMT_BUILTIN_CTZLL\n  int t = FMT_BUILTIN_CTZLL(n);\n#else\n  int t = ctzll(n);\n#endif\n  if (t > float_info<double>::max_trailing_zeros)\n    t = float_info<double>::max_trailing_zeros;\n  // Divide by 10^8 and reduce to 32-bits\n  // Since ret_value.significand <= (2^64 - 1) / 1000 < 10^17,\n  // both of the quotient and the r should fit in 32-bits\n\n  const uint32_t mod_inv1 = 0xcccccccd;\n  const uint32_t max_quotient1 = 0x33333333;\n  const uint64_t mod_inv8 = 0xc767074b22e90e21;\n  const uint64_t max_quotient8 = 0x00002af31dc46118;\n\n  // If the number is divisible by 1'0000'0000, work with the quotient\n  if (t >= 8) {\n    auto quotient_candidate = n * mod_inv8;\n\n    if (quotient_candidate <= max_quotient8) {\n      auto quotient = static_cast<uint32_t>(quotient_candidate >> 8);\n\n      int s = 8;\n      for (; s < t; ++s) {\n        if (quotient * mod_inv1 > max_quotient1) break;\n        quotient *= mod_inv1;\n      }\n      quotient >>= (s - 8);\n      n = quotient;\n      return s;\n    }\n  }\n\n  // Otherwise, work with the remainder\n  auto quotient = static_cast<uint32_t>(n / 100000000);\n  auto remainder = static_cast<uint32_t>(n - 100000000 * quotient);\n\n  if (t == 0 || remainder * mod_inv1 > max_quotient1) {\n    return 0;\n  }\n  remainder *= mod_inv1;\n\n  if (t == 1 || remainder * mod_inv1 > max_quotient1) {\n    n = (remainder >> 1) + quotient * 10000000ull;\n    return 1;\n  }\n  remainder *= mod_inv1;\n\n  if (t == 2 || remainder * mod_inv1 > max_quotient1) {\n    n = (remainder >> 2) + quotient * 1000000ull;\n    return 2;\n  }\n  remainder *= mod_inv1;\n\n  if (t == 3 || remainder * mod_inv1 > max_quotient1) {\n    n = (remainder >> 3) + quotient * 100000ull;\n    return 3;\n  }\n  remainder *= mod_inv1;\n\n  if (t == 4 || remainder * mod_inv1 > max_quotient1) {\n    n = (remainder >> 4) + quotient * 10000ull;\n    return 4;\n  }\n  remainder *= mod_inv1;\n\n  if (t == 5 || remainder * mod_inv1 > max_quotient1) {\n    n = (remainder >> 5) + quotient * 1000ull;\n    return 5;\n  }\n  remainder *= mod_inv1;\n\n  if (t == 6 || remainder * mod_inv1 > max_quotient1) {\n    n = (remainder >> 6) + quotient * 100ull;\n    return 6;\n  }\n  remainder *= mod_inv1;\n\n  n = (remainder >> 7) + quotient * 10ull;\n  return 7;\n}\n\n// The main algorithm for shorter interval case\ntemplate <class T>\nFMT_INLINE decimal_fp<T> shorter_interval_case(int exponent) FMT_NOEXCEPT {\n  decimal_fp<T> ret_value;\n  // Compute k and beta\n  const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent);\n  const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k);\n\n  // Compute xi and zi\n  using cache_entry_type = typename cache_accessor<T>::cache_entry_type;\n  const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k);\n\n  auto xi = cache_accessor<T>::compute_left_endpoint_for_shorter_interval_case(\n      cache, beta_minus_1);\n  auto zi = cache_accessor<T>::compute_right_endpoint_for_shorter_interval_case(\n      cache, beta_minus_1);\n\n  // If the left endpoint is not an integer, increase it\n  if (!is_left_endpoint_integer_shorter_interval<T>(exponent)) ++xi;\n\n  // Try bigger divisor\n  ret_value.significand = zi / 10;\n\n  // If succeed, remove trailing zeros if necessary and return\n  if (ret_value.significand * 10 >= xi) {\n    ret_value.exponent = minus_k + 1;\n    ret_value.exponent += remove_trailing_zeros(ret_value.significand);\n    return ret_value;\n  }\n\n  // Otherwise, compute the round-up of y\n  ret_value.significand =\n      cache_accessor<T>::compute_round_up_for_shorter_interval_case(\n          cache, beta_minus_1);\n  ret_value.exponent = minus_k;\n\n  // When tie occurs, choose one of them according to the rule\n  if (exponent >= float_info<T>::shorter_interval_tie_lower_threshold &&\n      exponent <= float_info<T>::shorter_interval_tie_upper_threshold) {\n    ret_value.significand = ret_value.significand % 2 == 0\n                                ? ret_value.significand\n                                : ret_value.significand - 1;\n  } else if (ret_value.significand < xi) {\n    ++ret_value.significand;\n  }\n  return ret_value;\n}\n\ntemplate <typename T> decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {\n  // Step 1: integer promotion & Schubfach multiplier calculation.\n\n  using carrier_uint = typename float_info<T>::carrier_uint;\n  using cache_entry_type = typename cache_accessor<T>::cache_entry_type;\n  auto br = bit_cast<carrier_uint>(x);\n\n  // Extract significand bits and exponent bits.\n  const carrier_uint significand_mask =\n      (static_cast<carrier_uint>(1) << float_info<T>::significand_bits) - 1;\n  carrier_uint significand = (br & significand_mask);\n  int exponent = static_cast<int>((br & exponent_mask<T>()) >>\n                                  float_info<T>::significand_bits);\n\n  if (exponent != 0) {  // Check if normal.\n    exponent += float_info<T>::exponent_bias - float_info<T>::significand_bits;\n\n    // Shorter interval case; proceed like Schubfach.\n    if (significand == 0) return shorter_interval_case<T>(exponent);\n\n    significand |=\n        (static_cast<carrier_uint>(1) << float_info<T>::significand_bits);\n  } else {\n    // Subnormal case; the interval is always regular.\n    if (significand == 0) return {0, 0};\n    exponent = float_info<T>::min_exponent - float_info<T>::significand_bits;\n  }\n\n  const bool include_left_endpoint = (significand % 2 == 0);\n  const bool include_right_endpoint = include_left_endpoint;\n\n  // Compute k and beta.\n  const int minus_k = floor_log10_pow2(exponent) - float_info<T>::kappa;\n  const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k);\n  const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k);\n\n  // Compute zi and deltai\n  // 10^kappa <= deltai < 10^(kappa + 1)\n  const uint32_t deltai = cache_accessor<T>::compute_delta(cache, beta_minus_1);\n  const carrier_uint two_fc = significand << 1;\n  const carrier_uint two_fr = two_fc | 1;\n  const carrier_uint zi =\n      cache_accessor<T>::compute_mul(two_fr << beta_minus_1, cache);\n\n  // Step 2: Try larger divisor; remove trailing zeros if necessary\n\n  // Using an upper bound on zi, we might be able to optimize the division\n  // better than the compiler; we are computing zi / big_divisor here\n  decimal_fp<T> ret_value;\n  ret_value.significand = divide_by_10_to_kappa_plus_1(zi);\n  uint32_t r = static_cast<uint32_t>(zi - float_info<T>::big_divisor *\n                                              ret_value.significand);\n\n  if (r > deltai) {\n    goto small_divisor_case_label;\n  } else if (r < deltai) {\n    // Exclude the right endpoint if necessary\n    if (r == 0 && !include_right_endpoint &&\n        is_endpoint_integer<T>(two_fr, exponent, minus_k)) {\n      --ret_value.significand;\n      r = float_info<T>::big_divisor;\n      goto small_divisor_case_label;\n    }\n  } else {\n    // r == deltai; compare fractional parts\n    // Check conditions in the order different from the paper\n    // to take advantage of short-circuiting\n    const carrier_uint two_fl = two_fc - 1;\n    if ((!include_left_endpoint ||\n         !is_endpoint_integer<T>(two_fl, exponent, minus_k)) &&\n        !cache_accessor<T>::compute_mul_parity(two_fl, cache, beta_minus_1)) {\n      goto small_divisor_case_label;\n    }\n  }\n  ret_value.exponent = minus_k + float_info<T>::kappa + 1;\n\n  // We may need to remove trailing zeros\n  ret_value.exponent += remove_trailing_zeros(ret_value.significand);\n  return ret_value;\n\n  // Step 3: Find the significand with the smaller divisor\n\nsmall_divisor_case_label:\n  ret_value.significand *= 10;\n  ret_value.exponent = minus_k + float_info<T>::kappa;\n\n  const uint32_t mask = (1u << float_info<T>::kappa) - 1;\n  auto dist = r - (deltai / 2) + (float_info<T>::small_divisor / 2);\n\n  // Is dist divisible by 2^kappa?\n  if ((dist & mask) == 0) {\n    const bool approx_y_parity =\n        ((dist ^ (float_info<T>::small_divisor / 2)) & 1) != 0;\n    dist >>= float_info<T>::kappa;\n\n    // Is dist divisible by 5^kappa?\n    if (check_divisibility_and_divide_by_pow5<float_info<T>::kappa>(dist)) {\n      ret_value.significand += dist;\n\n      // Check z^(f) >= epsilon^(f)\n      // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,\n      // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f)\n      // Since there are only 2 possibilities, we only need to care about the\n      // parity. Also, zi and r should have the same parity since the divisor\n      // is an even number\n      if (cache_accessor<T>::compute_mul_parity(two_fc, cache, beta_minus_1) !=\n          approx_y_parity) {\n        --ret_value.significand;\n      } else {\n        // If z^(f) >= epsilon^(f), we might have a tie\n        // when z^(f) == epsilon^(f), or equivalently, when y is an integer\n        if (is_center_integer<T>(two_fc, exponent, minus_k)) {\n          ret_value.significand = ret_value.significand % 2 == 0\n                                      ? ret_value.significand\n                                      : ret_value.significand - 1;\n        }\n      }\n    }\n    // Is dist not divisible by 5^kappa?\n    else {\n      ret_value.significand += dist;\n    }\n  }\n  // Is dist not divisible by 2^kappa?\n  else {\n    // Since we know dist is small, we might be able to optimize the division\n    // better than the compiler; we are computing dist / small_divisor here\n    ret_value.significand +=\n        small_division_by_pow10<float_info<T>::kappa>(dist);\n  }\n  return ret_value;\n}\n}  // namespace dragonbox\n\n// Formats a floating-point number using a variation of the Fixed-Precision\n// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:\n// https://fmt.dev/papers/p372-steele.pdf.\nFMT_CONSTEXPR20 inline void format_dragon(fp value, bool is_predecessor_closer,\n                                          int num_digits, buffer<char>& buf,\n                                          int& exp10) {\n  bigint numerator;    // 2 * R in (FPP)^2.\n  bigint denominator;  // 2 * S in (FPP)^2.\n  // lower and upper are differences between value and corresponding boundaries.\n  bigint lower;             // (M^- in (FPP)^2).\n  bigint upper_store;       // upper's value if different from lower.\n  bigint* upper = nullptr;  // (M^+ in (FPP)^2).\n  // Shift numerator and denominator by an extra bit or two (if lower boundary\n  // is closer) to make lower and upper integers. This eliminates multiplication\n  // by 2 during later computations.\n  int shift = is_predecessor_closer ? 2 : 1;\n  uint64_t significand = value.f << shift;\n  if (value.e >= 0) {\n    numerator.assign(significand);\n    numerator <<= value.e;\n    lower.assign(1);\n    lower <<= value.e;\n    if (shift != 1) {\n      upper_store.assign(1);\n      upper_store <<= value.e + 1;\n      upper = &upper_store;\n    }\n    denominator.assign_pow10(exp10);\n    denominator <<= shift;\n  } else if (exp10 < 0) {\n    numerator.assign_pow10(-exp10);\n    lower.assign(numerator);\n    if (shift != 1) {\n      upper_store.assign(numerator);\n      upper_store <<= 1;\n      upper = &upper_store;\n    }\n    numerator *= significand;\n    denominator.assign(1);\n    denominator <<= shift - value.e;\n  } else {\n    numerator.assign(significand);\n    denominator.assign_pow10(exp10);\n    denominator <<= shift - value.e;\n    lower.assign(1);\n    if (shift != 1) {\n      upper_store.assign(1ULL << 1);\n      upper = &upper_store;\n    }\n  }\n  // Invariant: value == (numerator / denominator) * pow(10, exp10).\n  if (num_digits < 0) {\n    // Generate the shortest representation.\n    if (!upper) upper = &lower;\n    bool even = (value.f & 1) == 0;\n    num_digits = 0;\n    char* data = buf.data();\n    for (;;) {\n      int digit = numerator.divmod_assign(denominator);\n      bool low = compare(numerator, lower) - even < 0;  // numerator <[=] lower.\n      // numerator + upper >[=] pow10:\n      bool high = add_compare(numerator, *upper, denominator) + even > 0;\n      data[num_digits++] = static_cast<char>('0' + digit);\n      if (low || high) {\n        if (!low) {\n          ++data[num_digits - 1];\n        } else if (high) {\n          int result = add_compare(numerator, numerator, denominator);\n          // Round half to even.\n          if (result > 0 || (result == 0 && (digit % 2) != 0))\n            ++data[num_digits - 1];\n        }\n        buf.try_resize(to_unsigned(num_digits));\n        exp10 -= num_digits - 1;\n        return;\n      }\n      numerator *= 10;\n      lower *= 10;\n      if (upper != &lower) *upper *= 10;\n    }\n  }\n  // Generate the given number of digits.\n  exp10 -= num_digits - 1;\n  if (num_digits == 0) {\n    denominator *= 10;\n    auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';\n    buf.push_back(digit);\n    return;\n  }\n  buf.try_resize(to_unsigned(num_digits));\n  for (int i = 0; i < num_digits - 1; ++i) {\n    int digit = numerator.divmod_assign(denominator);\n    buf[i] = static_cast<char>('0' + digit);\n    numerator *= 10;\n  }\n  int digit = numerator.divmod_assign(denominator);\n  auto result = add_compare(numerator, numerator, denominator);\n  if (result > 0 || (result == 0 && (digit % 2) != 0)) {\n    if (digit == 9) {\n      const auto overflow = '0' + 10;\n      buf[num_digits - 1] = overflow;\n      // Propagate the carry.\n      for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {\n        buf[i] = '0';\n        ++buf[i - 1];\n      }\n      if (buf[0] == overflow) {\n        buf[0] = '1';\n        ++exp10;\n      }\n      return;\n    }\n    ++digit;\n  }\n  buf[num_digits - 1] = static_cast<char>('0' + digit);\n}\n\ntemplate <typename Float>\nFMT_HEADER_ONLY_CONSTEXPR20 int format_float(Float value, int precision,\n                                             float_specs specs,\n                                             buffer<char>& buf) {\n  // float is passed as double to reduce the number of instantiations.\n  static_assert(!std::is_same<Float, float>::value, \"\");\n  FMT_ASSERT(value >= 0, \"value is negative\");\n\n  const bool fixed = specs.format == float_format::fixed;\n  if (value <= 0) {  // <= instead of == to silence a warning.\n    if (precision <= 0 || !fixed) {\n      buf.push_back('0');\n      return 0;\n    }\n    buf.try_resize(to_unsigned(precision));\n    fill_n(buf.data(), precision, '0');\n    return -precision;\n  }\n\n  if (specs.fallback) return snprintf_float(value, precision, specs, buf);\n\n  if (!is_constant_evaluated() && precision < 0) {\n    // Use Dragonbox for the shortest format.\n    if (specs.binary32) {\n      auto dec = dragonbox::to_decimal(static_cast<float>(value));\n      write<char>(buffer_appender<char>(buf), dec.significand);\n      return dec.exponent;\n    }\n    auto dec = dragonbox::to_decimal(static_cast<double>(value));\n    write<char>(buffer_appender<char>(buf), dec.significand);\n    return dec.exponent;\n  }\n\n  int exp = 0;\n  bool use_dragon = true;\n  if (is_fast_float<Float>()) {\n    // Use Grisu + Dragon4 for the given precision:\n    // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf.\n    const int min_exp = -60;  // alpha in Grisu.\n    int cached_exp10 = 0;     // K in Grisu.\n    fp normalized = normalize(fp(value));\n    const auto cached_pow = get_cached_power(\n        min_exp - (normalized.e + fp::num_significand_bits), cached_exp10);\n    normalized = normalized * cached_pow;\n    gen_digits_handler handler{buf.data(), 0, precision, -cached_exp10, fixed};\n    if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error &&\n        !is_constant_evaluated()) {\n      exp += handler.exp10;\n      buf.try_resize(to_unsigned(handler.size));\n      use_dragon = false;\n    } else {\n      exp += handler.size - cached_exp10 - 1;\n      precision = handler.precision;\n    }\n  }\n  if (use_dragon) {\n    auto f = fp();\n    bool is_predecessor_closer =\n        specs.binary32 ? f.assign(static_cast<float>(value)) : f.assign(value);\n    // Limit precision to the maximum possible number of significant digits in\n    // an IEEE754 double because we don't need to generate zeros.\n    const int max_double_digits = 767;\n    if (precision > max_double_digits) precision = max_double_digits;\n    format_dragon(f, is_predecessor_closer, precision, buf, exp);\n  }\n  if (!fixed && !specs.showpoint) {\n    // Remove trailing zeros.\n    auto num_digits = buf.size();\n    while (num_digits > 0 && buf[num_digits - 1] == '0') {\n      --num_digits;\n      ++exp;\n    }\n    buf.try_resize(num_digits);\n  }\n  return exp;\n}\n\ntemplate <typename T>\nint snprintf_float(T value, int precision, float_specs specs,\n                   buffer<char>& buf) {\n  // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.\n  FMT_ASSERT(buf.capacity() > buf.size(), \"empty buffer\");\n  static_assert(!std::is_same<T, float>::value, \"\");\n\n  // Subtract 1 to account for the difference in precision since we use %e for\n  // both general and exponent format.\n  if (specs.format == float_format::general ||\n      specs.format == float_format::exp)\n    precision = (precision >= 0 ? precision : 6) - 1;\n\n  // Build the format string.\n  enum { max_format_size = 7 };  // The longest format is \"%#.*Le\".\n  char format[max_format_size];\n  char* format_ptr = format;\n  *format_ptr++ = '%';\n  if (specs.showpoint && specs.format == float_format::hex) *format_ptr++ = '#';\n  if (precision >= 0) {\n    *format_ptr++ = '.';\n    *format_ptr++ = '*';\n  }\n  if (std::is_same<T, long double>()) *format_ptr++ = 'L';\n  *format_ptr++ = specs.format != float_format::hex\n                      ? (specs.format == float_format::fixed ? 'f' : 'e')\n                      : (specs.upper ? 'A' : 'a');\n  *format_ptr = '\\0';\n\n  // Format using snprintf.\n  auto offset = buf.size();\n  for (;;) {\n    auto begin = buf.data() + offset;\n    auto capacity = buf.capacity() - offset;\n#ifdef FMT_FUZZ\n    if (precision > 100000)\n      throw std::runtime_error(\n          \"fuzz mode - avoid large allocation inside snprintf\");\n#endif\n    // Suppress the warning about a nonliteral format string.\n    // Cannot use auto because of a bug in MinGW (#1532).\n    int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;\n    int result = precision >= 0\n                     ? snprintf_ptr(begin, capacity, format, precision, value)\n                     : snprintf_ptr(begin, capacity, format, value);\n    if (result < 0) {\n      // The buffer will grow exponentially.\n      buf.try_reserve(buf.capacity() + 1);\n      continue;\n    }\n    auto size = to_unsigned(result);\n    // Size equal to capacity means that the last character was truncated.\n    if (size >= capacity) {\n      buf.try_reserve(size + offset + 1);  // Add 1 for the terminating '\\0'.\n      continue;\n    }\n    auto is_digit = [](char c) { return c >= '0' && c <= '9'; };\n    if (specs.format == float_format::fixed) {\n      if (precision == 0) {\n        buf.try_resize(size);\n        return 0;\n      }\n      // Find and remove the decimal point.\n      auto end = begin + size, p = end;\n      do {\n        --p;\n      } while (is_digit(*p));\n      int fraction_size = static_cast<int>(end - p - 1);\n      std::memmove(p, p + 1, to_unsigned(fraction_size));\n      buf.try_resize(size - 1);\n      return -fraction_size;\n    }\n    if (specs.format == float_format::hex) {\n      buf.try_resize(size + offset);\n      return 0;\n    }\n    // Find and parse the exponent.\n    auto end = begin + size, exp_pos = end;\n    do {\n      --exp_pos;\n    } while (*exp_pos != 'e');\n    char sign = exp_pos[1];\n    FMT_ASSERT(sign == '+' || sign == '-', \"\");\n    int exp = 0;\n    auto p = exp_pos + 2;  // Skip 'e' and sign.\n    do {\n      FMT_ASSERT(is_digit(*p), \"\");\n      exp = exp * 10 + (*p++ - '0');\n    } while (p != end);\n    if (sign == '-') exp = -exp;\n    int fraction_size = 0;\n    if (exp_pos != begin + 1) {\n      // Remove trailing zeros.\n      auto fraction_end = exp_pos - 1;\n      while (*fraction_end == '0') --fraction_end;\n      // Move the fractional part left to get rid of the decimal point.\n      fraction_size = static_cast<int>(fraction_end - begin - 1);\n      std::memmove(begin + 1, begin + 2, to_unsigned(fraction_size));\n    }\n    buf.try_resize(to_unsigned(fraction_size) + offset + 1);\n    return exp - fraction_size;\n  }\n}\n}  // namespace detail\n\ntemplate <> struct formatter<detail::bigint> {\n  FMT_CONSTEXPR format_parse_context::iterator parse(\n      format_parse_context& ctx) {\n    return ctx.begin();\n  }\n\n  format_context::iterator format(const detail::bigint& n,\n                                  format_context& ctx) {\n    auto out = ctx.out();\n    bool first = true;\n    for (auto i = n.bigits_.size(); i > 0; --i) {\n      auto value = n.bigits_[i - 1u];\n      if (first) {\n        out = format_to(out, FMT_STRING(\"{:x}\"), value);\n        first = false;\n        continue;\n      }\n      out = format_to(out, FMT_STRING(\"{:08x}\"), value);\n    }\n    if (n.exp_ > 0)\n      out = format_to(out, FMT_STRING(\"p{}\"),\n                      n.exp_ * detail::bigint::bigit_bits);\n    return out;\n  }\n};\n\nFMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {\n  for_each_codepoint(s, [this](uint32_t cp, string_view) {\n    if (cp == invalid_code_point) FMT_THROW(std::runtime_error(\"invalid utf8\"));\n    if (cp <= 0xFFFF) {\n      buffer_.push_back(static_cast<wchar_t>(cp));\n    } else {\n      cp -= 0x10000;\n      buffer_.push_back(static_cast<wchar_t>(0xD800 + (cp >> 10)));\n      buffer_.push_back(static_cast<wchar_t>(0xDC00 + (cp & 0x3FF)));\n    }\n    return true;\n  });\n  buffer_.push_back(0);\n}\n\nFMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,\n                                  const char* message) FMT_NOEXCEPT {\n  FMT_TRY {\n    auto ec = std::error_code(error_code, std::generic_category());\n    write(std::back_inserter(out), std::system_error(ec, message).what());\n    return;\n  }\n  FMT_CATCH(...) {}\n  format_error_code(out, error_code, message);\n}\n\nFMT_FUNC void report_system_error(int error_code,\n                                  const char* message) FMT_NOEXCEPT {\n  report_error(format_system_error, error_code, message);\n}\n\n// DEPRECATED!\n// This function is defined here and not inline for ABI compatiblity.\nFMT_FUNC void detail::error_handler::on_error(const char* message) {\n  throw_format_error(message);\n}\n\nFMT_FUNC std::string vformat(string_view fmt, format_args args) {\n  // Don't optimize the \"{}\" case to keep the binary size small and because it\n  // can be better optimized in fmt::format anyway.\n  auto buffer = memory_buffer();\n  detail::vformat_to(buffer, fmt, args);\n  return to_string(buffer);\n}\n\n#ifdef _WIN32\nnamespace detail {\nusing dword = conditional_t<sizeof(long) == 4, unsigned long, unsigned>;\nextern \"C\" __declspec(dllimport) int __stdcall WriteConsoleW(  //\n    void*, const void*, dword, dword*, void*);\n}  // namespace detail\n#endif\n\nnamespace detail {\nFMT_FUNC void print(std::FILE* f, string_view text) {\n#ifdef _WIN32\n  auto fd = _fileno(f);\n  if (_isatty(fd)) {\n    detail::utf8_to_utf16 u16(string_view(text.data(), text.size()));\n    auto written = detail::dword();\n    if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)),\n                              u16.c_str(), static_cast<uint32_t>(u16.size()),\n                              &written, nullptr)) {\n      return;\n    }\n    // Fallback to fwrite on failure. It can happen if the output has been\n    // redirected to NUL.\n  }\n#endif\n  detail::fwrite_fully(text.data(), 1, text.size(), f);\n}\n}  // namespace detail\n\nFMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {\n  memory_buffer buffer;\n  detail::vformat_to(buffer, format_str, args);\n  detail::print(f, {buffer.data(), buffer.size()});\n}\n\n#ifdef _WIN32\n// Print assuming legacy (non-Unicode) encoding.\nFMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str,\n                                      format_args args) {\n  memory_buffer buffer;\n  detail::vformat_to(buffer, format_str,\n                     basic_format_args<buffer_context<char>>(args));\n  fwrite_fully(buffer.data(), 1, buffer.size(), f);\n}\n#endif\n\nFMT_FUNC void vprint(string_view format_str, format_args args) {\n  vprint(stdout, format_str, args);\n}\n\nFMT_END_NAMESPACE\n\n#endif  // FMT_FORMAT_INL_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/format.h",
    "content": "/*\n Formatting library for C++\n\n Copyright (c) 2012 - present, Victor Zverovich\n\n Permission is hereby granted, free of charge, to any person obtaining\n a copy of this software and associated documentation files (the\n \"Software\"), to deal in the Software without restriction, including\n without limitation the rights to use, copy, modify, merge, publish,\n distribute, sublicense, and/or sell copies of the Software, and to\n permit persons to whom the Software is furnished to do so, subject to\n the following conditions:\n\n The above copyright notice and this permission notice shall be\n included in all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n --- Optional exception to the license ---\n\n As an exception, if, as a result of your compiling your source code, portions\n of this Software are embedded into a machine-executable object form of such\n source code, you may redistribute such embedded portions in such object form\n without including the above copyright and permission notices.\n */\n\n#ifndef FMT_FORMAT_H_\n#define FMT_FORMAT_H_\n\n#include <cmath>         // std::signbit\n#include <cstdint>       // uint32_t\n#include <limits>        // std::numeric_limits\n#include <memory>        // std::uninitialized_copy\n#include <stdexcept>     // std::runtime_error\n#include <system_error>  // std::system_error\n#include <utility>       // std::swap\n\n#ifdef __cpp_lib_bit_cast\n#  include <bit>  // std::bitcast\n#endif\n\n#include \"core.h\"\n\n#if FMT_GCC_VERSION\n#  define FMT_GCC_VISIBILITY_HIDDEN __attribute__((visibility(\"hidden\")))\n#else\n#  define FMT_GCC_VISIBILITY_HIDDEN\n#endif\n\n#ifdef __NVCC__\n#  define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__)\n#else\n#  define FMT_CUDA_VERSION 0\n#endif\n\n#ifdef __has_builtin\n#  define FMT_HAS_BUILTIN(x) __has_builtin(x)\n#else\n#  define FMT_HAS_BUILTIN(x) 0\n#endif\n\n#if FMT_GCC_VERSION || FMT_CLANG_VERSION\n#  define FMT_NOINLINE __attribute__((noinline))\n#else\n#  define FMT_NOINLINE\n#endif\n\n#if FMT_MSC_VER\n#  define FMT_MSC_DEFAULT = default\n#else\n#  define FMT_MSC_DEFAULT\n#endif\n\n#ifndef FMT_THROW\n#  if FMT_EXCEPTIONS\n#    if FMT_MSC_VER || FMT_NVCC\nFMT_BEGIN_NAMESPACE\nnamespace detail {\ntemplate <typename Exception> inline void do_throw(const Exception& x) {\n  // Silence unreachable code warnings in MSVC and NVCC because these\n  // are nearly impossible to fix in a generic code.\n  volatile bool b = true;\n  if (b) throw x;\n}\n}  // namespace detail\nFMT_END_NAMESPACE\n#      define FMT_THROW(x) detail::do_throw(x)\n#    else\n#      define FMT_THROW(x) throw x\n#    endif\n#  else\n#    define FMT_THROW(x)               \\\n      do {                             \\\n        FMT_ASSERT(false, (x).what()); \\\n      } while (false)\n#  endif\n#endif\n\n#if FMT_EXCEPTIONS\n#  define FMT_TRY try\n#  define FMT_CATCH(x) catch (x)\n#else\n#  define FMT_TRY if (true)\n#  define FMT_CATCH(x) if (false)\n#endif\n\n#ifndef FMT_MAYBE_UNUSED\n#  if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)\n#    define FMT_MAYBE_UNUSED [[maybe_unused]]\n#  else\n#    define FMT_MAYBE_UNUSED\n#  endif\n#endif\n\n// Workaround broken [[deprecated]] in the Intel, PGI and NVCC compilers.\n#if FMT_ICC_VERSION || defined(__PGI) || FMT_NVCC\n#  define FMT_DEPRECATED_ALIAS\n#else\n#  define FMT_DEPRECATED_ALIAS FMT_DEPRECATED\n#endif\n\n#ifndef FMT_USE_USER_DEFINED_LITERALS\n// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.\n#  if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \\\n       FMT_MSC_VER >= 1900) &&                                         \\\n      (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)\n#    define FMT_USE_USER_DEFINED_LITERALS 1\n#  else\n#    define FMT_USE_USER_DEFINED_LITERALS 0\n#  endif\n#endif\n\n// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of\n// integer formatter template instantiations to just one by only using the\n// largest integer type. This results in a reduction in binary size but will\n// cause a decrease in integer formatting performance.\n#if !defined(FMT_REDUCE_INT_INSTANTIATIONS)\n#  define FMT_REDUCE_INT_INSTANTIATIONS 0\n#endif\n\n// __builtin_clz is broken in clang with Microsoft CodeGen:\n// https://github.com/fmtlib/fmt/issues/519.\n#if !FMT_MSC_VER\n#  if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION\n#    define FMT_BUILTIN_CLZ(n) __builtin_clz(n)\n#  endif\n#  if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION\n#    define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)\n#  endif\n#endif\n\n// __builtin_ctz is broken in Intel Compiler Classic on Windows:\n// https://github.com/fmtlib/fmt/issues/2510.\n#ifndef __ICL\n#  if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION\n#    define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)\n#  endif\n#  if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || FMT_ICC_VERSION\n#    define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)\n#  endif\n#endif\n\n#if FMT_MSC_VER\n#  include <intrin.h>  // _BitScanReverse[64], _BitScanForward[64], _umul128\n#endif\n\n// Some compilers masquerade as both MSVC and GCC-likes or otherwise support\n// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the\n// MSVC intrinsics if the clz and clzll builtins are not available.\n#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(FMT_BUILTIN_CTZLL)\nFMT_BEGIN_NAMESPACE\nnamespace detail {\n// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.\n#  if !defined(__clang__)\n#    pragma intrinsic(_BitScanForward)\n#    pragma intrinsic(_BitScanReverse)\n#    if defined(_WIN64)\n#      pragma intrinsic(_BitScanForward64)\n#      pragma intrinsic(_BitScanReverse64)\n#    endif\n#  endif\n\ninline auto clz(uint32_t x) -> int {\n  unsigned long r = 0;\n  _BitScanReverse(&r, x);\n  FMT_ASSERT(x != 0, \"\");\n  // Static analysis complains about using uninitialized data\n  // \"r\", but the only way that can happen is if \"x\" is 0,\n  // which the callers guarantee to not happen.\n  FMT_MSC_WARNING(suppress : 6102)\n  return 31 ^ static_cast<int>(r);\n}\n#  define FMT_BUILTIN_CLZ(n) detail::clz(n)\n\ninline auto clzll(uint64_t x) -> int {\n  unsigned long r = 0;\n#  ifdef _WIN64\n  _BitScanReverse64(&r, x);\n#  else\n  // Scan the high 32 bits.\n  if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) return 63 ^ (r + 32);\n  // Scan the low 32 bits.\n  _BitScanReverse(&r, static_cast<uint32_t>(x));\n#  endif\n  FMT_ASSERT(x != 0, \"\");\n  FMT_MSC_WARNING(suppress : 6102)  // Suppress a bogus static analysis warning.\n  return 63 ^ static_cast<int>(r);\n}\n#  define FMT_BUILTIN_CLZLL(n) detail::clzll(n)\n\ninline auto ctz(uint32_t x) -> int {\n  unsigned long r = 0;\n  _BitScanForward(&r, x);\n  FMT_ASSERT(x != 0, \"\");\n  FMT_MSC_WARNING(suppress : 6102)  // Suppress a bogus static analysis warning.\n  return static_cast<int>(r);\n}\n#  define FMT_BUILTIN_CTZ(n) detail::ctz(n)\n\ninline auto ctzll(uint64_t x) -> int {\n  unsigned long r = 0;\n  FMT_ASSERT(x != 0, \"\");\n  FMT_MSC_WARNING(suppress : 6102)  // Suppress a bogus static analysis warning.\n#  ifdef _WIN64\n  _BitScanForward64(&r, x);\n#  else\n  // Scan the low 32 bits.\n  if (_BitScanForward(&r, static_cast<uint32_t>(x))) return static_cast<int>(r);\n  // Scan the high 32 bits.\n  _BitScanForward(&r, static_cast<uint32_t>(x >> 32));\n  r += 32;\n#  endif\n  return static_cast<int>(r);\n}\n#  define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)\n}  // namespace detail\nFMT_END_NAMESPACE\n#endif\n\n#ifdef FMT_HEADER_ONLY\n#  define FMT_HEADER_ONLY_CONSTEXPR20 FMT_CONSTEXPR20\n#else\n#  define FMT_HEADER_ONLY_CONSTEXPR20\n#endif\n\nFMT_BEGIN_NAMESPACE\nnamespace detail {\n\ntemplate <typename Streambuf> class formatbuf : public Streambuf {\n private:\n  using char_type = typename Streambuf::char_type;\n  using streamsize = decltype(std::declval<Streambuf>().sputn(nullptr, 0));\n  using int_type = typename Streambuf::int_type;\n  using traits_type = typename Streambuf::traits_type;\n\n  buffer<char_type>& buffer_;\n\n public:\n  explicit formatbuf(buffer<char_type>& buf) : buffer_(buf) {}\n\n protected:\n  // The put area is always empty. This makes the implementation simpler and has\n  // the advantage that the streambuf and the buffer are always in sync and\n  // sputc never writes into uninitialized memory. A disadvantage is that each\n  // call to sputc always results in a (virtual) call to overflow. There is no\n  // disadvantage here for sputn since this always results in a call to xsputn.\n\n  auto overflow(int_type ch) -> int_type override {\n    if (!traits_type::eq_int_type(ch, traits_type::eof()))\n      buffer_.push_back(static_cast<char_type>(ch));\n    return ch;\n  }\n\n  auto xsputn(const char_type* s, streamsize count) -> streamsize override {\n    buffer_.append(s, s + count);\n    return count;\n  }\n};\n\n// Implementation of std::bit_cast for pre-C++20.\ntemplate <typename To, typename From>\nFMT_CONSTEXPR20 auto bit_cast(const From& from) -> To {\n  static_assert(sizeof(To) == sizeof(From), \"size mismatch\");\n#ifdef __cpp_lib_bit_cast\n  if (is_constant_evaluated()) return std::bit_cast<To>(from);\n#endif\n  auto to = To();\n  std::memcpy(&to, &from, sizeof(to));\n  return to;\n}\n\ninline auto is_big_endian() -> bool {\n#ifdef _WIN32\n  return false;\n#elif defined(__BIG_ENDIAN__)\n  return true;\n#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)\n  return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;\n#else\n  struct bytes {\n    char data[sizeof(int)];\n  };\n  return bit_cast<bytes>(1).data[0] == 0;\n#endif\n}\n\n// A fallback implementation of uintptr_t for systems that lack it.\nstruct fallback_uintptr {\n  unsigned char value[sizeof(void*)];\n\n  fallback_uintptr() = default;\n  explicit fallback_uintptr(const void* p) {\n    *this = bit_cast<fallback_uintptr>(p);\n    if (const_check(is_big_endian())) {\n      for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)\n        std::swap(value[i], value[j]);\n    }\n  }\n};\n#ifdef UINTPTR_MAX\nusing uintptr_t = ::uintptr_t;\ninline auto to_uintptr(const void* p) -> uintptr_t {\n  return bit_cast<uintptr_t>(p);\n}\n#else\nusing uintptr_t = fallback_uintptr;\ninline auto to_uintptr(const void* p) -> fallback_uintptr {\n  return fallback_uintptr(p);\n}\n#endif\n\n// Returns the largest possible value for type T. Same as\n// std::numeric_limits<T>::max() but shorter and not affected by the max macro.\ntemplate <typename T> constexpr auto max_value() -> T {\n  return (std::numeric_limits<T>::max)();\n}\ntemplate <typename T> constexpr auto num_bits() -> int {\n  return std::numeric_limits<T>::digits;\n}\n// std::numeric_limits<T>::digits may return 0 for 128-bit ints.\ntemplate <> constexpr auto num_bits<int128_t>() -> int { return 128; }\ntemplate <> constexpr auto num_bits<uint128_t>() -> int { return 128; }\ntemplate <> constexpr auto num_bits<fallback_uintptr>() -> int {\n  return static_cast<int>(sizeof(void*) *\n                          std::numeric_limits<unsigned char>::digits);\n}\n\nFMT_INLINE void assume(bool condition) {\n  (void)condition;\n#if FMT_HAS_BUILTIN(__builtin_assume)\n  __builtin_assume(condition);\n#endif\n}\n\n// An approximation of iterator_t for pre-C++20 systems.\ntemplate <typename T>\nusing iterator_t = decltype(std::begin(std::declval<T&>()));\ntemplate <typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));\n\n// A workaround for std::string not having mutable data() until C++17.\ntemplate <typename Char>\ninline auto get_data(std::basic_string<Char>& s) -> Char* {\n  return &s[0];\n}\ntemplate <typename Container>\ninline auto get_data(Container& c) -> typename Container::value_type* {\n  return c.data();\n}\n\n#if defined(_SECURE_SCL) && _SECURE_SCL\n// Make a checked iterator to avoid MSVC warnings.\ntemplate <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;\ntemplate <typename T>\nconstexpr auto make_checked(T* p, size_t size) -> checked_ptr<T> {\n  return {p, size};\n}\n#else\ntemplate <typename T> using checked_ptr = T*;\ntemplate <typename T> constexpr auto make_checked(T* p, size_t) -> T* {\n  return p;\n}\n#endif\n\n// Attempts to reserve space for n extra characters in the output range.\n// Returns a pointer to the reserved range or a reference to it.\ntemplate <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>\n#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION\n__attribute__((no_sanitize(\"undefined\")))\n#endif\ninline auto\nreserve(std::back_insert_iterator<Container> it, size_t n)\n    -> checked_ptr<typename Container::value_type> {\n  Container& c = get_container(it);\n  size_t size = c.size();\n  c.resize(size + n);\n  return make_checked(get_data(c) + size, n);\n}\n\ntemplate <typename T>\ninline auto reserve(buffer_appender<T> it, size_t n) -> buffer_appender<T> {\n  buffer<T>& buf = get_container(it);\n  buf.try_reserve(buf.size() + n);\n  return it;\n}\n\ntemplate <typename Iterator>\nconstexpr auto reserve(Iterator& it, size_t) -> Iterator& {\n  return it;\n}\n\ntemplate <typename OutputIt>\nusing reserve_iterator =\n    remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;\n\ntemplate <typename T, typename OutputIt>\nconstexpr auto to_pointer(OutputIt, size_t) -> T* {\n  return nullptr;\n}\ntemplate <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* {\n  buffer<T>& buf = get_container(it);\n  auto size = buf.size();\n  if (buf.capacity() < size + n) return nullptr;\n  buf.try_resize(size + n);\n  return buf.data() + size;\n}\n\ntemplate <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>\ninline auto base_iterator(std::back_insert_iterator<Container>& it,\n                          checked_ptr<typename Container::value_type>)\n    -> std::back_insert_iterator<Container> {\n  return it;\n}\n\ntemplate <typename Iterator>\nconstexpr auto base_iterator(Iterator, Iterator it) -> Iterator {\n  return it;\n}\n\n// <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n\n// instead (#1998).\ntemplate <typename OutputIt, typename Size, typename T>\nFMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value)\n    -> OutputIt {\n  for (Size i = 0; i < count; ++i) *out++ = value;\n  return out;\n}\ntemplate <typename T, typename Size>\nFMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {\n  if (is_constant_evaluated()) {\n    return fill_n<T*, Size, T>(out, count, value);\n  }\n  std::memset(out, value, to_unsigned(count));\n  return out + count;\n}\n\n#ifdef __cpp_char8_t\nusing char8_type = char8_t;\n#else\nenum char8_type : unsigned char {};\n#endif\n\ntemplate <typename OutChar, typename InputIt, typename OutputIt>\nFMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end,\n                                                  OutputIt out) -> OutputIt {\n  return copy_str<OutChar>(begin, end, out);\n}\n\n// A public domain branchless UTF-8 decoder by Christopher Wellons:\n// https://github.com/skeeto/branchless-utf8\n/* Decode the next character, c, from s, reporting errors in e.\n *\n * Since this is a branchless decoder, four bytes will be read from the\n * buffer regardless of the actual length of the next character. This\n * means the buffer _must_ have at least three bytes of zero padding\n * following the end of the data stream.\n *\n * Errors are reported in e, which will be non-zero if the parsed\n * character was somehow invalid: invalid byte sequence, non-canonical\n * encoding, or a surrogate half.\n *\n * The function returns a pointer to the next character. When an error\n * occurs, this pointer will be a guess that depends on the particular\n * error, but it will always advance at least one byte.\n */\nFMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e)\n    -> const char* {\n  constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};\n  constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536};\n  constexpr const int shiftc[] = {0, 18, 12, 6, 0};\n  constexpr const int shifte[] = {0, 6, 4, 2, 0};\n\n  int len = code_point_length(s);\n  const char* next = s + len;\n\n  // Assume a four-byte character and load four bytes. Unused bits are\n  // shifted out.\n  *c = uint32_t(s[0] & masks[len]) << 18;\n  *c |= uint32_t(s[1] & 0x3f) << 12;\n  *c |= uint32_t(s[2] & 0x3f) << 6;\n  *c |= uint32_t(s[3] & 0x3f) << 0;\n  *c >>= shiftc[len];\n\n  // Accumulate the various error conditions.\n  using uchar = unsigned char;\n  *e = (*c < mins[len]) << 6;       // non-canonical encoding\n  *e |= ((*c >> 11) == 0x1b) << 7;  // surrogate half?\n  *e |= (*c > 0x10FFFF) << 8;       // out of range?\n  *e |= (uchar(s[1]) & 0xc0) >> 2;\n  *e |= (uchar(s[2]) & 0xc0) >> 4;\n  *e |= uchar(s[3]) >> 6;\n  *e ^= 0x2a;  // top two bits of each tail byte correct?\n  *e >>= shifte[len];\n\n  return next;\n}\n\nconstexpr uint32_t invalid_code_point = ~uint32_t();\n\n// Invokes f(cp, sv) for every code point cp in s with sv being the string view\n// corresponding to the code point. cp is invalid_code_point on error.\ntemplate <typename F>\nFMT_CONSTEXPR void for_each_codepoint(string_view s, F f) {\n  auto decode = [f](const char* buf_ptr, const char* ptr) {\n    auto cp = uint32_t();\n    auto error = 0;\n    auto end = utf8_decode(buf_ptr, &cp, &error);\n    bool result = f(error ? invalid_code_point : cp,\n                    string_view(ptr, to_unsigned(end - buf_ptr)));\n    return result ? end : nullptr;\n  };\n  auto p = s.data();\n  const size_t block_size = 4;  // utf8_decode always reads blocks of 4 chars.\n  if (s.size() >= block_size) {\n    for (auto end = p + s.size() - block_size + 1; p < end;) {\n      p = decode(p, p);\n      if (!p) return;\n    }\n  }\n  if (auto num_chars_left = s.data() + s.size() - p) {\n    char buf[2 * block_size - 1] = {};\n    copy_str<char>(p, p + num_chars_left, buf);\n    const char* buf_ptr = buf;\n    do {\n      auto end = decode(buf_ptr, p);\n      if (!end) return;\n      p += end - buf_ptr;\n      buf_ptr = end;\n    } while (buf_ptr - buf < num_chars_left);\n  }\n}\n\ntemplate <typename Char>\ninline auto compute_width(basic_string_view<Char> s) -> size_t {\n  return s.size();\n}\n\n// Computes approximate display width of a UTF-8 string.\nFMT_CONSTEXPR inline size_t compute_width(string_view s) {\n  size_t num_code_points = 0;\n  // It is not a lambda for compatibility with C++14.\n  struct count_code_points {\n    size_t* count;\n    FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool {\n      *count += detail::to_unsigned(\n          1 +\n          (cp >= 0x1100 &&\n           (cp <= 0x115f ||  // Hangul Jamo init. consonants\n            cp == 0x2329 ||  // LEFT-POINTING ANGLE BRACKET\n            cp == 0x232a ||  // RIGHT-POINTING ANGLE BRACKET\n            // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:\n            (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||\n            (cp >= 0xac00 && cp <= 0xd7a3) ||    // Hangul Syllables\n            (cp >= 0xf900 && cp <= 0xfaff) ||    // CJK Compatibility Ideographs\n            (cp >= 0xfe10 && cp <= 0xfe19) ||    // Vertical Forms\n            (cp >= 0xfe30 && cp <= 0xfe6f) ||    // CJK Compatibility Forms\n            (cp >= 0xff00 && cp <= 0xff60) ||    // Fullwidth Forms\n            (cp >= 0xffe0 && cp <= 0xffe6) ||    // Fullwidth Forms\n            (cp >= 0x20000 && cp <= 0x2fffd) ||  // CJK\n            (cp >= 0x30000 && cp <= 0x3fffd) ||\n            // Miscellaneous Symbols and Pictographs + Emoticons:\n            (cp >= 0x1f300 && cp <= 0x1f64f) ||\n            // Supplemental Symbols and Pictographs:\n            (cp >= 0x1f900 && cp <= 0x1f9ff))));\n      return true;\n    }\n  };\n  for_each_codepoint(s, count_code_points{&num_code_points});\n  return num_code_points;\n}\n\ninline auto compute_width(basic_string_view<char8_type> s) -> size_t {\n  return compute_width(basic_string_view<char>(\n      reinterpret_cast<const char*>(s.data()), s.size()));\n}\n\ntemplate <typename Char>\ninline auto code_point_index(basic_string_view<Char> s, size_t n) -> size_t {\n  size_t size = s.size();\n  return n < size ? n : size;\n}\n\n// Calculates the index of the nth code point in a UTF-8 string.\ninline auto code_point_index(basic_string_view<char8_type> s, size_t n)\n    -> size_t {\n  const char8_type* data = s.data();\n  size_t num_code_points = 0;\n  for (size_t i = 0, size = s.size(); i != size; ++i) {\n    if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) return i;\n  }\n  return s.size();\n}\n\ntemplate <typename T, bool = std::is_floating_point<T>::value>\nstruct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 &&\n                                     sizeof(T) <= sizeof(double)> {};\ntemplate <typename T> struct is_fast_float<T, false> : std::false_type {};\n\n#ifndef FMT_USE_FULL_CACHE_DRAGONBOX\n#  define FMT_USE_FULL_CACHE_DRAGONBOX 0\n#endif\n\ntemplate <typename T>\ntemplate <typename U>\nvoid buffer<T>::append(const U* begin, const U* end) {\n  while (begin != end) {\n    auto count = to_unsigned(end - begin);\n    try_reserve(size_ + count);\n    auto free_cap = capacity_ - size_;\n    if (free_cap < count) count = free_cap;\n    std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count));\n    size_ += count;\n    begin += count;\n  }\n}\n\ntemplate <typename T, typename Enable = void>\nstruct is_locale : std::false_type {};\ntemplate <typename T>\nstruct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};\n}  // namespace detail\n\nFMT_MODULE_EXPORT_BEGIN\n\n// The number of characters to store in the basic_memory_buffer object itself\n// to avoid dynamic memory allocation.\nenum { inline_buffer_size = 500 };\n\n/**\n  \\rst\n  A dynamically growing memory buffer for trivially copyable/constructible types\n  with the first ``SIZE`` elements stored in the object itself.\n\n  You can use the ``memory_buffer`` type alias for ``char`` instead.\n\n  **Example**::\n\n     auto out = fmt::memory_buffer();\n     format_to(std::back_inserter(out), \"The answer is {}.\", 42);\n\n  This will append the following output to the ``out`` object:\n\n  .. code-block:: none\n\n     The answer is 42.\n\n  The output can be converted to an ``std::string`` with ``to_string(out)``.\n  \\endrst\n */\ntemplate <typename T, size_t SIZE = inline_buffer_size,\n          typename Allocator = std::allocator<T>>\nclass basic_memory_buffer final : public detail::buffer<T> {\n private:\n  T store_[SIZE];\n\n  // Don't inherit from Allocator avoid generating type_info for it.\n  Allocator alloc_;\n\n  // Deallocate memory allocated by the buffer.\n  FMT_CONSTEXPR20 void deallocate() {\n    T* data = this->data();\n    if (data != store_) alloc_.deallocate(data, this->capacity());\n  }\n\n protected:\n  FMT_CONSTEXPR20 void grow(size_t size) override;\n\n public:\n  using value_type = T;\n  using const_reference = const T&;\n\n  FMT_CONSTEXPR20 explicit basic_memory_buffer(\n      const Allocator& alloc = Allocator())\n      : alloc_(alloc) {\n    this->set(store_, SIZE);\n    if (detail::is_constant_evaluated()) {\n      detail::fill_n(store_, SIZE, T{});\n    }\n  }\n  FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); }\n\n private:\n  // Move data from other to this buffer.\n  FMT_CONSTEXPR20 void move(basic_memory_buffer& other) {\n    alloc_ = std::move(other.alloc_);\n    T* data = other.data();\n    size_t size = other.size(), capacity = other.capacity();\n    if (data == other.store_) {\n      this->set(store_, capacity);\n      if (detail::is_constant_evaluated()) {\n        detail::copy_str<T>(other.store_, other.store_ + size,\n                            detail::make_checked(store_, capacity));\n      } else {\n        std::uninitialized_copy(other.store_, other.store_ + size,\n                                detail::make_checked(store_, capacity));\n      }\n    } else {\n      this->set(data, capacity);\n      // Set pointer to the inline array so that delete is not called\n      // when deallocating.\n      other.set(other.store_, 0);\n    }\n    this->resize(size);\n  }\n\n public:\n  /**\n    \\rst\n    Constructs a :class:`fmt::basic_memory_buffer` object moving the content\n    of the other object to it.\n    \\endrst\n   */\n  FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other)\n      FMT_NOEXCEPT {\n    move(other);\n  }\n\n  /**\n    \\rst\n    Moves the content of the other ``basic_memory_buffer`` object to this one.\n    \\endrst\n   */\n  auto operator=(basic_memory_buffer&& other) FMT_NOEXCEPT\n      -> basic_memory_buffer& {\n    FMT_ASSERT(this != &other, \"\");\n    deallocate();\n    move(other);\n    return *this;\n  }\n\n  // Returns a copy of the allocator associated with this buffer.\n  auto get_allocator() const -> Allocator { return alloc_; }\n\n  /**\n    Resizes the buffer to contain *count* elements. If T is a POD type new\n    elements may not be initialized.\n   */\n  FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); }\n\n  /** Increases the buffer capacity to *new_capacity*. */\n  void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }\n\n  // Directly append data into the buffer\n  using detail::buffer<T>::append;\n  template <typename ContiguousRange>\n  void append(const ContiguousRange& range) {\n    append(range.data(), range.data() + range.size());\n  }\n};\n\ntemplate <typename T, size_t SIZE, typename Allocator>\nFMT_CONSTEXPR20 void basic_memory_buffer<T, SIZE, Allocator>::grow(\n    size_t size) {\n#ifdef FMT_FUZZ\n  if (size > 5000) throw std::runtime_error(\"fuzz mode - won't grow that much\");\n#endif\n  const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);\n  size_t old_capacity = this->capacity();\n  size_t new_capacity = old_capacity + old_capacity / 2;\n  if (size > new_capacity)\n    new_capacity = size;\n  else if (new_capacity > max_size)\n    new_capacity = size > max_size ? size : max_size;\n  T* old_data = this->data();\n  T* new_data =\n      std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);\n  // The following code doesn't throw, so the raw pointer above doesn't leak.\n  std::uninitialized_copy(old_data, old_data + this->size(),\n                          detail::make_checked(new_data, new_capacity));\n  this->set(new_data, new_capacity);\n  // deallocate must not throw according to the standard, but even if it does,\n  // the buffer already uses the new storage and will deallocate it in\n  // destructor.\n  if (old_data != store_) alloc_.deallocate(old_data, old_capacity);\n}\n\nusing memory_buffer = basic_memory_buffer<char>;\n\ntemplate <typename T, size_t SIZE, typename Allocator>\nstruct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {\n};\n\nnamespace detail {\nFMT_API void print(std::FILE*, string_view);\n}\n\n/** A formatting error such as invalid format string. */\nFMT_CLASS_API\nclass FMT_API format_error : public std::runtime_error {\n public:\n  explicit format_error(const char* message) : std::runtime_error(message) {}\n  explicit format_error(const std::string& message)\n      : std::runtime_error(message) {}\n  format_error(const format_error&) = default;\n  format_error& operator=(const format_error&) = default;\n  format_error(format_error&&) = default;\n  format_error& operator=(format_error&&) = default;\n  ~format_error() FMT_NOEXCEPT override FMT_MSC_DEFAULT;\n};\n\n/**\n  \\rst\n  Constructs a `~fmt::format_arg_store` object that contains references\n  to arguments and can be implicitly converted to `~fmt::format_args`.\n  If ``fmt`` is a compile-time string then `make_args_checked` checks\n  its validity at compile time.\n  \\endrst\n */\ntemplate <typename... Args, typename S, typename Char = char_t<S>>\nFMT_INLINE auto make_args_checked(const S& fmt,\n                                  const remove_reference_t<Args>&... args)\n    -> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> {\n  static_assert(\n      detail::count<(\n              std::is_base_of<detail::view, remove_reference_t<Args>>::value &&\n              std::is_reference<Args>::value)...>() == 0,\n      \"passing views as lvalues is disallowed\");\n  detail::check_format_string<Args...>(fmt);\n  return {args...};\n}\n\n// compile-time support\nnamespace detail_exported {\n#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\ntemplate <typename Char, size_t N> struct fixed_string {\n  constexpr fixed_string(const Char (&str)[N]) {\n    detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str),\n                                               str + N, data);\n  }\n  Char data[N]{};\n};\n#endif\n\n// Converts a compile-time string to basic_string_view.\ntemplate <typename Char, size_t N>\nconstexpr auto compile_string_to_view(const Char (&s)[N])\n    -> basic_string_view<Char> {\n  // Remove trailing NUL character if needed. Won't be present if this is used\n  // with a raw character array (i.e. not defined as a string).\n  return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};\n}\ntemplate <typename Char>\nconstexpr auto compile_string_to_view(detail::std_string_view<Char> s)\n    -> basic_string_view<Char> {\n  return {s.data(), s.size()};\n}\n}  // namespace detail_exported\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\ntemplate <typename T> struct is_integral : std::is_integral<T> {};\ntemplate <> struct is_integral<int128_t> : std::true_type {};\ntemplate <> struct is_integral<uint128_t> : std::true_type {};\n\ntemplate <typename T>\nusing is_signed =\n    std::integral_constant<bool, std::numeric_limits<T>::is_signed ||\n                                     std::is_same<T, int128_t>::value>;\n\n// Returns true if value is negative, false otherwise.\n// Same as `value < 0` but doesn't produce warnings if T is an unsigned type.\ntemplate <typename T, FMT_ENABLE_IF(is_signed<T>::value)>\nFMT_CONSTEXPR auto is_negative(T value) -> bool {\n  return value < 0;\n}\ntemplate <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>\nFMT_CONSTEXPR auto is_negative(T) -> bool {\n  return false;\n}\n\ntemplate <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>\nFMT_CONSTEXPR auto is_supported_floating_point(T) -> uint16_t {\n  return (std::is_same<T, float>::value && FMT_USE_FLOAT) ||\n         (std::is_same<T, double>::value && FMT_USE_DOUBLE) ||\n         (std::is_same<T, long double>::value && FMT_USE_LONG_DOUBLE);\n}\n\n// Smallest of uint32_t, uint64_t, uint128_t that is large enough to\n// represent all values of an integral type T.\ntemplate <typename T>\nusing uint32_or_64_or_128_t =\n    conditional_t<num_bits<T>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS,\n                  uint32_t,\n                  conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;\ntemplate <typename T>\nusing uint64_or_128_t = conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>;\n\n#define FMT_POWERS_OF_10(factor)                                             \\\n  factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \\\n      (factor)*1000000, (factor)*10000000, (factor)*100000000,               \\\n      (factor)*1000000000\n\n// Converts value in the range [0, 100) to a string.\nconstexpr const char* digits2(size_t value) {\n  // GCC generates slightly better code when value is pointer-size.\n  return &\"0001020304050607080910111213141516171819\"\n         \"2021222324252627282930313233343536373839\"\n         \"4041424344454647484950515253545556575859\"\n         \"6061626364656667686970717273747576777879\"\n         \"8081828384858687888990919293949596979899\"[value * 2];\n}\n\n// Sign is a template parameter to workaround a bug in gcc 4.8.\ntemplate <typename Char, typename Sign> constexpr Char sign(Sign s) {\n#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604\n  static_assert(std::is_same<Sign, sign_t>::value, \"\");\n#endif\n  return static_cast<Char>(\"\\0-+ \"[s]);\n}\n\ntemplate <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {\n  int count = 1;\n  for (;;) {\n    // Integer division is slow so do it for a group of four digits instead\n    // of for every digit. The idea comes from the talk by Alexandrescu\n    // \"Three Optimization Tips for C++\". See speed-test for a comparison.\n    if (n < 10) return count;\n    if (n < 100) return count + 1;\n    if (n < 1000) return count + 2;\n    if (n < 10000) return count + 3;\n    n /= 10000u;\n    count += 4;\n  }\n}\n#if FMT_USE_INT128\nFMT_CONSTEXPR inline auto count_digits(uint128_t n) -> int {\n  return count_digits_fallback(n);\n}\n#endif\n\n#ifdef FMT_BUILTIN_CLZLL\n// It is a separate function rather than a part of count_digits to workaround\n// the lack of static constexpr in constexpr functions.\ninline auto do_count_digits(uint64_t n) -> int {\n  // This has comparable performance to the version by Kendall Willets\n  // (https://github.com/fmtlib/format-benchmark/blob/master/digits10)\n  // but uses smaller tables.\n  // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).\n  static constexpr uint8_t bsr2log10[] = {\n      1,  1,  1,  2,  2,  2,  3,  3,  3,  4,  4,  4,  4,  5,  5,  5,\n      6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9,  10, 10, 10,\n      10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,\n      15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};\n  auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];\n  static constexpr const uint64_t zero_or_powers_of_10[] = {\n      0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),\n      10000000000000000000ULL};\n  return t - (n < zero_or_powers_of_10[t]);\n}\n#endif\n\n// Returns the number of decimal digits in n. Leading zeros are not counted\n// except for n == 0 in which case count_digits returns 1.\nFMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int {\n#ifdef FMT_BUILTIN_CLZLL\n  if (!is_constant_evaluated()) {\n    return do_count_digits(n);\n  }\n#endif\n  return count_digits_fallback(n);\n}\n\n// Counts the number of digits in n. BITS = log2(radix).\ntemplate <int BITS, typename UInt>\nFMT_CONSTEXPR auto count_digits(UInt n) -> int {\n#ifdef FMT_BUILTIN_CLZ\n  if (num_bits<UInt>() == 32)\n    return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1;\n#endif\n  // Lambda avoids unreachable code warnings from NVHPC.\n  return [](UInt m) {\n    int num_digits = 0;\n    do {\n      ++num_digits;\n    } while ((m >>= BITS) != 0);\n    return num_digits;\n  }(n);\n}\n\ntemplate <> auto count_digits<4>(detail::fallback_uintptr n) -> int;\n\n#ifdef FMT_BUILTIN_CLZ\n// It is a separate function rather than a part of count_digits to workaround\n// the lack of static constexpr in constexpr functions.\nFMT_INLINE auto do_count_digits(uint32_t n) -> int {\n// An optimization by Kendall Willets from https://bit.ly/3uOIQrB.\n// This increments the upper 32 bits (log10(T) - 1) when >= T is added.\n#  define FMT_INC(T) (((sizeof(#  T) - 1ull) << 32) - T)\n  static constexpr uint64_t table[] = {\n      FMT_INC(0),          FMT_INC(0),          FMT_INC(0),           // 8\n      FMT_INC(10),         FMT_INC(10),         FMT_INC(10),          // 64\n      FMT_INC(100),        FMT_INC(100),        FMT_INC(100),         // 512\n      FMT_INC(1000),       FMT_INC(1000),       FMT_INC(1000),        // 4096\n      FMT_INC(10000),      FMT_INC(10000),      FMT_INC(10000),       // 32k\n      FMT_INC(100000),     FMT_INC(100000),     FMT_INC(100000),      // 256k\n      FMT_INC(1000000),    FMT_INC(1000000),    FMT_INC(1000000),     // 2048k\n      FMT_INC(10000000),   FMT_INC(10000000),   FMT_INC(10000000),    // 16M\n      FMT_INC(100000000),  FMT_INC(100000000),  FMT_INC(100000000),   // 128M\n      FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000),  // 1024M\n      FMT_INC(1000000000), FMT_INC(1000000000)                        // 4B\n  };\n  auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31];\n  return static_cast<int>((n + inc) >> 32);\n}\n#endif\n\n// Optional version of count_digits for better performance on 32-bit platforms.\nFMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int {\n#ifdef FMT_BUILTIN_CLZ\n  if (!is_constant_evaluated()) {\n    return do_count_digits(n);\n  }\n#endif\n  return count_digits_fallback(n);\n}\n\ntemplate <typename Int> constexpr auto digits10() FMT_NOEXCEPT -> int {\n  return std::numeric_limits<Int>::digits10;\n}\ntemplate <> constexpr auto digits10<int128_t>() FMT_NOEXCEPT -> int {\n  return 38;\n}\ntemplate <> constexpr auto digits10<uint128_t>() FMT_NOEXCEPT -> int {\n  return 38;\n}\n\ntemplate <typename Char> struct thousands_sep_result {\n  std::string grouping;\n  Char thousands_sep;\n};\n\ntemplate <typename Char>\nFMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>;\ntemplate <typename Char>\ninline auto thousands_sep(locale_ref loc) -> thousands_sep_result<Char> {\n  auto result = thousands_sep_impl<char>(loc);\n  return {result.grouping, Char(result.thousands_sep)};\n}\ntemplate <>\ninline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> {\n  return thousands_sep_impl<wchar_t>(loc);\n}\n\ntemplate <typename Char>\nFMT_API auto decimal_point_impl(locale_ref loc) -> Char;\ntemplate <typename Char> inline auto decimal_point(locale_ref loc) -> Char {\n  return Char(decimal_point_impl<char>(loc));\n}\ntemplate <> inline auto decimal_point(locale_ref loc) -> wchar_t {\n  return decimal_point_impl<wchar_t>(loc);\n}\n\n// Compares two characters for equality.\ntemplate <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool {\n  return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);\n}\ninline auto equal2(const char* lhs, const char* rhs) -> bool {\n  return memcmp(lhs, rhs, 2) == 0;\n}\n\n// Copies two characters from src to dst.\ntemplate <typename Char>\nFMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) {\n  if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) {\n    memcpy(dst, src, 2);\n    return;\n  }\n  *dst++ = static_cast<Char>(*src++);\n  *dst = static_cast<Char>(*src);\n}\n\ntemplate <typename Iterator> struct format_decimal_result {\n  Iterator begin;\n  Iterator end;\n};\n\n// Formats a decimal unsigned integer value writing into out pointing to a\n// buffer of specified size. The caller must ensure that the buffer is large\n// enough.\ntemplate <typename Char, typename UInt>\nFMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size)\n    -> format_decimal_result<Char*> {\n  FMT_ASSERT(size >= count_digits(value), \"invalid digit count\");\n  out += size;\n  Char* end = out;\n  while (value >= 100) {\n    // Integer division is slow so do it for a group of two digits instead\n    // of for every digit. The idea comes from the talk by Alexandrescu\n    // \"Three Optimization Tips for C++\". See speed-test for a comparison.\n    out -= 2;\n    copy2(out, digits2(static_cast<size_t>(value % 100)));\n    value /= 100;\n  }\n  if (value < 10) {\n    *--out = static_cast<Char>('0' + value);\n    return {out, end};\n  }\n  out -= 2;\n  copy2(out, digits2(static_cast<size_t>(value)));\n  return {out, end};\n}\n\ntemplate <typename Char, typename UInt, typename Iterator,\n          FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>\ninline auto format_decimal(Iterator out, UInt value, int size)\n    -> format_decimal_result<Iterator> {\n  // Buffer is large enough to hold all digits (digits10 + 1).\n  Char buffer[digits10<UInt>() + 1];\n  auto end = format_decimal(buffer, value, size).end;\n  return {out, detail::copy_str_noinline<Char>(buffer, end, out)};\n}\n\ntemplate <unsigned BASE_BITS, typename Char, typename UInt>\nFMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits,\n                               bool upper = false) -> Char* {\n  buffer += num_digits;\n  Char* end = buffer;\n  do {\n    const char* digits = upper ? \"0123456789ABCDEF\" : \"0123456789abcdef\";\n    unsigned digit = (value & ((1 << BASE_BITS) - 1));\n    *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)\n                                                : digits[digit]);\n  } while ((value >>= BASE_BITS) != 0);\n  return end;\n}\n\ntemplate <unsigned BASE_BITS, typename Char>\nauto format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits,\n                 bool = false) -> Char* {\n  auto char_digits = std::numeric_limits<unsigned char>::digits / 4;\n  int start = (num_digits + char_digits - 1) / char_digits - 1;\n  if (int start_digits = num_digits % char_digits) {\n    unsigned value = n.value[start--];\n    buffer = format_uint<BASE_BITS>(buffer, value, start_digits);\n  }\n  for (; start >= 0; --start) {\n    unsigned value = n.value[start];\n    buffer += char_digits;\n    auto p = buffer;\n    for (int i = 0; i < char_digits; ++i) {\n      unsigned digit = (value & ((1 << BASE_BITS) - 1));\n      *--p = static_cast<Char>(\"0123456789abcdef\"[digit]);\n      value >>= BASE_BITS;\n    }\n  }\n  return buffer;\n}\n\ntemplate <unsigned BASE_BITS, typename Char, typename It, typename UInt>\ninline auto format_uint(It out, UInt value, int num_digits, bool upper = false)\n    -> It {\n  if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {\n    format_uint<BASE_BITS>(ptr, value, num_digits, upper);\n    return out;\n  }\n  // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).\n  char buffer[num_bits<UInt>() / BASE_BITS + 1];\n  format_uint<BASE_BITS>(buffer, value, num_digits, upper);\n  return detail::copy_str_noinline<Char>(buffer, buffer + num_digits, out);\n}\n\n// A converter from UTF-8 to UTF-16.\nclass utf8_to_utf16 {\n private:\n  basic_memory_buffer<wchar_t> buffer_;\n\n public:\n  FMT_API explicit utf8_to_utf16(string_view s);\n  operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; }\n  auto size() const -> size_t { return buffer_.size() - 1; }\n  auto c_str() const -> const wchar_t* { return &buffer_[0]; }\n  auto str() const -> std::wstring { return {&buffer_[0], size()}; }\n};\n\nnamespace dragonbox {\n\n// Type-specific information that Dragonbox uses.\ntemplate <class T> struct float_info;\n\ntemplate <> struct float_info<float> {\n  using carrier_uint = uint32_t;\n  static const int significand_bits = 23;\n  static const int exponent_bits = 8;\n  static const int min_exponent = -126;\n  static const int max_exponent = 127;\n  static const int exponent_bias = -127;\n  static const int decimal_digits = 9;\n  static const int kappa = 1;\n  static const int big_divisor = 100;\n  static const int small_divisor = 10;\n  static const int min_k = -31;\n  static const int max_k = 46;\n  static const int cache_bits = 64;\n  static const int divisibility_check_by_5_threshold = 39;\n  static const int case_fc_pm_half_lower_threshold = -1;\n  static const int case_fc_pm_half_upper_threshold = 6;\n  static const int case_fc_lower_threshold = -2;\n  static const int case_fc_upper_threshold = 6;\n  static const int case_shorter_interval_left_endpoint_lower_threshold = 2;\n  static const int case_shorter_interval_left_endpoint_upper_threshold = 3;\n  static const int shorter_interval_tie_lower_threshold = -35;\n  static const int shorter_interval_tie_upper_threshold = -35;\n  static const int max_trailing_zeros = 7;\n};\n\ntemplate <> struct float_info<double> {\n  using carrier_uint = uint64_t;\n  static const int significand_bits = 52;\n  static const int exponent_bits = 11;\n  static const int min_exponent = -1022;\n  static const int max_exponent = 1023;\n  static const int exponent_bias = -1023;\n  static const int decimal_digits = 17;\n  static const int kappa = 2;\n  static const int big_divisor = 1000;\n  static const int small_divisor = 100;\n  static const int min_k = -292;\n  static const int max_k = 326;\n  static const int cache_bits = 128;\n  static const int divisibility_check_by_5_threshold = 86;\n  static const int case_fc_pm_half_lower_threshold = -2;\n  static const int case_fc_pm_half_upper_threshold = 9;\n  static const int case_fc_lower_threshold = -4;\n  static const int case_fc_upper_threshold = 9;\n  static const int case_shorter_interval_left_endpoint_lower_threshold = 2;\n  static const int case_shorter_interval_left_endpoint_upper_threshold = 3;\n  static const int shorter_interval_tie_lower_threshold = -77;\n  static const int shorter_interval_tie_upper_threshold = -77;\n  static const int max_trailing_zeros = 16;\n};\n\ntemplate <typename T> struct decimal_fp {\n  using significand_type = typename float_info<T>::carrier_uint;\n  significand_type significand;\n  int exponent;\n};\n\ntemplate <typename T>\nFMT_API auto to_decimal(T x) FMT_NOEXCEPT -> decimal_fp<T>;\n}  // namespace dragonbox\n\ntemplate <typename T>\nconstexpr auto exponent_mask() ->\n    typename dragonbox::float_info<T>::carrier_uint {\n  using uint = typename dragonbox::float_info<T>::carrier_uint;\n  return ((uint(1) << dragonbox::float_info<T>::exponent_bits) - 1)\n         << dragonbox::float_info<T>::significand_bits;\n}\n\n// Writes the exponent exp in the form \"[+-]d{2,3}\" to buffer.\ntemplate <typename Char, typename It>\nFMT_CONSTEXPR auto write_exponent(int exp, It it) -> It {\n  FMT_ASSERT(-10000 < exp && exp < 10000, \"exponent out of range\");\n  if (exp < 0) {\n    *it++ = static_cast<Char>('-');\n    exp = -exp;\n  } else {\n    *it++ = static_cast<Char>('+');\n  }\n  if (exp >= 100) {\n    const char* top = digits2(to_unsigned(exp / 100));\n    if (exp >= 1000) *it++ = static_cast<Char>(top[0]);\n    *it++ = static_cast<Char>(top[1]);\n    exp %= 100;\n  }\n  const char* d = digits2(to_unsigned(exp));\n  *it++ = static_cast<Char>(d[0]);\n  *it++ = static_cast<Char>(d[1]);\n  return it;\n}\n\ntemplate <typename T>\nFMT_HEADER_ONLY_CONSTEXPR20 auto format_float(T value, int precision,\n                                              float_specs specs,\n                                              buffer<char>& buf) -> int;\n\n// Formats a floating-point number with snprintf.\ntemplate <typename T>\nauto snprintf_float(T value, int precision, float_specs specs,\n                    buffer<char>& buf) -> int;\n\ntemplate <typename T> constexpr auto promote_float(T value) -> T {\n  return value;\n}\nconstexpr auto promote_float(float value) -> double {\n  return static_cast<double>(value);\n}\n\ntemplate <typename OutputIt, typename Char>\nFMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n,\n                                     const fill_t<Char>& fill) -> OutputIt {\n  auto fill_size = fill.size();\n  if (fill_size == 1) return detail::fill_n(it, n, fill[0]);\n  auto data = fill.data();\n  for (size_t i = 0; i < n; ++i)\n    it = copy_str<Char>(data, data + fill_size, it);\n  return it;\n}\n\n// Writes the output of f, padded according to format specifications in specs.\n// size: output size in code units.\n// width: output display width in (terminal) column positions.\ntemplate <align::type align = align::left, typename OutputIt, typename Char,\n          typename F>\nFMT_CONSTEXPR auto write_padded(OutputIt out,\n                                const basic_format_specs<Char>& specs,\n                                size_t size, size_t width, F&& f) -> OutputIt {\n  static_assert(align == align::left || align == align::right, \"\");\n  unsigned spec_width = to_unsigned(specs.width);\n  size_t padding = spec_width > width ? spec_width - width : 0;\n  // Shifts are encoded as string literals because static constexpr is not\n  // supported in constexpr functions.\n  auto* shifts = align == align::left ? \"\\x1f\\x1f\\x00\\x01\" : \"\\x00\\x1f\\x00\\x01\";\n  size_t left_padding = padding >> shifts[specs.align];\n  size_t right_padding = padding - left_padding;\n  auto it = reserve(out, size + padding * specs.fill.size());\n  if (left_padding != 0) it = fill(it, left_padding, specs.fill);\n  it = f(it);\n  if (right_padding != 0) it = fill(it, right_padding, specs.fill);\n  return base_iterator(out, it);\n}\n\ntemplate <align::type align = align::left, typename OutputIt, typename Char,\n          typename F>\nconstexpr auto write_padded(OutputIt out, const basic_format_specs<Char>& specs,\n                            size_t size, F&& f) -> OutputIt {\n  return write_padded<align>(out, specs, size, size, f);\n}\n\ntemplate <align::type align = align::left, typename Char, typename OutputIt>\nFMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes,\n                               const basic_format_specs<Char>& specs)\n    -> OutputIt {\n  return write_padded<align>(\n      out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {\n        const char* data = bytes.data();\n        return copy_str<Char>(data, data + bytes.size(), it);\n      });\n}\n\ntemplate <typename Char, typename OutputIt, typename UIntPtr>\nauto write_ptr(OutputIt out, UIntPtr value,\n               const basic_format_specs<Char>* specs) -> OutputIt {\n  int num_digits = count_digits<4>(value);\n  auto size = to_unsigned(num_digits) + size_t(2);\n  auto write = [=](reserve_iterator<OutputIt> it) {\n    *it++ = static_cast<Char>('0');\n    *it++ = static_cast<Char>('x');\n    return format_uint<4, Char>(it, value, num_digits);\n  };\n  return specs ? write_padded<align::right>(out, *specs, size, write)\n               : base_iterator(out, write(reserve(out, size)));\n}\n\ntemplate <typename Char, typename OutputIt>\nFMT_CONSTEXPR auto write_char(OutputIt out, Char value,\n                              const basic_format_specs<Char>& specs)\n    -> OutputIt {\n  return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {\n    *it++ = value;\n    return it;\n  });\n}\ntemplate <typename Char, typename OutputIt>\nFMT_CONSTEXPR auto write(OutputIt out, Char value,\n                         const basic_format_specs<Char>& specs,\n                         locale_ref loc = {}) -> OutputIt {\n  return check_char_specs(specs)\n             ? write_char(out, value, specs)\n             : write(out, static_cast<int>(value), specs, loc);\n}\n\n// Data for write_int that doesn't depend on output iterator type. It is used to\n// avoid template code bloat.\ntemplate <typename Char> struct write_int_data {\n  size_t size;\n  size_t padding;\n\n  FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix,\n                               const basic_format_specs<Char>& specs)\n      : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) {\n    if (specs.align == align::numeric) {\n      auto width = to_unsigned(specs.width);\n      if (width > size) {\n        padding = width - size;\n        size = width;\n      }\n    } else if (specs.precision > num_digits) {\n      size = (prefix >> 24) + to_unsigned(specs.precision);\n      padding = to_unsigned(specs.precision - num_digits);\n    }\n  }\n};\n\n// Writes an integer in the format\n//   <left-padding><prefix><numeric-padding><digits><right-padding>\n// where <digits> are written by write_digits(it).\n// prefix contains chars in three lower bytes and the size in the fourth byte.\ntemplate <typename OutputIt, typename Char, typename W>\nFMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits,\n                                        unsigned prefix,\n                                        const basic_format_specs<Char>& specs,\n                                        W write_digits) -> OutputIt {\n  // Slightly faster check for specs.width == 0 && specs.precision == -1.\n  if ((specs.width | (specs.precision + 1)) == 0) {\n    auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24));\n    if (prefix != 0) {\n      for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)\n        *it++ = static_cast<Char>(p & 0xff);\n    }\n    return base_iterator(out, write_digits(it));\n  }\n  auto data = write_int_data<Char>(num_digits, prefix, specs);\n  return write_padded<align::right>(\n      out, specs, data.size, [=](reserve_iterator<OutputIt> it) {\n        for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)\n          *it++ = static_cast<Char>(p & 0xff);\n        it = detail::fill_n(it, data.padding, static_cast<Char>('0'));\n        return write_digits(it);\n      });\n}\n\ntemplate <typename Char> class digit_grouping {\n private:\n  thousands_sep_result<Char> sep_;\n\n  struct next_state {\n    std::string::const_iterator group;\n    int pos;\n  };\n  next_state initial_state() const { return {sep_.grouping.begin(), 0}; }\n\n  // Returns the next digit group separator position.\n  int next(next_state& state) const {\n    if (!sep_.thousands_sep) return max_value<int>();\n    if (state.group == sep_.grouping.end())\n      return state.pos += sep_.grouping.back();\n    if (*state.group <= 0 || *state.group == max_value<char>())\n      return max_value<int>();\n    state.pos += *state.group++;\n    return state.pos;\n  }\n\n public:\n  explicit digit_grouping(locale_ref loc, bool localized = true) {\n    if (localized)\n      sep_ = thousands_sep<Char>(loc);\n    else\n      sep_.thousands_sep = Char();\n  }\n  explicit digit_grouping(thousands_sep_result<Char> sep) : sep_(sep) {}\n\n  Char separator() const { return sep_.thousands_sep; }\n\n  int count_separators(int num_digits) const {\n    int count = 0;\n    auto state = initial_state();\n    while (num_digits > next(state)) ++count;\n    return count;\n  }\n\n  // Applies grouping to digits and write the output to out.\n  template <typename Out, typename C>\n  Out apply(Out out, basic_string_view<C> digits) const {\n    auto num_digits = static_cast<int>(digits.size());\n    auto separators = basic_memory_buffer<int>();\n    separators.push_back(0);\n    auto state = initial_state();\n    while (int i = next(state)) {\n      if (i >= num_digits) break;\n      separators.push_back(i);\n    }\n    for (int i = 0, sep_index = static_cast<int>(separators.size() - 1);\n         i < num_digits; ++i) {\n      if (num_digits - i == separators[sep_index]) {\n        *out++ = separator();\n        --sep_index;\n      }\n      *out++ = static_cast<Char>(digits[to_unsigned(i)]);\n    }\n    return out;\n  }\n};\n\ntemplate <typename OutputIt, typename UInt, typename Char>\nauto write_int_localized(OutputIt out, UInt value, unsigned prefix,\n                         const basic_format_specs<Char>& specs,\n                         const digit_grouping<Char>& grouping) -> OutputIt {\n  static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, \"\");\n  int num_digits = count_digits(value);\n  char digits[40];\n  format_decimal(digits, value, num_digits);\n  unsigned size = to_unsigned((prefix != 0 ? 1 : 0) + num_digits +\n                              grouping.count_separators(num_digits));\n  return write_padded<align::right>(\n      out, specs, size, size, [&](reserve_iterator<OutputIt> it) {\n        if (prefix != 0) *it++ = static_cast<Char>(prefix);\n        return grouping.apply(it, string_view(digits, to_unsigned(num_digits)));\n      });\n}\n\ntemplate <typename OutputIt, typename UInt, typename Char>\nauto write_int_localized(OutputIt& out, UInt value, unsigned prefix,\n                         const basic_format_specs<Char>& specs, locale_ref loc)\n    -> bool {\n  auto grouping = digit_grouping<Char>(loc);\n  out = write_int_localized(out, value, prefix, specs, grouping);\n  return true;\n}\n\nFMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {\n  prefix |= prefix != 0 ? value << 8 : value;\n  prefix += (1u + (value > 0xff ? 1 : 0)) << 24;\n}\n\ntemplate <typename UInt> struct write_int_arg {\n  UInt abs_value;\n  unsigned prefix;\n};\n\ntemplate <typename T>\nFMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign)\n    -> write_int_arg<uint32_or_64_or_128_t<T>> {\n  auto prefix = 0u;\n  auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);\n  if (is_negative(value)) {\n    prefix = 0x01000000 | '-';\n    abs_value = 0 - abs_value;\n  } else {\n    constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',\n                                            0x1000000u | ' '};\n    prefix = prefixes[sign];\n  }\n  return {abs_value, prefix};\n}\n\ntemplate <typename Char, typename OutputIt, typename T>\nFMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg<T> arg,\n                                        const basic_format_specs<Char>& specs,\n                                        locale_ref loc) -> OutputIt {\n  static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value, \"\");\n  auto abs_value = arg.abs_value;\n  auto prefix = arg.prefix;\n  switch (specs.type) {\n  case presentation_type::none:\n  case presentation_type::dec: {\n    if (specs.localized &&\n        write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value),\n                            prefix, specs, loc)) {\n      return out;\n    }\n    auto num_digits = count_digits(abs_value);\n    return write_int(\n        out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {\n          return format_decimal<Char>(it, abs_value, num_digits).end;\n        });\n  }\n  case presentation_type::hex_lower:\n  case presentation_type::hex_upper: {\n    bool upper = specs.type == presentation_type::hex_upper;\n    if (specs.alt)\n      prefix_append(prefix, unsigned(upper ? 'X' : 'x') << 8 | '0');\n    int num_digits = count_digits<4>(abs_value);\n    return write_int(\n        out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {\n          return format_uint<4, Char>(it, abs_value, num_digits, upper);\n        });\n  }\n  case presentation_type::bin_lower:\n  case presentation_type::bin_upper: {\n    bool upper = specs.type == presentation_type::bin_upper;\n    if (specs.alt)\n      prefix_append(prefix, unsigned(upper ? 'B' : 'b') << 8 | '0');\n    int num_digits = count_digits<1>(abs_value);\n    return write_int(out, num_digits, prefix, specs,\n                     [=](reserve_iterator<OutputIt> it) {\n                       return format_uint<1, Char>(it, abs_value, num_digits);\n                     });\n  }\n  case presentation_type::oct: {\n    int num_digits = count_digits<3>(abs_value);\n    // Octal prefix '0' is counted as a digit, so only add it if precision\n    // is not greater than the number of digits.\n    if (specs.alt && specs.precision <= num_digits && abs_value != 0)\n      prefix_append(prefix, '0');\n    return write_int(out, num_digits, prefix, specs,\n                     [=](reserve_iterator<OutputIt> it) {\n                       return format_uint<3, Char>(it, abs_value, num_digits);\n                     });\n  }\n  case presentation_type::chr:\n    return write_char(out, static_cast<Char>(abs_value), specs);\n  default:\n    throw_format_error(\"invalid type specifier\");\n  }\n  return out;\n}\ntemplate <typename Char, typename OutputIt, typename T>\nFMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(\n    OutputIt out, write_int_arg<T> arg, const basic_format_specs<Char>& specs,\n    locale_ref loc) -> OutputIt {\n  return write_int(out, arg, specs, loc);\n}\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(is_integral<T>::value &&\n                        !std::is_same<T, bool>::value &&\n                        std::is_same<OutputIt, buffer_appender<Char>>::value)>\nFMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value,\n                                    const basic_format_specs<Char>& specs,\n                                    locale_ref loc) -> OutputIt {\n  return write_int_noinline(out, make_write_int_arg(value, specs.sign), specs,\n                            loc);\n}\n// An inlined version of write used in format string compilation.\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(is_integral<T>::value &&\n                        !std::is_same<T, bool>::value &&\n                        !std::is_same<OutputIt, buffer_appender<Char>>::value)>\nFMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value,\n                                    const basic_format_specs<Char>& specs,\n                                    locale_ref loc) -> OutputIt {\n  return write_int(out, make_write_int_arg(value, specs.sign), specs, loc);\n}\n\ntemplate <typename Char, typename OutputIt>\nFMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> s,\n                         const basic_format_specs<Char>& specs) -> OutputIt {\n  auto data = s.data();\n  auto size = s.size();\n  if (specs.precision >= 0 && to_unsigned(specs.precision) < size)\n    size = code_point_index(s, to_unsigned(specs.precision));\n  auto width =\n      specs.width != 0 ? compute_width(basic_string_view<Char>(data, size)) : 0;\n  return write_padded(out, specs, size, width,\n                      [=](reserve_iterator<OutputIt> it) {\n                        return copy_str<Char>(data, data + size, it);\n                      });\n}\ntemplate <typename Char, typename OutputIt>\nFMT_CONSTEXPR auto write(OutputIt out,\n                         basic_string_view<type_identity_t<Char>> s,\n                         const basic_format_specs<Char>& specs, locale_ref)\n    -> OutputIt {\n  check_string_type_spec(specs.type);\n  return write(out, s, specs);\n}\ntemplate <typename Char, typename OutputIt>\nFMT_CONSTEXPR auto write(OutputIt out, const Char* s,\n                         const basic_format_specs<Char>& specs, locale_ref)\n    -> OutputIt {\n  return check_cstring_type_spec(specs.type)\n             ? write(out, basic_string_view<Char>(s), specs, {})\n             : write_ptr<Char>(out, to_uintptr(s), &specs);\n}\n\ntemplate <typename Char, typename OutputIt>\nFMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isinf,\n                                     basic_format_specs<Char> specs,\n                                     const float_specs& fspecs) -> OutputIt {\n  auto str =\n      isinf ? (fspecs.upper ? \"INF\" : \"inf\") : (fspecs.upper ? \"NAN\" : \"nan\");\n  constexpr size_t str_size = 3;\n  auto sign = fspecs.sign;\n  auto size = str_size + (sign ? 1 : 0);\n  // Replace '0'-padding with space for non-finite values.\n  const bool is_zero_fill =\n      specs.fill.size() == 1 && *specs.fill.data() == static_cast<Char>('0');\n  if (is_zero_fill) specs.fill[0] = static_cast<Char>(' ');\n  return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) {\n    if (sign) *it++ = detail::sign<Char>(sign);\n    return copy_str<Char>(str, str + str_size, it);\n  });\n}\n\n// A decimal floating-point number significand * pow(10, exp).\nstruct big_decimal_fp {\n  const char* significand;\n  int significand_size;\n  int exponent;\n};\n\nconstexpr auto get_significand_size(const big_decimal_fp& fp) -> int {\n  return fp.significand_size;\n}\ntemplate <typename T>\ninline auto get_significand_size(const dragonbox::decimal_fp<T>& fp) -> int {\n  return count_digits(fp.significand);\n}\n\ntemplate <typename Char, typename OutputIt>\nconstexpr auto write_significand(OutputIt out, const char* significand,\n                                 int significand_size) -> OutputIt {\n  return copy_str<Char>(significand, significand + significand_size, out);\n}\ntemplate <typename Char, typename OutputIt, typename UInt>\ninline auto write_significand(OutputIt out, UInt significand,\n                              int significand_size) -> OutputIt {\n  return format_decimal<Char>(out, significand, significand_size).end;\n}\ntemplate <typename Char, typename OutputIt, typename T, typename Grouping>\nFMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,\n                                       int significand_size, int exponent,\n                                       const Grouping& grouping) -> OutputIt {\n  if (!grouping.separator()) {\n    out = write_significand<Char>(out, significand, significand_size);\n    return detail::fill_n(out, exponent, static_cast<Char>('0'));\n  }\n  auto buffer = memory_buffer();\n  write_significand<char>(appender(buffer), significand, significand_size);\n  detail::fill_n(appender(buffer), exponent, '0');\n  return grouping.apply(out, string_view(buffer.data(), buffer.size()));\n}\n\ntemplate <typename Char, typename UInt,\n          FMT_ENABLE_IF(std::is_integral<UInt>::value)>\ninline auto write_significand(Char* out, UInt significand, int significand_size,\n                              int integral_size, Char decimal_point) -> Char* {\n  if (!decimal_point)\n    return format_decimal(out, significand, significand_size).end;\n  out += significand_size + 1;\n  Char* end = out;\n  int floating_size = significand_size - integral_size;\n  for (int i = floating_size / 2; i > 0; --i) {\n    out -= 2;\n    copy2(out, digits2(significand % 100));\n    significand /= 100;\n  }\n  if (floating_size % 2 != 0) {\n    *--out = static_cast<Char>('0' + significand % 10);\n    significand /= 10;\n  }\n  *--out = decimal_point;\n  format_decimal(out - integral_size, significand, integral_size);\n  return end;\n}\n\ntemplate <typename OutputIt, typename UInt, typename Char,\n          FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)>\ninline auto write_significand(OutputIt out, UInt significand,\n                              int significand_size, int integral_size,\n                              Char decimal_point) -> OutputIt {\n  // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.\n  Char buffer[digits10<UInt>() + 2];\n  auto end = write_significand(buffer, significand, significand_size,\n                               integral_size, decimal_point);\n  return detail::copy_str_noinline<Char>(buffer, end, out);\n}\n\ntemplate <typename OutputIt, typename Char>\nFMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand,\n                                     int significand_size, int integral_size,\n                                     Char decimal_point) -> OutputIt {\n  out = detail::copy_str_noinline<Char>(significand,\n                                        significand + integral_size, out);\n  if (!decimal_point) return out;\n  *out++ = decimal_point;\n  return detail::copy_str_noinline<Char>(significand + integral_size,\n                                         significand + significand_size, out);\n}\n\ntemplate <typename OutputIt, typename Char, typename T, typename Grouping>\nFMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,\n                                       int significand_size, int integral_size,\n                                       Char decimal_point,\n                                       const Grouping& grouping) -> OutputIt {\n  if (!grouping.separator()) {\n    return write_significand(out, significand, significand_size, integral_size,\n                             decimal_point);\n  }\n  auto buffer = basic_memory_buffer<Char>();\n  write_significand(buffer_appender<Char>(buffer), significand,\n                    significand_size, integral_size, decimal_point);\n  grouping.apply(\n      out, basic_string_view<Char>(buffer.data(), to_unsigned(integral_size)));\n  return detail::copy_str_noinline<Char>(buffer.data() + integral_size,\n                                         buffer.end(), out);\n}\n\ntemplate <typename OutputIt, typename DecimalFP, typename Char,\n          typename Grouping = digit_grouping<Char>>\nFMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& fp,\n                                    const basic_format_specs<Char>& specs,\n                                    float_specs fspecs, locale_ref loc)\n    -> OutputIt {\n  auto significand = fp.significand;\n  int significand_size = get_significand_size(fp);\n  constexpr Char zero = static_cast<Char>('0');\n  auto sign = fspecs.sign;\n  size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);\n  using iterator = reserve_iterator<OutputIt>;\n\n  Char decimal_point =\n      fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.');\n\n  int output_exp = fp.exponent + significand_size - 1;\n  auto use_exp_format = [=]() {\n    if (fspecs.format == float_format::exp) return true;\n    if (fspecs.format != float_format::general) return false;\n    // Use the fixed notation if the exponent is in [exp_lower, exp_upper),\n    // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.\n    const int exp_lower = -4, exp_upper = 16;\n    return output_exp < exp_lower ||\n           output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper);\n  };\n  if (use_exp_format()) {\n    int num_zeros = 0;\n    if (fspecs.showpoint) {\n      num_zeros = fspecs.precision - significand_size;\n      if (num_zeros < 0) num_zeros = 0;\n      size += to_unsigned(num_zeros);\n    } else if (significand_size == 1) {\n      decimal_point = Char();\n    }\n    auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;\n    int exp_digits = 2;\n    if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3;\n\n    size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits);\n    char exp_char = fspecs.upper ? 'E' : 'e';\n    auto write = [=](iterator it) {\n      if (sign) *it++ = detail::sign<Char>(sign);\n      // Insert a decimal point after the first digit and add an exponent.\n      it = write_significand(it, significand, significand_size, 1,\n                             decimal_point);\n      if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero);\n      *it++ = static_cast<Char>(exp_char);\n      return write_exponent<Char>(output_exp, it);\n    };\n    return specs.width > 0 ? write_padded<align::right>(out, specs, size, write)\n                           : base_iterator(out, write(reserve(out, size)));\n  }\n\n  int exp = fp.exponent + significand_size;\n  if (fp.exponent >= 0) {\n    // 1234e5 -> 123400000[.0+]\n    size += to_unsigned(fp.exponent);\n    int num_zeros = fspecs.precision - exp;\n#ifdef FMT_FUZZ\n    if (num_zeros > 5000)\n      throw std::runtime_error(\"fuzz mode - avoiding excessive cpu use\");\n#endif\n    if (fspecs.showpoint) {\n      if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1;\n      if (num_zeros > 0) size += to_unsigned(num_zeros) + 1;\n    }\n    auto grouping = Grouping(loc, fspecs.locale);\n    size += to_unsigned(grouping.count_separators(significand_size));\n    return write_padded<align::right>(out, specs, size, [&](iterator it) {\n      if (sign) *it++ = detail::sign<Char>(sign);\n      it = write_significand<Char>(it, significand, significand_size,\n                                   fp.exponent, grouping);\n      if (!fspecs.showpoint) return it;\n      *it++ = decimal_point;\n      return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;\n    });\n  } else if (exp > 0) {\n    // 1234e-2 -> 12.34[0+]\n    int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0;\n    size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);\n    auto grouping = Grouping(loc, fspecs.locale);\n    size += to_unsigned(grouping.count_separators(significand_size));\n    return write_padded<align::right>(out, specs, size, [&](iterator it) {\n      if (sign) *it++ = detail::sign<Char>(sign);\n      it = write_significand(it, significand, significand_size, exp,\n                             decimal_point, grouping);\n      return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;\n    });\n  }\n  // 1234e-6 -> 0.001234\n  int num_zeros = -exp;\n  if (significand_size == 0 && fspecs.precision >= 0 &&\n      fspecs.precision < num_zeros) {\n    num_zeros = fspecs.precision;\n  }\n  bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint;\n  size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros);\n  return write_padded<align::right>(out, specs, size, [&](iterator it) {\n    if (sign) *it++ = detail::sign<Char>(sign);\n    *it++ = zero;\n    if (!pointy) return it;\n    *it++ = decimal_point;\n    it = detail::fill_n(it, num_zeros, zero);\n    return write_significand<Char>(it, significand, significand_size);\n  });\n}\n\ntemplate <typename Char> class fallback_digit_grouping {\n public:\n  constexpr fallback_digit_grouping(locale_ref, bool) {}\n\n  constexpr Char separator() const { return Char(); }\n\n  constexpr int count_separators(int) const { return 0; }\n\n  template <typename Out, typename C>\n  constexpr Out apply(Out out, basic_string_view<C>) const {\n    return out;\n  }\n};\n\ntemplate <typename OutputIt, typename DecimalFP, typename Char>\nFMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& fp,\n                                 const basic_format_specs<Char>& specs,\n                                 float_specs fspecs, locale_ref loc)\n    -> OutputIt {\n  if (is_constant_evaluated()) {\n    return do_write_float<OutputIt, DecimalFP, Char,\n                          fallback_digit_grouping<Char>>(out, fp, specs, fspecs,\n                                                         loc);\n  } else {\n    return do_write_float(out, fp, specs, fspecs, loc);\n  }\n}\n\ntemplate <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>\nFMT_CONSTEXPR20 bool isinf(T value) {\n  if (is_constant_evaluated()) {\n#if defined(__cpp_if_constexpr)\n    if constexpr (std::numeric_limits<double>::is_iec559) {\n      auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));\n      constexpr auto significand_bits =\n          dragonbox::float_info<double>::significand_bits;\n      return (bits & exponent_mask<double>()) &&\n             !(bits & ((uint64_t(1) << significand_bits) - 1));\n    }\n#endif\n  }\n  return std::isinf(value);\n}\n\ntemplate <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>\nFMT_CONSTEXPR20 bool isfinite(T value) {\n  if (is_constant_evaluated()) {\n#if defined(__cpp_if_constexpr)\n    if constexpr (std::numeric_limits<double>::is_iec559) {\n      auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));\n      return (bits & exponent_mask<double>()) != exponent_mask<double>();\n    }\n#endif\n  }\n  return std::isfinite(value);\n}\n\ntemplate <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>\nFMT_INLINE FMT_CONSTEXPR bool signbit(T value) {\n  if (is_constant_evaluated()) {\n#ifdef __cpp_if_constexpr\n    if constexpr (std::numeric_limits<double>::is_iec559) {\n      auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));\n      return (bits & (uint64_t(1) << (num_bits<uint64_t>() - 1))) != 0;\n    }\n#endif\n  }\n  return std::signbit(value);\n}\n\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(std::is_floating_point<T>::value)>\nFMT_CONSTEXPR20 auto write(OutputIt out, T value,\n                           basic_format_specs<Char> specs, locale_ref loc = {})\n    -> OutputIt {\n  if (const_check(!is_supported_floating_point(value))) return out;\n  float_specs fspecs = parse_float_type_spec(specs);\n  fspecs.sign = specs.sign;\n  if (detail::signbit(value)) {  // value < 0 is false for NaN so use signbit.\n    fspecs.sign = sign::minus;\n    value = -value;\n  } else if (fspecs.sign == sign::minus) {\n    fspecs.sign = sign::none;\n  }\n\n  if (!detail::isfinite(value))\n    return write_nonfinite(out, detail::isinf(value), specs, fspecs);\n\n  if (specs.align == align::numeric && fspecs.sign) {\n    auto it = reserve(out, 1);\n    *it++ = detail::sign<Char>(fspecs.sign);\n    out = base_iterator(out, it);\n    fspecs.sign = sign::none;\n    if (specs.width != 0) --specs.width;\n  }\n\n  memory_buffer buffer;\n  if (fspecs.format == float_format::hex) {\n    if (fspecs.sign) buffer.push_back(detail::sign<char>(fspecs.sign));\n    snprintf_float(promote_float(value), specs.precision, fspecs, buffer);\n    return write_bytes<align::right>(out, {buffer.data(), buffer.size()},\n                                     specs);\n  }\n  int precision = specs.precision >= 0 || specs.type == presentation_type::none\n                      ? specs.precision\n                      : 6;\n  if (fspecs.format == float_format::exp) {\n    if (precision == max_value<int>())\n      throw_format_error(\"number is too big\");\n    else\n      ++precision;\n  }\n  if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;\n  if (!is_fast_float<T>()) fspecs.fallback = true;\n  int exp = format_float(promote_float(value), precision, fspecs, buffer);\n  fspecs.precision = precision;\n  auto fp = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};\n  return write_float(out, fp, specs, fspecs, loc);\n}\n\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(is_fast_float<T>::value)>\nFMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {\n  if (is_constant_evaluated()) {\n    return write(out, value, basic_format_specs<Char>());\n  }\n\n  if (const_check(!is_supported_floating_point(value))) return out;\n\n  using floaty = conditional_t<std::is_same<T, long double>::value, double, T>;\n  using uint = typename dragonbox::float_info<floaty>::carrier_uint;\n  auto bits = bit_cast<uint>(value);\n\n  auto fspecs = float_specs();\n  if (detail::signbit(value)) {\n    fspecs.sign = sign::minus;\n    value = -value;\n  }\n\n  constexpr auto specs = basic_format_specs<Char>();\n  uint mask = exponent_mask<floaty>();\n  if ((bits & mask) == mask)\n    return write_nonfinite(out, std::isinf(value), specs, fspecs);\n\n  auto dec = dragonbox::to_decimal(static_cast<floaty>(value));\n  return write_float(out, dec, specs, fspecs, {});\n}\n\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(std::is_floating_point<T>::value &&\n                        !is_fast_float<T>::value)>\ninline auto write(OutputIt out, T value) -> OutputIt {\n  return write(out, value, basic_format_specs<Char>());\n}\n\ntemplate <typename Char, typename OutputIt>\nauto write(OutputIt out, monostate, basic_format_specs<Char> = {},\n           locale_ref = {}) -> OutputIt {\n  FMT_ASSERT(false, \"\");\n  return out;\n}\n\ntemplate <typename Char, typename OutputIt>\nFMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> value)\n    -> OutputIt {\n  auto it = reserve(out, value.size());\n  it = copy_str_noinline<Char>(value.begin(), value.end(), it);\n  return base_iterator(out, it);\n}\n\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(is_string<T>::value)>\nconstexpr auto write(OutputIt out, const T& value) -> OutputIt {\n  return write<Char>(out, to_string_view(value));\n}\n\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(is_integral<T>::value &&\n                        !std::is_same<T, bool>::value &&\n                        !std::is_same<T, Char>::value)>\nFMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {\n  auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);\n  bool negative = is_negative(value);\n  // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.\n  if (negative) abs_value = ~abs_value + 1;\n  int num_digits = count_digits(abs_value);\n  auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);\n  auto it = reserve(out, size);\n  if (auto ptr = to_pointer<Char>(it, size)) {\n    if (negative) *ptr++ = static_cast<Char>('-');\n    format_decimal<Char>(ptr, abs_value, num_digits);\n    return out;\n  }\n  if (negative) *it++ = static_cast<Char>('-');\n  it = format_decimal<Char>(it, abs_value, num_digits).end;\n  return base_iterator(out, it);\n}\n\n// FMT_ENABLE_IF() condition separated to workaround an MSVC bug.\ntemplate <\n    typename Char, typename OutputIt, typename T,\n    bool check =\n        std::is_enum<T>::value && !std::is_same<T, Char>::value &&\n        mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value !=\n            type::custom_type,\n    FMT_ENABLE_IF(check)>\nFMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {\n  return write<Char>(\n      out, static_cast<typename std::underlying_type<T>::type>(value));\n}\n\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(std::is_same<T, bool>::value)>\nFMT_CONSTEXPR auto write(OutputIt out, T value,\n                         const basic_format_specs<Char>& specs = {},\n                         locale_ref = {}) -> OutputIt {\n  return specs.type != presentation_type::none &&\n                 specs.type != presentation_type::string\n             ? write(out, value ? 1 : 0, specs, {})\n             : write_bytes(out, value ? \"true\" : \"false\", specs);\n}\n\ntemplate <typename Char, typename OutputIt>\nFMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt {\n  auto it = reserve(out, 1);\n  *it++ = value;\n  return base_iterator(out, it);\n}\n\ntemplate <typename Char, typename OutputIt>\nFMT_CONSTEXPR_CHAR_TRAITS auto write(OutputIt out, const Char* value)\n    -> OutputIt {\n  if (!value) {\n    throw_format_error(\"string pointer is null\");\n  } else {\n    out = write(out, basic_string_view<Char>(value));\n  }\n  return out;\n}\n\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(std::is_same<T, void>::value)>\nauto write(OutputIt out, const T* value,\n           const basic_format_specs<Char>& specs = {}, locale_ref = {})\n    -> OutputIt {\n  check_pointer_type_spec(specs.type, error_handler());\n  return write_ptr<Char>(out, to_uintptr(value), &specs);\n}\n\n// A write overload that handles implicit conversions.\ntemplate <typename Char, typename OutputIt, typename T,\n          typename Context = basic_format_context<OutputIt, Char>>\nFMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t<\n    std::is_class<T>::value && !is_string<T>::value &&\n        !std::is_same<T, Char>::value &&\n        !std::is_same<const T&,\n                      decltype(arg_mapper<Context>().map(value))>::value,\n    OutputIt> {\n  return write<Char>(out, arg_mapper<Context>().map(value));\n}\n\ntemplate <typename Char, typename OutputIt, typename T,\n          typename Context = basic_format_context<OutputIt, Char>>\nFMT_CONSTEXPR auto write(OutputIt out, const T& value)\n    -> enable_if_t<mapped_type_constant<T, Context>::value == type::custom_type,\n                   OutputIt> {\n  using formatter_type =\n      conditional_t<has_formatter<T, Context>::value,\n                    typename Context::template formatter_type<T>,\n                    fallback_formatter<T, Char>>;\n  auto ctx = Context(out, {}, {});\n  return formatter_type().format(value, ctx);\n}\n\n// An argument visitor that formats the argument and writes it via the output\n// iterator. It's a class and not a generic lambda for compatibility with C++11.\ntemplate <typename Char> struct default_arg_formatter {\n  using iterator = buffer_appender<Char>;\n  using context = buffer_context<Char>;\n\n  iterator out;\n  basic_format_args<context> args;\n  locale_ref loc;\n\n  template <typename T> auto operator()(T value) -> iterator {\n    return write<Char>(out, value);\n  }\n  auto operator()(typename basic_format_arg<context>::handle h) -> iterator {\n    basic_format_parse_context<Char> parse_ctx({});\n    context format_ctx(out, args, loc);\n    h.format(parse_ctx, format_ctx);\n    return format_ctx.out();\n  }\n};\n\ntemplate <typename Char> struct arg_formatter {\n  using iterator = buffer_appender<Char>;\n  using context = buffer_context<Char>;\n\n  iterator out;\n  const basic_format_specs<Char>& specs;\n  locale_ref locale;\n\n  template <typename T>\n  FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator {\n    return detail::write(out, value, specs, locale);\n  }\n  auto operator()(typename basic_format_arg<context>::handle) -> iterator {\n    // User-defined types are handled separately because they require access\n    // to the parse context.\n    return out;\n  }\n};\n\ntemplate <typename Char> struct custom_formatter {\n  basic_format_parse_context<Char>& parse_ctx;\n  buffer_context<Char>& ctx;\n\n  void operator()(\n      typename basic_format_arg<buffer_context<Char>>::handle h) const {\n    h.format(parse_ctx, ctx);\n  }\n  template <typename T> void operator()(T) const {}\n};\n\ntemplate <typename T>\nusing is_integer =\n    bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&\n                  !std::is_same<T, char>::value &&\n                  !std::is_same<T, wchar_t>::value>;\n\ntemplate <typename ErrorHandler> class width_checker {\n public:\n  explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {}\n\n  template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>\n  FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {\n    if (is_negative(value)) handler_.on_error(\"negative width\");\n    return static_cast<unsigned long long>(value);\n  }\n\n  template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>\n  FMT_CONSTEXPR auto operator()(T) -> unsigned long long {\n    handler_.on_error(\"width is not integer\");\n    return 0;\n  }\n\n private:\n  ErrorHandler& handler_;\n};\n\ntemplate <typename ErrorHandler> class precision_checker {\n public:\n  explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {}\n\n  template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>\n  FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {\n    if (is_negative(value)) handler_.on_error(\"negative precision\");\n    return static_cast<unsigned long long>(value);\n  }\n\n  template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>\n  FMT_CONSTEXPR auto operator()(T) -> unsigned long long {\n    handler_.on_error(\"precision is not integer\");\n    return 0;\n  }\n\n private:\n  ErrorHandler& handler_;\n};\n\ntemplate <template <typename> class Handler, typename FormatArg,\n          typename ErrorHandler>\nFMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) -> int {\n  unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg);\n  if (value > to_unsigned(max_value<int>())) eh.on_error(\"number is too big\");\n  return static_cast<int>(value);\n}\n\ntemplate <typename Context, typename ID>\nFMT_CONSTEXPR auto get_arg(Context& ctx, ID id) ->\n    typename Context::format_arg {\n  auto arg = ctx.arg(id);\n  if (!arg) ctx.on_error(\"argument not found\");\n  return arg;\n}\n\n// The standard format specifier handler with checking.\ntemplate <typename Char> class specs_handler : public specs_setter<Char> {\n private:\n  basic_format_parse_context<Char>& parse_context_;\n  buffer_context<Char>& context_;\n\n  // This is only needed for compatibility with gcc 4.4.\n  using format_arg = basic_format_arg<buffer_context<Char>>;\n\n  FMT_CONSTEXPR auto get_arg(auto_id) -> format_arg {\n    return detail::get_arg(context_, parse_context_.next_arg_id());\n  }\n\n  FMT_CONSTEXPR auto get_arg(int arg_id) -> format_arg {\n    parse_context_.check_arg_id(arg_id);\n    return detail::get_arg(context_, arg_id);\n  }\n\n  FMT_CONSTEXPR auto get_arg(basic_string_view<Char> arg_id) -> format_arg {\n    parse_context_.check_arg_id(arg_id);\n    return detail::get_arg(context_, arg_id);\n  }\n\n public:\n  FMT_CONSTEXPR specs_handler(basic_format_specs<Char>& specs,\n                              basic_format_parse_context<Char>& parse_ctx,\n                              buffer_context<Char>& ctx)\n      : specs_setter<Char>(specs), parse_context_(parse_ctx), context_(ctx) {}\n\n  template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {\n    this->specs_.width = get_dynamic_spec<width_checker>(\n        get_arg(arg_id), context_.error_handler());\n  }\n\n  template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {\n    this->specs_.precision = get_dynamic_spec<precision_checker>(\n        get_arg(arg_id), context_.error_handler());\n  }\n\n  void on_error(const char* message) { context_.on_error(message); }\n};\n\ntemplate <template <typename> class Handler, typename Context>\nFMT_CONSTEXPR void handle_dynamic_spec(int& value,\n                                       arg_ref<typename Context::char_type> ref,\n                                       Context& ctx) {\n  switch (ref.kind) {\n  case arg_id_kind::none:\n    break;\n  case arg_id_kind::index:\n    value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.index),\n                                              ctx.error_handler());\n    break;\n  case arg_id_kind::name:\n    value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.name),\n                                              ctx.error_handler());\n    break;\n  }\n}\n\n#define FMT_STRING_IMPL(s, base, explicit)                                 \\\n  [] {                                                                     \\\n    /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \\\n    /* Use a macro-like name to avoid shadowing warnings. */               \\\n    struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base {           \\\n      using char_type = fmt::remove_cvref_t<decltype(s[0])>;               \\\n      FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit                              \\\n      operator fmt::basic_string_view<char_type>() const {                 \\\n        return fmt::detail_exported::compile_string_to_view<char_type>(s); \\\n      }                                                                    \\\n    };                                                                     \\\n    return FMT_COMPILE_STRING();                                           \\\n  }()\n\n/**\n  \\rst\n  Constructs a compile-time format string from a string literal *s*.\n\n  **Example**::\n\n    // A compile-time error because 'd' is an invalid specifier for strings.\n    std::string s = fmt::format(FMT_STRING(\"{:d}\"), \"foo\");\n  \\endrst\n */\n#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string, )\n\n#if FMT_USE_USER_DEFINED_LITERALS\ntemplate <typename Char> struct udl_formatter {\n  basic_string_view<Char> str;\n\n  template <typename... T>\n  auto operator()(T&&... args) const -> std::basic_string<Char> {\n    return vformat(str, fmt::make_args_checked<T...>(str, args...));\n  }\n};\n\n#  if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\ntemplate <typename T, typename Char, size_t N,\n          fmt::detail_exported::fixed_string<Char, N> Str>\nstruct statically_named_arg : view {\n  static constexpr auto name = Str.data;\n\n  const T& value;\n  statically_named_arg(const T& v) : value(v) {}\n};\n\ntemplate <typename T, typename Char, size_t N,\n          fmt::detail_exported::fixed_string<Char, N> Str>\nstruct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};\n\ntemplate <typename T, typename Char, size_t N,\n          fmt::detail_exported::fixed_string<Char, N> Str>\nstruct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>\n    : std::true_type {};\n\ntemplate <typename Char, size_t N,\n          fmt::detail_exported::fixed_string<Char, N> Str>\nstruct udl_arg {\n  template <typename T> auto operator=(T&& value) const {\n    return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));\n  }\n};\n#  else\ntemplate <typename Char> struct udl_arg {\n  const Char* str;\n\n  template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> {\n    return {str, std::forward<T>(value)};\n  }\n};\n#  endif\n#endif  // FMT_USE_USER_DEFINED_LITERALS\n\ntemplate <typename Locale, typename Char>\nauto vformat(const Locale& loc, basic_string_view<Char> format_str,\n             basic_format_args<buffer_context<type_identity_t<Char>>> args)\n    -> std::basic_string<Char> {\n  basic_memory_buffer<Char> buffer;\n  detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc));\n  return {buffer.data(), buffer.size()};\n}\n\nusing format_func = void (*)(detail::buffer<char>&, int, const char*);\n\nFMT_API void format_error_code(buffer<char>& out, int error_code,\n                               string_view message) FMT_NOEXCEPT;\n\nFMT_API void report_error(format_func func, int error_code,\n                          const char* message) FMT_NOEXCEPT;\nFMT_END_DETAIL_NAMESPACE\n\nFMT_API auto vsystem_error(int error_code, string_view format_str,\n                           format_args args) -> std::system_error;\n\n/**\n \\rst\n Constructs :class:`std::system_error` with a message formatted with\n ``fmt::format(fmt, args...)``.\n  *error_code* is a system error code as given by ``errno``.\n\n **Example**::\n\n   // This throws std::system_error with the description\n   //   cannot open file 'madeup': No such file or directory\n   // or similar (system message may vary).\n   const char* filename = \"madeup\";\n   std::FILE* file = std::fopen(filename, \"r\");\n   if (!file)\n     throw fmt::system_error(errno, \"cannot open file '{}'\", filename);\n \\endrst\n*/\ntemplate <typename... T>\nauto system_error(int error_code, format_string<T...> fmt, T&&... args)\n    -> std::system_error {\n  return vsystem_error(error_code, fmt, fmt::make_format_args(args...));\n}\n\n/**\n  \\rst\n  Formats an error message for an error returned by an operating system or a\n  language runtime, for example a file opening error, and writes it to *out*.\n  The format is the same as the one used by ``std::system_error(ec, message)``\n  where ``ec`` is ``std::error_code(error_code, std::generic_category()})``.\n  It is implementation-defined but normally looks like:\n\n  .. parsed-literal::\n     *<message>*: *<system-message>*\n\n  where *<message>* is the passed message and *<system-message>* is the system\n  message corresponding to the error code.\n  *error_code* is a system error code as given by ``errno``.\n  \\endrst\n */\nFMT_API void format_system_error(detail::buffer<char>& out, int error_code,\n                                 const char* message) FMT_NOEXCEPT;\n\n// Reports a system error without throwing an exception.\n// Can be used to report errors from destructors.\nFMT_API void report_system_error(int error_code,\n                                 const char* message) FMT_NOEXCEPT;\n\n/** Fast integer formatter. */\nclass format_int {\n private:\n  // Buffer should be large enough to hold all digits (digits10 + 1),\n  // a sign and a null character.\n  enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };\n  mutable char buffer_[buffer_size];\n  char* str_;\n\n  template <typename UInt> auto format_unsigned(UInt value) -> char* {\n    auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);\n    return detail::format_decimal(buffer_, n, buffer_size - 1).begin;\n  }\n\n  template <typename Int> auto format_signed(Int value) -> char* {\n    auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);\n    bool negative = value < 0;\n    if (negative) abs_value = 0 - abs_value;\n    auto begin = format_unsigned(abs_value);\n    if (negative) *--begin = '-';\n    return begin;\n  }\n\n public:\n  explicit format_int(int value) : str_(format_signed(value)) {}\n  explicit format_int(long value) : str_(format_signed(value)) {}\n  explicit format_int(long long value) : str_(format_signed(value)) {}\n  explicit format_int(unsigned value) : str_(format_unsigned(value)) {}\n  explicit format_int(unsigned long value) : str_(format_unsigned(value)) {}\n  explicit format_int(unsigned long long value)\n      : str_(format_unsigned(value)) {}\n\n  /** Returns the number of characters written to the output buffer. */\n  auto size() const -> size_t {\n    return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);\n  }\n\n  /**\n    Returns a pointer to the output buffer content. No terminating null\n    character is appended.\n   */\n  auto data() const -> const char* { return str_; }\n\n  /**\n    Returns a pointer to the output buffer content with terminating null\n    character appended.\n   */\n  auto c_str() const -> const char* {\n    buffer_[buffer_size - 1] = '\\0';\n    return str_;\n  }\n\n  /**\n    \\rst\n    Returns the content of the output buffer as an ``std::string``.\n    \\endrst\n   */\n  auto str() const -> std::string { return std::string(str_, size()); }\n};\n\ntemplate <typename T, typename Char>\ntemplate <typename FormatContext>\nFMT_CONSTEXPR FMT_INLINE auto\nformatter<T, Char,\n          enable_if_t<detail::type_constant<T, Char>::value !=\n                      detail::type::custom_type>>::format(const T& val,\n                                                          FormatContext& ctx)\n    const -> decltype(ctx.out()) {\n  if (specs_.width_ref.kind != detail::arg_id_kind::none ||\n      specs_.precision_ref.kind != detail::arg_id_kind::none) {\n    auto specs = specs_;\n    detail::handle_dynamic_spec<detail::width_checker>(specs.width,\n                                                       specs.width_ref, ctx);\n    detail::handle_dynamic_spec<detail::precision_checker>(\n        specs.precision, specs.precision_ref, ctx);\n    return detail::write<Char>(ctx.out(), val, specs, ctx.locale());\n  }\n  return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());\n}\n\n#define FMT_FORMAT_AS(Type, Base)                                        \\\n  template <typename Char>                                               \\\n  struct formatter<Type, Char> : formatter<Base, Char> {                 \\\n    template <typename FormatContext>                                    \\\n    auto format(Type const& val, FormatContext& ctx) const               \\\n        -> decltype(ctx.out()) {                                         \\\n      return formatter<Base, Char>::format(static_cast<Base>(val), ctx); \\\n    }                                                                    \\\n  }\n\nFMT_FORMAT_AS(signed char, int);\nFMT_FORMAT_AS(unsigned char, unsigned);\nFMT_FORMAT_AS(short, int);\nFMT_FORMAT_AS(unsigned short, unsigned);\nFMT_FORMAT_AS(long, long long);\nFMT_FORMAT_AS(unsigned long, unsigned long long);\nFMT_FORMAT_AS(Char*, const Char*);\nFMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);\nFMT_FORMAT_AS(std::nullptr_t, const void*);\nFMT_FORMAT_AS(detail::byte, unsigned char);\nFMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);\n\ntemplate <typename Char>\nstruct formatter<void*, Char> : formatter<const void*, Char> {\n  template <typename FormatContext>\n  auto format(void* val, FormatContext& ctx) const -> decltype(ctx.out()) {\n    return formatter<const void*, Char>::format(val, ctx);\n  }\n};\n\ntemplate <typename Char, size_t N>\nstruct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {\n  template <typename FormatContext>\n  FMT_CONSTEXPR auto format(const Char* val, FormatContext& ctx) const\n      -> decltype(ctx.out()) {\n    return formatter<basic_string_view<Char>, Char>::format(val, ctx);\n  }\n};\n\n// A formatter for types known only at run time such as variant alternatives.\n//\n// Usage:\n//   using variant = std::variant<int, std::string>;\n//   template <>\n//   struct formatter<variant>: dynamic_formatter<> {\n//     auto format(const variant& v, format_context& ctx) {\n//       return visit([&](const auto& val) {\n//           return dynamic_formatter<>::format(val, ctx);\n//       }, v);\n//     }\n//   };\ntemplate <typename Char = char> class dynamic_formatter {\n private:\n  detail::dynamic_format_specs<Char> specs_;\n  const Char* format_str_;\n\n  struct null_handler : detail::error_handler {\n    void on_align(align_t) {}\n    void on_sign(sign_t) {}\n    void on_hash() {}\n  };\n\n  template <typename Context> void handle_specs(Context& ctx) {\n    detail::handle_dynamic_spec<detail::width_checker>(specs_.width,\n                                                       specs_.width_ref, ctx);\n    detail::handle_dynamic_spec<detail::precision_checker>(\n        specs_.precision, specs_.precision_ref, ctx);\n  }\n\n public:\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    format_str_ = ctx.begin();\n    // Checks are deferred to formatting time when the argument type is known.\n    detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx);\n    return detail::parse_format_specs(ctx.begin(), ctx.end(), handler);\n  }\n\n  template <typename T, typename FormatContext>\n  auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {\n    handle_specs(ctx);\n    detail::specs_checker<null_handler> checker(\n        null_handler(), detail::mapped_type_constant<T, FormatContext>::value);\n    checker.on_align(specs_.align);\n    if (specs_.sign != sign::none) checker.on_sign(specs_.sign);\n    if (specs_.alt) checker.on_hash();\n    if (specs_.precision >= 0) checker.end_precision();\n    return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());\n  }\n};\n\n/**\n  \\rst\n  Converts ``p`` to ``const void*`` for pointer formatting.\n\n  **Example**::\n\n    auto s = fmt::format(\"{}\", fmt::ptr(p));\n  \\endrst\n */\ntemplate <typename T> auto ptr(T p) -> const void* {\n  static_assert(std::is_pointer<T>::value, \"\");\n  return detail::bit_cast<const void*>(p);\n}\ntemplate <typename T> auto ptr(const std::unique_ptr<T>& p) -> const void* {\n  return p.get();\n}\ntemplate <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {\n  return p.get();\n}\n\nclass bytes {\n private:\n  string_view data_;\n  friend struct formatter<bytes>;\n\n public:\n  explicit bytes(string_view data) : data_(data) {}\n};\n\ntemplate <> struct formatter<bytes> {\n private:\n  detail::dynamic_format_specs<char> specs_;\n\n public:\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    using handler_type = detail::dynamic_specs_handler<ParseContext>;\n    detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),\n                                                detail::type::string_type);\n    auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);\n    detail::check_string_type_spec(specs_.type, ctx.error_handler());\n    return it;\n  }\n\n  template <typename FormatContext>\n  auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {\n    detail::handle_dynamic_spec<detail::width_checker>(specs_.width,\n                                                       specs_.width_ref, ctx);\n    detail::handle_dynamic_spec<detail::precision_checker>(\n        specs_.precision, specs_.precision_ref, ctx);\n    return detail::write_bytes(ctx.out(), b.data_, specs_);\n  }\n};\n\n// group_digits_view is not derived from view because it copies the argument.\ntemplate <typename T> struct group_digits_view { T value; };\n\n/**\n  \\rst\n  Returns a view that formats an integer value using ',' as a locale-independent\n  thousands separator.\n\n  **Example**::\n\n    fmt::print(\"{}\", fmt::group_digits(12345));\n    // Output: \"12,345\"\n  \\endrst\n */\ntemplate <typename T> auto group_digits(T value) -> group_digits_view<T> {\n  return {value};\n}\n\ntemplate <typename T> struct formatter<group_digits_view<T>> : formatter<T> {\n private:\n  detail::dynamic_format_specs<char> specs_;\n\n public:\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    using handler_type = detail::dynamic_specs_handler<ParseContext>;\n    detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),\n                                                detail::type::int_type);\n    auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);\n    detail::check_string_type_spec(specs_.type, ctx.error_handler());\n    return it;\n  }\n\n  template <typename FormatContext>\n  auto format(group_digits_view<T> t, FormatContext& ctx)\n      -> decltype(ctx.out()) {\n    detail::handle_dynamic_spec<detail::width_checker>(specs_.width,\n                                                       specs_.width_ref, ctx);\n    detail::handle_dynamic_spec<detail::precision_checker>(\n        specs_.precision, specs_.precision_ref, ctx);\n    return detail::write_int_localized(\n        ctx.out(), static_cast<detail::uint64_or_128_t<T>>(t.value), 0, specs_,\n        detail::digit_grouping<char>({\"\\3\", ','}));\n  }\n};\n\ntemplate <typename It, typename Sentinel, typename Char = char>\nstruct join_view : detail::view {\n  It begin;\n  Sentinel end;\n  basic_string_view<Char> sep;\n\n  join_view(It b, Sentinel e, basic_string_view<Char> s)\n      : begin(b), end(e), sep(s) {}\n};\n\ntemplate <typename It, typename Sentinel, typename Char>\nusing arg_join FMT_DEPRECATED_ALIAS = join_view<It, Sentinel, Char>;\n\ntemplate <typename It, typename Sentinel, typename Char>\nstruct formatter<join_view<It, Sentinel, Char>, Char> {\n private:\n  using value_type =\n#ifdef __cpp_lib_ranges\n      std::iter_value_t<It>;\n#else\n      typename std::iterator_traits<It>::value_type;\n#endif\n  using context = buffer_context<Char>;\n  using mapper = detail::arg_mapper<context>;\n\n  template <typename T, FMT_ENABLE_IF(has_formatter<T, context>::value)>\n  static auto map(const T& value) -> const T& {\n    return value;\n  }\n  template <typename T, FMT_ENABLE_IF(!has_formatter<T, context>::value)>\n  static auto map(const T& value) -> decltype(mapper().map(value)) {\n    return mapper().map(value);\n  }\n\n  using formatter_type =\n      conditional_t<is_formattable<value_type, Char>::value,\n                    formatter<remove_cvref_t<decltype(map(\n                                  std::declval<const value_type&>()))>,\n                              Char>,\n                    detail::fallback_formatter<value_type, Char>>;\n\n  formatter_type value_formatter_;\n\n public:\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    return value_formatter_.parse(ctx);\n  }\n\n  template <typename FormatContext>\n  auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx)\n      -> decltype(ctx.out()) {\n    auto it = value.begin;\n    auto out = ctx.out();\n    if (it != value.end) {\n      out = value_formatter_.format(map(*it), ctx);\n      ++it;\n      while (it != value.end) {\n        out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out);\n        ctx.advance_to(out);\n        out = value_formatter_.format(map(*it), ctx);\n        ++it;\n      }\n    }\n    return out;\n  }\n};\n\n/**\n  Returns a view that formats the iterator range `[begin, end)` with elements\n  separated by `sep`.\n */\ntemplate <typename It, typename Sentinel>\nauto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {\n  return {begin, end, sep};\n}\n\n/**\n  \\rst\n  Returns a view that formats `range` with elements separated by `sep`.\n\n  **Example**::\n\n    std::vector<int> v = {1, 2, 3};\n    fmt::print(\"{}\", fmt::join(v, \", \"));\n    // Output: \"1, 2, 3\"\n\n  ``fmt::join`` applies passed format specifiers to the range elements::\n\n    fmt::print(\"{:02}\", fmt::join(v, \", \"));\n    // Output: \"01, 02, 03\"\n  \\endrst\n */\ntemplate <typename Range>\nauto join(Range&& range, string_view sep)\n    -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>> {\n  return join(std::begin(range), std::end(range), sep);\n}\n\n/**\n  \\rst\n  Converts *value* to ``std::string`` using the default format for type *T*.\n\n  **Example**::\n\n    #include <fmt/format.h>\n\n    std::string answer = fmt::to_string(42);\n  \\endrst\n */\ntemplate <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>\ninline auto to_string(const T& value) -> std::string {\n  auto result = std::string();\n  detail::write<char>(std::back_inserter(result), value);\n  return result;\n}\n\ntemplate <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>\nFMT_NODISCARD inline auto to_string(T value) -> std::string {\n  // The buffer should be large enough to store the number including the sign\n  // or \"false\" for bool.\n  constexpr int max_size = detail::digits10<T>() + 2;\n  char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];\n  char* begin = buffer;\n  return std::string(begin, detail::write<char>(begin, value));\n}\n\ntemplate <typename Char, size_t SIZE>\nFMT_NODISCARD auto to_string(const basic_memory_buffer<Char, SIZE>& buf)\n    -> std::basic_string<Char> {\n  auto size = buf.size();\n  detail::assume(size < std::basic_string<Char>().max_size());\n  return std::basic_string<Char>(buf.data(), size);\n}\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\ntemplate <typename Char>\nvoid vformat_to(\n    buffer<Char>& buf, basic_string_view<Char> fmt,\n    basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args,\n    locale_ref loc) {\n  // workaround for msvc bug regarding name-lookup in module\n  // link names into function scope\n  using detail::arg_formatter;\n  using detail::buffer_appender;\n  using detail::custom_formatter;\n  using detail::default_arg_formatter;\n  using detail::get_arg;\n  using detail::locale_ref;\n  using detail::parse_format_specs;\n  using detail::specs_checker;\n  using detail::specs_handler;\n  using detail::to_unsigned;\n  using detail::type;\n  using detail::write;\n  auto out = buffer_appender<Char>(buf);\n  if (fmt.size() == 2 && equal2(fmt.data(), \"{}\")) {\n    auto arg = args.get(0);\n    if (!arg) error_handler().on_error(\"argument not found\");\n    visit_format_arg(default_arg_formatter<Char>{out, args, loc}, arg);\n    return;\n  }\n\n  struct format_handler : error_handler {\n    basic_format_parse_context<Char> parse_context;\n    buffer_context<Char> context;\n\n    format_handler(buffer_appender<Char> out, basic_string_view<Char> str,\n                   basic_format_args<buffer_context<Char>> args, locale_ref loc)\n        : parse_context(str), context(out, args, loc) {}\n\n    void on_text(const Char* begin, const Char* end) {\n      auto text = basic_string_view<Char>(begin, to_unsigned(end - begin));\n      context.advance_to(write<Char>(context.out(), text));\n    }\n\n    FMT_CONSTEXPR auto on_arg_id() -> int {\n      return parse_context.next_arg_id();\n    }\n    FMT_CONSTEXPR auto on_arg_id(int id) -> int {\n      return parse_context.check_arg_id(id), id;\n    }\n    FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {\n      int arg_id = context.arg_id(id);\n      if (arg_id < 0) on_error(\"argument not found\");\n      return arg_id;\n    }\n\n    FMT_INLINE void on_replacement_field(int id, const Char*) {\n      auto arg = get_arg(context, id);\n      context.advance_to(visit_format_arg(\n          default_arg_formatter<Char>{context.out(), context.args(),\n                                      context.locale()},\n          arg));\n    }\n\n    auto on_format_specs(int id, const Char* begin, const Char* end)\n        -> const Char* {\n      auto arg = get_arg(context, id);\n      if (arg.type() == type::custom_type) {\n        parse_context.advance_to(parse_context.begin() +\n                                 (begin - &*parse_context.begin()));\n        visit_format_arg(custom_formatter<Char>{parse_context, context}, arg);\n        return parse_context.begin();\n      }\n      auto specs = basic_format_specs<Char>();\n      specs_checker<specs_handler<Char>> handler(\n          specs_handler<Char>(specs, parse_context, context), arg.type());\n      begin = parse_format_specs(begin, end, handler);\n      if (begin == end || *begin != '}')\n        on_error(\"missing '}' in format string\");\n      auto f = arg_formatter<Char>{context.out(), specs, context.locale()};\n      context.advance_to(visit_format_arg(f, arg));\n      return begin;\n    }\n  };\n  detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc));\n}\n\n#ifndef FMT_HEADER_ONLY\nextern template FMT_API auto thousands_sep_impl<char>(locale_ref)\n    -> thousands_sep_result<char>;\nextern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref)\n    -> thousands_sep_result<wchar_t>;\nextern template FMT_API auto decimal_point_impl(locale_ref) -> char;\nextern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;\nextern template auto format_float<double>(double value, int precision,\n                                          float_specs specs, buffer<char>& buf)\n    -> int;\nextern template auto format_float<long double>(long double value, int precision,\n                                               float_specs specs,\n                                               buffer<char>& buf) -> int;\nvoid snprintf_float(float, int, float_specs, buffer<char>&) = delete;\nextern template auto snprintf_float<double>(double value, int precision,\n                                            float_specs specs,\n                                            buffer<char>& buf) -> int;\nextern template auto snprintf_float<long double>(long double value,\n                                                 int precision,\n                                                 float_specs specs,\n                                                 buffer<char>& buf) -> int;\n#endif  // FMT_HEADER_ONLY\n\nFMT_END_DETAIL_NAMESPACE\n\n#if FMT_USE_USER_DEFINED_LITERALS\ninline namespace literals {\n/**\n  \\rst\n  User-defined literal equivalent of :func:`fmt::arg`.\n\n  **Example**::\n\n    using namespace fmt::literals;\n    fmt::print(\"Elapsed time: {s:.2f} seconds\", \"s\"_a=1.23);\n  \\endrst\n */\n#  if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\ntemplate <detail_exported::fixed_string Str>\nconstexpr auto operator\"\"_a()\n    -> detail::udl_arg<remove_cvref_t<decltype(Str.data[0])>,\n                       sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> {\n  return {};\n}\n#  else\nconstexpr auto operator\"\"_a(const char* s, size_t) -> detail::udl_arg<char> {\n  return {s};\n}\n#  endif\n\n// DEPRECATED!\n// User-defined literal equivalent of fmt::format.\nFMT_DEPRECATED constexpr auto operator\"\"_format(const char* s, size_t n)\n    -> detail::udl_formatter<char> {\n  return {{s, n}};\n}\n}  // namespace literals\n#endif  // FMT_USE_USER_DEFINED_LITERALS\n\ntemplate <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>\ninline auto vformat(const Locale& loc, string_view fmt, format_args args)\n    -> std::string {\n  return detail::vformat(loc, fmt, args);\n}\n\ntemplate <typename Locale, typename... T,\n          FMT_ENABLE_IF(detail::is_locale<Locale>::value)>\ninline auto format(const Locale& loc, format_string<T...> fmt, T&&... args)\n    -> std::string {\n  return vformat(loc, string_view(fmt), fmt::make_format_args(args...));\n}\n\ntemplate <typename... T, size_t SIZE, typename Allocator>\nFMT_DEPRECATED auto format_to(basic_memory_buffer<char, SIZE, Allocator>& buf,\n                              format_string<T...> fmt, T&&... args)\n    -> appender {\n  detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...));\n  return appender(buf);\n}\n\ntemplate <typename OutputIt, typename Locale,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&\n                            detail::is_locale<Locale>::value)>\nauto vformat_to(OutputIt out, const Locale& loc, string_view fmt,\n                format_args args) -> OutputIt {\n  using detail::get_buffer;\n  auto&& buf = get_buffer<char>(out);\n  detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));\n  return detail::get_iterator(buf);\n}\n\ntemplate <typename OutputIt, typename Locale, typename... T,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&\n                            detail::is_locale<Locale>::value)>\nFMT_INLINE auto format_to(OutputIt out, const Locale& loc,\n                          format_string<T...> fmt, T&&... args) -> OutputIt {\n  return vformat_to(out, loc, fmt, fmt::make_format_args(args...));\n}\n\nFMT_MODULE_EXPORT_END\nFMT_END_NAMESPACE\n\n#ifdef FMT_DEPRECATED_INCLUDE_XCHAR\n#  include \"xchar.h\"\n#endif\n\n#ifdef FMT_HEADER_ONLY\n#  define FMT_FUNC inline\n#  include \"format-inl.h\"\n#else\n#  define FMT_FUNC\n#endif\n\n#endif  // FMT_FORMAT_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/locale.h",
    "content": "#include \"xchar.h\"\n#warning fmt/locale.h is deprecated, include fmt/format.h or fmt/xchar.h instead\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/os.h",
    "content": "// Formatting library for C++ - optional OS-specific functionality\n//\n// Copyright (c) 2012 - present, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_OS_H_\n#define FMT_OS_H_\n\n#include <cerrno>\n#include <clocale>  // locale_t\n#include <cstddef>\n#include <cstdio>\n#include <cstdlib>       // strtod_l\n#include <system_error>  // std::system_error\n\n#if defined __APPLE__ || defined(__FreeBSD__)\n#  include <xlocale.h>  // for LC_NUMERIC_MASK on OS X\n#endif\n\n#include \"format.h\"\n\n#ifndef FMT_USE_FCNTL\n// UWP doesn't provide _pipe.\n#  if FMT_HAS_INCLUDE(\"winapifamily.h\")\n#    include <winapifamily.h>\n#  endif\n#  if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \\\n       defined(__linux__)) &&                              \\\n      (!defined(WINAPI_FAMILY) ||                          \\\n       (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))\n#    include <fcntl.h>  // for O_RDONLY\n#    define FMT_USE_FCNTL 1\n#  else\n#    define FMT_USE_FCNTL 0\n#  endif\n#endif\n\n#ifndef FMT_POSIX\n#  if defined(_WIN32) && !defined(__MINGW32__)\n// Fix warnings about deprecated symbols.\n#    define FMT_POSIX(call) _##call\n#  else\n#    define FMT_POSIX(call) call\n#  endif\n#endif\n\n// Calls to system functions are wrapped in FMT_SYSTEM for testability.\n#ifdef FMT_SYSTEM\n#  define FMT_POSIX_CALL(call) FMT_SYSTEM(call)\n#else\n#  define FMT_SYSTEM(call) ::call\n#  ifdef _WIN32\n// Fix warnings about deprecated symbols.\n#    define FMT_POSIX_CALL(call) ::_##call\n#  else\n#    define FMT_POSIX_CALL(call) ::call\n#  endif\n#endif\n\n// Retries the expression while it evaluates to error_result and errno\n// equals to EINTR.\n#ifndef _WIN32\n#  define FMT_RETRY_VAL(result, expression, error_result) \\\n    do {                                                  \\\n      (result) = (expression);                            \\\n    } while ((result) == (error_result) && errno == EINTR)\n#else\n#  define FMT_RETRY_VAL(result, expression, error_result) result = (expression)\n#endif\n\n#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)\n\nFMT_BEGIN_NAMESPACE\nFMT_MODULE_EXPORT_BEGIN\n\n/**\n  \\rst\n  A reference to a null-terminated string. It can be constructed from a C\n  string or ``std::string``.\n\n  You can use one of the following type aliases for common character types:\n\n  +---------------+-----------------------------+\n  | Type          | Definition                  |\n  +===============+=============================+\n  | cstring_view  | basic_cstring_view<char>    |\n  +---------------+-----------------------------+\n  | wcstring_view | basic_cstring_view<wchar_t> |\n  +---------------+-----------------------------+\n\n  This class is most useful as a parameter type to allow passing\n  different types of strings to a function, for example::\n\n    template <typename... Args>\n    std::string format(cstring_view format_str, const Args & ... args);\n\n    format(\"{}\", 42);\n    format(std::string(\"{}\"), 42);\n  \\endrst\n */\ntemplate <typename Char> class basic_cstring_view {\n private:\n  const Char* data_;\n\n public:\n  /** Constructs a string reference object from a C string. */\n  basic_cstring_view(const Char* s) : data_(s) {}\n\n  /**\n    \\rst\n    Constructs a string reference from an ``std::string`` object.\n    \\endrst\n   */\n  basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}\n\n  /** Returns the pointer to a C string. */\n  const Char* c_str() const { return data_; }\n};\n\nusing cstring_view = basic_cstring_view<char>;\nusing wcstring_view = basic_cstring_view<wchar_t>;\n\ntemplate <typename Char> struct formatter<std::error_code, Char> {\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    return ctx.begin();\n  }\n\n  template <typename FormatContext>\n  FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const\n      -> decltype(ctx.out()) {\n    auto out = ctx.out();\n    out = detail::write_bytes(out, ec.category().name(),\n                              basic_format_specs<Char>());\n    out = detail::write<Char>(out, Char(':'));\n    out = detail::write<Char>(out, ec.value());\n    return out;\n  }\n};\n\n#ifdef _WIN32\nFMT_API const std::error_category& system_category() FMT_NOEXCEPT;\n\nFMT_BEGIN_DETAIL_NAMESPACE\n// A converter from UTF-16 to UTF-8.\n// It is only provided for Windows since other systems support UTF-8 natively.\nclass utf16_to_utf8 {\n private:\n  memory_buffer buffer_;\n\n public:\n  utf16_to_utf8() {}\n  FMT_API explicit utf16_to_utf8(basic_string_view<wchar_t> s);\n  operator string_view() const { return string_view(&buffer_[0], size()); }\n  size_t size() const { return buffer_.size() - 1; }\n  const char* c_str() const { return &buffer_[0]; }\n  std::string str() const { return std::string(&buffer_[0], size()); }\n\n  // Performs conversion returning a system error code instead of\n  // throwing exception on conversion error. This method may still throw\n  // in case of memory allocation error.\n  FMT_API int convert(basic_string_view<wchar_t> s);\n};\n\nFMT_API void format_windows_error(buffer<char>& out, int error_code,\n                                  const char* message) FMT_NOEXCEPT;\nFMT_END_DETAIL_NAMESPACE\n\nFMT_API std::system_error vwindows_error(int error_code, string_view format_str,\n                                         format_args args);\n\n/**\n \\rst\n Constructs a :class:`std::system_error` object with the description\n of the form\n\n .. parsed-literal::\n   *<message>*: *<system-message>*\n\n where *<message>* is the formatted message and *<system-message>* is the\n system message corresponding to the error code.\n *error_code* is a Windows error code as given by ``GetLastError``.\n If *error_code* is not a valid error code such as -1, the system message\n will look like \"error -1\".\n\n **Example**::\n\n   // This throws a system_error with the description\n   //   cannot open file 'madeup': The system cannot find the file specified.\n   // or similar (system message may vary).\n   const char *filename = \"madeup\";\n   LPOFSTRUCT of = LPOFSTRUCT();\n   HFILE file = OpenFile(filename, &of, OF_READ);\n   if (file == HFILE_ERROR) {\n     throw fmt::windows_error(GetLastError(),\n                              \"cannot open file '{}'\", filename);\n   }\n \\endrst\n*/\ntemplate <typename... Args>\nstd::system_error windows_error(int error_code, string_view message,\n                                const Args&... args) {\n  return vwindows_error(error_code, message, fmt::make_format_args(args...));\n}\n\n// Reports a Windows error without throwing an exception.\n// Can be used to report errors from destructors.\nFMT_API void report_windows_error(int error_code,\n                                  const char* message) FMT_NOEXCEPT;\n#else\ninline const std::error_category& system_category() FMT_NOEXCEPT {\n  return std::system_category();\n}\n#endif  // _WIN32\n\n// std::system is not available on some platforms such as iOS (#2248).\n#ifdef __OSX__\ntemplate <typename S, typename... Args, typename Char = char_t<S>>\nvoid say(const S& format_str, Args&&... args) {\n  std::system(format(\"say \\\"{}\\\"\", format(format_str, args...)).c_str());\n}\n#endif\n\n// A buffered file.\nclass buffered_file {\n private:\n  FILE* file_;\n\n  friend class file;\n\n  explicit buffered_file(FILE* f) : file_(f) {}\n\n public:\n  buffered_file(const buffered_file&) = delete;\n  void operator=(const buffered_file&) = delete;\n\n  // Constructs a buffered_file object which doesn't represent any file.\n  buffered_file() FMT_NOEXCEPT : file_(nullptr) {}\n\n  // Destroys the object closing the file it represents if any.\n  FMT_API ~buffered_file() FMT_NOEXCEPT;\n\n public:\n  buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) {\n    other.file_ = nullptr;\n  }\n\n  buffered_file& operator=(buffered_file&& other) {\n    close();\n    file_ = other.file_;\n    other.file_ = nullptr;\n    return *this;\n  }\n\n  // Opens a file.\n  FMT_API buffered_file(cstring_view filename, cstring_view mode);\n\n  // Closes the file.\n  FMT_API void close();\n\n  // Returns the pointer to a FILE object representing this file.\n  FILE* get() const FMT_NOEXCEPT { return file_; }\n\n  // We place parentheses around fileno to workaround a bug in some versions\n  // of MinGW that define fileno as a macro.\n  FMT_API int(fileno)() const;\n\n  void vprint(string_view format_str, format_args args) {\n    fmt::vprint(file_, format_str, args);\n  }\n\n  template <typename... Args>\n  inline void print(string_view format_str, const Args&... args) {\n    vprint(format_str, fmt::make_format_args(args...));\n  }\n};\n\n#if FMT_USE_FCNTL\n// A file. Closed file is represented by a file object with descriptor -1.\n// Methods that are not declared with FMT_NOEXCEPT may throw\n// fmt::system_error in case of failure. Note that some errors such as\n// closing the file multiple times will cause a crash on Windows rather\n// than an exception. You can get standard behavior by overriding the\n// invalid parameter handler with _set_invalid_parameter_handler.\nclass file {\n private:\n  int fd_;  // File descriptor.\n\n  // Constructs a file object with a given descriptor.\n  explicit file(int fd) : fd_(fd) {}\n\n public:\n  // Possible values for the oflag argument to the constructor.\n  enum {\n    RDONLY = FMT_POSIX(O_RDONLY),  // Open for reading only.\n    WRONLY = FMT_POSIX(O_WRONLY),  // Open for writing only.\n    RDWR = FMT_POSIX(O_RDWR),      // Open for reading and writing.\n    CREATE = FMT_POSIX(O_CREAT),   // Create if the file doesn't exist.\n    APPEND = FMT_POSIX(O_APPEND),  // Open in append mode.\n    TRUNC = FMT_POSIX(O_TRUNC)     // Truncate the content of the file.\n  };\n\n  // Constructs a file object which doesn't represent any file.\n  file() FMT_NOEXCEPT : fd_(-1) {}\n\n  // Opens a file and constructs a file object representing this file.\n  FMT_API file(cstring_view path, int oflag);\n\n public:\n  file(const file&) = delete;\n  void operator=(const file&) = delete;\n\n  file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }\n\n  // Move assignment is not noexcept because close may throw.\n  file& operator=(file&& other) {\n    close();\n    fd_ = other.fd_;\n    other.fd_ = -1;\n    return *this;\n  }\n\n  // Destroys the object closing the file it represents if any.\n  FMT_API ~file() FMT_NOEXCEPT;\n\n  // Returns the file descriptor.\n  int descriptor() const FMT_NOEXCEPT { return fd_; }\n\n  // Closes the file.\n  FMT_API void close();\n\n  // Returns the file size. The size has signed type for consistency with\n  // stat::st_size.\n  FMT_API long long size() const;\n\n  // Attempts to read count bytes from the file into the specified buffer.\n  FMT_API size_t read(void* buffer, size_t count);\n\n  // Attempts to write count bytes from the specified buffer to the file.\n  FMT_API size_t write(const void* buffer, size_t count);\n\n  // Duplicates a file descriptor with the dup function and returns\n  // the duplicate as a file object.\n  FMT_API static file dup(int fd);\n\n  // Makes fd be the copy of this file descriptor, closing fd first if\n  // necessary.\n  FMT_API void dup2(int fd);\n\n  // Makes fd be the copy of this file descriptor, closing fd first if\n  // necessary.\n  FMT_API void dup2(int fd, std::error_code& ec) FMT_NOEXCEPT;\n\n  // Creates a pipe setting up read_end and write_end file objects for reading\n  // and writing respectively.\n  FMT_API static void pipe(file& read_end, file& write_end);\n\n  // Creates a buffered_file object associated with this file and detaches\n  // this file object from the file.\n  FMT_API buffered_file fdopen(const char* mode);\n};\n\n// Returns the memory page size.\nlong getpagesize();\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\nstruct buffer_size {\n  buffer_size() = default;\n  size_t value = 0;\n  buffer_size operator=(size_t val) const {\n    auto bs = buffer_size();\n    bs.value = val;\n    return bs;\n  }\n};\n\nstruct ostream_params {\n  int oflag = file::WRONLY | file::CREATE | file::TRUNC;\n  size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;\n\n  ostream_params() {}\n\n  template <typename... T>\n  ostream_params(T... params, int new_oflag) : ostream_params(params...) {\n    oflag = new_oflag;\n  }\n\n  template <typename... T>\n  ostream_params(T... params, detail::buffer_size bs)\n      : ostream_params(params...) {\n    this->buffer_size = bs.value;\n  }\n\n// Intel has a bug that results in failure to deduce a constructor\n// for empty parameter packs.\n#  if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000\n  ostream_params(int new_oflag) : oflag(new_oflag) {}\n  ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {}\n#  endif\n};\n\nFMT_END_DETAIL_NAMESPACE\n\n// Added {} below to work around default constructor error known to\n// occur in Xcode versions 7.2.1 and 8.2.1.\nconstexpr detail::buffer_size buffer_size{};\n\n/** A fast output stream which is not thread-safe. */\nclass FMT_API ostream final : private detail::buffer<char> {\n private:\n  file file_;\n\n  void grow(size_t) override;\n\n  ostream(cstring_view path, const detail::ostream_params& params)\n      : file_(path, params.oflag) {\n    set(new char[params.buffer_size], params.buffer_size);\n  }\n\n public:\n  ostream(ostream&& other)\n      : detail::buffer<char>(other.data(), other.size(), other.capacity()),\n        file_(std::move(other.file_)) {\n    other.clear();\n    other.set(nullptr, 0);\n  }\n  ~ostream() {\n    flush();\n    delete[] data();\n  }\n\n  void flush() {\n    if (size() == 0) return;\n    file_.write(data(), size());\n    clear();\n  }\n\n  template <typename... T>\n  friend ostream output_file(cstring_view path, T... params);\n\n  void close() {\n    flush();\n    file_.close();\n  }\n\n  /**\n    Formats ``args`` according to specifications in ``fmt`` and writes the\n    output to the file.\n   */\n  template <typename... T> void print(format_string<T...> fmt, T&&... args) {\n    vformat_to(detail::buffer_appender<char>(*this), fmt,\n               fmt::make_format_args(args...));\n  }\n};\n\n/**\n  \\rst\n  Opens a file for writing. Supported parameters passed in *params*:\n\n  * ``<integer>``: Flags passed to `open\n    <https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html>`_\n    (``file::WRONLY | file::CREATE`` by default)\n  * ``buffer_size=<integer>``: Output buffer size\n\n  **Example**::\n\n    auto out = fmt::output_file(\"guide.txt\");\n    out.print(\"Don't {}\", \"Panic\");\n  \\endrst\n */\ntemplate <typename... T>\ninline ostream output_file(cstring_view path, T... params) {\n  return {path, detail::ostream_params(params...)};\n}\n#endif  // FMT_USE_FCNTL\n\n#ifdef FMT_LOCALE\n// A \"C\" numeric locale.\nclass locale {\n private:\n#  ifdef _WIN32\n  using locale_t = _locale_t;\n\n  static void freelocale(locale_t loc) { _free_locale(loc); }\n\n  static double strtod_l(const char* nptr, char** endptr, _locale_t loc) {\n    return _strtod_l(nptr, endptr, loc);\n  }\n#  endif\n\n  locale_t locale_;\n\n public:\n  using type = locale_t;\n  locale(const locale&) = delete;\n  void operator=(const locale&) = delete;\n\n  locale() {\n#  ifndef _WIN32\n    locale_ = FMT_SYSTEM(newlocale(LC_NUMERIC_MASK, \"C\", nullptr));\n#  else\n    locale_ = _create_locale(LC_NUMERIC, \"C\");\n#  endif\n    if (!locale_) FMT_THROW(system_error(errno, \"cannot create locale\"));\n  }\n  ~locale() { freelocale(locale_); }\n\n  type get() const { return locale_; }\n\n  // Converts string to floating-point number and advances str past the end\n  // of the parsed input.\n  FMT_DEPRECATED double strtod(const char*& str) const {\n    char* end = nullptr;\n    double result = strtod_l(str, &end, locale_);\n    str = end;\n    return result;\n  }\n};\nusing Locale FMT_DEPRECATED_ALIAS = locale;\n#endif  // FMT_LOCALE\nFMT_MODULE_EXPORT_END\nFMT_END_NAMESPACE\n\n#endif  // FMT_OS_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/ostream.h",
    "content": "// Formatting library for C++ - std::ostream support\n//\n// Copyright (c) 2012 - present, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_OSTREAM_H_\n#define FMT_OSTREAM_H_\n\n#include <ostream>\n\n#include \"format.h\"\n\nFMT_BEGIN_NAMESPACE\n\ntemplate <typename OutputIt, typename Char> class basic_printf_context;\n\nnamespace detail {\n\n// Checks if T has a user-defined operator<<.\ntemplate <typename T, typename Char, typename Enable = void>\nclass is_streamable {\n private:\n  template <typename U>\n  static auto test(int)\n      -> bool_constant<sizeof(std::declval<std::basic_ostream<Char>&>()\n                              << std::declval<U>()) != 0>;\n\n  template <typename> static auto test(...) -> std::false_type;\n\n  using result = decltype(test<T>(0));\n\n public:\n  is_streamable() = default;\n\n  static const bool value = result::value;\n};\n\n// Formatting of built-in types and arrays is intentionally disabled because\n// it's handled by standard (non-ostream) formatters.\ntemplate <typename T, typename Char>\nstruct is_streamable<\n    T, Char,\n    enable_if_t<\n        std::is_arithmetic<T>::value || std::is_array<T>::value ||\n        std::is_pointer<T>::value || std::is_same<T, char8_type>::value ||\n        std::is_same<T, std::basic_string<Char>>::value ||\n        std::is_same<T, std_string_view<Char>>::value ||\n        (std::is_convertible<T, int>::value && !std::is_enum<T>::value)>>\n    : std::false_type {};\n\n// Write the content of buf to os.\n// It is a separate function rather than a part of vprint to simplify testing.\ntemplate <typename Char>\nvoid write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {\n  const Char* buf_data = buf.data();\n  using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;\n  unsigned_streamsize size = buf.size();\n  unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());\n  do {\n    unsigned_streamsize n = size <= max_size ? size : max_size;\n    os.write(buf_data, static_cast<std::streamsize>(n));\n    buf_data += n;\n    size -= n;\n  } while (size != 0);\n}\n\ntemplate <typename Char, typename T>\nvoid format_value(buffer<Char>& buf, const T& value,\n                  locale_ref loc = locale_ref()) {\n  auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);\n  auto&& output = std::basic_ostream<Char>(&format_buf);\n#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)\n  if (loc) output.imbue(loc.get<std::locale>());\n#endif\n  output << value;\n  output.exceptions(std::ios_base::failbit | std::ios_base::badbit);\n  buf.try_resize(buf.size());\n}\n\n// Formats an object of type T that has an overloaded ostream operator<<.\ntemplate <typename T, typename Char>\nstruct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>\n    : private formatter<basic_string_view<Char>, Char> {\n  using formatter<basic_string_view<Char>, Char>::parse;\n\n  template <typename OutputIt>\n  auto format(const T& value, basic_format_context<OutputIt, Char>& ctx)\n      -> OutputIt {\n    auto buffer = basic_memory_buffer<Char>();\n    format_value(buffer, value, ctx.locale());\n    return formatter<basic_string_view<Char>, Char>::format(\n        {buffer.data(), buffer.size()}, ctx);\n  }\n\n  // DEPRECATED!\n  template <typename OutputIt>\n  auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx)\n      -> OutputIt {\n    auto buffer = basic_memory_buffer<Char>();\n    format_value(buffer, value, ctx.locale());\n    return std::copy(buffer.begin(), buffer.end(), ctx.out());\n  }\n};\n}  // namespace detail\n\nFMT_MODULE_EXPORT\ntemplate <typename Char>\nvoid vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,\n            basic_format_args<buffer_context<type_identity_t<Char>>> args) {\n  auto buffer = basic_memory_buffer<Char>();\n  detail::vformat_to(buffer, format_str, args);\n  detail::write_buffer(os, buffer);\n}\n\n/**\n  \\rst\n  Prints formatted data to the stream *os*.\n\n  **Example**::\n\n    fmt::print(cerr, \"Don't {}!\", \"panic\");\n  \\endrst\n */\nFMT_MODULE_EXPORT\ntemplate <typename S, typename... Args,\n          typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>\nvoid print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {\n  vprint(os, to_string_view(format_str),\n         fmt::make_args_checked<Args...>(format_str, args...));\n}\nFMT_END_NAMESPACE\n\n#endif  // FMT_OSTREAM_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/posix.h",
    "content": "#include \"os.h\"\n#warning \"fmt/posix.h is deprecated; use fmt/os.h instead\""
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/printf.h",
    "content": "// Formatting library for C++ - legacy printf implementation\n//\n// Copyright (c) 2012 - 2016, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_PRINTF_H_\n#define FMT_PRINTF_H_\n\n#include <algorithm>  // std::max\n#include <limits>     // std::numeric_limits\n#include <ostream>\n\n#include \"format.h\"\n\nFMT_BEGIN_NAMESPACE\nFMT_MODULE_EXPORT_BEGIN\n\ntemplate <typename T> struct printf_formatter { printf_formatter() = delete; };\n\ntemplate <typename Char>\nclass basic_printf_parse_context : public basic_format_parse_context<Char> {\n  using basic_format_parse_context<Char>::basic_format_parse_context;\n};\n\ntemplate <typename OutputIt, typename Char> class basic_printf_context {\n private:\n  OutputIt out_;\n  basic_format_args<basic_printf_context> args_;\n\n public:\n  using char_type = Char;\n  using format_arg = basic_format_arg<basic_printf_context>;\n  using parse_context_type = basic_printf_parse_context<Char>;\n  template <typename T> using formatter_type = printf_formatter<T>;\n\n  /**\n    \\rst\n    Constructs a ``printf_context`` object. References to the arguments are\n    stored in the context object so make sure they have appropriate lifetimes.\n    \\endrst\n   */\n  basic_printf_context(OutputIt out,\n                       basic_format_args<basic_printf_context> args)\n      : out_(out), args_(args) {}\n\n  OutputIt out() { return out_; }\n  void advance_to(OutputIt it) { out_ = it; }\n\n  detail::locale_ref locale() { return {}; }\n\n  format_arg arg(int id) const { return args_.get(id); }\n\n  FMT_CONSTEXPR void on_error(const char* message) {\n    detail::error_handler().on_error(message);\n  }\n};\n\nFMT_BEGIN_DETAIL_NAMESPACE\n\n// Checks if a value fits in int - used to avoid warnings about comparing\n// signed and unsigned integers.\ntemplate <bool IsSigned> struct int_checker {\n  template <typename T> static bool fits_in_int(T value) {\n    unsigned max = max_value<int>();\n    return value <= max;\n  }\n  static bool fits_in_int(bool) { return true; }\n};\n\ntemplate <> struct int_checker<true> {\n  template <typename T> static bool fits_in_int(T value) {\n    return value >= (std::numeric_limits<int>::min)() &&\n           value <= max_value<int>();\n  }\n  static bool fits_in_int(int) { return true; }\n};\n\nclass printf_precision_handler {\n public:\n  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>\n  int operator()(T value) {\n    if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))\n      FMT_THROW(format_error(\"number is too big\"));\n    return (std::max)(static_cast<int>(value), 0);\n  }\n\n  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>\n  int operator()(T) {\n    FMT_THROW(format_error(\"precision is not integer\"));\n    return 0;\n  }\n};\n\n// An argument visitor that returns true iff arg is a zero integer.\nclass is_zero_int {\n public:\n  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>\n  bool operator()(T value) {\n    return value == 0;\n  }\n\n  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>\n  bool operator()(T) {\n    return false;\n  }\n};\n\ntemplate <typename T> struct make_unsigned_or_bool : std::make_unsigned<T> {};\n\ntemplate <> struct make_unsigned_or_bool<bool> { using type = bool; };\n\ntemplate <typename T, typename Context> class arg_converter {\n private:\n  using char_type = typename Context::char_type;\n\n  basic_format_arg<Context>& arg_;\n  char_type type_;\n\n public:\n  arg_converter(basic_format_arg<Context>& arg, char_type type)\n      : arg_(arg), type_(type) {}\n\n  void operator()(bool value) {\n    if (type_ != 's') operator()<bool>(value);\n  }\n\n  template <typename U, FMT_ENABLE_IF(std::is_integral<U>::value)>\n  void operator()(U value) {\n    bool is_signed = type_ == 'd' || type_ == 'i';\n    using target_type = conditional_t<std::is_same<T, void>::value, U, T>;\n    if (const_check(sizeof(target_type) <= sizeof(int))) {\n      // Extra casts are used to silence warnings.\n      if (is_signed) {\n        arg_ = detail::make_arg<Context>(\n            static_cast<int>(static_cast<target_type>(value)));\n      } else {\n        using unsigned_type = typename make_unsigned_or_bool<target_type>::type;\n        arg_ = detail::make_arg<Context>(\n            static_cast<unsigned>(static_cast<unsigned_type>(value)));\n      }\n    } else {\n      if (is_signed) {\n        // glibc's printf doesn't sign extend arguments of smaller types:\n        //   std::printf(\"%lld\", -42);  // prints \"4294967254\"\n        // but we don't have to do the same because it's a UB.\n        arg_ = detail::make_arg<Context>(static_cast<long long>(value));\n      } else {\n        arg_ = detail::make_arg<Context>(\n            static_cast<typename make_unsigned_or_bool<U>::type>(value));\n      }\n    }\n  }\n\n  template <typename U, FMT_ENABLE_IF(!std::is_integral<U>::value)>\n  void operator()(U) {}  // No conversion needed for non-integral types.\n};\n\n// Converts an integer argument to T for printf, if T is an integral type.\n// If T is void, the argument is converted to corresponding signed or unsigned\n// type depending on the type specifier: 'd' and 'i' - signed, other -\n// unsigned).\ntemplate <typename T, typename Context, typename Char>\nvoid convert_arg(basic_format_arg<Context>& arg, Char type) {\n  visit_format_arg(arg_converter<T, Context>(arg, type), arg);\n}\n\n// Converts an integer argument to char for printf.\ntemplate <typename Context> class char_converter {\n private:\n  basic_format_arg<Context>& arg_;\n\n public:\n  explicit char_converter(basic_format_arg<Context>& arg) : arg_(arg) {}\n\n  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>\n  void operator()(T value) {\n    arg_ = detail::make_arg<Context>(\n        static_cast<typename Context::char_type>(value));\n  }\n\n  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>\n  void operator()(T) {}  // No conversion needed for non-integral types.\n};\n\n// An argument visitor that return a pointer to a C string if argument is a\n// string or null otherwise.\ntemplate <typename Char> struct get_cstring {\n  template <typename T> const Char* operator()(T) { return nullptr; }\n  const Char* operator()(const Char* s) { return s; }\n};\n\n// Checks if an argument is a valid printf width specifier and sets\n// left alignment if it is negative.\ntemplate <typename Char> class printf_width_handler {\n private:\n  using format_specs = basic_format_specs<Char>;\n\n  format_specs& specs_;\n\n public:\n  explicit printf_width_handler(format_specs& specs) : specs_(specs) {}\n\n  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>\n  unsigned operator()(T value) {\n    auto width = static_cast<uint32_or_64_or_128_t<T>>(value);\n    if (detail::is_negative(value)) {\n      specs_.align = align::left;\n      width = 0 - width;\n    }\n    unsigned int_max = max_value<int>();\n    if (width > int_max) FMT_THROW(format_error(\"number is too big\"));\n    return static_cast<unsigned>(width);\n  }\n\n  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>\n  unsigned operator()(T) {\n    FMT_THROW(format_error(\"width is not integer\"));\n    return 0;\n  }\n};\n\n// The ``printf`` argument formatter.\ntemplate <typename OutputIt, typename Char>\nclass printf_arg_formatter : public arg_formatter<Char> {\n private:\n  using base = arg_formatter<Char>;\n  using context_type = basic_printf_context<OutputIt, Char>;\n  using format_specs = basic_format_specs<Char>;\n\n  context_type& context_;\n\n  OutputIt write_null_pointer(bool is_string = false) {\n    auto s = this->specs;\n    s.type = presentation_type::none;\n    return write_bytes(this->out, is_string ? \"(null)\" : \"(nil)\", s);\n  }\n\n public:\n  printf_arg_formatter(OutputIt iter, format_specs& s, context_type& ctx)\n      : base{iter, s, locale_ref()}, context_(ctx) {}\n\n  OutputIt operator()(monostate value) { return base::operator()(value); }\n\n  template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)>\n  OutputIt operator()(T value) {\n    // MSVC2013 fails to compile separate overloads for bool and Char so use\n    // std::is_same instead.\n    if (std::is_same<T, Char>::value) {\n      format_specs fmt_specs = this->specs;\n      if (fmt_specs.type != presentation_type::none &&\n          fmt_specs.type != presentation_type::chr) {\n        return (*this)(static_cast<int>(value));\n      }\n      fmt_specs.sign = sign::none;\n      fmt_specs.alt = false;\n      fmt_specs.fill[0] = ' ';  // Ignore '0' flag for char types.\n      // align::numeric needs to be overwritten here since the '0' flag is\n      // ignored for non-numeric types\n      if (fmt_specs.align == align::none || fmt_specs.align == align::numeric)\n        fmt_specs.align = align::right;\n      return write<Char>(this->out, static_cast<Char>(value), fmt_specs);\n    }\n    return base::operator()(value);\n  }\n\n  template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>\n  OutputIt operator()(T value) {\n    return base::operator()(value);\n  }\n\n  /** Formats a null-terminated C string. */\n  OutputIt operator()(const char* value) {\n    if (value) return base::operator()(value);\n    return write_null_pointer(this->specs.type != presentation_type::pointer);\n  }\n\n  /** Formats a null-terminated wide C string. */\n  OutputIt operator()(const wchar_t* value) {\n    if (value) return base::operator()(value);\n    return write_null_pointer(this->specs.type != presentation_type::pointer);\n  }\n\n  OutputIt operator()(basic_string_view<Char> value) {\n    return base::operator()(value);\n  }\n\n  /** Formats a pointer. */\n  OutputIt operator()(const void* value) {\n    return value ? base::operator()(value) : write_null_pointer();\n  }\n\n  /** Formats an argument of a custom (user-defined) type. */\n  OutputIt operator()(typename basic_format_arg<context_type>::handle handle) {\n    auto parse_ctx =\n        basic_printf_parse_context<Char>(basic_string_view<Char>());\n    handle.format(parse_ctx, context_);\n    return this->out;\n  }\n};\n\ntemplate <typename Char>\nvoid parse_flags(basic_format_specs<Char>& specs, const Char*& it,\n                 const Char* end) {\n  for (; it != end; ++it) {\n    switch (*it) {\n    case '-':\n      specs.align = align::left;\n      break;\n    case '+':\n      specs.sign = sign::plus;\n      break;\n    case '0':\n      specs.fill[0] = '0';\n      break;\n    case ' ':\n      if (specs.sign != sign::plus) {\n        specs.sign = sign::space;\n      }\n      break;\n    case '#':\n      specs.alt = true;\n      break;\n    default:\n      return;\n    }\n  }\n}\n\ntemplate <typename Char, typename GetArg>\nint parse_header(const Char*& it, const Char* end,\n                 basic_format_specs<Char>& specs, GetArg get_arg) {\n  int arg_index = -1;\n  Char c = *it;\n  if (c >= '0' && c <= '9') {\n    // Parse an argument index (if followed by '$') or a width possibly\n    // preceded with '0' flag(s).\n    int value = parse_nonnegative_int(it, end, -1);\n    if (it != end && *it == '$') {  // value is an argument index\n      ++it;\n      arg_index = value != -1 ? value : max_value<int>();\n    } else {\n      if (c == '0') specs.fill[0] = '0';\n      if (value != 0) {\n        // Nonzero value means that we parsed width and don't need to\n        // parse it or flags again, so return now.\n        if (value == -1) FMT_THROW(format_error(\"number is too big\"));\n        specs.width = value;\n        return arg_index;\n      }\n    }\n  }\n  parse_flags(specs, it, end);\n  // Parse width.\n  if (it != end) {\n    if (*it >= '0' && *it <= '9') {\n      specs.width = parse_nonnegative_int(it, end, -1);\n      if (specs.width == -1) FMT_THROW(format_error(\"number is too big\"));\n    } else if (*it == '*') {\n      ++it;\n      specs.width = static_cast<int>(visit_format_arg(\n          detail::printf_width_handler<Char>(specs), get_arg(-1)));\n    }\n  }\n  return arg_index;\n}\n\ntemplate <typename Char, typename Context>\nvoid vprintf(buffer<Char>& buf, basic_string_view<Char> format,\n             basic_format_args<Context> args) {\n  using OutputIt = buffer_appender<Char>;\n  auto out = OutputIt(buf);\n  auto context = basic_printf_context<OutputIt, Char>(out, args);\n  auto parse_ctx = basic_printf_parse_context<Char>(format);\n\n  // Returns the argument with specified index or, if arg_index is -1, the next\n  // argument.\n  auto get_arg = [&](int arg_index) {\n    if (arg_index < 0)\n      arg_index = parse_ctx.next_arg_id();\n    else\n      parse_ctx.check_arg_id(--arg_index);\n    return detail::get_arg(context, arg_index);\n  };\n\n  const Char* start = parse_ctx.begin();\n  const Char* end = parse_ctx.end();\n  auto it = start;\n  while (it != end) {\n    if (!detail::find<false, Char>(it, end, '%', it)) {\n      it = end;  // detail::find leaves it == nullptr if it doesn't find '%'\n      break;\n    }\n    Char c = *it++;\n    if (it != end && *it == c) {\n      out = detail::write(\n          out, basic_string_view<Char>(start, detail::to_unsigned(it - start)));\n      start = ++it;\n      continue;\n    }\n    out = detail::write(out, basic_string_view<Char>(\n                                 start, detail::to_unsigned(it - 1 - start)));\n\n    basic_format_specs<Char> specs;\n    specs.align = align::right;\n\n    // Parse argument index, flags and width.\n    int arg_index = parse_header(it, end, specs, get_arg);\n    if (arg_index == 0) parse_ctx.on_error(\"argument not found\");\n\n    // Parse precision.\n    if (it != end && *it == '.') {\n      ++it;\n      c = it != end ? *it : 0;\n      if ('0' <= c && c <= '9') {\n        specs.precision = parse_nonnegative_int(it, end, 0);\n      } else if (c == '*') {\n        ++it;\n        specs.precision = static_cast<int>(\n            visit_format_arg(detail::printf_precision_handler(), get_arg(-1)));\n      } else {\n        specs.precision = 0;\n      }\n    }\n\n    auto arg = get_arg(arg_index);\n    // For d, i, o, u, x, and X conversion specifiers, if a precision is\n    // specified, the '0' flag is ignored\n    if (specs.precision >= 0 && arg.is_integral())\n      specs.fill[0] =\n          ' ';  // Ignore '0' flag for non-numeric types or if '-' present.\n    if (specs.precision >= 0 && arg.type() == detail::type::cstring_type) {\n      auto str = visit_format_arg(detail::get_cstring<Char>(), arg);\n      auto str_end = str + specs.precision;\n      auto nul = std::find(str, str_end, Char());\n      arg = detail::make_arg<basic_printf_context<OutputIt, Char>>(\n          basic_string_view<Char>(\n              str, detail::to_unsigned(nul != str_end ? nul - str\n                                                      : specs.precision)));\n    }\n    if (specs.alt && visit_format_arg(detail::is_zero_int(), arg))\n      specs.alt = false;\n    if (specs.fill[0] == '0') {\n      if (arg.is_arithmetic() && specs.align != align::left)\n        specs.align = align::numeric;\n      else\n        specs.fill[0] = ' ';  // Ignore '0' flag for non-numeric types or if '-'\n                              // flag is also present.\n    }\n\n    // Parse length and convert the argument to the required type.\n    c = it != end ? *it++ : 0;\n    Char t = it != end ? *it : 0;\n    using detail::convert_arg;\n    switch (c) {\n    case 'h':\n      if (t == 'h') {\n        ++it;\n        t = it != end ? *it : 0;\n        convert_arg<signed char>(arg, t);\n      } else {\n        convert_arg<short>(arg, t);\n      }\n      break;\n    case 'l':\n      if (t == 'l') {\n        ++it;\n        t = it != end ? *it : 0;\n        convert_arg<long long>(arg, t);\n      } else {\n        convert_arg<long>(arg, t);\n      }\n      break;\n    case 'j':\n      convert_arg<intmax_t>(arg, t);\n      break;\n    case 'z':\n      convert_arg<size_t>(arg, t);\n      break;\n    case 't':\n      convert_arg<std::ptrdiff_t>(arg, t);\n      break;\n    case 'L':\n      // printf produces garbage when 'L' is omitted for long double, no\n      // need to do the same.\n      break;\n    default:\n      --it;\n      convert_arg<void>(arg, c);\n    }\n\n    // Parse type.\n    if (it == end) FMT_THROW(format_error(\"invalid format string\"));\n    char type = static_cast<char>(*it++);\n    if (arg.is_integral()) {\n      // Normalize type.\n      switch (type) {\n      case 'i':\n      case 'u':\n        type = 'd';\n        break;\n      case 'c':\n        visit_format_arg(\n            detail::char_converter<basic_printf_context<OutputIt, Char>>(arg),\n            arg);\n        break;\n      }\n    }\n    specs.type = parse_presentation_type(type);\n    if (specs.type == presentation_type::none)\n      parse_ctx.on_error(\"invalid type specifier\");\n\n    start = it;\n\n    // Format argument.\n    out = visit_format_arg(\n        detail::printf_arg_formatter<OutputIt, Char>(out, specs, context), arg);\n  }\n  detail::write(out, basic_string_view<Char>(start, to_unsigned(it - start)));\n}\nFMT_END_DETAIL_NAMESPACE\n\ntemplate <typename Char>\nusing basic_printf_context_t =\n    basic_printf_context<detail::buffer_appender<Char>, Char>;\n\nusing printf_context = basic_printf_context_t<char>;\nusing wprintf_context = basic_printf_context_t<wchar_t>;\n\nusing printf_args = basic_format_args<printf_context>;\nusing wprintf_args = basic_format_args<wprintf_context>;\n\n/**\n  \\rst\n  Constructs an `~fmt::format_arg_store` object that contains references to\n  arguments and can be implicitly converted to `~fmt::printf_args`.\n  \\endrst\n */\ntemplate <typename... T>\ninline auto make_printf_args(const T&... args)\n    -> format_arg_store<printf_context, T...> {\n  return {args...};\n}\n\n/**\n  \\rst\n  Constructs an `~fmt::format_arg_store` object that contains references to\n  arguments and can be implicitly converted to `~fmt::wprintf_args`.\n  \\endrst\n */\ntemplate <typename... T>\ninline auto make_wprintf_args(const T&... args)\n    -> format_arg_store<wprintf_context, T...> {\n  return {args...};\n}\n\ntemplate <typename S, typename Char = char_t<S>>\ninline auto vsprintf(\n    const S& fmt,\n    basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)\n    -> std::basic_string<Char> {\n  basic_memory_buffer<Char> buffer;\n  vprintf(buffer, to_string_view(fmt), args);\n  return to_string(buffer);\n}\n\n/**\n  \\rst\n  Formats arguments and returns the result as a string.\n\n  **Example**::\n\n    std::string message = fmt::sprintf(\"The answer is %d\", 42);\n  \\endrst\n*/\ntemplate <typename S, typename... T,\n          typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>\ninline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> {\n  using context = basic_printf_context_t<Char>;\n  return vsprintf(to_string_view(fmt), fmt::make_format_args<context>(args...));\n}\n\ntemplate <typename S, typename Char = char_t<S>>\ninline auto vfprintf(\n    std::FILE* f, const S& fmt,\n    basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)\n    -> int {\n  basic_memory_buffer<Char> buffer;\n  vprintf(buffer, to_string_view(fmt), args);\n  size_t size = buffer.size();\n  return std::fwrite(buffer.data(), sizeof(Char), size, f) < size\n             ? -1\n             : static_cast<int>(size);\n}\n\n/**\n  \\rst\n  Prints formatted data to the file *f*.\n\n  **Example**::\n\n    fmt::fprintf(stderr, \"Don't %s!\", \"panic\");\n  \\endrst\n */\ntemplate <typename S, typename... T, typename Char = char_t<S>>\ninline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int {\n  using context = basic_printf_context_t<Char>;\n  return vfprintf(f, to_string_view(fmt),\n                  fmt::make_format_args<context>(args...));\n}\n\ntemplate <typename S, typename Char = char_t<S>>\ninline auto vprintf(\n    const S& fmt,\n    basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)\n    -> int {\n  return vfprintf(stdout, to_string_view(fmt), args);\n}\n\n/**\n  \\rst\n  Prints formatted data to ``stdout``.\n\n  **Example**::\n\n    fmt::printf(\"Elapsed time: %.2f seconds\", 1.23);\n  \\endrst\n */\ntemplate <typename S, typename... T, FMT_ENABLE_IF(detail::is_string<S>::value)>\ninline auto printf(const S& fmt, const T&... args) -> int {\n  return vprintf(\n      to_string_view(fmt),\n      fmt::make_format_args<basic_printf_context_t<char_t<S>>>(args...));\n}\n\ntemplate <typename S, typename Char = char_t<S>>\nFMT_DEPRECATED auto vfprintf(\n    std::basic_ostream<Char>& os, const S& fmt,\n    basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)\n    -> int {\n  basic_memory_buffer<Char> buffer;\n  vprintf(buffer, to_string_view(fmt), args);\n  os.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));\n  return static_cast<int>(buffer.size());\n}\ntemplate <typename S, typename... T, typename Char = char_t<S>>\nFMT_DEPRECATED auto fprintf(std::basic_ostream<Char>& os, const S& fmt,\n                            const T&... args) -> int {\n  return vfprintf(os, to_string_view(fmt),\n                  fmt::make_format_args<basic_printf_context_t<Char>>(args...));\n}\n\nFMT_MODULE_EXPORT_END\nFMT_END_NAMESPACE\n\n#endif  // FMT_PRINTF_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/ranges.h",
    "content": "// Formatting library for C++ - experimental range support\n//\n// Copyright (c) 2012 - present, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n//\n// Copyright (c) 2018 - present, Remotion (Igor Schulz)\n// All Rights Reserved\n// {fmt} support for ranges, containers and types tuple interface.\n\n#ifndef FMT_RANGES_H_\n#define FMT_RANGES_H_\n\n#include <initializer_list>\n#include <tuple>\n#include <type_traits>\n\n#include \"format.h\"\n\nFMT_BEGIN_NAMESPACE\n\nnamespace detail {\n\ntemplate <typename RangeT, typename OutputIterator>\nOutputIterator copy(const RangeT& range, OutputIterator out) {\n  for (auto it = range.begin(), end = range.end(); it != end; ++it)\n    *out++ = *it;\n  return out;\n}\n\ntemplate <typename OutputIterator>\nOutputIterator copy(const char* str, OutputIterator out) {\n  while (*str) *out++ = *str++;\n  return out;\n}\n\ntemplate <typename OutputIterator>\nOutputIterator copy(char ch, OutputIterator out) {\n  *out++ = ch;\n  return out;\n}\n\ntemplate <typename OutputIterator>\nOutputIterator copy(wchar_t ch, OutputIterator out) {\n  *out++ = ch;\n  return out;\n}\n\n// Returns true if T has a std::string-like interface, like std::string_view.\ntemplate <typename T> class is_std_string_like {\n  template <typename U>\n  static auto check(U* p)\n      -> decltype((void)p->find('a'), p->length(), (void)p->data(), int());\n  template <typename> static void check(...);\n\n public:\n  static FMT_CONSTEXPR_DECL const bool value =\n      is_string<T>::value ||\n      std::is_convertible<T, std_string_view<char>>::value ||\n      !std::is_void<decltype(check<T>(nullptr))>::value;\n};\n\ntemplate <typename Char>\nstruct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};\n\ntemplate <typename T> class is_map {\n  template <typename U> static auto check(U*) -> typename U::mapped_type;\n  template <typename> static void check(...);\n\n public:\n#ifdef FMT_FORMAT_MAP_AS_LIST\n  static FMT_CONSTEXPR_DECL const bool value = false;\n#else\n  static FMT_CONSTEXPR_DECL const bool value =\n      !std::is_void<decltype(check<T>(nullptr))>::value;\n#endif\n};\n\ntemplate <typename T> class is_set {\n  template <typename U> static auto check(U*) -> typename U::key_type;\n  template <typename> static void check(...);\n\n public:\n#ifdef FMT_FORMAT_SET_AS_LIST\n  static FMT_CONSTEXPR_DECL const bool value = false;\n#else\n  static FMT_CONSTEXPR_DECL const bool value =\n      !std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;\n#endif\n};\n\ntemplate <typename... Ts> struct conditional_helper {};\n\ntemplate <typename T, typename _ = void> struct is_range_ : std::false_type {};\n\n#if !FMT_MSC_VER || FMT_MSC_VER > 1800\n\n#  define FMT_DECLTYPE_RETURN(val)  \\\n    ->decltype(val) { return val; } \\\n    static_assert(                  \\\n        true, \"\")  // This makes it so that a semicolon is required after the\n                   // macro, which helps clang-format handle the formatting.\n\n// C array overload\ntemplate <typename T, std::size_t N>\nauto range_begin(const T (&arr)[N]) -> const T* {\n  return arr;\n}\ntemplate <typename T, std::size_t N>\nauto range_end(const T (&arr)[N]) -> const T* {\n  return arr + N;\n}\n\ntemplate <typename T, typename Enable = void>\nstruct has_member_fn_begin_end_t : std::false_type {};\n\ntemplate <typename T>\nstruct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),\n                                           decltype(std::declval<T>().end())>>\n    : std::true_type {};\n\n// Member function overload\ntemplate <typename T>\nauto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());\ntemplate <typename T>\nauto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());\n\n// ADL overload. Only participates in overload resolution if member functions\n// are not found.\ntemplate <typename T>\nauto range_begin(T&& rng)\n    -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,\n                   decltype(begin(static_cast<T&&>(rng)))> {\n  return begin(static_cast<T&&>(rng));\n}\ntemplate <typename T>\nauto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,\n                                       decltype(end(static_cast<T&&>(rng)))> {\n  return end(static_cast<T&&>(rng));\n}\n\ntemplate <typename T, typename Enable = void>\nstruct has_const_begin_end : std::false_type {};\ntemplate <typename T, typename Enable = void>\nstruct has_mutable_begin_end : std::false_type {};\n\ntemplate <typename T>\nstruct has_const_begin_end<\n    T,\n    void_t<\n        decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),\n        decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>\n    : std::true_type {};\n\ntemplate <typename T>\nstruct has_mutable_begin_end<\n    T, void_t<decltype(detail::range_begin(std::declval<T>())),\n              decltype(detail::range_end(std::declval<T>())),\n              enable_if_t<std::is_copy_constructible<T>::value>>>\n    : std::true_type {};\n\ntemplate <typename T>\nstruct is_range_<T, void>\n    : std::integral_constant<bool, (has_const_begin_end<T>::value ||\n                                    has_mutable_begin_end<T>::value)> {};\n#  undef FMT_DECLTYPE_RETURN\n#endif\n\n// tuple_size and tuple_element check.\ntemplate <typename T> class is_tuple_like_ {\n  template <typename U>\n  static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());\n  template <typename> static void check(...);\n\n public:\n  static FMT_CONSTEXPR_DECL const bool value =\n      !std::is_void<decltype(check<T>(nullptr))>::value;\n};\n\n// Check for integer_sequence\n#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900\ntemplate <typename T, T... N>\nusing integer_sequence = std::integer_sequence<T, N...>;\ntemplate <size_t... N> using index_sequence = std::index_sequence<N...>;\ntemplate <size_t N> using make_index_sequence = std::make_index_sequence<N>;\n#else\ntemplate <typename T, T... N> struct integer_sequence {\n  using value_type = T;\n\n  static FMT_CONSTEXPR size_t size() { return sizeof...(N); }\n};\n\ntemplate <size_t... N> using index_sequence = integer_sequence<size_t, N...>;\n\ntemplate <typename T, size_t N, T... Ns>\nstruct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};\ntemplate <typename T, T... Ns>\nstruct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};\n\ntemplate <size_t N>\nusing make_index_sequence = make_integer_sequence<size_t, N>;\n#endif\n\ntemplate <class Tuple, class F, size_t... Is>\nvoid for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT {\n  using std::get;\n  // using free function get<I>(T) now.\n  const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};\n  (void)_;  // blocks warnings\n}\n\ntemplate <class T>\nFMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(\n    T const&) {\n  return {};\n}\n\ntemplate <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {\n  const auto indexes = get_indexes(tup);\n  for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));\n}\n\ntemplate <typename Range>\nusing value_type =\n    remove_cvref_t<decltype(*detail::range_begin(std::declval<Range>()))>;\n\ntemplate <typename OutputIt> OutputIt write_delimiter(OutputIt out) {\n  *out++ = ',';\n  *out++ = ' ';\n  return out;\n}\n\nstruct singleton {\n  unsigned char upper;\n  unsigned char lower_count;\n};\n\ninline auto is_printable(uint16_t x, const singleton* singletons,\n                         size_t singletons_size,\n                         const unsigned char* singleton_lowers,\n                         const unsigned char* normal, size_t normal_size)\n    -> bool {\n  auto upper = x >> 8;\n  auto lower_start = 0;\n  for (size_t i = 0; i < singletons_size; ++i) {\n    auto s = singletons[i];\n    auto lower_end = lower_start + s.lower_count;\n    if (upper < s.upper) break;\n    if (upper == s.upper) {\n      for (auto j = lower_start; j < lower_end; ++j) {\n        if (singleton_lowers[j] == (x & 0xff)) return false;\n      }\n    }\n    lower_start = lower_end;\n  }\n\n  auto xsigned = static_cast<int>(x);\n  auto current = true;\n  for (size_t i = 0; i < normal_size; ++i) {\n    auto v = static_cast<int>(normal[i]);\n    auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v;\n    xsigned -= len;\n    if (xsigned < 0) break;\n    current = !current;\n  }\n  return current;\n}\n\n// Returns true iff the code point cp is printable.\n// This code is generated by support/printable.py.\ninline auto is_printable(uint32_t cp) -> bool {\n  static constexpr singleton singletons0[] = {\n      {0x00, 1},  {0x03, 5},  {0x05, 6},  {0x06, 3},  {0x07, 6},  {0x08, 8},\n      {0x09, 17}, {0x0a, 28}, {0x0b, 25}, {0x0c, 20}, {0x0d, 16}, {0x0e, 13},\n      {0x0f, 4},  {0x10, 3},  {0x12, 18}, {0x13, 9},  {0x16, 1},  {0x17, 5},\n      {0x18, 2},  {0x19, 3},  {0x1a, 7},  {0x1c, 2},  {0x1d, 1},  {0x1f, 22},\n      {0x20, 3},  {0x2b, 3},  {0x2c, 2},  {0x2d, 11}, {0x2e, 1},  {0x30, 3},\n      {0x31, 2},  {0x32, 1},  {0xa7, 2},  {0xa9, 2},  {0xaa, 4},  {0xab, 8},\n      {0xfa, 2},  {0xfb, 5},  {0xfd, 4},  {0xfe, 3},  {0xff, 9},\n  };\n  static constexpr unsigned char singletons0_lower[] = {\n      0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90,\n      0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f,\n      0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, 0xa9, 0xb1,\n      0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04,\n      0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, 0x5d,\n      0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf,\n      0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,\n      0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d,\n      0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d,\n      0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d,\n      0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5,\n      0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7,\n      0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49,\n      0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7,\n      0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7,\n      0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e,\n      0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16,\n      0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e,\n      0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f,\n      0x74, 0x75, 0x96, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf,\n      0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0,\n      0xc1, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27,\n      0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91,\n      0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7,\n      0xfe, 0xff,\n  };\n  static constexpr singleton singletons1[] = {\n      {0x00, 6},  {0x01, 1}, {0x03, 1},  {0x04, 2}, {0x08, 8},  {0x09, 2},\n      {0x0a, 5},  {0x0b, 2}, {0x0e, 4},  {0x10, 1}, {0x11, 2},  {0x12, 5},\n      {0x13, 17}, {0x14, 1}, {0x15, 2},  {0x17, 2}, {0x19, 13}, {0x1c, 5},\n      {0x1d, 8},  {0x24, 1}, {0x6a, 3},  {0x6b, 2}, {0xbc, 2},  {0xd1, 2},\n      {0xd4, 12}, {0xd5, 9}, {0xd6, 2},  {0xd7, 2}, {0xda, 1},  {0xe0, 5},\n      {0xe1, 2},  {0xe8, 2}, {0xee, 32}, {0xf0, 4}, {0xf8, 2},  {0xf9, 2},\n      {0xfa, 2},  {0xfb, 1},\n  };\n  static constexpr unsigned char singletons1_lower[] = {\n      0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07,\n      0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36,\n      0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, 0x35, 0xe0, 0x12, 0x87,\n      0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,\n      0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5c, 0xb6, 0xb7, 0x1b,\n      0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9,\n      0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66,\n      0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27,\n      0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc,\n      0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7,\n      0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xc5, 0xc6,\n      0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c,\n      0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66,\n      0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0,\n      0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93,\n  };\n  static constexpr unsigned char normal0[] = {\n      0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, 0x82, 0x44, 0x08, 0x1b, 0x04,\n      0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, 0x28, 0x0b, 0x80, 0xe0,\n      0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, 0x34, 0x04, 0x07, 0x03, 0x01,\n      0x07, 0x06, 0x07, 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, 0x55, 0x07, 0x03,\n      0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, 0x07, 0x03, 0x02, 0x03, 0x03,\n      0x03, 0x0c, 0x04, 0x05, 0x03, 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, 0x3a,\n      0x03, 0x11, 0x07, 0x06, 0x05, 0x10, 0x07, 0x57, 0x07, 0x02, 0x07, 0x15,\n      0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, 0x11, 0x06, 0x0f,\n      0x0c, 0x3a, 0x04, 0x1d, 0x25, 0x5f, 0x20, 0x6d, 0x04, 0x6a, 0x25, 0x80,\n      0xc8, 0x05, 0x82, 0xb0, 0x03, 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07,\n      0x15, 0x0b, 0x17, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, 0x0a, 0x06,\n      0x1a, 0x06, 0x59, 0x07, 0x2b, 0x05, 0x46, 0x0a, 0x2c, 0x04, 0x0c, 0x04,\n      0x01, 0x03, 0x31, 0x0b, 0x2c, 0x04, 0x1a, 0x06, 0x0b, 0x03, 0x80, 0xac,\n      0x06, 0x0a, 0x06, 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, 0x3c,\n      0x03, 0x0f, 0x03, 0x3c, 0x07, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11,\n      0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c,\n      0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, 0x3b,\n      0x07, 0x02, 0x0e, 0x18, 0x09, 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6,\n      0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, 0xee, 0x0d, 0x03,\n      0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, 0x80,\n      0xcb, 0x2a, 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, 0x0c, 0x06,\n      0x74, 0x0b, 0x1e, 0x03, 0x5a, 0x04, 0x59, 0x09, 0x80, 0x83, 0x18, 0x1c,\n      0x0a, 0x16, 0x09, 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17,\n      0x04, 0x31, 0xa1, 0x04, 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, 0x80,\n      0xa5, 0x11, 0x81, 0x6d, 0x10, 0x78, 0x28, 0x2a, 0x06, 0x4c, 0x04, 0x80,\n      0x8d, 0x04, 0x80, 0xbe, 0x03, 0x1b, 0x03, 0x0f, 0x0d,\n  };\n  static constexpr unsigned char normal1[] = {\n      0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, 0x66, 0x03, 0x01, 0x2f,\n      0x2e, 0x80, 0x82, 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, 0x24, 0x09, 0x1e,\n      0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, 0x80, 0xaa, 0x06, 0x24, 0x04,\n      0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, 0x01, 0x80, 0x90, 0x81, 0x37, 0x09,\n      0x16, 0x0a, 0x08, 0x80, 0x98, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, 0x16,\n      0x05, 0x21, 0x03, 0x1b, 0x05, 0x01, 0x40, 0x38, 0x04, 0x4b, 0x05, 0x2f,\n      0x04, 0x0a, 0x07, 0x09, 0x07, 0x40, 0x20, 0x27, 0x04, 0x0c, 0x09, 0x36,\n      0x03, 0x3a, 0x05, 0x1a, 0x07, 0x04, 0x0c, 0x07, 0x50, 0x49, 0x37, 0x33,\n      0x0d, 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08,\n      0x2a, 0x56, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e,\n      0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41,\n      0x2a, 0x06, 0x3b, 0x05, 0x0a, 0x06, 0x51, 0x06, 0x01, 0x05, 0x10, 0x03,\n      0x05, 0x80, 0x8b, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22,\n      0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, 0x39, 0x07, 0x0a, 0x36, 0x2c, 0x04,\n      0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45,\n      0x1b, 0x48, 0x08, 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03,\n      0x47, 0x49, 0x37, 0x03, 0x0e, 0x08, 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81,\n      0x36, 0x19, 0x80, 0xb7, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75,\n      0x0b, 0x80, 0xc4, 0x8a, 0xbc, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1,\n      0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x02, 0x60, 0x26, 0x0a, 0x46, 0x0a,\n      0x28, 0x05, 0x13, 0x82, 0xb0, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, 0x11,\n      0x40, 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, 0x09,\n      0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89,\n      0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, 0x10, 0x93, 0x60, 0x80, 0xf6,\n      0x0a, 0x73, 0x08, 0x6e, 0x17, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09,\n      0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, 0x15, 0x85, 0x50,\n      0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, 0x02, 0x81, 0x70, 0x3a, 0x05,\n      0x01, 0x85, 0x00, 0x80, 0xd7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83,\n      0x11, 0x44, 0x4c, 0x3d, 0x80, 0xc2, 0x3c, 0x06, 0x01, 0x04, 0x55, 0x05,\n      0x1b, 0x34, 0x02, 0x81, 0x0e, 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, 0x80,\n      0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80,\n      0x9a, 0x83, 0xd8, 0x08, 0x0d, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07,\n      0x0c, 0x14, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, 0x22, 0x4e,\n      0x81, 0x54, 0x0c, 0x15, 0x03, 0x03, 0x05, 0x07, 0x09, 0x19, 0x07, 0x07,\n      0x09, 0x03, 0x0d, 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06,\n  };\n  auto lower = static_cast<uint16_t>(cp);\n  if (cp < 0x10000) {\n    return is_printable(lower, singletons0,\n                        sizeof(singletons0) / sizeof(*singletons0),\n                        singletons0_lower, normal0, sizeof(normal0));\n  }\n  if (cp < 0x20000) {\n    return is_printable(lower, singletons1,\n                        sizeof(singletons1) / sizeof(*singletons1),\n                        singletons1_lower, normal1, sizeof(normal1));\n  }\n  if (0x2a6de <= cp && cp < 0x2a700) return false;\n  if (0x2b735 <= cp && cp < 0x2b740) return false;\n  if (0x2b81e <= cp && cp < 0x2b820) return false;\n  if (0x2cea2 <= cp && cp < 0x2ceb0) return false;\n  if (0x2ebe1 <= cp && cp < 0x2f800) return false;\n  if (0x2fa1e <= cp && cp < 0x30000) return false;\n  if (0x3134b <= cp && cp < 0xe0100) return false;\n  if (0xe01f0 <= cp && cp < 0x110000) return false;\n  return cp < 0x110000;\n}\n\ninline auto needs_escape(uint32_t cp) -> bool {\n  return cp < 0x20 || cp == 0x7f || cp == '\"' || cp == '\\\\' ||\n         !is_printable(cp);\n}\n\ntemplate <typename Char> struct find_escape_result {\n  const Char* begin;\n  const Char* end;\n  uint32_t cp;\n};\n\ntemplate <typename Char>\nauto find_escape(const Char* begin, const Char* end)\n    -> find_escape_result<Char> {\n  for (; begin != end; ++begin) {\n    auto cp = static_cast<typename std::make_unsigned<Char>::type>(*begin);\n    if (sizeof(Char) == 1 && cp >= 0x80) continue;\n    if (needs_escape(cp)) return {begin, begin + 1, cp};\n  }\n  return {begin, nullptr, 0};\n}\n\ninline auto find_escape(const char* begin, const char* end)\n    -> find_escape_result<char> {\n  if (!is_utf8()) return find_escape<char>(begin, end);\n  auto result = find_escape_result<char>{end, nullptr, 0};\n  for_each_codepoint(string_view(begin, to_unsigned(end - begin)),\n                     [&](uint32_t cp, string_view sv) {\n                       if (needs_escape(cp)) {\n                         result = {sv.begin(), sv.end(), cp};\n                         return false;\n                       }\n                       return true;\n                     });\n  return result;\n}\n\ntemplate <typename Char, typename OutputIt>\nauto write_range_entry(OutputIt out, basic_string_view<Char> str) -> OutputIt {\n  *out++ = '\"';\n  auto begin = str.begin(), end = str.end();\n  do {\n    auto escape = find_escape(begin, end);\n    out = copy_str<Char>(begin, escape.begin, out);\n    begin = escape.end;\n    if (!begin) break;\n    auto c = static_cast<Char>(escape.cp);\n    switch (escape.cp) {\n    case '\\n':\n      *out++ = '\\\\';\n      c = 'n';\n      break;\n    case '\\r':\n      *out++ = '\\\\';\n      c = 'r';\n      break;\n    case '\\t':\n      *out++ = '\\\\';\n      c = 't';\n      break;\n    case '\"':\n      FMT_FALLTHROUGH;\n    case '\\\\':\n      *out++ = '\\\\';\n      break;\n    default:\n      if (is_utf8()) {\n        if (escape.cp < 0x100) {\n          out = format_to(out, \"\\\\x{:02x}\", escape.cp);\n          continue;\n        }\n        if (escape.cp < 0x10000) {\n          out = format_to(out, \"\\\\u{:04x}\", escape.cp);\n          continue;\n        }\n        if (escape.cp < 0x110000) {\n          out = format_to(out, \"\\\\U{:08x}\", escape.cp);\n          continue;\n        }\n      }\n      for (Char escape_char : basic_string_view<Char>(\n               escape.begin, to_unsigned(escape.end - escape.begin))) {\n        out = format_to(\n            out, \"\\\\x{:02x}\",\n            static_cast<typename std::make_unsigned<Char>::type>(escape_char));\n      }\n      continue;\n    }\n    *out++ = c;\n  } while (begin != end);\n  *out++ = '\"';\n  return out;\n}\n\ntemplate <typename Char, typename OutputIt, typename T,\n          FMT_ENABLE_IF(std::is_convertible<T, std_string_view<char>>::value)>\ninline auto write_range_entry(OutputIt out, const T& str) -> OutputIt {\n  auto sv = std_string_view<Char>(str);\n  return write_range_entry<Char>(out, basic_string_view<Char>(sv));\n}\n\ntemplate <typename Char, typename OutputIt, typename Arg,\n          FMT_ENABLE_IF(std::is_same<Arg, Char>::value)>\nOutputIt write_range_entry(OutputIt out, const Arg v) {\n  *out++ = '\\'';\n  *out++ = v;\n  *out++ = '\\'';\n  return out;\n}\n\ntemplate <\n    typename Char, typename OutputIt, typename Arg,\n    FMT_ENABLE_IF(!is_std_string_like<typename std::decay<Arg>::type>::value &&\n                  !std::is_same<Arg, Char>::value)>\nOutputIt write_range_entry(OutputIt out, const Arg& v) {\n  return write<Char>(out, v);\n}\n\n}  // namespace detail\n\ntemplate <typename T> struct is_tuple_like {\n  static FMT_CONSTEXPR_DECL const bool value =\n      detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;\n};\n\ntemplate <typename TupleT, typename Char>\nstruct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {\n private:\n  // C++11 generic lambda for format().\n  template <typename FormatContext> struct format_each {\n    template <typename T> void operator()(const T& v) {\n      if (i > 0) out = detail::write_delimiter(out);\n      out = detail::write_range_entry<Char>(out, v);\n      ++i;\n    }\n    int i;\n    typename FormatContext::iterator& out;\n  };\n\n public:\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    return ctx.begin();\n  }\n\n  template <typename FormatContext = format_context>\n  auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {\n    auto out = ctx.out();\n    *out++ = '(';\n    detail::for_each(values, format_each<FormatContext>{0, out});\n    *out++ = ')';\n    return out;\n  }\n};\n\ntemplate <typename T, typename Char> struct is_range {\n  static FMT_CONSTEXPR_DECL const bool value =\n      detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&\n      !detail::is_map<T>::value &&\n      !std::is_convertible<T, std::basic_string<Char>>::value &&\n      !std::is_constructible<detail::std_string_view<Char>, T>::value;\n};\n\ntemplate <typename T, typename Char>\nstruct formatter<\n    T, Char,\n    enable_if_t<\n        fmt::is_range<T, Char>::value\n// Workaround a bug in MSVC 2019 and earlier.\n#if !FMT_MSC_VER\n        && (is_formattable<detail::value_type<T>, Char>::value ||\n            detail::has_fallback_formatter<detail::value_type<T>, Char>::value)\n#endif\n        >> {\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    return ctx.begin();\n  }\n\n  template <\n      typename FormatContext, typename U,\n      FMT_ENABLE_IF(\n          std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,\n                                        const T, T>>::value)>\n  auto format(U& range, FormatContext& ctx) -> decltype(ctx.out()) {\n#ifdef FMT_DEPRECATED_BRACED_RANGES\n    Char prefix = '{';\n    Char postfix = '}';\n#else\n    Char prefix = detail::is_set<T>::value ? '{' : '[';\n    Char postfix = detail::is_set<T>::value ? '}' : ']';\n#endif\n    auto out = ctx.out();\n    *out++ = prefix;\n    int i = 0;\n    auto it = std::begin(range);\n    auto end = std::end(range);\n    for (; it != end; ++it) {\n      if (i > 0) out = detail::write_delimiter(out);\n      out = detail::write_range_entry<Char>(out, *it);\n      ++i;\n    }\n    *out++ = postfix;\n    return out;\n  }\n};\n\ntemplate <typename T, typename Char>\nstruct formatter<\n    T, Char,\n    enable_if_t<\n        detail::is_map<T>::value\n// Workaround a bug in MSVC 2019 and earlier.\n#if !FMT_MSC_VER\n        && (is_formattable<detail::value_type<T>, Char>::value ||\n            detail::has_fallback_formatter<detail::value_type<T>, Char>::value)\n#endif\n        >> {\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    return ctx.begin();\n  }\n\n  template <\n      typename FormatContext, typename U,\n      FMT_ENABLE_IF(\n          std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,\n                                        const T, T>>::value)>\n  auto format(U& map, FormatContext& ctx) -> decltype(ctx.out()) {\n    auto out = ctx.out();\n    *out++ = '{';\n    int i = 0;\n    for (const auto& item : map) {\n      if (i > 0) out = detail::write_delimiter(out);\n      out = detail::write_range_entry<Char>(out, item.first);\n      *out++ = ':';\n      *out++ = ' ';\n      out = detail::write_range_entry<Char>(out, item.second);\n      ++i;\n    }\n    *out++ = '}';\n    return out;\n  }\n};\n\ntemplate <typename Char, typename... T> struct tuple_join_view : detail::view {\n  const std::tuple<T...>& tuple;\n  basic_string_view<Char> sep;\n\n  tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)\n      : tuple(t), sep{s} {}\n};\n\ntemplate <typename Char, typename... T>\nusing tuple_arg_join = tuple_join_view<Char, T...>;\n\n// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers\n// support in tuple_join. It is disabled by default because of issues with\n// the dynamic width and precision.\n#ifndef FMT_TUPLE_JOIN_SPECIFIERS\n#  define FMT_TUPLE_JOIN_SPECIFIERS 0\n#endif\n\ntemplate <typename Char, typename... T>\nstruct formatter<tuple_join_view<Char, T...>, Char> {\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {\n    return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());\n  }\n\n  template <typename FormatContext>\n  auto format(const tuple_join_view<Char, T...>& value,\n              FormatContext& ctx) const -> typename FormatContext::iterator {\n    return do_format(value, ctx,\n                     std::integral_constant<size_t, sizeof...(T)>());\n  }\n\n private:\n  std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;\n\n  template <typename ParseContext>\n  FMT_CONSTEXPR auto do_parse(ParseContext& ctx,\n                              std::integral_constant<size_t, 0>)\n      -> decltype(ctx.begin()) {\n    return ctx.begin();\n  }\n\n  template <typename ParseContext, size_t N>\n  FMT_CONSTEXPR auto do_parse(ParseContext& ctx,\n                              std::integral_constant<size_t, N>)\n      -> decltype(ctx.begin()) {\n    auto end = ctx.begin();\n#if FMT_TUPLE_JOIN_SPECIFIERS\n    end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);\n    if (N > 1) {\n      auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());\n      if (end != end1)\n        FMT_THROW(format_error(\"incompatible format specs for tuple elements\"));\n    }\n#endif\n    return end;\n  }\n\n  template <typename FormatContext>\n  auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,\n                 std::integral_constant<size_t, 0>) const ->\n      typename FormatContext::iterator {\n    return ctx.out();\n  }\n\n  template <typename FormatContext, size_t N>\n  auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,\n                 std::integral_constant<size_t, N>) const ->\n      typename FormatContext::iterator {\n    auto out = std::get<sizeof...(T) - N>(formatters_)\n                   .format(std::get<sizeof...(T) - N>(value.tuple), ctx);\n    if (N > 1) {\n      out = std::copy(value.sep.begin(), value.sep.end(), out);\n      ctx.advance_to(out);\n      return do_format(value, ctx, std::integral_constant<size_t, N - 1>());\n    }\n    return out;\n  }\n};\n\nFMT_MODULE_EXPORT_BEGIN\n\n/**\n  \\rst\n  Returns an object that formats `tuple` with elements separated by `sep`.\n\n  **Example**::\n\n    std::tuple<int, char> t = {1, 'a'};\n    fmt::print(\"{}\", fmt::join(t, \", \"));\n    // Output: \"1, a\"\n  \\endrst\n */\ntemplate <typename... T>\nFMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)\n    -> tuple_join_view<char, T...> {\n  return {tuple, sep};\n}\n\ntemplate <typename... T>\nFMT_CONSTEXPR auto join(const std::tuple<T...>& tuple,\n                        basic_string_view<wchar_t> sep)\n    -> tuple_join_view<wchar_t, T...> {\n  return {tuple, sep};\n}\n\n/**\n  \\rst\n  Returns an object that formats `initializer_list` with elements separated by\n  `sep`.\n\n  **Example**::\n\n    fmt::print(\"{}\", fmt::join({1, 2, 3}, \", \"));\n    // Output: \"1, 2, 3\"\n  \\endrst\n */\ntemplate <typename T>\nauto join(std::initializer_list<T> list, string_view sep)\n    -> join_view<const T*, const T*> {\n  return join(std::begin(list), std::end(list), sep);\n}\n\nFMT_MODULE_EXPORT_END\nFMT_END_NAMESPACE\n\n#endif  // FMT_RANGES_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/bundled/xchar.h",
    "content": "// Formatting library for C++ - optional wchar_t and exotic character support\n//\n// Copyright (c) 2012 - present, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_XCHAR_H_\n#define FMT_XCHAR_H_\n\n#include <cwchar>\n#include <tuple>\n\n#include \"format.h\"\n\nFMT_BEGIN_NAMESPACE\nnamespace detail {\ntemplate <typename T>\nusing is_exotic_char = bool_constant<!std::is_same<T, char>::value>;\n}\n\nFMT_MODULE_EXPORT_BEGIN\n\nusing wstring_view = basic_string_view<wchar_t>;\nusing wformat_parse_context = basic_format_parse_context<wchar_t>;\nusing wformat_context = buffer_context<wchar_t>;\nusing wformat_args = basic_format_args<wformat_context>;\nusing wmemory_buffer = basic_memory_buffer<wchar_t>;\n\n#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409\n// Workaround broken conversion on older gcc.\ntemplate <typename... Args> using wformat_string = wstring_view;\n#else\ntemplate <typename... Args>\nusing wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;\n#endif\n\ntemplate <> struct is_char<wchar_t> : std::true_type {};\ntemplate <> struct is_char<detail::char8_type> : std::true_type {};\ntemplate <> struct is_char<char16_t> : std::true_type {};\ntemplate <> struct is_char<char32_t> : std::true_type {};\n\ntemplate <typename... Args>\nconstexpr format_arg_store<wformat_context, Args...> make_wformat_args(\n    const Args&... args) {\n  return {args...};\n}\n\ninline namespace literals {\nconstexpr auto operator\"\"_format(const wchar_t* s, size_t n)\n    -> detail::udl_formatter<wchar_t> {\n  return {{s, n}};\n}\n\n#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_PARAMETERS\nconstexpr detail::udl_arg<wchar_t> operator\"\"_a(const wchar_t* s, size_t) {\n  return {s};\n}\n#endif\n}  // namespace literals\n\ntemplate <typename It, typename Sentinel>\nauto join(It begin, Sentinel end, wstring_view sep)\n    -> join_view<It, Sentinel, wchar_t> {\n  return {begin, end, sep};\n}\n\ntemplate <typename Range>\nauto join(Range&& range, wstring_view sep)\n    -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>,\n                 wchar_t> {\n  return join(std::begin(range), std::end(range), sep);\n}\n\ntemplate <typename T>\nauto join(std::initializer_list<T> list, wstring_view sep)\n    -> join_view<const T*, const T*, wchar_t> {\n  return join(std::begin(list), std::end(list), sep);\n}\n\ntemplate <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>\nauto vformat(basic_string_view<Char> format_str,\n             basic_format_args<buffer_context<type_identity_t<Char>>> args)\n    -> std::basic_string<Char> {\n  basic_memory_buffer<Char> buffer;\n  detail::vformat_to(buffer, format_str, args);\n  return to_string(buffer);\n}\n\n// Pass char_t as a default template parameter instead of using\n// std::basic_string<char_t<S>> to reduce the symbol size.\ntemplate <typename S, typename... Args, typename Char = char_t<S>,\n          FMT_ENABLE_IF(!std::is_same<Char, char>::value)>\nauto format(const S& format_str, Args&&... args) -> std::basic_string<Char> {\n  const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);\n  return vformat(to_string_view(format_str), vargs);\n}\n\ntemplate <typename Locale, typename S, typename Char = char_t<S>,\n          FMT_ENABLE_IF(detail::is_locale<Locale>::value&&\n                            detail::is_exotic_char<Char>::value)>\ninline auto vformat(\n    const Locale& loc, const S& format_str,\n    basic_format_args<buffer_context<type_identity_t<Char>>> args)\n    -> std::basic_string<Char> {\n  return detail::vformat(loc, to_string_view(format_str), args);\n}\n\ntemplate <typename Locale, typename S, typename... Args,\n          typename Char = char_t<S>,\n          FMT_ENABLE_IF(detail::is_locale<Locale>::value&&\n                            detail::is_exotic_char<Char>::value)>\ninline auto format(const Locale& loc, const S& format_str, Args&&... args)\n    -> std::basic_string<Char> {\n  return detail::vformat(loc, to_string_view(format_str),\n                         fmt::make_args_checked<Args...>(format_str, args...));\n}\n\ntemplate <typename OutputIt, typename S, typename Char = char_t<S>,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&\n                            detail::is_exotic_char<Char>::value)>\nauto vformat_to(OutputIt out, const S& format_str,\n                basic_format_args<buffer_context<type_identity_t<Char>>> args)\n    -> OutputIt {\n  auto&& buf = detail::get_buffer<Char>(out);\n  detail::vformat_to(buf, to_string_view(format_str), args);\n  return detail::get_iterator(buf);\n}\n\ntemplate <typename OutputIt, typename S, typename... Args,\n          typename Char = char_t<S>,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&\n                            detail::is_exotic_char<Char>::value)>\ninline auto format_to(OutputIt out, const S& fmt, Args&&... args) -> OutputIt {\n  const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);\n  return vformat_to(out, to_string_view(fmt), vargs);\n}\n\ntemplate <typename S, typename... Args, typename Char, size_t SIZE,\n          typename Allocator, FMT_ENABLE_IF(detail::is_string<S>::value)>\nFMT_DEPRECATED auto format_to(basic_memory_buffer<Char, SIZE, Allocator>& buf,\n                              const S& format_str, Args&&... args) ->\n    typename buffer_context<Char>::iterator {\n  const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);\n  detail::vformat_to(buf, to_string_view(format_str), vargs, {});\n  return detail::buffer_appender<Char>(buf);\n}\n\ntemplate <typename Locale, typename S, typename OutputIt, typename... Args,\n          typename Char = char_t<S>,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&\n                            detail::is_locale<Locale>::value&&\n                                detail::is_exotic_char<Char>::value)>\ninline auto vformat_to(\n    OutputIt out, const Locale& loc, const S& format_str,\n    basic_format_args<buffer_context<type_identity_t<Char>>> args) -> OutputIt {\n  auto&& buf = detail::get_buffer<Char>(out);\n  vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc));\n  return detail::get_iterator(buf);\n}\n\ntemplate <\n    typename OutputIt, typename Locale, typename S, typename... Args,\n    typename Char = char_t<S>,\n    bool enable = detail::is_output_iterator<OutputIt, Char>::value&&\n        detail::is_locale<Locale>::value&& detail::is_exotic_char<Char>::value>\ninline auto format_to(OutputIt out, const Locale& loc, const S& format_str,\n                      Args&&... args) ->\n    typename std::enable_if<enable, OutputIt>::type {\n  const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);\n  return vformat_to(out, loc, to_string_view(format_str), vargs);\n}\n\ntemplate <typename OutputIt, typename Char, typename... Args,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&\n                            detail::is_exotic_char<Char>::value)>\ninline auto vformat_to_n(\n    OutputIt out, size_t n, basic_string_view<Char> format_str,\n    basic_format_args<buffer_context<type_identity_t<Char>>> args)\n    -> format_to_n_result<OutputIt> {\n  detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(out,\n                                                                           n);\n  detail::vformat_to(buf, format_str, args);\n  return {buf.out(), buf.count()};\n}\n\ntemplate <typename OutputIt, typename S, typename... Args,\n          typename Char = char_t<S>,\n          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&\n                            detail::is_exotic_char<Char>::value)>\ninline auto format_to_n(OutputIt out, size_t n, const S& fmt,\n                        const Args&... args) -> format_to_n_result<OutputIt> {\n  const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);\n  return vformat_to_n(out, n, to_string_view(fmt), vargs);\n}\n\ntemplate <typename S, typename... Args, typename Char = char_t<S>,\n          FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>\ninline auto formatted_size(const S& fmt, Args&&... args) -> size_t {\n  detail::counting_buffer<Char> buf;\n  const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);\n  detail::vformat_to(buf, to_string_view(fmt), vargs);\n  return buf.count();\n}\n\ninline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) {\n  wmemory_buffer buffer;\n  detail::vformat_to(buffer, fmt, args);\n  buffer.push_back(L'\\0');\n  if (std::fputws(buffer.data(), f) == -1)\n    FMT_THROW(system_error(errno, FMT_STRING(\"cannot write to file\")));\n}\n\ninline void vprint(wstring_view fmt, wformat_args args) {\n  vprint(stdout, fmt, args);\n}\n\ntemplate <typename... T>\nvoid print(std::FILE* f, wformat_string<T...> fmt, T&&... args) {\n  return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...));\n}\n\ntemplate <typename... T> void print(wformat_string<T...> fmt, T&&... args) {\n  return vprint(wstring_view(fmt), fmt::make_wformat_args(args...));\n}\n\n/**\n  Converts *value* to ``std::wstring`` using the default format for type *T*.\n */\ntemplate <typename T> inline auto to_wstring(const T& value) -> std::wstring {\n  return format(FMT_STRING(L\"{}\"), value);\n}\nFMT_MODULE_EXPORT_END\nFMT_END_NAMESPACE\n\n#endif  // FMT_XCHAR_H_\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/chrono.h",
    "content": "//\n// Copyright(c) 2016 Gabi Melman.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n//\n\n#pragma once\n//\n// include bundled or external copy of fmtlib's chrono support\n//\n\n#if !defined(SPDLOG_USE_STD_FORMAT)\n#    if !defined(SPDLOG_FMT_EXTERNAL)\n#        ifdef SPDLOG_HEADER_ONLY\n#            ifndef FMT_HEADER_ONLY\n#                define FMT_HEADER_ONLY\n#            endif\n#        endif\n#        include <spdlog/fmt/bundled/chrono.h>\n#    else\n#        include <fmt/chrono.h>\n#    endif\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/compile.h",
    "content": "//\n// Copyright(c) 2016 Gabi Melman.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n//\n\n#pragma once\n//\n// include bundled or external copy of fmtlib's compile-time support\n//\n\n#if !defined(SPDLOG_USE_STD_FORMAT)\n#    if !defined(SPDLOG_FMT_EXTERNAL)\n#        ifdef SPDLOG_HEADER_ONLY\n#            ifndef FMT_HEADER_ONLY\n#                define FMT_HEADER_ONLY\n#            endif\n#        endif\n#        include <spdlog/fmt/bundled/compile.h>\n#    else\n#        include <fmt/compile.h>\n#    endif\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/fmt.h",
    "content": "//\n// Copyright(c) 2016-2018 Gabi Melman.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n//\n\n#pragma once\n\n//\n// Include a bundled header-only copy of fmtlib or an external one.\n// By default spdlog include its own copy.\n//\n\n#if defined(SPDLOG_USE_STD_FORMAT) // SPDLOG_USE_STD_FORMAT is defined - use std::format\n#    include <format>\n#elif !defined(SPDLOG_FMT_EXTERNAL)\n#    if !defined(SPDLOG_COMPILED_LIB) && !defined(FMT_HEADER_ONLY)\n#        define FMT_HEADER_ONLY\n#    endif\n#    ifndef FMT_USE_WINDOWS_H\n#        define FMT_USE_WINDOWS_H 0\n#    endif\n// enable the 'n' flag in for backward compatibility with fmt 6.x\n#    define FMT_DEPRECATED_N_SPECIFIER\n#    include <spdlog/fmt/bundled/core.h>\n#    include <spdlog/fmt/bundled/format.h>\n#else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib\n#    include <fmt/core.h>\n#    include <fmt/format.h>\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/ostr.h",
    "content": "//\n// Copyright(c) 2016 Gabi Melman.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n//\n\n#pragma once\n//\n// include bundled or external copy of fmtlib's ostream support\n//\n\n#if !defined(SPDLOG_USE_STD_FORMAT)\n#    if !defined(SPDLOG_FMT_EXTERNAL)\n#        ifdef SPDLOG_HEADER_ONLY\n#            ifndef FMT_HEADER_ONLY\n#                define FMT_HEADER_ONLY\n#            endif\n#        endif\n#        include <spdlog/fmt/bundled/ostream.h>\n#    else\n#        include <fmt/ostream.h>\n#    endif\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/ranges.h",
    "content": "//\n// Copyright(c) 2016 Gabi Melman.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n//\n\n#pragma once\n//\n// include bundled or external copy of fmtlib's ranges support\n//\n\n#if !defined(SPDLOG_USE_STD_FORMAT)\n#    if !defined(SPDLOG_FMT_EXTERNAL)\n#        ifdef SPDLOG_HEADER_ONLY\n#            ifndef FMT_HEADER_ONLY\n#                define FMT_HEADER_ONLY\n#            endif\n#        endif\n#        include <spdlog/fmt/bundled/ranges.h>\n#    else\n#        include <fmt/ranges.h>\n#    endif\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fmt/xchar.h",
    "content": "//\n// Copyright(c) 2016 Gabi Melman.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n//\n\n#pragma once\n//\n// include bundled or external copy of fmtlib's xchar support\n//\n\n#if !defined(SPDLOG_USE_STD_FORMAT)\n#    if !defined(SPDLOG_FMT_EXTERNAL)\n#        ifdef SPDLOG_HEADER_ONLY\n#            ifndef FMT_HEADER_ONLY\n#                define FMT_HEADER_ONLY\n#            endif\n#        endif\n#        include <spdlog/fmt/bundled/xchar.h>\n#    else\n#        include <fmt/xchar.h>\n#    endif\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/formatter.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/fmt/fmt.h>\n#include <spdlog/details/log_msg.h>\n\nnamespace spdlog {\n\nclass formatter\n{\npublic:\n    virtual ~formatter() = default;\n    virtual void format(const details::log_msg &msg, memory_buf_t &dest) = 0;\n    virtual std::unique_ptr<formatter> clone() const = 0;\n};\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/fwd.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\nnamespace spdlog {\nclass logger;\nclass formatter;\n\nnamespace sinks {\nclass sink;\n}\n\nnamespace level {\nenum level_enum : int;\n}\n\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/logger-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/logger.h>\n#endif\n\n#include <spdlog/sinks/sink.h>\n#include <spdlog/details/backtracer.h>\n#include <spdlog/pattern_formatter.h>\n\n#include <cstdio>\n\nnamespace spdlog {\n\n// public methods\nSPDLOG_INLINE logger::logger(const logger &other)\n    : name_(other.name_)\n    , sinks_(other.sinks_)\n    , level_(other.level_.load(std::memory_order_relaxed))\n    , flush_level_(other.flush_level_.load(std::memory_order_relaxed))\n    , custom_err_handler_(other.custom_err_handler_)\n    , tracer_(other.tracer_)\n{}\n\nSPDLOG_INLINE logger::logger(logger &&other) SPDLOG_NOEXCEPT : name_(std::move(other.name_)),\n                                                               sinks_(std::move(other.sinks_)),\n                                                               level_(other.level_.load(std::memory_order_relaxed)),\n                                                               flush_level_(other.flush_level_.load(std::memory_order_relaxed)),\n                                                               custom_err_handler_(std::move(other.custom_err_handler_)),\n                                                               tracer_(std::move(other.tracer_))\n\n{}\n\nSPDLOG_INLINE logger &logger::operator=(logger other) SPDLOG_NOEXCEPT\n{\n    this->swap(other);\n    return *this;\n}\n\nSPDLOG_INLINE void logger::swap(spdlog::logger &other) SPDLOG_NOEXCEPT\n{\n    name_.swap(other.name_);\n    sinks_.swap(other.sinks_);\n\n    // swap level_\n    auto other_level = other.level_.load();\n    auto my_level = level_.exchange(other_level);\n    other.level_.store(my_level);\n\n    // swap flush level_\n    other_level = other.flush_level_.load();\n    my_level = flush_level_.exchange(other_level);\n    other.flush_level_.store(my_level);\n\n    custom_err_handler_.swap(other.custom_err_handler_);\n    std::swap(tracer_, other.tracer_);\n}\n\nSPDLOG_INLINE void swap(logger &a, logger &b)\n{\n    a.swap(b);\n}\n\nSPDLOG_INLINE void logger::set_level(level::level_enum log_level)\n{\n    level_.store(log_level);\n}\n\nSPDLOG_INLINE level::level_enum logger::level() const\n{\n    return static_cast<level::level_enum>(level_.load(std::memory_order_relaxed));\n}\n\nSPDLOG_INLINE const std::string &logger::name() const\n{\n    return name_;\n}\n\n// set formatting for the sinks in this logger.\n// each sink will get a separate instance of the formatter object.\nSPDLOG_INLINE void logger::set_formatter(std::unique_ptr<formatter> f)\n{\n    for (auto it = sinks_.begin(); it != sinks_.end(); ++it)\n    {\n        if (std::next(it) == sinks_.end())\n        {\n            // last element - we can be move it.\n            (*it)->set_formatter(std::move(f));\n            break; // to prevent clang-tidy warning\n        }\n        else\n        {\n            (*it)->set_formatter(f->clone());\n        }\n    }\n}\n\nSPDLOG_INLINE void logger::set_pattern(std::string pattern, pattern_time_type time_type)\n{\n    auto new_formatter = details::make_unique<pattern_formatter>(std::move(pattern), time_type);\n    set_formatter(std::move(new_formatter));\n}\n\n// create new backtrace sink and move to it all our child sinks\nSPDLOG_INLINE void logger::enable_backtrace(size_t n_messages)\n{\n    tracer_.enable(n_messages);\n}\n\n// restore orig sinks and level and delete the backtrace sink\nSPDLOG_INLINE void logger::disable_backtrace()\n{\n    tracer_.disable();\n}\n\nSPDLOG_INLINE void logger::dump_backtrace()\n{\n    dump_backtrace_();\n}\n\n// flush functions\nSPDLOG_INLINE void logger::flush()\n{\n    flush_();\n}\n\nSPDLOG_INLINE void logger::flush_on(level::level_enum log_level)\n{\n    flush_level_.store(log_level);\n}\n\nSPDLOG_INLINE level::level_enum logger::flush_level() const\n{\n    return static_cast<level::level_enum>(flush_level_.load(std::memory_order_relaxed));\n}\n\n// sinks\nSPDLOG_INLINE const std::vector<sink_ptr> &logger::sinks() const\n{\n    return sinks_;\n}\n\nSPDLOG_INLINE std::vector<sink_ptr> &logger::sinks()\n{\n    return sinks_;\n}\n\n// error handler\nSPDLOG_INLINE void logger::set_error_handler(err_handler handler)\n{\n    custom_err_handler_ = std::move(handler);\n}\n\n// create new logger with same sinks and configuration.\nSPDLOG_INLINE std::shared_ptr<logger> logger::clone(std::string logger_name)\n{\n    auto cloned = std::make_shared<logger>(*this);\n    cloned->name_ = std::move(logger_name);\n    return cloned;\n}\n\n// protected methods\nSPDLOG_INLINE void logger::log_it_(const spdlog::details::log_msg &log_msg, bool log_enabled, bool traceback_enabled)\n{\n    if (log_enabled)\n    {\n        sink_it_(log_msg);\n    }\n    if (traceback_enabled)\n    {\n        tracer_.push_back(log_msg);\n    }\n}\n\nSPDLOG_INLINE void logger::sink_it_(const details::log_msg &msg)\n{\n    for (auto &sink : sinks_)\n    {\n        if (sink->should_log(msg.level))\n        {\n            SPDLOG_TRY\n            {\n                sink->log(msg);\n            }\n            SPDLOG_LOGGER_CATCH(msg.source)\n        }\n    }\n\n    if (should_flush_(msg))\n    {\n        flush_();\n    }\n}\n\nSPDLOG_INLINE void logger::flush_()\n{\n    for (auto &sink : sinks_)\n    {\n        SPDLOG_TRY\n        {\n            sink->flush();\n        }\n        SPDLOG_LOGGER_CATCH(source_loc())\n    }\n}\n\nSPDLOG_INLINE void logger::dump_backtrace_()\n{\n    using details::log_msg;\n    if (tracer_.enabled())\n    {\n        sink_it_(log_msg{name(), level::info, \"****************** Backtrace Start ******************\"});\n        tracer_.foreach_pop([this](const log_msg &msg) { this->sink_it_(msg); });\n        sink_it_(log_msg{name(), level::info, \"****************** Backtrace End ********************\"});\n    }\n}\n\nSPDLOG_INLINE bool logger::should_flush_(const details::log_msg &msg)\n{\n    auto flush_level = flush_level_.load(std::memory_order_relaxed);\n    return (msg.level >= flush_level) && (msg.level != level::off);\n}\n\nSPDLOG_INLINE void logger::err_handler_(const std::string &msg)\n{\n    if (custom_err_handler_)\n    {\n        custom_err_handler_(msg);\n    }\n    else\n    {\n        using std::chrono::system_clock;\n        static std::mutex mutex;\n        static std::chrono::system_clock::time_point last_report_time;\n        static size_t err_counter = 0;\n        std::lock_guard<std::mutex> lk{mutex};\n        auto now = system_clock::now();\n        err_counter++;\n        if (now - last_report_time < std::chrono::seconds(1))\n        {\n            return;\n        }\n        last_report_time = now;\n        auto tm_time = details::os::localtime(system_clock::to_time_t(now));\n        char date_buf[64];\n        std::strftime(date_buf, sizeof(date_buf), \"%Y-%m-%d %H:%M:%S\", &tm_time);\n#if defined(USING_R) && defined(R_R_H) // if in R environment\n        REprintf(\"[*** LOG ERROR #%04zu ***] [%s] [%s] {%s}\\n\", err_counter, date_buf, name().c_str(), msg.c_str());\n#else\n        std::fprintf(stderr, \"[*** LOG ERROR #%04zu ***] [%s] [%s] {%s}\\n\", err_counter, date_buf, name().c_str(), msg.c_str());\n#endif\n    }\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/logger.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n// Thread safe logger (except for set_error_handler())\n// Has name, log level, vector of std::shared sink pointers and formatter\n// Upon each log write the logger:\n// 1. Checks if its log level is enough to log the message and if yes:\n// 2. Call the underlying sinks to do the job.\n// 3. Each sink use its own private copy of a formatter to format the message\n// and send to its destination.\n//\n// The use of private formatter per sink provides the opportunity to cache some\n// formatted data, and support for different format per sink.\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/common.h>\n#include <spdlog/details/log_msg.h>\n#include <spdlog/details/backtracer.h>\n\n#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT\n#    ifndef _WIN32\n#        error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows\n#    endif\n#    include <spdlog/details/os.h>\n#endif\n\n#include <vector>\n\n#ifndef SPDLOG_NO_EXCEPTIONS\n#    define SPDLOG_LOGGER_CATCH(location)                                                                                                  \\\n        catch (const std::exception &ex)                                                                                                   \\\n        {                                                                                                                                  \\\n            if (location.filename)                                                                                                         \\\n            {                                                                                                                              \\\n                err_handler_(fmt_lib::format(\"{} [{}({})]\", ex.what(), location.filename, location.line));                                 \\\n            }                                                                                                                              \\\n            else                                                                                                                           \\\n            {                                                                                                                              \\\n                err_handler_(ex.what());                                                                                                   \\\n            }                                                                                                                              \\\n        }                                                                                                                                  \\\n        catch (...)                                                                                                                        \\\n        {                                                                                                                                  \\\n            err_handler_(\"Rethrowing unknown exception in logger\");                                                                        \\\n            throw;                                                                                                                         \\\n        }\n#else\n#    define SPDLOG_LOGGER_CATCH(location)\n#endif\n\nnamespace spdlog {\n\nclass SPDLOG_API logger\n{\npublic:\n    // Empty logger\n    explicit logger(std::string name)\n        : name_(std::move(name))\n        , sinks_()\n    {}\n\n    // Logger with range on sinks\n    template<typename It>\n    logger(std::string name, It begin, It end)\n        : name_(std::move(name))\n        , sinks_(begin, end)\n    {}\n\n    // Logger with single sink\n    logger(std::string name, sink_ptr single_sink)\n        : logger(std::move(name), {std::move(single_sink)})\n    {}\n\n    // Logger with sinks init list\n    logger(std::string name, sinks_init_list sinks)\n        : logger(std::move(name), sinks.begin(), sinks.end())\n    {}\n\n    virtual ~logger() = default;\n\n    logger(const logger &other);\n    logger(logger &&other) SPDLOG_NOEXCEPT;\n    logger &operator=(logger other) SPDLOG_NOEXCEPT;\n    void swap(spdlog::logger &other) SPDLOG_NOEXCEPT;\n\n    template<typename... Args>\n    void log(source_loc loc, level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args)\n    {\n        log_(loc, lvl, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void log(level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args)\n    {\n        log(source_loc{}, lvl, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename T>\n    void log(level::level_enum lvl, const T &msg)\n    {\n        log(source_loc{}, lvl, msg);\n    }\n\n    // T cannot be statically converted to format string (including string_view/wstring_view)\n    template<class T, typename std::enable_if<!is_convertible_to_any_format_string<const T &>::value, int>::type = 0>\n    void log(source_loc loc, level::level_enum lvl, const T &msg)\n    {\n        log(loc, lvl, \"{}\", msg);\n    }\n\n    void log(log_clock::time_point log_time, source_loc loc, level::level_enum lvl, string_view_t msg)\n    {\n        bool log_enabled = should_log(lvl);\n        bool traceback_enabled = tracer_.enabled();\n        if (!log_enabled && !traceback_enabled)\n        {\n            return;\n        }\n\n        details::log_msg log_msg(log_time, loc, name_, lvl, msg);\n        log_it_(log_msg, log_enabled, traceback_enabled);\n    }\n\n    void log(source_loc loc, level::level_enum lvl, string_view_t msg)\n    {\n        bool log_enabled = should_log(lvl);\n        bool traceback_enabled = tracer_.enabled();\n        if (!log_enabled && !traceback_enabled)\n        {\n            return;\n        }\n\n        details::log_msg log_msg(loc, name_, lvl, msg);\n        log_it_(log_msg, log_enabled, traceback_enabled);\n    }\n\n    void log(level::level_enum lvl, string_view_t msg)\n    {\n        log(source_loc{}, lvl, msg);\n    }\n\n    template<typename... Args>\n    void trace(format_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::trace, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void debug(format_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::debug, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void info(format_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::info, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void warn(format_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::warn, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void error(format_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::err, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void critical(format_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::critical, fmt, std::forward<Args>(args)...);\n    }\n\n#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT\n    template<typename... Args>\n    void log(source_loc loc, level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args)\n    {\n        log_(loc, lvl, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void log(level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args)\n    {\n        log(source_loc{}, lvl, fmt, std::forward<Args>(args)...);\n    }\n\n    void log(log_clock::time_point log_time, source_loc loc, level::level_enum lvl, wstring_view_t msg)\n    {\n        bool log_enabled = should_log(lvl);\n        bool traceback_enabled = tracer_.enabled();\n        if (!log_enabled && !traceback_enabled)\n        {\n            return;\n        }\n\n        memory_buf_t buf;\n        details::os::wstr_to_utf8buf(wstring_view_t(msg.data(), msg.size()), buf);\n        details::log_msg log_msg(log_time, loc, name_, lvl, string_view_t(buf.data(), buf.size()));\n        log_it_(log_msg, log_enabled, traceback_enabled);\n    }\n\n    void log(source_loc loc, level::level_enum lvl, wstring_view_t msg)\n    {\n        bool log_enabled = should_log(lvl);\n        bool traceback_enabled = tracer_.enabled();\n        if (!log_enabled && !traceback_enabled)\n        {\n            return;\n        }\n\n        memory_buf_t buf;\n        details::os::wstr_to_utf8buf(wstring_view_t(msg.data(), msg.size()), buf);\n        details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));\n        log_it_(log_msg, log_enabled, traceback_enabled);\n    }\n\n    void log(level::level_enum lvl, wstring_view_t msg)\n    {\n        log(source_loc{}, lvl, msg);\n    }\n\n    template<typename... Args>\n    void trace(wformat_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::trace, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void debug(wformat_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::debug, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void info(wformat_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::info, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void warn(wformat_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::warn, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void error(wformat_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::err, fmt, std::forward<Args>(args)...);\n    }\n\n    template<typename... Args>\n    void critical(wformat_string_t<Args...> fmt, Args &&... args)\n    {\n        log(level::critical, fmt, std::forward<Args>(args)...);\n    }\n#endif\n\n    template<typename T>\n    void trace(const T &msg)\n    {\n        log(level::trace, msg);\n    }\n\n    template<typename T>\n    void debug(const T &msg)\n    {\n        log(level::debug, msg);\n    }\n\n    template<typename T>\n    void info(const T &msg)\n    {\n        log(level::info, msg);\n    }\n\n    template<typename T>\n    void warn(const T &msg)\n    {\n        log(level::warn, msg);\n    }\n\n    template<typename T>\n    void error(const T &msg)\n    {\n        log(level::err, msg);\n    }\n\n    template<typename T>\n    void critical(const T &msg)\n    {\n        log(level::critical, msg);\n    }\n\n    // return true logging is enabled for the given level.\n    bool should_log(level::level_enum msg_level) const\n    {\n        return msg_level >= level_.load(std::memory_order_relaxed);\n    }\n\n    // return true if backtrace logging is enabled.\n    bool should_backtrace() const\n    {\n        return tracer_.enabled();\n    }\n\n    void set_level(level::level_enum log_level);\n\n    level::level_enum level() const;\n\n    const std::string &name() const;\n\n    // set formatting for the sinks in this logger.\n    // each sink will get a separate instance of the formatter object.\n    void set_formatter(std::unique_ptr<formatter> f);\n\n    void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local);\n\n    // backtrace support.\n    // efficiently store all debug/trace messages in a circular buffer until needed for debugging.\n    void enable_backtrace(size_t n_messages);\n    void disable_backtrace();\n    void dump_backtrace();\n\n    // flush functions\n    void flush();\n    void flush_on(level::level_enum log_level);\n    level::level_enum flush_level() const;\n\n    // sinks\n    const std::vector<sink_ptr> &sinks() const;\n\n    std::vector<sink_ptr> &sinks();\n\n    // error handler\n    void set_error_handler(err_handler);\n\n    // create new logger with same sinks and configuration.\n    virtual std::shared_ptr<logger> clone(std::string logger_name);\n\nprotected:\n    std::string name_;\n    std::vector<sink_ptr> sinks_;\n    spdlog::level_t level_{level::info};\n    spdlog::level_t flush_level_{level::off};\n    err_handler custom_err_handler_{nullptr};\n    details::backtracer tracer_;\n\n    // common implementation for after templated public api has been resolved\n    template<typename... Args>\n    void log_(source_loc loc, level::level_enum lvl, string_view_t fmt, Args &&... args)\n    {\n        bool log_enabled = should_log(lvl);\n        bool traceback_enabled = tracer_.enabled();\n        if (!log_enabled && !traceback_enabled)\n        {\n            return;\n        }\n        SPDLOG_TRY\n        {\n            memory_buf_t buf;\n#ifdef SPDLOG_USE_STD_FORMAT\n            fmt_lib::vformat_to(std::back_inserter(buf), fmt, fmt_lib::make_format_args(std::forward<Args>(args)...));\n#else\n            // seems that fmt::detail::vformat_to(buf, ...) is ~20ns faster than fmt::vformat_to(std::back_inserter(buf),..)\n            fmt::detail::vformat_to(buf, fmt, fmt::make_format_args(std::forward<Args>(args)...));\n#endif\n\n            details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));\n            log_it_(log_msg, log_enabled, traceback_enabled);\n        }\n        SPDLOG_LOGGER_CATCH(loc)\n    }\n\n#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT\n    template<typename... Args>\n    void log_(source_loc loc, level::level_enum lvl, wstring_view_t fmt, Args &&... args)\n    {\n        bool log_enabled = should_log(lvl);\n        bool traceback_enabled = tracer_.enabled();\n        if (!log_enabled && !traceback_enabled)\n        {\n            return;\n        }\n        SPDLOG_TRY\n        {\n            // format to wmemory_buffer and convert to utf8\n            wmemory_buf_t wbuf;\n#    ifdef SPDLOG_USE_STD_FORMAT\n            fmt_lib::vformat_to(\n                std::back_inserter(wbuf), fmt, fmt_lib::make_format_args<fmt_lib::wformat_context>(std::forward<Args>(args)...));\n#    else\n            fmt::detail::vformat_to(wbuf, fmt, fmt::make_format_args<fmt::wformat_context>(std::forward<Args>(args)...));\n#    endif\n\n            memory_buf_t buf;\n            details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), buf);\n            details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));\n            log_it_(log_msg, log_enabled, traceback_enabled);\n        }\n        SPDLOG_LOGGER_CATCH(loc)\n    }\n\n    // T can be statically converted to wstring_view, and no formatting needed.\n    template<class T, typename std::enable_if<std::is_convertible<const T &, spdlog::wstring_view_t>::value, int>::type = 0>\n    void log_(source_loc loc, level::level_enum lvl, const T &msg)\n    {\n        bool log_enabled = should_log(lvl);\n        bool traceback_enabled = tracer_.enabled();\n        if (!log_enabled && !traceback_enabled)\n        {\n            return;\n        }\n        SPDLOG_TRY\n        {\n            memory_buf_t buf;\n            details::os::wstr_to_utf8buf(msg, buf);\n            details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));\n            log_it_(log_msg, log_enabled, traceback_enabled);\n        }\n        SPDLOG_LOGGER_CATCH(loc)\n    }\n\n#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT\n\n    // log the given message (if the given log level is high enough),\n    // and save backtrace (if backtrace is enabled).\n    void log_it_(const details::log_msg &log_msg, bool log_enabled, bool traceback_enabled);\n    virtual void sink_it_(const details::log_msg &msg);\n    virtual void flush_();\n    void dump_backtrace_();\n    bool should_flush_(const details::log_msg &msg);\n\n    // handle errors during logging.\n    // default handler prints the error to stderr at max rate of 1 message/sec.\n    void err_handler_(const std::string &msg);\n};\n\nvoid swap(logger &a, logger &b);\n\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"logger-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/pattern_formatter-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/pattern_formatter.h>\n#endif\n\n#include <spdlog/details/fmt_helper.h>\n#include <spdlog/details/log_msg.h>\n#include <spdlog/details/os.h>\n#include <spdlog/fmt/fmt.h>\n#include <spdlog/formatter.h>\n\n#include <algorithm>\n#include <array>\n#include <chrono>\n#include <ctime>\n#include <cctype>\n#include <cstring>\n#include <iterator>\n#include <memory>\n#include <mutex>\n#include <string>\n#include <thread>\n#include <utility>\n#include <vector>\n\nnamespace spdlog {\nnamespace details {\n\n///////////////////////////////////////////////////////////////////////\n// name & level pattern appender\n///////////////////////////////////////////////////////////////////////\n\nclass scoped_padder\n{\npublic:\n    scoped_padder(size_t wrapped_size, const padding_info &padinfo, memory_buf_t &dest)\n        : padinfo_(padinfo)\n        , dest_(dest)\n    {\n        remaining_pad_ = static_cast<long>(padinfo.width_) - static_cast<long>(wrapped_size);\n        if (remaining_pad_ <= 0)\n        {\n            return;\n        }\n\n        if (padinfo_.side_ == padding_info::pad_side::left)\n        {\n            pad_it(remaining_pad_);\n            remaining_pad_ = 0;\n        }\n        else if (padinfo_.side_ == padding_info::pad_side::center)\n        {\n            auto half_pad = remaining_pad_ / 2;\n            auto reminder = remaining_pad_ & 1;\n            pad_it(half_pad);\n            remaining_pad_ = half_pad + reminder; // for the right side\n        }\n    }\n\n    template<typename T>\n    static unsigned int count_digits(T n)\n    {\n        return fmt_helper::count_digits(n);\n    }\n\n    ~scoped_padder()\n    {\n        if (remaining_pad_ >= 0)\n        {\n            pad_it(remaining_pad_);\n        }\n        else if (padinfo_.truncate_)\n        {\n            long new_size = static_cast<long>(dest_.size()) + remaining_pad_;\n            dest_.resize(static_cast<size_t>(new_size));\n        }\n    }\n\nprivate:\n    void pad_it(long count)\n    {\n        fmt_helper::append_string_view(string_view_t(spaces_.data(), static_cast<size_t>(count)), dest_);\n    }\n\n    const padding_info &padinfo_;\n    memory_buf_t &dest_;\n    long remaining_pad_;\n    string_view_t spaces_{\"                                                                \", 64};\n};\n\nstruct null_scoped_padder\n{\n    null_scoped_padder(size_t /*wrapped_size*/, const padding_info & /*padinfo*/, memory_buf_t & /*dest*/) {}\n\n    template<typename T>\n    static unsigned int count_digits(T /* number */)\n    {\n        return 0;\n    }\n};\n\ntemplate<typename ScopedPadder>\nclass name_formatter final : public flag_formatter\n{\npublic:\n    explicit name_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        ScopedPadder p(msg.logger_name.size(), padinfo_, dest);\n        fmt_helper::append_string_view(msg.logger_name, dest);\n    }\n};\n\n// log level appender\ntemplate<typename ScopedPadder>\nclass level_formatter final : public flag_formatter\n{\npublic:\n    explicit level_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        const string_view_t &level_name = level::to_string_view(msg.level);\n        ScopedPadder p(level_name.size(), padinfo_, dest);\n        fmt_helper::append_string_view(level_name, dest);\n    }\n};\n\n// short log level appender\ntemplate<typename ScopedPadder>\nclass short_level_formatter final : public flag_formatter\n{\npublic:\n    explicit short_level_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        string_view_t level_name{level::to_short_c_str(msg.level)};\n        ScopedPadder p(level_name.size(), padinfo_, dest);\n        fmt_helper::append_string_view(level_name, dest);\n    }\n};\n\n///////////////////////////////////////////////////////////////////////\n// Date time pattern appenders\n///////////////////////////////////////////////////////////////////////\n\nstatic const char *ampm(const tm &t)\n{\n    return t.tm_hour >= 12 ? \"PM\" : \"AM\";\n}\n\nstatic int to12h(const tm &t)\n{\n    return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour;\n}\n\n// Abbreviated weekday name\nstatic std::array<const char *, 7> days{{\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"}};\n\ntemplate<typename ScopedPadder>\nclass a_formatter final : public flag_formatter\n{\npublic:\n    explicit a_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        string_view_t field_value{days[static_cast<size_t>(tm_time.tm_wday)]};\n        ScopedPadder p(field_value.size(), padinfo_, dest);\n        fmt_helper::append_string_view(field_value, dest);\n    }\n};\n\n// Full weekday name\nstatic std::array<const char *, 7> full_days{{\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"}};\n\ntemplate<typename ScopedPadder>\nclass A_formatter : public flag_formatter\n{\npublic:\n    explicit A_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        string_view_t field_value{full_days[static_cast<size_t>(tm_time.tm_wday)]};\n        ScopedPadder p(field_value.size(), padinfo_, dest);\n        fmt_helper::append_string_view(field_value, dest);\n    }\n};\n\n// Abbreviated month\nstatic const std::array<const char *, 12> months{{\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sept\", \"Oct\", \"Nov\", \"Dec\"}};\n\ntemplate<typename ScopedPadder>\nclass b_formatter final : public flag_formatter\n{\npublic:\n    explicit b_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        string_view_t field_value{months[static_cast<size_t>(tm_time.tm_mon)]};\n        ScopedPadder p(field_value.size(), padinfo_, dest);\n        fmt_helper::append_string_view(field_value, dest);\n    }\n};\n\n// Full month name\nstatic const std::array<const char *, 12> full_months{\n    {\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"}};\n\ntemplate<typename ScopedPadder>\nclass B_formatter final : public flag_formatter\n{\npublic:\n    explicit B_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        string_view_t field_value{full_months[static_cast<size_t>(tm_time.tm_mon)]};\n        ScopedPadder p(field_value.size(), padinfo_, dest);\n        fmt_helper::append_string_view(field_value, dest);\n    }\n};\n\n// Date and time representation (Thu Aug 23 15:35:46 2014)\ntemplate<typename ScopedPadder>\nclass c_formatter final : public flag_formatter\n{\npublic:\n    explicit c_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 24;\n        ScopedPadder p(field_size, padinfo_, dest);\n\n        fmt_helper::append_string_view(days[static_cast<size_t>(tm_time.tm_wday)], dest);\n        dest.push_back(' ');\n        fmt_helper::append_string_view(months[static_cast<size_t>(tm_time.tm_mon)], dest);\n        dest.push_back(' ');\n        fmt_helper::append_int(tm_time.tm_mday, dest);\n        dest.push_back(' ');\n        // time\n\n        fmt_helper::pad2(tm_time.tm_hour, dest);\n        dest.push_back(':');\n        fmt_helper::pad2(tm_time.tm_min, dest);\n        dest.push_back(':');\n        fmt_helper::pad2(tm_time.tm_sec, dest);\n        dest.push_back(' ');\n        fmt_helper::append_int(tm_time.tm_year + 1900, dest);\n    }\n};\n\n// year - 2 digit\ntemplate<typename ScopedPadder>\nclass C_formatter final : public flag_formatter\n{\npublic:\n    explicit C_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 2;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad2(tm_time.tm_year % 100, dest);\n    }\n};\n\n// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01\ntemplate<typename ScopedPadder>\nclass D_formatter final : public flag_formatter\n{\npublic:\n    explicit D_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 10;\n        ScopedPadder p(field_size, padinfo_, dest);\n\n        fmt_helper::pad2(tm_time.tm_mon + 1, dest);\n        dest.push_back('/');\n        fmt_helper::pad2(tm_time.tm_mday, dest);\n        dest.push_back('/');\n        fmt_helper::pad2(tm_time.tm_year % 100, dest);\n    }\n};\n\n// year - 4 digit\ntemplate<typename ScopedPadder>\nclass Y_formatter final : public flag_formatter\n{\npublic:\n    explicit Y_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 4;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::append_int(tm_time.tm_year + 1900, dest);\n    }\n};\n\n// month 1-12\ntemplate<typename ScopedPadder>\nclass m_formatter final : public flag_formatter\n{\npublic:\n    explicit m_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 2;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad2(tm_time.tm_mon + 1, dest);\n    }\n};\n\n// day of month 1-31\ntemplate<typename ScopedPadder>\nclass d_formatter final : public flag_formatter\n{\npublic:\n    explicit d_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 2;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad2(tm_time.tm_mday, dest);\n    }\n};\n\n// hours in 24 format 0-23\ntemplate<typename ScopedPadder>\nclass H_formatter final : public flag_formatter\n{\npublic:\n    explicit H_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 2;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad2(tm_time.tm_hour, dest);\n    }\n};\n\n// hours in 12 format 1-12\ntemplate<typename ScopedPadder>\nclass I_formatter final : public flag_formatter\n{\npublic:\n    explicit I_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 2;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad2(to12h(tm_time), dest);\n    }\n};\n\n// minutes 0-59\ntemplate<typename ScopedPadder>\nclass M_formatter final : public flag_formatter\n{\npublic:\n    explicit M_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 2;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad2(tm_time.tm_min, dest);\n    }\n};\n\n// seconds 0-59\ntemplate<typename ScopedPadder>\nclass S_formatter final : public flag_formatter\n{\npublic:\n    explicit S_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 2;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad2(tm_time.tm_sec, dest);\n    }\n};\n\n// milliseconds\ntemplate<typename ScopedPadder>\nclass e_formatter final : public flag_formatter\n{\npublic:\n    explicit e_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        auto millis = fmt_helper::time_fraction<std::chrono::milliseconds>(msg.time);\n        const size_t field_size = 3;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad3(static_cast<uint32_t>(millis.count()), dest);\n    }\n};\n\n// microseconds\ntemplate<typename ScopedPadder>\nclass f_formatter final : public flag_formatter\n{\npublic:\n    explicit f_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        auto micros = fmt_helper::time_fraction<std::chrono::microseconds>(msg.time);\n\n        const size_t field_size = 6;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad6(static_cast<size_t>(micros.count()), dest);\n    }\n};\n\n// nanoseconds\ntemplate<typename ScopedPadder>\nclass F_formatter final : public flag_formatter\n{\npublic:\n    explicit F_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        auto ns = fmt_helper::time_fraction<std::chrono::nanoseconds>(msg.time);\n        const size_t field_size = 9;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::pad9(static_cast<size_t>(ns.count()), dest);\n    }\n};\n\n// seconds since epoch\ntemplate<typename ScopedPadder>\nclass E_formatter final : public flag_formatter\n{\npublic:\n    explicit E_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        const size_t field_size = 10;\n        ScopedPadder p(field_size, padinfo_, dest);\n        auto duration = msg.time.time_since_epoch();\n        auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();\n        fmt_helper::append_int(seconds, dest);\n    }\n};\n\n// AM/PM\ntemplate<typename ScopedPadder>\nclass p_formatter final : public flag_formatter\n{\npublic:\n    explicit p_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 2;\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::append_string_view(ampm(tm_time), dest);\n    }\n};\n\n// 12 hour clock 02:55:02 pm\ntemplate<typename ScopedPadder>\nclass r_formatter final : public flag_formatter\n{\npublic:\n    explicit r_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 11;\n        ScopedPadder p(field_size, padinfo_, dest);\n\n        fmt_helper::pad2(to12h(tm_time), dest);\n        dest.push_back(':');\n        fmt_helper::pad2(tm_time.tm_min, dest);\n        dest.push_back(':');\n        fmt_helper::pad2(tm_time.tm_sec, dest);\n        dest.push_back(' ');\n        fmt_helper::append_string_view(ampm(tm_time), dest);\n    }\n};\n\n// 24-hour HH:MM time, equivalent to %H:%M\ntemplate<typename ScopedPadder>\nclass R_formatter final : public flag_formatter\n{\npublic:\n    explicit R_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 5;\n        ScopedPadder p(field_size, padinfo_, dest);\n\n        fmt_helper::pad2(tm_time.tm_hour, dest);\n        dest.push_back(':');\n        fmt_helper::pad2(tm_time.tm_min, dest);\n    }\n};\n\n// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S\ntemplate<typename ScopedPadder>\nclass T_formatter final : public flag_formatter\n{\npublic:\n    explicit T_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 8;\n        ScopedPadder p(field_size, padinfo_, dest);\n\n        fmt_helper::pad2(tm_time.tm_hour, dest);\n        dest.push_back(':');\n        fmt_helper::pad2(tm_time.tm_min, dest);\n        dest.push_back(':');\n        fmt_helper::pad2(tm_time.tm_sec, dest);\n    }\n};\n\n// ISO 8601 offset from UTC in timezone (+-HH:MM)\ntemplate<typename ScopedPadder>\nclass z_formatter final : public flag_formatter\n{\npublic:\n    explicit z_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    z_formatter() = default;\n    z_formatter(const z_formatter &) = delete;\n    z_formatter &operator=(const z_formatter &) = delete;\n\n    void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        const size_t field_size = 6;\n        ScopedPadder p(field_size, padinfo_, dest);\n\n        auto total_minutes = get_cached_offset(msg, tm_time);\n        bool is_negative = total_minutes < 0;\n        if (is_negative)\n        {\n            total_minutes = -total_minutes;\n            dest.push_back('-');\n        }\n        else\n        {\n            dest.push_back('+');\n        }\n\n        fmt_helper::pad2(total_minutes / 60, dest); // hours\n        dest.push_back(':');\n        fmt_helper::pad2(total_minutes % 60, dest); // minutes\n    }\n\nprivate:\n    log_clock::time_point last_update_{std::chrono::seconds(0)};\n    int offset_minutes_{0};\n\n    int get_cached_offset(const log_msg &msg, const std::tm &tm_time)\n    {\n        // refresh every 10 seconds\n        if (msg.time - last_update_ >= std::chrono::seconds(10))\n        {\n            offset_minutes_ = os::utc_minutes_offset(tm_time);\n            last_update_ = msg.time;\n        }\n        return offset_minutes_;\n    }\n};\n\n// Thread id\ntemplate<typename ScopedPadder>\nclass t_formatter final : public flag_formatter\n{\npublic:\n    explicit t_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        const auto field_size = ScopedPadder::count_digits(msg.thread_id);\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::append_int(msg.thread_id, dest);\n    }\n};\n\n// Current pid\ntemplate<typename ScopedPadder>\nclass pid_formatter final : public flag_formatter\n{\npublic:\n    explicit pid_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override\n    {\n        const auto pid = static_cast<uint32_t>(details::os::pid());\n        auto field_size = ScopedPadder::count_digits(pid);\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::append_int(pid, dest);\n    }\n};\n\ntemplate<typename ScopedPadder>\nclass v_formatter final : public flag_formatter\n{\npublic:\n    explicit v_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        ScopedPadder p(msg.payload.size(), padinfo_, dest);\n        fmt_helper::append_string_view(msg.payload, dest);\n    }\n};\n\nclass ch_formatter final : public flag_formatter\n{\npublic:\n    explicit ch_formatter(char ch)\n        : ch_(ch)\n    {}\n\n    void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override\n    {\n        dest.push_back(ch_);\n    }\n\nprivate:\n    char ch_;\n};\n\n// aggregate user chars to display as is\nclass aggregate_formatter final : public flag_formatter\n{\npublic:\n    aggregate_formatter() = default;\n\n    void add_ch(char ch)\n    {\n        str_ += ch;\n    }\n    void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override\n    {\n        fmt_helper::append_string_view(str_, dest);\n    }\n\nprivate:\n    std::string str_;\n};\n\n// mark the color range. expect it to be in the form of \"%^colored text%$\"\nclass color_start_formatter final : public flag_formatter\n{\npublic:\n    explicit color_start_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        msg.color_range_start = dest.size();\n    }\n};\n\nclass color_stop_formatter final : public flag_formatter\n{\npublic:\n    explicit color_stop_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        msg.color_range_end = dest.size();\n    }\n};\n\n// print source location\ntemplate<typename ScopedPadder>\nclass source_location_formatter final : public flag_formatter\n{\npublic:\n    explicit source_location_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        if (msg.source.empty())\n        {\n            ScopedPadder p(0, padinfo_, dest);\n            return;\n        }\n\n        size_t text_size;\n        if (padinfo_.enabled())\n        {\n            // calc text size for padding based on \"filename:line\"\n            text_size = std::char_traits<char>::length(msg.source.filename) + ScopedPadder::count_digits(msg.source.line) + 1;\n        }\n        else\n        {\n            text_size = 0;\n        }\n\n        ScopedPadder p(text_size, padinfo_, dest);\n        fmt_helper::append_string_view(msg.source.filename, dest);\n        dest.push_back(':');\n        fmt_helper::append_int(msg.source.line, dest);\n    }\n};\n\n// print source filename\ntemplate<typename ScopedPadder>\nclass source_filename_formatter final : public flag_formatter\n{\npublic:\n    explicit source_filename_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        if (msg.source.empty())\n        {\n            ScopedPadder p(0, padinfo_, dest);\n            return;\n        }\n        size_t text_size = padinfo_.enabled() ? std::char_traits<char>::length(msg.source.filename) : 0;\n        ScopedPadder p(text_size, padinfo_, dest);\n        fmt_helper::append_string_view(msg.source.filename, dest);\n    }\n};\n\ntemplate<typename ScopedPadder>\nclass short_filename_formatter final : public flag_formatter\n{\npublic:\n    explicit short_filename_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n#ifdef _MSC_VER\n#    pragma warning(push)\n#    pragma warning(disable : 4127) // consider using 'if constexpr' instead\n#endif                              // _MSC_VER\n    static const char *basename(const char *filename)\n    {\n        // if the size is 2 (1 character + null terminator) we can use the more efficient strrchr\n        // the branch will be elided by optimizations\n        if (sizeof(os::folder_seps) == 2)\n        {\n            const char *rv = std::strrchr(filename, os::folder_seps[0]);\n            return rv != nullptr ? rv + 1 : filename;\n        }\n        else\n        {\n            const std::reverse_iterator<const char *> begin(filename + std::strlen(filename));\n            const std::reverse_iterator<const char *> end(filename);\n\n            const auto it = std::find_first_of(begin, end, std::begin(os::folder_seps), std::end(os::folder_seps) - 1);\n            return it != end ? it.base() : filename;\n        }\n    }\n#ifdef _MSC_VER\n#    pragma warning(pop)\n#endif // _MSC_VER\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        if (msg.source.empty())\n        {\n            ScopedPadder p(0, padinfo_, dest);\n            return;\n        }\n        auto filename = basename(msg.source.filename);\n        size_t text_size = padinfo_.enabled() ? std::char_traits<char>::length(filename) : 0;\n        ScopedPadder p(text_size, padinfo_, dest);\n        fmt_helper::append_string_view(filename, dest);\n    }\n};\n\ntemplate<typename ScopedPadder>\nclass source_linenum_formatter final : public flag_formatter\n{\npublic:\n    explicit source_linenum_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        if (msg.source.empty())\n        {\n            ScopedPadder p(0, padinfo_, dest);\n            return;\n        }\n\n        auto field_size = ScopedPadder::count_digits(msg.source.line);\n        ScopedPadder p(field_size, padinfo_, dest);\n        fmt_helper::append_int(msg.source.line, dest);\n    }\n};\n\n// print source funcname\ntemplate<typename ScopedPadder>\nclass source_funcname_formatter final : public flag_formatter\n{\npublic:\n    explicit source_funcname_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        if (msg.source.empty())\n        {\n            ScopedPadder p(0, padinfo_, dest);\n            return;\n        }\n        size_t text_size = padinfo_.enabled() ? std::char_traits<char>::length(msg.source.funcname) : 0;\n        ScopedPadder p(text_size, padinfo_, dest);\n        fmt_helper::append_string_view(msg.source.funcname, dest);\n    }\n};\n\n// print elapsed time since last message\ntemplate<typename ScopedPadder, typename Units>\nclass elapsed_formatter final : public flag_formatter\n{\npublic:\n    using DurationUnits = Units;\n\n    explicit elapsed_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n        , last_message_time_(log_clock::now())\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override\n    {\n        auto delta = (std::max)(msg.time - last_message_time_, log_clock::duration::zero());\n        auto delta_units = std::chrono::duration_cast<DurationUnits>(delta);\n        last_message_time_ = msg.time;\n        auto delta_count = static_cast<size_t>(delta_units.count());\n        auto n_digits = static_cast<size_t>(ScopedPadder::count_digits(delta_count));\n        ScopedPadder p(n_digits, padinfo_, dest);\n        fmt_helper::append_int(delta_count, dest);\n    }\n\nprivate:\n    log_clock::time_point last_message_time_;\n};\n\n// Full info formatter\n// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] [%s:%#] %v\nclass full_formatter final : public flag_formatter\n{\npublic:\n    explicit full_formatter(padding_info padinfo)\n        : flag_formatter(padinfo)\n    {}\n\n    void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) override\n    {\n        using std::chrono::duration_cast;\n        using std::chrono::milliseconds;\n        using std::chrono::seconds;\n\n        // cache the date/time part for the next second.\n        auto duration = msg.time.time_since_epoch();\n        auto secs = duration_cast<seconds>(duration);\n\n        if (cache_timestamp_ != secs || cached_datetime_.size() == 0)\n        {\n            cached_datetime_.clear();\n            cached_datetime_.push_back('[');\n            fmt_helper::append_int(tm_time.tm_year + 1900, cached_datetime_);\n            cached_datetime_.push_back('-');\n\n            fmt_helper::pad2(tm_time.tm_mon + 1, cached_datetime_);\n            cached_datetime_.push_back('-');\n\n            fmt_helper::pad2(tm_time.tm_mday, cached_datetime_);\n            cached_datetime_.push_back(' ');\n\n            fmt_helper::pad2(tm_time.tm_hour, cached_datetime_);\n            cached_datetime_.push_back(':');\n\n            fmt_helper::pad2(tm_time.tm_min, cached_datetime_);\n            cached_datetime_.push_back(':');\n\n            fmt_helper::pad2(tm_time.tm_sec, cached_datetime_);\n            cached_datetime_.push_back('.');\n\n            cache_timestamp_ = secs;\n        }\n        dest.append(cached_datetime_.begin(), cached_datetime_.end());\n\n        auto millis = fmt_helper::time_fraction<milliseconds>(msg.time);\n        fmt_helper::pad3(static_cast<uint32_t>(millis.count()), dest);\n        dest.push_back(']');\n        dest.push_back(' ');\n\n        // append logger name if exists\n        if (msg.logger_name.size() > 0)\n        {\n            dest.push_back('[');\n            fmt_helper::append_string_view(msg.logger_name, dest);\n            dest.push_back(']');\n            dest.push_back(' ');\n        }\n\n        dest.push_back('[');\n        // wrap the level name with color\n        msg.color_range_start = dest.size();\n        // fmt_helper::append_string_view(level::to_c_str(msg.level), dest);\n        fmt_helper::append_string_view(level::to_string_view(msg.level), dest);\n        msg.color_range_end = dest.size();\n        dest.push_back(']');\n        dest.push_back(' ');\n\n        // add source location if present\n        if (!msg.source.empty())\n        {\n            dest.push_back('[');\n            const char *filename = details::short_filename_formatter<details::null_scoped_padder>::basename(msg.source.filename);\n            fmt_helper::append_string_view(filename, dest);\n            dest.push_back(':');\n            fmt_helper::append_int(msg.source.line, dest);\n            dest.push_back(']');\n            dest.push_back(' ');\n        }\n        // fmt_helper::append_string_view(msg.msg(), dest);\n        fmt_helper::append_string_view(msg.payload, dest);\n    }\n\nprivate:\n    std::chrono::seconds cache_timestamp_{0};\n    memory_buf_t cached_datetime_;\n};\n\n} // namespace details\n\nSPDLOG_INLINE pattern_formatter::pattern_formatter(\n    std::string pattern, pattern_time_type time_type, std::string eol, custom_flags custom_user_flags)\n    : pattern_(std::move(pattern))\n    , eol_(std::move(eol))\n    , pattern_time_type_(time_type)\n    , need_localtime_(false)\n    , last_log_secs_(0)\n    , custom_handlers_(std::move(custom_user_flags))\n{\n    std::memset(&cached_tm_, 0, sizeof(cached_tm_));\n    compile_pattern_(pattern_);\n}\n\n// use by default full formatter for if pattern is not given\nSPDLOG_INLINE pattern_formatter::pattern_formatter(pattern_time_type time_type, std::string eol)\n    : pattern_(\"%+\")\n    , eol_(std::move(eol))\n    , pattern_time_type_(time_type)\n    , need_localtime_(true)\n    , last_log_secs_(0)\n{\n    std::memset(&cached_tm_, 0, sizeof(cached_tm_));\n    formatters_.push_back(details::make_unique<details::full_formatter>(details::padding_info{}));\n}\n\nSPDLOG_INLINE std::unique_ptr<formatter> pattern_formatter::clone() const\n{\n    custom_flags cloned_custom_formatters;\n    for (auto &it : custom_handlers_)\n    {\n        cloned_custom_formatters[it.first] = it.second->clone();\n    }\n    auto cloned = details::make_unique<pattern_formatter>(pattern_, pattern_time_type_, eol_, std::move(cloned_custom_formatters));\n    cloned->need_localtime(need_localtime_);\n    return cloned;\n}\n\nSPDLOG_INLINE void pattern_formatter::format(const details::log_msg &msg, memory_buf_t &dest)\n{\n    if (need_localtime_)\n    {\n        const auto secs = std::chrono::duration_cast<std::chrono::seconds>(msg.time.time_since_epoch());\n        if (secs != last_log_secs_)\n        {\n            cached_tm_ = get_time_(msg);\n            last_log_secs_ = secs;\n        }\n    }\n\n    for (auto &f : formatters_)\n    {\n        f->format(msg, cached_tm_, dest);\n    }\n    // write eol\n    details::fmt_helper::append_string_view(eol_, dest);\n}\n\nSPDLOG_INLINE void pattern_formatter::set_pattern(std::string pattern)\n{\n    pattern_ = std::move(pattern);\n    need_localtime_ = false;\n    compile_pattern_(pattern_);\n}\n\nSPDLOG_INLINE void pattern_formatter::need_localtime(bool need)\n{\n    need_localtime_ = need;\n}\n\nSPDLOG_INLINE std::tm pattern_formatter::get_time_(const details::log_msg &msg)\n{\n    if (pattern_time_type_ == pattern_time_type::local)\n    {\n        return details::os::localtime(log_clock::to_time_t(msg.time));\n    }\n    return details::os::gmtime(log_clock::to_time_t(msg.time));\n}\n\ntemplate<typename Padder>\nSPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_info padding)\n{\n    // process custom flags\n    auto it = custom_handlers_.find(flag);\n    if (it != custom_handlers_.end())\n    {\n        auto custom_handler = it->second->clone();\n        custom_handler->set_padding_info(padding);\n        formatters_.push_back(std::move(custom_handler));\n        return;\n    }\n\n    // process built-in flags\n    switch (flag)\n    {\n    case ('+'): // default formatter\n        formatters_.push_back(details::make_unique<details::full_formatter>(padding));\n        need_localtime_ = true;\n        break;\n\n    case 'n': // logger name\n        formatters_.push_back(details::make_unique<details::name_formatter<Padder>>(padding));\n        break;\n\n    case 'l': // level\n        formatters_.push_back(details::make_unique<details::level_formatter<Padder>>(padding));\n        break;\n\n    case 'L': // short level\n        formatters_.push_back(details::make_unique<details::short_level_formatter<Padder>>(padding));\n        break;\n\n    case ('t'): // thread id\n        formatters_.push_back(details::make_unique<details::t_formatter<Padder>>(padding));\n        break;\n\n    case ('v'): // the message text\n        formatters_.push_back(details::make_unique<details::v_formatter<Padder>>(padding));\n        break;\n\n    case ('a'): // weekday\n        formatters_.push_back(details::make_unique<details::a_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('A'): // short weekday\n        formatters_.push_back(details::make_unique<details::A_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('b'):\n    case ('h'): // month\n        formatters_.push_back(details::make_unique<details::b_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('B'): // short month\n        formatters_.push_back(details::make_unique<details::B_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('c'): // datetime\n        formatters_.push_back(details::make_unique<details::c_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('C'): // year 2 digits\n        formatters_.push_back(details::make_unique<details::C_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('Y'): // year 4 digits\n        formatters_.push_back(details::make_unique<details::Y_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('D'):\n    case ('x'): // datetime MM/DD/YY\n        formatters_.push_back(details::make_unique<details::D_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('m'): // month 1-12\n        formatters_.push_back(details::make_unique<details::m_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('d'): // day of month 1-31\n        formatters_.push_back(details::make_unique<details::d_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('H'): // hours 24\n        formatters_.push_back(details::make_unique<details::H_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('I'): // hours 12\n        formatters_.push_back(details::make_unique<details::I_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('M'): // minutes\n        formatters_.push_back(details::make_unique<details::M_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('S'): // seconds\n        formatters_.push_back(details::make_unique<details::S_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('e'): // milliseconds\n        formatters_.push_back(details::make_unique<details::e_formatter<Padder>>(padding));\n        break;\n\n    case ('f'): // microseconds\n        formatters_.push_back(details::make_unique<details::f_formatter<Padder>>(padding));\n        break;\n\n    case ('F'): // nanoseconds\n        formatters_.push_back(details::make_unique<details::F_formatter<Padder>>(padding));\n        break;\n\n    case ('E'): // seconds since epoch\n        formatters_.push_back(details::make_unique<details::E_formatter<Padder>>(padding));\n        break;\n\n    case ('p'): // am/pm\n        formatters_.push_back(details::make_unique<details::p_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('r'): // 12 hour clock 02:55:02 pm\n        formatters_.push_back(details::make_unique<details::r_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('R'): // 24-hour HH:MM time\n        formatters_.push_back(details::make_unique<details::R_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('T'):\n    case ('X'): // ISO 8601 time format (HH:MM:SS)\n        formatters_.push_back(details::make_unique<details::T_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('z'): // timezone\n        formatters_.push_back(details::make_unique<details::z_formatter<Padder>>(padding));\n        need_localtime_ = true;\n        break;\n\n    case ('P'): // pid\n        formatters_.push_back(details::make_unique<details::pid_formatter<Padder>>(padding));\n        break;\n\n    case ('^'): // color range start\n        formatters_.push_back(details::make_unique<details::color_start_formatter>(padding));\n        break;\n\n    case ('$'): // color range end\n        formatters_.push_back(details::make_unique<details::color_stop_formatter>(padding));\n        break;\n\n    case ('@'): // source location (filename:filenumber)\n        formatters_.push_back(details::make_unique<details::source_location_formatter<Padder>>(padding));\n        break;\n\n    case ('s'): // short source filename - without directory name\n        formatters_.push_back(details::make_unique<details::short_filename_formatter<Padder>>(padding));\n        break;\n\n    case ('g'): // full source filename\n        formatters_.push_back(details::make_unique<details::source_filename_formatter<Padder>>(padding));\n        break;\n\n    case ('#'): // source line number\n        formatters_.push_back(details::make_unique<details::source_linenum_formatter<Padder>>(padding));\n        break;\n\n    case ('!'): // source funcname\n        formatters_.push_back(details::make_unique<details::source_funcname_formatter<Padder>>(padding));\n        break;\n\n    case ('%'): // % char\n        formatters_.push_back(details::make_unique<details::ch_formatter>('%'));\n        break;\n\n    case ('u'): // elapsed time since last log message in nanos\n        formatters_.push_back(details::make_unique<details::elapsed_formatter<Padder, std::chrono::nanoseconds>>(padding));\n        break;\n\n    case ('i'): // elapsed time since last log message in micros\n        formatters_.push_back(details::make_unique<details::elapsed_formatter<Padder, std::chrono::microseconds>>(padding));\n        break;\n\n    case ('o'): // elapsed time since last log message in millis\n        formatters_.push_back(details::make_unique<details::elapsed_formatter<Padder, std::chrono::milliseconds>>(padding));\n        break;\n\n    case ('O'): // elapsed time since last log message in seconds\n        formatters_.push_back(details::make_unique<details::elapsed_formatter<Padder, std::chrono::seconds>>(padding));\n        break;\n\n    default: // Unknown flag appears as is\n        auto unknown_flag = details::make_unique<details::aggregate_formatter>();\n\n        if (!padding.truncate_)\n        {\n            unknown_flag->add_ch('%');\n            unknown_flag->add_ch(flag);\n            formatters_.push_back((std::move(unknown_flag)));\n        }\n        // fix issue #1617 (prev char was '!' and should have been treated as funcname flag instead of truncating flag)\n        // spdlog::set_pattern(\"[%10!] %v\") => \"[      main] some message\"\n        // spdlog::set_pattern(\"[%3!!] %v\") => \"[mai] some message\"\n        else\n        {\n            padding.truncate_ = false;\n            formatters_.push_back(details::make_unique<details::source_funcname_formatter<Padder>>(padding));\n            unknown_flag->add_ch(flag);\n            formatters_.push_back((std::move(unknown_flag)));\n        }\n\n        break;\n    }\n}\n\n// Extract given pad spec (e.g. %8X, %=8X, %-8!X, %8!X, %=8!X, %-8!X, %+8!X)\n// Advance the given it pass the end of the padding spec found (if any)\n// Return padding.\nSPDLOG_INLINE details::padding_info pattern_formatter::handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end)\n{\n    using details::padding_info;\n    using details::scoped_padder;\n    const size_t max_width = 64;\n    if (it == end)\n    {\n        return padding_info{};\n    }\n\n    padding_info::pad_side side;\n    switch (*it)\n    {\n    case '-':\n        side = padding_info::pad_side::right;\n        ++it;\n        break;\n    case '=':\n        side = padding_info::pad_side::center;\n        ++it;\n        break;\n    default:\n        side = details::padding_info::pad_side::left;\n        break;\n    }\n\n    if (it == end || !std::isdigit(static_cast<unsigned char>(*it)))\n    {\n        return padding_info{}; // no padding if no digit found here\n    }\n\n    auto width = static_cast<size_t>(*it) - '0';\n    for (++it; it != end && std::isdigit(static_cast<unsigned char>(*it)); ++it)\n    {\n        auto digit = static_cast<size_t>(*it) - '0';\n        width = width * 10 + digit;\n    }\n\n    // search for the optional truncate marker '!'\n    bool truncate;\n    if (it != end && *it == '!')\n    {\n        truncate = true;\n        ++it;\n    }\n    else\n    {\n        truncate = false;\n    }\n    return details::padding_info{std::min<size_t>(width, max_width), side, truncate};\n}\n\nSPDLOG_INLINE void pattern_formatter::compile_pattern_(const std::string &pattern)\n{\n    auto end = pattern.end();\n    std::unique_ptr<details::aggregate_formatter> user_chars;\n    formatters_.clear();\n    for (auto it = pattern.begin(); it != end; ++it)\n    {\n        if (*it == '%')\n        {\n            if (user_chars) // append user chars found so far\n            {\n                formatters_.push_back(std::move(user_chars));\n            }\n\n            auto padding = handle_padspec_(++it, end);\n\n            if (it != end)\n            {\n                if (padding.enabled())\n                {\n                    handle_flag_<details::scoped_padder>(*it, padding);\n                }\n                else\n                {\n                    handle_flag_<details::null_scoped_padder>(*it, padding);\n                }\n            }\n            else\n            {\n                break;\n            }\n        }\n        else // chars not following the % sign should be displayed as is\n        {\n            if (!user_chars)\n            {\n                user_chars = details::make_unique<details::aggregate_formatter>();\n            }\n            user_chars->add_ch(*it);\n        }\n    }\n    if (user_chars) // append raw chars found so far\n    {\n        formatters_.push_back(std::move(user_chars));\n    }\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/pattern_formatter.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#pragma warning(disable:4275)\n#endif\n\n#include <spdlog/common.h>\n#include <spdlog/details/log_msg.h>\n#include <spdlog/details/os.h>\n#include <spdlog/formatter.h>\n\n#include <chrono>\n#include <ctime>\n#include <memory>\n\n#include <string>\n#include <vector>\n#include <unordered_map>\n\nnamespace spdlog {\nnamespace details {\n\n// padding information.\nstruct padding_info\n{\n    enum class pad_side\n    {\n        left,\n        right,\n        center\n    };\n\n    padding_info() = default;\n    padding_info(size_t width, padding_info::pad_side side, bool truncate)\n        : width_(width)\n        , side_(side)\n        , truncate_(truncate)\n        , enabled_(true)\n    {}\n\n    bool enabled() const\n    {\n        return enabled_;\n    }\n    size_t width_ = 0;\n    pad_side side_ = pad_side::left;\n    bool truncate_ = false;\n    bool enabled_ = false;\n};\n\nclass SPDLOG_API flag_formatter\n{\npublic:\n    explicit flag_formatter(padding_info padinfo)\n        : padinfo_(padinfo)\n    {}\n    flag_formatter() = default;\n    virtual ~flag_formatter() = default;\n    virtual void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) = 0;\n\nprotected:\n    padding_info padinfo_;\n};\n\n} // namespace details\n\nclass SPDLOG_API custom_flag_formatter : public details::flag_formatter\n{\npublic:\n    virtual std::unique_ptr<custom_flag_formatter> clone() const = 0;\n\n    void set_padding_info(const details::padding_info &padding)\n    {\n        flag_formatter::padinfo_ = padding;\n    }\n};\n\nclass SPDLOG_API pattern_formatter final : public formatter\n{\npublic:\n    using custom_flags = std::unordered_map<char, std::unique_ptr<custom_flag_formatter>>;\n\n    explicit pattern_formatter(std::string pattern, pattern_time_type time_type = pattern_time_type::local,\n        std::string eol = spdlog::details::os::default_eol, custom_flags custom_user_flags = custom_flags());\n\n    // use default pattern is not given\n    explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol);\n\n    pattern_formatter(const pattern_formatter &other) = delete;\n    pattern_formatter &operator=(const pattern_formatter &other) = delete;\n\n    std::unique_ptr<formatter> clone() const override;\n    void format(const details::log_msg &msg, memory_buf_t &dest) override;\n\n    template<typename T, typename... Args>\n    pattern_formatter &add_flag(char flag, Args &&... args)\n    {\n        custom_handlers_[flag] = details::make_unique<T>(std::forward<Args>(args)...);\n        return *this;\n    }\n    void set_pattern(std::string pattern);\n    void need_localtime(bool need = true);\n\nprivate:\n    std::string pattern_;\n    std::string eol_;\n    pattern_time_type pattern_time_type_;\n    bool need_localtime_;\n    std::tm cached_tm_;\n    std::chrono::seconds last_log_secs_;\n    std::vector<std::unique_ptr<details::flag_formatter>> formatters_;\n    custom_flags custom_handlers_;\n\n    std::tm get_time_(const details::log_msg &msg);\n    template<typename Padder>\n    void handle_flag_(char flag, details::padding_info padding);\n\n    // Extract given pad spec (e.g. %8X)\n    // Advance the given it pass the end of the padding spec found (if any)\n    // Return padding.\n    static details::padding_info handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end);\n\n    void compile_pattern_(const std::string &pattern);\n};\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"pattern_formatter-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/android_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifdef __ANDROID__\n\n#    include <spdlog/details/fmt_helper.h>\n#    include <spdlog/details/null_mutex.h>\n#    include <spdlog/details/os.h>\n#    include <spdlog/sinks/base_sink.h>\n#    include <spdlog/details/synchronous_factory.h>\n\n#    include <android/log.h>\n#    include <chrono>\n#    include <mutex>\n#    include <string>\n#    include <thread>\n#    include <type_traits>\n\n#    if !defined(SPDLOG_ANDROID_RETRIES)\n#        define SPDLOG_ANDROID_RETRIES 2\n#    endif\n\nnamespace spdlog {\nnamespace sinks {\n\n/*\n * Android sink\n * (logging using __android_log_write or __android_log_buf_write depending on the specified BufferID)\n */\ntemplate<typename Mutex, int BufferID = log_id::LOG_ID_MAIN>\nclass android_sink final : public base_sink<Mutex>\n{\npublic:\n    explicit android_sink(std::string tag = \"spdlog\", bool use_raw_msg = false)\n        : tag_(std::move(tag))\n        , use_raw_msg_(use_raw_msg)\n    {}\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        const android_LogPriority priority = convert_to_android_(msg.level);\n        memory_buf_t formatted;\n        if (use_raw_msg_)\n        {\n            details::fmt_helper::append_string_view(msg.payload, formatted);\n        }\n        else\n        {\n            base_sink<Mutex>::formatter_->format(msg, formatted);\n        }\n        formatted.push_back('\\0');\n        const char *msg_output = formatted.data();\n\n        // See system/core/liblog/logger_write.c for explanation of return value\n        int ret = android_log(priority, tag_.c_str(), msg_output);\n        int retry_count = 0;\n        while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES))\n        {\n            details::os::sleep_for_millis(5);\n            ret = android_log(priority, tag_.c_str(), msg_output);\n            retry_count++;\n        }\n\n        if (ret < 0)\n        {\n            throw_spdlog_ex(\"logging to Android failed\", ret);\n        }\n    }\n\n    void flush_() override {}\n\nprivate:\n    // There might be liblog versions used, that do not support __android_log_buf_write. So we only compile and link against\n    // __android_log_buf_write, if user explicitely provides a non-default log buffer. Otherwise, when using the default log buffer, always\n    // log via __android_log_write.\n    template<int ID = BufferID>\n    typename std::enable_if<ID == static_cast<int>(log_id::LOG_ID_MAIN), int>::type android_log(int prio, const char *tag, const char *text)\n    {\n        return __android_log_write(prio, tag, text);\n    }\n\n    template<int ID = BufferID>\n    typename std::enable_if<ID != static_cast<int>(log_id::LOG_ID_MAIN), int>::type android_log(int prio, const char *tag, const char *text)\n    {\n        return __android_log_buf_write(ID, prio, tag, text);\n    }\n\n    static android_LogPriority convert_to_android_(spdlog::level::level_enum level)\n    {\n        switch (level)\n        {\n        case spdlog::level::trace:\n            return ANDROID_LOG_VERBOSE;\n        case spdlog::level::debug:\n            return ANDROID_LOG_DEBUG;\n        case spdlog::level::info:\n            return ANDROID_LOG_INFO;\n        case spdlog::level::warn:\n            return ANDROID_LOG_WARN;\n        case spdlog::level::err:\n            return ANDROID_LOG_ERROR;\n        case spdlog::level::critical:\n            return ANDROID_LOG_FATAL;\n        default:\n            return ANDROID_LOG_DEFAULT;\n        }\n    }\n\n    std::string tag_;\n    bool use_raw_msg_;\n};\n\nusing android_sink_mt = android_sink<std::mutex>;\nusing android_sink_st = android_sink<details::null_mutex>;\n\ntemplate<int BufferId = log_id::LOG_ID_MAIN>\nusing android_sink_buf_mt = android_sink<std::mutex, BufferId>;\ntemplate<int BufferId = log_id::LOG_ID_MAIN>\nusing android_sink_buf_st = android_sink<details::null_mutex, BufferId>;\n\n} // namespace sinks\n\n// Create and register android syslog logger\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> android_logger_mt(const std::string &logger_name, const std::string &tag = \"spdlog\")\n{\n    return Factory::template create<sinks::android_sink_mt>(logger_name, tag);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> android_logger_st(const std::string &logger_name, const std::string &tag = \"spdlog\")\n{\n    return Factory::template create<sinks::android_sink_st>(logger_name, tag);\n}\n\n} // namespace spdlog\n\n#endif // __ANDROID__"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/ansicolor_sink-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/sinks/ansicolor_sink.h>\n#endif\n\n#include <spdlog/pattern_formatter.h>\n#include <spdlog/details/os.h>\n\nnamespace spdlog {\nnamespace sinks {\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE ansicolor_sink<ConsoleMutex>::ansicolor_sink(FILE *target_file, color_mode mode)\n    : target_file_(target_file)\n    , mutex_(ConsoleMutex::mutex())\n    , formatter_(details::make_unique<spdlog::pattern_formatter>())\n\n{\n    set_color_mode(mode);\n    colors_[level::trace] = to_string_(white);\n    colors_[level::debug] = to_string_(cyan);\n    colors_[level::info] = to_string_(green);\n    colors_[level::warn] = to_string_(yellow_bold);\n    colors_[level::err] = to_string_(red_bold);\n    colors_[level::critical] = to_string_(bold_on_red);\n    colors_[level::off] = to_string_(reset);\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color(level::level_enum color_level, string_view_t color)\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    colors_[static_cast<size_t>(color_level)] = to_string_(color);\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::log(const details::log_msg &msg)\n{\n    // Wrap the originally formatted message in color codes.\n    // If color is not supported in the terminal, log as is instead.\n    std::lock_guard<mutex_t> lock(mutex_);\n    msg.color_range_start = 0;\n    msg.color_range_end = 0;\n    memory_buf_t formatted;\n    formatter_->format(msg, formatted);\n    if (should_do_colors_ && msg.color_range_end > msg.color_range_start)\n    {\n        // before color range\n        print_range_(formatted, 0, msg.color_range_start);\n        // in color range\n        print_ccode_(colors_[static_cast<size_t>(msg.level)]);\n        print_range_(formatted, msg.color_range_start, msg.color_range_end);\n        print_ccode_(reset);\n        // after color range\n        print_range_(formatted, msg.color_range_end, formatted.size());\n    }\n    else // no color\n    {\n        print_range_(formatted, 0, formatted.size());\n    }\n    fflush(target_file_);\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::flush()\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    fflush(target_file_);\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_pattern(const std::string &pattern)\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern));\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter)\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    formatter_ = std::move(sink_formatter);\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE bool ansicolor_sink<ConsoleMutex>::should_color()\n{\n    return should_do_colors_;\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color_mode(color_mode mode)\n{\n    switch (mode)\n    {\n    case color_mode::always:\n        should_do_colors_ = true;\n        return;\n    case color_mode::automatic:\n        should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal();\n        return;\n    case color_mode::never:\n        should_do_colors_ = false;\n        return;\n    default:\n        should_do_colors_ = false;\n    }\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_ccode_(const string_view_t &color_code)\n{\n    fwrite(color_code.data(), sizeof(char), color_code.size(), target_file_);\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end)\n{\n    fwrite(formatted.data() + start, sizeof(char), end - start, target_file_);\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE std::string ansicolor_sink<ConsoleMutex>::to_string_(const string_view_t &sv)\n{\n    return std::string(sv.data(), sv.size());\n}\n\n// ansicolor_stdout_sink\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE ansicolor_stdout_sink<ConsoleMutex>::ansicolor_stdout_sink(color_mode mode)\n    : ansicolor_sink<ConsoleMutex>(stdout, mode)\n{}\n\n// ansicolor_stderr_sink\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE ansicolor_stderr_sink<ConsoleMutex>::ansicolor_stderr_sink(color_mode mode)\n    : ansicolor_sink<ConsoleMutex>(stderr, mode)\n{}\n\n} // namespace sinks\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/ansicolor_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/details/console_globals.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/sinks/sink.h>\n#include <memory>\n#include <mutex>\n#include <string>\n#include <array>\n\nnamespace spdlog {\nnamespace sinks {\n\n/**\n * This sink prefixes the output with an ANSI escape sequence color code\n * depending on the severity\n * of the message.\n * If no color terminal detected, omit the escape codes.\n */\n\ntemplate<typename ConsoleMutex>\nclass ansicolor_sink : public sink\n{\npublic:\n    using mutex_t = typename ConsoleMutex::mutex_t;\n    ansicolor_sink(FILE *target_file, color_mode mode);\n    ~ansicolor_sink() override = default;\n\n    ansicolor_sink(const ansicolor_sink &other) = delete;\n    ansicolor_sink(ansicolor_sink &&other) = delete;\n\n    ansicolor_sink &operator=(const ansicolor_sink &other) = delete;\n    ansicolor_sink &operator=(ansicolor_sink &&other) = delete;\n\n    void set_color(level::level_enum color_level, string_view_t color);\n    void set_color_mode(color_mode mode);\n    bool should_color();\n\n    void log(const details::log_msg &msg) override;\n    void flush() override;\n    void set_pattern(const std::string &pattern) final;\n    void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) override;\n\n    // Formatting codes\n    const string_view_t reset = \"\\033[m\";\n    const string_view_t bold = \"\\033[1m\";\n    const string_view_t dark = \"\\033[2m\";\n    const string_view_t underline = \"\\033[4m\";\n    const string_view_t blink = \"\\033[5m\";\n    const string_view_t reverse = \"\\033[7m\";\n    const string_view_t concealed = \"\\033[8m\";\n    const string_view_t clear_line = \"\\033[K\";\n\n    // Foreground colors\n    const string_view_t black = \"\\033[30m\";\n    const string_view_t red = \"\\033[31m\";\n    const string_view_t green = \"\\033[32m\";\n    const string_view_t yellow = \"\\033[33m\";\n    const string_view_t blue = \"\\033[34m\";\n    const string_view_t magenta = \"\\033[35m\";\n    const string_view_t cyan = \"\\033[36m\";\n    const string_view_t white = \"\\033[37m\";\n\n    /// Background colors\n    const string_view_t on_black = \"\\033[40m\";\n    const string_view_t on_red = \"\\033[41m\";\n    const string_view_t on_green = \"\\033[42m\";\n    const string_view_t on_yellow = \"\\033[43m\";\n    const string_view_t on_blue = \"\\033[44m\";\n    const string_view_t on_magenta = \"\\033[45m\";\n    const string_view_t on_cyan = \"\\033[46m\";\n    const string_view_t on_white = \"\\033[47m\";\n\n    /// Bold colors\n    const string_view_t yellow_bold = \"\\033[33m\\033[1m\";\n    const string_view_t red_bold = \"\\033[31m\\033[1m\";\n    const string_view_t bold_on_red = \"\\033[1m\\033[41m\";\n\nprivate:\n    FILE *target_file_;\n    mutex_t &mutex_;\n    bool should_do_colors_;\n    std::unique_ptr<spdlog::formatter> formatter_;\n    std::array<std::string, level::n_levels> colors_;\n    void print_ccode_(const string_view_t &color_code);\n    void print_range_(const memory_buf_t &formatted, size_t start, size_t end);\n    static std::string to_string_(const string_view_t &sv);\n};\n\ntemplate<typename ConsoleMutex>\nclass ansicolor_stdout_sink : public ansicolor_sink<ConsoleMutex>\n{\npublic:\n    explicit ansicolor_stdout_sink(color_mode mode = color_mode::automatic);\n};\n\ntemplate<typename ConsoleMutex>\nclass ansicolor_stderr_sink : public ansicolor_sink<ConsoleMutex>\n{\npublic:\n    explicit ansicolor_stderr_sink(color_mode mode = color_mode::automatic);\n};\n\nusing ansicolor_stdout_sink_mt = ansicolor_stdout_sink<details::console_mutex>;\nusing ansicolor_stdout_sink_st = ansicolor_stdout_sink<details::console_nullmutex>;\n\nusing ansicolor_stderr_sink_mt = ansicolor_stderr_sink<details::console_mutex>;\nusing ansicolor_stderr_sink_st = ansicolor_stderr_sink<details::console_nullmutex>;\n\n} // namespace sinks\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"ansicolor_sink-inl.h\"\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/base_sink-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/sinks/base_sink.h>\n#endif\n\n#include <spdlog/common.h>\n#include <spdlog/pattern_formatter.h>\n\n#include <memory>\n\ntemplate<typename Mutex>\nSPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::base_sink()\n    : formatter_{details::make_unique<spdlog::pattern_formatter>()}\n{}\n\ntemplate<typename Mutex>\nSPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::base_sink(std::unique_ptr<spdlog::formatter> formatter)\n    : formatter_{std::move(formatter)}\n{}\n\ntemplate<typename Mutex>\nvoid SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::log(const details::log_msg &msg)\n{\n    std::lock_guard<Mutex> lock(mutex_);\n    sink_it_(msg);\n}\n\ntemplate<typename Mutex>\nvoid SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::flush()\n{\n    std::lock_guard<Mutex> lock(mutex_);\n    flush_();\n}\n\ntemplate<typename Mutex>\nvoid SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_pattern(const std::string &pattern)\n{\n    std::lock_guard<Mutex> lock(mutex_);\n    set_pattern_(pattern);\n}\n\ntemplate<typename Mutex>\nvoid SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter)\n{\n    std::lock_guard<Mutex> lock(mutex_);\n    set_formatter_(std::move(sink_formatter));\n}\n\ntemplate<typename Mutex>\nvoid SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_pattern_(const std::string &pattern)\n{\n    set_formatter_(details::make_unique<spdlog::pattern_formatter>(pattern));\n}\n\ntemplate<typename Mutex>\nvoid SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter)\n{\n    formatter_ = std::move(sink_formatter);\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/base_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n//\n// base sink templated over a mutex (either dummy or real)\n// concrete implementation should override the sink_it_() and flush_()  methods.\n// locking is taken care of in this class - no locking needed by the\n// implementers..\n//\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/common.h>\n#include <spdlog/details/log_msg.h>\n#include <spdlog/sinks/sink.h>\n\nnamespace spdlog {\nnamespace sinks {\ntemplate<typename Mutex>\nclass SPDLOG_API base_sink : public sink\n{\npublic:\n    base_sink();\n    explicit base_sink(std::unique_ptr<spdlog::formatter> formatter);\n    ~base_sink() override = default;\n\n    base_sink(const base_sink &) = delete;\n    base_sink(base_sink &&) = delete;\n\n    base_sink &operator=(const base_sink &) = delete;\n    base_sink &operator=(base_sink &&) = delete;\n\n    void log(const details::log_msg &msg) final;\n    void flush() final;\n    void set_pattern(const std::string &pattern) final;\n    void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) final;\n\nprotected:\n    // sink formatter\n    std::unique_ptr<spdlog::formatter> formatter_;\n    Mutex mutex_;\n\n    virtual void sink_it_(const details::log_msg &msg) = 0;\n    virtual void flush_() = 0;\n    virtual void set_pattern_(const std::string &pattern);\n    virtual void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter);\n};\n} // namespace sinks\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"base_sink-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/basic_file_sink-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/sinks/basic_file_sink.h>\n#endif\n\n#include <spdlog/common.h>\n#include <spdlog/details/os.h>\n\nnamespace spdlog {\nnamespace sinks {\n\ntemplate<typename Mutex>\nSPDLOG_INLINE basic_file_sink<Mutex>::basic_file_sink(const filename_t &filename, bool truncate, const file_event_handlers &event_handlers)\n    : file_helper_{event_handlers}\n{\n    file_helper_.open(filename, truncate);\n}\n\ntemplate<typename Mutex>\nSPDLOG_INLINE const filename_t &basic_file_sink<Mutex>::filename() const\n{\n    return file_helper_.filename();\n}\n\ntemplate<typename Mutex>\nSPDLOG_INLINE void basic_file_sink<Mutex>::sink_it_(const details::log_msg &msg)\n{\n    memory_buf_t formatted;\n    base_sink<Mutex>::formatter_->format(msg, formatted);\n    file_helper_.write(formatted);\n}\n\ntemplate<typename Mutex>\nSPDLOG_INLINE void basic_file_sink<Mutex>::flush_()\n{\n    file_helper_.flush();\n}\n\n} // namespace sinks\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/basic_file_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/details/file_helper.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/sinks/base_sink.h>\n#include <spdlog/details/synchronous_factory.h>\n\n#include <mutex>\n#include <string>\n\nnamespace spdlog {\nnamespace sinks {\n/*\n * Trivial file sink with single file as target\n */\ntemplate<typename Mutex>\nclass basic_file_sink final : public base_sink<Mutex>\n{\npublic:\n    explicit basic_file_sink(const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {});\n    const filename_t &filename() const;\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override;\n    void flush_() override;\n\nprivate:\n    details::file_helper file_helper_;\n};\n\nusing basic_file_sink_mt = basic_file_sink<std::mutex>;\nusing basic_file_sink_st = basic_file_sink<details::null_mutex>;\n\n} // namespace sinks\n\n//\n// factory functions\n//\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> basic_logger_mt(\n    const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::basic_file_sink_mt>(logger_name, filename, truncate, event_handlers);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> basic_logger_st(\n    const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::basic_file_sink_st>(logger_name, filename, truncate, event_handlers);\n}\n\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"basic_file_sink-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/daily_file_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/common.h>\n#include <spdlog/details/file_helper.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/fmt/fmt.h>\n#include <spdlog/fmt/chrono.h>\n#include <spdlog/sinks/base_sink.h>\n#include <spdlog/details/os.h>\n#include <spdlog/details/circular_q.h>\n#include <spdlog/details/synchronous_factory.h>\n\n#include <chrono>\n#include <cstdio>\n#include <ctime>\n#include <mutex>\n#include <string>\n\nnamespace spdlog {\nnamespace sinks {\n\n/*\n * Generator of daily log file names in format basename.YYYY-MM-DD.ext\n */\nstruct daily_filename_calculator\n{\n    // Create filename for the form basename.YYYY-MM-DD\n    static filename_t calc_filename(const filename_t &filename, const tm &now_tm)\n    {\n        filename_t basename, ext;\n        std::tie(basename, ext) = details::file_helper::split_by_extension(filename);\n        return fmt_lib::format(\n            SPDLOG_FILENAME_T(\"{}_{:04d}-{:02d}-{:02d}{}\"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, ext);\n    }\n};\n\n/*\n * Generator of daily log file names with strftime format.\n * Usages:\n *    auto sink =  std::make_shared<spdlog::sinks::daily_file_format_sink_mt>(\"myapp-%Y-%m-%d:%H:%M:%S.log\", hour, minute);\"\n *    auto logger = spdlog::daily_logger_format_mt(\"loggername, \"myapp-%Y-%m-%d:%X.log\", hour,  minute)\"\n *\n */\nstruct daily_filename_format_calculator\n{\n    static filename_t calc_filename(const filename_t &filename, const tm &now_tm)\n    {\n#ifdef SPDLOG_USE_STD_FORMAT\n        // adapted from fmtlib: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/chrono.h#L522-L546\n\n        filename_t tm_format;\n        tm_format.append(filename);\n        // By appending an extra space we can distinguish an empty result that\n        // indicates insufficient buffer size from a guaranteed non-empty result\n        // https://github.com/fmtlib/fmt/issues/2238\n        tm_format.push_back(' ');\n\n        const size_t MIN_SIZE = 10;\n        filename_t buf;\n        buf.resize(MIN_SIZE);\n        for (;;)\n        {\n            size_t count = strftime(buf.data(), buf.size(), tm_format.c_str(), &now_tm);\n            if (count != 0)\n            {\n                // Remove the extra space.\n                buf.resize(count - 1);\n                break;\n            }\n            buf.resize(buf.size() * 2);\n        }\n\n        return buf;\n#else\n        // generate fmt datetime format string, e.g. {:%Y-%m-%d}.\n        filename_t fmt_filename = fmt::format(SPDLOG_FILENAME_T(\"{{:{}}}\"), filename);\n#    if defined(_MSC_VER) && defined(SPDLOG_WCHAR_FILENAMES) // for some reason msvc doesn't allow fmt::runtime(..) with wchar here\n        return fmt::format(fmt_filename, now_tm);\n#    else\n        return fmt::format(SPDLOG_FMT_RUNTIME(fmt_filename), now_tm);\n#    endif\n#endif\n    }\n\nprivate:\n#if defined __GNUC__\n#    pragma GCC diagnostic push\n#    pragma GCC diagnostic ignored \"-Wformat-nonliteral\"\n#endif\n\n    static size_t strftime(char *str, size_t count, const char *format, const std::tm *time)\n    {\n        return std::strftime(str, count, format, time);\n    }\n\n    static size_t strftime(wchar_t *str, size_t count, const wchar_t *format, const std::tm *time)\n    {\n        return std::wcsftime(str, count, format, time);\n    }\n\n#if defined(__GNUC__)\n#    pragma GCC diagnostic pop\n#endif\n};\n\n/*\n * Rotating file sink based on date.\n * If truncate != false , the created file will be truncated.\n * If max_files > 0, retain only the last max_files and delete previous.\n */\ntemplate<typename Mutex, typename FileNameCalc = daily_filename_calculator>\nclass daily_file_sink final : public base_sink<Mutex>\n{\npublic:\n    // create daily file sink which rotates on given time\n    daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0,\n        const file_event_handlers &event_handlers = {})\n        : base_filename_(std::move(base_filename))\n        , rotation_h_(rotation_hour)\n        , rotation_m_(rotation_minute)\n        , file_helper_{event_handlers}\n        , truncate_(truncate)\n        , max_files_(max_files)\n        , filenames_q_()\n    {\n        if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)\n        {\n            throw_spdlog_ex(\"daily_file_sink: Invalid rotation time in ctor\");\n        }\n\n        auto now = log_clock::now();\n        auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));\n        file_helper_.open(filename, truncate_);\n        rotation_tp_ = next_rotation_tp_();\n\n        if (max_files_ > 0)\n        {\n            init_filenames_q_();\n        }\n    }\n\n    filename_t filename()\n    {\n        std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);\n        return file_helper_.filename();\n    }\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        auto time = msg.time;\n        bool should_rotate = time >= rotation_tp_;\n        if (should_rotate)\n        {\n            auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time));\n            file_helper_.open(filename, truncate_);\n            rotation_tp_ = next_rotation_tp_();\n        }\n        memory_buf_t formatted;\n        base_sink<Mutex>::formatter_->format(msg, formatted);\n        file_helper_.write(formatted);\n\n        // Do the cleaning only at the end because it might throw on failure.\n        if (should_rotate && max_files_ > 0)\n        {\n            delete_old_();\n        }\n    }\n\n    void flush_() override\n    {\n        file_helper_.flush();\n    }\n\nprivate:\n    void init_filenames_q_()\n    {\n        using details::os::path_exists;\n\n        filenames_q_ = details::circular_q<filename_t>(static_cast<size_t>(max_files_));\n        std::vector<filename_t> filenames;\n        auto now = log_clock::now();\n        while (filenames.size() < max_files_)\n        {\n            auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));\n            if (!path_exists(filename))\n            {\n                break;\n            }\n            filenames.emplace_back(filename);\n            now -= std::chrono::hours(24);\n        }\n        for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter)\n        {\n            filenames_q_.push_back(std::move(*iter));\n        }\n    }\n\n    tm now_tm(log_clock::time_point tp)\n    {\n        time_t tnow = log_clock::to_time_t(tp);\n        return spdlog::details::os::localtime(tnow);\n    }\n\n    log_clock::time_point next_rotation_tp_()\n    {\n        auto now = log_clock::now();\n        tm date = now_tm(now);\n        date.tm_hour = rotation_h_;\n        date.tm_min = rotation_m_;\n        date.tm_sec = 0;\n        auto rotation_time = log_clock::from_time_t(std::mktime(&date));\n        if (rotation_time > now)\n        {\n            return rotation_time;\n        }\n        return {rotation_time + std::chrono::hours(24)};\n    }\n\n    // Delete the file N rotations ago.\n    // Throw spdlog_ex on failure to delete the old file.\n    void delete_old_()\n    {\n        using details::os::filename_to_str;\n        using details::os::remove_if_exists;\n\n        filename_t current_file = file_helper_.filename();\n        if (filenames_q_.full())\n        {\n            auto old_filename = std::move(filenames_q_.front());\n            filenames_q_.pop_front();\n            bool ok = remove_if_exists(old_filename) == 0;\n            if (!ok)\n            {\n                filenames_q_.push_back(std::move(current_file));\n                throw_spdlog_ex(\"Failed removing daily file \" + filename_to_str(old_filename), errno);\n            }\n        }\n        filenames_q_.push_back(std::move(current_file));\n    }\n\n    filename_t base_filename_;\n    int rotation_h_;\n    int rotation_m_;\n    log_clock::time_point rotation_tp_;\n    details::file_helper file_helper_;\n    bool truncate_;\n    uint16_t max_files_;\n    details::circular_q<filename_t> filenames_q_;\n};\n\nusing daily_file_sink_mt = daily_file_sink<std::mutex>;\nusing daily_file_sink_st = daily_file_sink<details::null_mutex>;\nusing daily_file_format_sink_mt = daily_file_sink<std::mutex, daily_filename_format_calculator>;\nusing daily_file_format_sink_st = daily_file_sink<details::null_mutex, daily_filename_format_calculator>;\n\n} // namespace sinks\n\n//\n// factory functions\n//\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> daily_logger_mt(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0,\n    bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files, event_handlers);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> daily_logger_format_mt(const std::string &logger_name, const filename_t &filename, int hour = 0,\n    int minute = 0, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::daily_file_format_sink_mt>(\n        logger_name, filename, hour, minute, truncate, max_files, event_handlers);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0,\n    bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files, event_handlers);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> daily_logger_format_st(const std::string &logger_name, const filename_t &filename, int hour = 0,\n    int minute = 0, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::daily_file_format_sink_st>(\n        logger_name, filename, hour, minute, truncate, max_files, event_handlers);\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/dist_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include \"base_sink.h\"\n#include <spdlog/details/log_msg.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/pattern_formatter.h>\n\n#include <algorithm>\n#include <memory>\n#include <mutex>\n#include <vector>\n\n// Distribution sink (mux). Stores a vector of sinks which get called when log\n// is called\n\nnamespace spdlog {\nnamespace sinks {\n\ntemplate<typename Mutex>\nclass dist_sink : public base_sink<Mutex>\n{\npublic:\n    dist_sink() = default;\n    explicit dist_sink(std::vector<std::shared_ptr<sink>> sinks)\n        : sinks_(sinks)\n    {}\n\n    dist_sink(const dist_sink &) = delete;\n    dist_sink &operator=(const dist_sink &) = delete;\n\n    void add_sink(std::shared_ptr<sink> sink)\n    {\n        std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);\n        sinks_.push_back(sink);\n    }\n\n    void remove_sink(std::shared_ptr<sink> sink)\n    {\n        std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);\n        sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end());\n    }\n\n    void set_sinks(std::vector<std::shared_ptr<sink>> sinks)\n    {\n        std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);\n        sinks_ = std::move(sinks);\n    }\n\n    std::vector<std::shared_ptr<sink>> &sinks()\n    {\n        return sinks_;\n    }\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        for (auto &sink : sinks_)\n        {\n            if (sink->should_log(msg.level))\n            {\n                sink->log(msg);\n            }\n        }\n    }\n\n    void flush_() override\n    {\n        for (auto &sink : sinks_)\n        {\n            sink->flush();\n        }\n    }\n\n    void set_pattern_(const std::string &pattern) override\n    {\n        set_formatter_(details::make_unique<spdlog::pattern_formatter>(pattern));\n    }\n\n    void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) override\n    {\n        base_sink<Mutex>::formatter_ = std::move(sink_formatter);\n        for (auto &sink : sinks_)\n        {\n            sink->set_formatter(base_sink<Mutex>::formatter_->clone());\n        }\n    }\n    std::vector<std::shared_ptr<sink>> sinks_;\n};\n\nusing dist_sink_mt = dist_sink<std::mutex>;\nusing dist_sink_st = dist_sink<details::null_mutex>;\n\n} // namespace sinks\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/dup_filter_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include \"dist_sink.h\"\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/details/log_msg.h>\n\n#include <cstdio>\n#include <mutex>\n#include <string>\n#include <chrono>\n\n// Duplicate message removal sink.\n// Skip the message if previous one is identical and less than \"max_skip_duration\" have passed\n//\n// Example:\n//\n//     #include <spdlog/sinks/dup_filter_sink.h>\n//\n//     int main() {\n//         auto dup_filter = std::make_shared<dup_filter_sink_st>(std::chrono::seconds(5));\n//         dup_filter->add_sink(std::make_shared<stdout_color_sink_mt>());\n//         spdlog::logger l(\"logger\", dup_filter);\n//         l.info(\"Hello\");\n//         l.info(\"Hello\");\n//         l.info(\"Hello\");\n//         l.info(\"Different Hello\");\n//     }\n//\n// Will produce:\n//       [2019-06-25 17:50:56.511] [logger] [info] Hello\n//       [2019-06-25 17:50:56.512] [logger] [info] Skipped 3 duplicate messages..\n//       [2019-06-25 17:50:56.512] [logger] [info] Different Hello\n\nnamespace spdlog {\nnamespace sinks {\ntemplate<typename Mutex>\nclass dup_filter_sink : public dist_sink<Mutex>\n{\npublic:\n    template<class Rep, class Period>\n    explicit dup_filter_sink(std::chrono::duration<Rep, Period> max_skip_duration)\n        : max_skip_duration_{max_skip_duration}\n    {}\n\nprotected:\n    std::chrono::microseconds max_skip_duration_;\n    log_clock::time_point last_msg_time_;\n    std::string last_msg_payload_;\n    size_t skip_counter_ = 0;\n\n    void sink_it_(const details::log_msg &msg) override\n    {\n        bool filtered = filter_(msg);\n        if (!filtered)\n        {\n            skip_counter_ += 1;\n            return;\n        }\n\n        // log the \"skipped..\" message\n        if (skip_counter_ > 0)\n        {\n            char buf[64];\n            auto msg_size = ::snprintf(buf, sizeof(buf), \"Skipped %u duplicate messages..\", static_cast<unsigned>(skip_counter_));\n            if (msg_size > 0 && static_cast<size_t>(msg_size) < sizeof(buf))\n            {\n                details::log_msg skipped_msg{msg.logger_name, level::info, string_view_t{buf, static_cast<size_t>(msg_size)}};\n                dist_sink<Mutex>::sink_it_(skipped_msg);\n            }\n        }\n\n        // log current message\n        dist_sink<Mutex>::sink_it_(msg);\n        last_msg_time_ = msg.time;\n        skip_counter_ = 0;\n        last_msg_payload_.assign(msg.payload.data(), msg.payload.data() + msg.payload.size());\n    }\n\n    // return whether the log msg should be displayed (true) or skipped (false)\n    bool filter_(const details::log_msg &msg)\n    {\n        auto filter_duration = msg.time - last_msg_time_;\n        return (filter_duration > max_skip_duration_) || (msg.payload != last_msg_payload_);\n    }\n};\n\nusing dup_filter_sink_mt = dup_filter_sink<std::mutex>;\nusing dup_filter_sink_st = dup_filter_sink<details::null_mutex>;\n\n} // namespace sinks\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/hourly_file_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/common.h>\n#include <spdlog/details/file_helper.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/fmt/fmt.h>\n#include <spdlog/sinks/base_sink.h>\n#include <spdlog/details/os.h>\n#include <spdlog/details/circular_q.h>\n#include <spdlog/details/synchronous_factory.h>\n\n#include <chrono>\n#include <cstdio>\n#include <ctime>\n#include <mutex>\n#include <string>\n\nnamespace spdlog {\nnamespace sinks {\n\n/*\n * Generator of Hourly log file names in format basename.YYYY-MM-DD-HH.ext\n */\nstruct hourly_filename_calculator\n{\n    // Create filename for the form basename.YYYY-MM-DD-H\n    static filename_t calc_filename(const filename_t &filename, const tm &now_tm)\n    {\n        filename_t basename, ext;\n        std::tie(basename, ext) = details::file_helper::split_by_extension(filename);\n        return fmt_lib::format(SPDLOG_FILENAME_T(\"{}_{:04d}-{:02d}-{:02d}_{:02d}{}\"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1,\n            now_tm.tm_mday, now_tm.tm_hour, ext);\n    }\n};\n\n/*\n * Rotating file sink based on time.\n * If truncate != false , the created file will be truncated.\n * If max_files > 0, retain only the last max_files and delete previous.\n */\ntemplate<typename Mutex, typename FileNameCalc = hourly_filename_calculator>\nclass hourly_file_sink final : public base_sink<Mutex>\n{\npublic:\n    // create hourly file sink which rotates on given time\n    hourly_file_sink(\n        filename_t base_filename, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {})\n        : base_filename_(std::move(base_filename))\n        , file_helper_{event_handlers}\n        , truncate_(truncate)\n        , max_files_(max_files)\n        , filenames_q_()\n    {\n        auto now = log_clock::now();\n        auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));\n        file_helper_.open(filename, truncate_);\n        rotation_tp_ = next_rotation_tp_();\n\n        if (max_files_ > 0)\n        {\n            init_filenames_q_();\n        }\n    }\n\n    filename_t filename()\n    {\n        std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);\n        return file_helper_.filename();\n    }\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        auto time = msg.time;\n        bool should_rotate = time >= rotation_tp_;\n        if (should_rotate)\n        {\n            auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time));\n            file_helper_.open(filename, truncate_);\n            rotation_tp_ = next_rotation_tp_();\n        }\n        memory_buf_t formatted;\n        base_sink<Mutex>::formatter_->format(msg, formatted);\n        file_helper_.write(formatted);\n\n        // Do the cleaning only at the end because it might throw on failure.\n        if (should_rotate && max_files_ > 0)\n        {\n            delete_old_();\n        }\n    }\n\n    void flush_() override\n    {\n        file_helper_.flush();\n    }\n\nprivate:\n    void init_filenames_q_()\n    {\n        using details::os::path_exists;\n\n        filenames_q_ = details::circular_q<filename_t>(static_cast<size_t>(max_files_));\n        std::vector<filename_t> filenames;\n        auto now = log_clock::now();\n        while (filenames.size() < max_files_)\n        {\n            auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));\n            if (!path_exists(filename))\n            {\n                break;\n            }\n            filenames.emplace_back(filename);\n            now -= std::chrono::hours(1);\n        }\n        for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter)\n        {\n            filenames_q_.push_back(std::move(*iter));\n        }\n    }\n\n    tm now_tm(log_clock::time_point tp)\n    {\n        time_t tnow = log_clock::to_time_t(tp);\n        return spdlog::details::os::localtime(tnow);\n    }\n\n    log_clock::time_point next_rotation_tp_()\n    {\n        auto now = log_clock::now();\n        tm date = now_tm(now);\n        date.tm_min = 0;\n        date.tm_sec = 0;\n        auto rotation_time = log_clock::from_time_t(std::mktime(&date));\n        if (rotation_time > now)\n        {\n            return rotation_time;\n        }\n        return {rotation_time + std::chrono::hours(1)};\n    }\n\n    // Delete the file N rotations ago.\n    // Throw spdlog_ex on failure to delete the old file.\n    void delete_old_()\n    {\n        using details::os::filename_to_str;\n        using details::os::remove_if_exists;\n\n        filename_t current_file = file_helper_.filename();\n        if (filenames_q_.full())\n        {\n            auto old_filename = std::move(filenames_q_.front());\n            filenames_q_.pop_front();\n            bool ok = remove_if_exists(old_filename) == 0;\n            if (!ok)\n            {\n                filenames_q_.push_back(std::move(current_file));\n                SPDLOG_THROW(spdlog_ex(\"Failed removing hourly file \" + filename_to_str(old_filename), errno));\n            }\n        }\n        filenames_q_.push_back(std::move(current_file));\n    }\n\n    filename_t base_filename_;\n    log_clock::time_point rotation_tp_;\n    details::file_helper file_helper_;\n    bool truncate_;\n    uint16_t max_files_;\n    details::circular_q<filename_t> filenames_q_;\n};\n\nusing hourly_file_sink_mt = hourly_file_sink<std::mutex>;\nusing hourly_file_sink_st = hourly_file_sink<details::null_mutex>;\n\n} // namespace sinks\n\n//\n// factory functions\n//\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> hourly_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false,\n    uint16_t max_files = 0, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::hourly_file_sink_mt>(logger_name, filename, truncate, max_files, event_handlers);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> hourly_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false,\n    uint16_t max_files = 0, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::hourly_file_sink_st>(logger_name, filename, truncate, max_files, event_handlers);\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/mongo_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n//\n// Custom sink for mongodb\n// Building and using requires mongocxx library.\n// For building mongocxx library check the url below\n// http://mongocxx.org/mongocxx-v3/installation/\n//\n\n#include \"spdlog/common.h\"\n#include \"spdlog/details/log_msg.h\"\n#include \"spdlog/sinks/base_sink.h\"\n#include <spdlog/details/synchronous_factory.h>\n\n#include <bsoncxx/builder/stream/document.hpp>\n#include <bsoncxx/types.hpp>\n#include <bsoncxx/view_or_value.hpp>\n\n#include <mongocxx/client.hpp>\n#include <mongocxx/instance.hpp>\n#include <mongocxx/uri.hpp>\n\nnamespace spdlog {\nnamespace sinks {\ntemplate<typename Mutex>\nclass mongo_sink : public base_sink<Mutex>\n{\npublic:\n    mongo_sink(const std::string &db_name, const std::string &collection_name, const std::string &uri = \"mongodb://localhost:27017\")\n    {\n        try\n        {\n            client_ = spdlog::details::make_unique<mongocxx::client>(mongocxx::uri{uri});\n            db_name_ = db_name;\n            coll_name_ = collection_name;\n        }\n        catch (const std::exception)\n        {\n            throw spdlog_ex(\"Error opening database\");\n        }\n    }\n\n    ~mongo_sink()\n    {\n        flush_();\n    }\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        using bsoncxx::builder::stream::document;\n        using bsoncxx::builder::stream::finalize;\n\n        if (client_ != nullptr)\n        {\n            auto doc = document{} << \"timestamp\" << bsoncxx::types::b_date(msg.time) << \"level\" << level::to_string_view(msg.level).data()\n                                  << \"message\" << std::string(msg.payload.begin(), msg.payload.end()) << \"logger_name\"\n                                  << std::string(msg.logger_name.begin(), msg.logger_name.end()) << \"thread_id\"\n                                  << static_cast<int>(msg.thread_id) << finalize;\n            client_->database(db_name_).collection(coll_name_).insert_one(doc.view());\n        }\n    }\n\n    void flush_() override {}\n\nprivate:\n    static mongocxx::instance instance_;\n    std::string db_name_;\n    std::string coll_name_;\n    std::unique_ptr<mongocxx::client> client_ = nullptr;\n};\ntemplate<>\nmongocxx::instance mongo_sink<std::mutex>::instance_{};\n\n#include \"spdlog/details/null_mutex.h\"\n#include <mutex>\nusing mongo_sink_mt = mongo_sink<std::mutex>;\nusing mongo_sink_st = mongo_sink<spdlog::details::null_mutex>;\n\n} // namespace sinks\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> mongo_logger_mt(const std::string &logger_name, const std::string &db_name,\n    const std::string &collection_name, const std::string &uri = \"mongodb://localhost:27017\")\n{\n    return Factory::template create<sinks::mongo_sink_mt>(logger_name, db_name, collection_name, uri);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> mongo_logger_st(const std::string &logger_name, const std::string &db_name,\n    const std::string &collection_name, const std::string &uri = \"mongodb://localhost:27017\")\n{\n    return Factory::template create<sinks::mongo_sink_st>(logger_name, db_name, collection_name, uri);\n}\n\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/msvc_sink.h",
    "content": "// Copyright(c) 2016 Alexander Dalshov.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_WIN32)\n\n#    include <spdlog/details/null_mutex.h>\n#    include <spdlog/sinks/base_sink.h>\n\n#    include <mutex>\n#    include <string>\n\n// Avoid including windows.h (https://stackoverflow.com/a/30741042)\nextern \"C\" __declspec(dllimport) void __stdcall OutputDebugStringA(const char *lpOutputString);\n\nnamespace spdlog {\nnamespace sinks {\n/*\n * MSVC sink (logging using OutputDebugStringA)\n */\ntemplate<typename Mutex>\nclass msvc_sink : public base_sink<Mutex>\n{\npublic:\n    msvc_sink() = default;\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        memory_buf_t formatted;\n        base_sink<Mutex>::formatter_->format(msg, formatted);\n        formatted.push_back('\\0'); // add a null terminator for OutputDebugStringA\n        OutputDebugStringA(formatted.data());\n    }\n\n    void flush_() override {}\n};\n\nusing msvc_sink_mt = msvc_sink<std::mutex>;\nusing msvc_sink_st = msvc_sink<details::null_mutex>;\n\nusing windebug_sink_mt = msvc_sink_mt;\nusing windebug_sink_st = msvc_sink_st;\n\n} // namespace sinks\n} // namespace spdlog\n\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/null_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/sinks/base_sink.h>\n#include <spdlog/details/synchronous_factory.h>\n\n#include <mutex>\n\nnamespace spdlog {\nnamespace sinks {\n\ntemplate<typename Mutex>\nclass null_sink : public base_sink<Mutex>\n{\nprotected:\n    void sink_it_(const details::log_msg &) override {}\n    void flush_() override {}\n};\n\nusing null_sink_mt = null_sink<details::null_mutex>;\nusing null_sink_st = null_sink<details::null_mutex>;\n\n} // namespace sinks\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> null_logger_mt(const std::string &logger_name)\n{\n    auto null_logger = Factory::template create<sinks::null_sink_mt>(logger_name);\n    null_logger->set_level(level::off);\n    return null_logger;\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> null_logger_st(const std::string &logger_name)\n{\n    auto null_logger = Factory::template create<sinks::null_sink_st>(logger_name);\n    null_logger->set_level(level::off);\n    return null_logger;\n}\n\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/ostream_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/sinks/base_sink.h>\n\n#include <mutex>\n#include <ostream>\n\nnamespace spdlog {\nnamespace sinks {\ntemplate<typename Mutex>\nclass ostream_sink final : public base_sink<Mutex>\n{\npublic:\n    explicit ostream_sink(std::ostream &os, bool force_flush = false)\n        : ostream_(os)\n        , force_flush_(force_flush)\n    {}\n    ostream_sink(const ostream_sink &) = delete;\n    ostream_sink &operator=(const ostream_sink &) = delete;\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        memory_buf_t formatted;\n        base_sink<Mutex>::formatter_->format(msg, formatted);\n        ostream_.write(formatted.data(), static_cast<std::streamsize>(formatted.size()));\n        if (force_flush_)\n        {\n            ostream_.flush();\n        }\n    }\n\n    void flush_() override\n    {\n        ostream_.flush();\n    }\n\n    std::ostream &ostream_;\n    bool force_flush_;\n};\n\nusing ostream_sink_mt = ostream_sink<std::mutex>;\nusing ostream_sink_st = ostream_sink<details::null_mutex>;\n\n} // namespace sinks\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/qt_sinks.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman, mguludag and spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n//\n// Custom sink for QPlainTextEdit or QTextEdit and its childs(QTextBrowser...\n// etc) Building and using requires Qt library.\n//\n\n#include \"spdlog/common.h\"\n#include \"spdlog/details/log_msg.h\"\n#include \"spdlog/details/synchronous_factory.h\"\n#include \"spdlog/sinks/base_sink.h\"\n\n#include <QTextEdit>\n#include <QPlainTextEdit>\n\n//\n// qt_sink class\n//\nnamespace spdlog {\nnamespace sinks {\ntemplate<typename Mutex>\nclass qt_sink : public base_sink<Mutex>\n{\npublic:\n    qt_sink(QObject *qt_object, const std::string &meta_method)\n    {\n        qt_object_ = qt_object;\n        meta_method_ = meta_method;\n    }\n\n    ~qt_sink()\n    {\n        flush_();\n    }\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        memory_buf_t formatted;\n        base_sink<Mutex>::formatter_->format(msg, formatted);\n        string_view_t str = string_view_t(formatted.data(), formatted.size());\n        QMetaObject::invokeMethod(qt_object_, meta_method_.c_str(), Qt::AutoConnection,\n            Q_ARG(QString, QString::fromUtf8(str.data(), static_cast<int>(str.size())).trimmed()));\n    }\n\n    void flush_() override {}\n\nprivate:\n    QObject *qt_object_ = nullptr;\n    std::string meta_method_;\n};\n\n#include \"spdlog/details/null_mutex.h\"\n#include <mutex>\nusing qt_sink_mt = qt_sink<std::mutex>;\nusing qt_sink_st = qt_sink<spdlog::details::null_mutex>;\n} // namespace sinks\n\n//\n// Factory functions\n//\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> qt_logger_mt(const std::string &logger_name, QTextEdit *qt_object, const std::string &meta_method = \"append\")\n{\n    return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> qt_logger_st(const std::string &logger_name, QTextEdit *qt_object, const std::string &meta_method = \"append\")\n{\n    return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> qt_logger_mt(\n    const std::string &logger_name, QPlainTextEdit *qt_object, const std::string &meta_method = \"appendPlainText\")\n{\n    return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> qt_logger_st(\n    const std::string &logger_name, QPlainTextEdit *qt_object, const std::string &meta_method = \"appendPlainText\")\n{\n    return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> qt_logger_mt(const std::string &logger_name, QObject *qt_object, const std::string &meta_method)\n{\n    return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> qt_logger_st(const std::string &logger_name, QObject *qt_object, const std::string &meta_method)\n{\n    return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/ringbuffer_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include \"spdlog/sinks/base_sink.h\"\n#include \"spdlog/details/circular_q.h\"\n#include \"spdlog/details/log_msg_buffer.h\"\n#include \"spdlog/details/null_mutex.h\"\n\n#include <mutex>\n#include <string>\n#include <vector>\n\nnamespace spdlog {\nnamespace sinks {\n/*\n * Ring buffer sink\n */\ntemplate<typename Mutex>\nclass ringbuffer_sink final : public base_sink<Mutex>\n{\npublic:\n    explicit ringbuffer_sink(size_t n_items)\n        : q_{n_items}\n    {}\n\n    std::vector<details::log_msg_buffer> last_raw(size_t lim = 0)\n    {\n        std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);\n        auto items_available = q_.size();\n        auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available;\n        std::vector<details::log_msg_buffer> ret;\n        ret.reserve(n_items);\n        for (size_t i = (items_available - n_items); i < items_available; i++)\n        {\n            ret.push_back(q_.at(i));\n        }\n        return ret;\n    }\n\n    std::vector<std::string> last_formatted(size_t lim = 0)\n    {\n        std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);\n        auto items_available = q_.size();\n        auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available;\n        std::vector<std::string> ret;\n        ret.reserve(n_items);\n        for (size_t i = (items_available - n_items); i < items_available; i++)\n        {\n            memory_buf_t formatted;\n            base_sink<Mutex>::formatter_->format(q_.at(i), formatted);\n            ret.push_back(std::move(SPDLOG_BUF_TO_STRING(formatted)));\n        }\n        return ret;\n    }\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        q_.push_back(details::log_msg_buffer{msg});\n    }\n    void flush_() override {}\n\nprivate:\n    details::circular_q<details::log_msg_buffer> q_;\n};\n\nusing ringbuffer_sink_mt = ringbuffer_sink<std::mutex>;\nusing ringbuffer_sink_st = ringbuffer_sink<details::null_mutex>;\n\n} // namespace sinks\n\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/rotating_file_sink-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/sinks/rotating_file_sink.h>\n#endif\n\n#include <spdlog/common.h>\n\n#include <spdlog/details/file_helper.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/fmt/fmt.h>\n\n#include <cerrno>\n#include <chrono>\n#include <ctime>\n#include <mutex>\n#include <string>\n#include <tuple>\n\nnamespace spdlog {\nnamespace sinks {\n\ntemplate<typename Mutex>\nSPDLOG_INLINE rotating_file_sink<Mutex>::rotating_file_sink(\n    filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open, const file_event_handlers &event_handlers)\n    : base_filename_(std::move(base_filename))\n    , max_size_(max_size)\n    , max_files_(max_files)\n    , file_helper_{event_handlers}\n{\n    if (max_size == 0)\n    {\n        throw_spdlog_ex(\"rotating sink constructor: max_size arg cannot be zero\");\n    }\n\n    if (max_files > 200000)\n    {\n        throw_spdlog_ex(\"rotating sink constructor: max_files arg cannot exceed 200000\");\n    }\n    file_helper_.open(calc_filename(base_filename_, 0));\n    current_size_ = file_helper_.size(); // expensive. called only once\n    if (rotate_on_open && current_size_ > 0)\n    {\n        rotate_();\n        current_size_ = 0;\n    }\n}\n\n// calc filename according to index and file extension if exists.\n// e.g. calc_filename(\"logs/mylog.txt, 3) => \"logs/mylog.3.txt\".\ntemplate<typename Mutex>\nSPDLOG_INLINE filename_t rotating_file_sink<Mutex>::calc_filename(const filename_t &filename, std::size_t index)\n{\n    if (index == 0u)\n    {\n        return filename;\n    }\n\n    filename_t basename, ext;\n    std::tie(basename, ext) = details::file_helper::split_by_extension(filename);\n    return fmt_lib::format(SPDLOG_FILENAME_T(\"{}.{}{}\"), basename, index, ext);\n}\n\ntemplate<typename Mutex>\nSPDLOG_INLINE filename_t rotating_file_sink<Mutex>::filename()\n{\n    std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);\n    return file_helper_.filename();\n}\n\ntemplate<typename Mutex>\nSPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &msg)\n{\n    memory_buf_t formatted;\n    base_sink<Mutex>::formatter_->format(msg, formatted);\n    auto new_size = current_size_ + formatted.size();\n\n    // rotate if the new estimated file size exceeds max size.\n    // rotate only if the real size > 0 to better deal with full disk (see issue #2261).\n    // we only check the real size when new_size > max_size_ because it is relatively expensive.\n    if (new_size > max_size_)\n    {\n        file_helper_.flush();\n        if (file_helper_.size() > 0)\n        {\n            rotate_();\n            new_size = formatted.size();\n        }\n    }\n    file_helper_.write(formatted);\n    current_size_ = new_size;\n}\n\ntemplate<typename Mutex>\nSPDLOG_INLINE void rotating_file_sink<Mutex>::flush_()\n{\n    file_helper_.flush();\n}\n\n// Rotate files:\n// log.txt -> log.1.txt\n// log.1.txt -> log.2.txt\n// log.2.txt -> log.3.txt\n// log.3.txt -> delete\ntemplate<typename Mutex>\nSPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_()\n{\n    using details::os::filename_to_str;\n    using details::os::path_exists;\n\n    file_helper_.close();\n    for (auto i = max_files_; i > 0; --i)\n    {\n        filename_t src = calc_filename(base_filename_, i - 1);\n        if (!path_exists(src))\n        {\n            continue;\n        }\n        filename_t target = calc_filename(base_filename_, i);\n\n        if (!rename_file_(src, target))\n        {\n            // if failed try again after a small delay.\n            // this is a workaround to a windows issue, where very high rotation\n            // rates can cause the rename to fail with permission denied (because of antivirus?).\n            details::os::sleep_for_millis(100);\n            if (!rename_file_(src, target))\n            {\n                file_helper_.reopen(true); // truncate the log file anyway to prevent it to grow beyond its limit!\n                current_size_ = 0;\n                throw_spdlog_ex(\"rotating_file_sink: failed renaming \" + filename_to_str(src) + \" to \" + filename_to_str(target), errno);\n            }\n        }\n    }\n    file_helper_.reopen(true);\n}\n\n// delete the target if exists, and rename the src file  to target\n// return true on success, false otherwise.\ntemplate<typename Mutex>\nSPDLOG_INLINE bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename, const filename_t &target_filename)\n{\n    // try to delete the target file in case it already exists.\n    (void)details::os::remove(target_filename);\n    return details::os::rename(src_filename, target_filename) == 0;\n}\n\n} // namespace sinks\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/rotating_file_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/sinks/base_sink.h>\n#include <spdlog/details/file_helper.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/details/synchronous_factory.h>\n\n#include <chrono>\n#include <mutex>\n#include <string>\n\nnamespace spdlog {\nnamespace sinks {\n\n//\n// Rotating file sink based on size\n//\ntemplate<typename Mutex>\nclass rotating_file_sink final : public base_sink<Mutex>\n{\npublic:\n    rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false,\n        const file_event_handlers &event_handlers = {});\n    static filename_t calc_filename(const filename_t &filename, std::size_t index);\n    filename_t filename();\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override;\n    void flush_() override;\n\nprivate:\n    // Rotate files:\n    // log.txt -> log.1.txt\n    // log.1.txt -> log.2.txt\n    // log.2.txt -> log.3.txt\n    // log.3.txt -> delete\n    void rotate_();\n\n    // delete the target if exists, and rename the src file  to target\n    // return true on success, false otherwise.\n    bool rename_file_(const filename_t &src_filename, const filename_t &target_filename);\n\n    filename_t base_filename_;\n    std::size_t max_size_;\n    std::size_t max_files_;\n    std::size_t current_size_;\n    details::file_helper file_helper_;\n};\n\nusing rotating_file_sink_mt = rotating_file_sink<std::mutex>;\nusing rotating_file_sink_st = rotating_file_sink<details::null_mutex>;\n\n} // namespace sinks\n\n//\n// factory functions\n//\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> rotating_logger_mt(const std::string &logger_name, const filename_t &filename, size_t max_file_size,\n    size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::rotating_file_sink_mt>(\n        logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> rotating_logger_st(const std::string &logger_name, const filename_t &filename, size_t max_file_size,\n    size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {})\n{\n    return Factory::template create<sinks::rotating_file_sink_st>(\n        logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers);\n}\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"rotating_file_sink-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/sink-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/sinks/sink.h>\n#endif\n\n#include <spdlog/common.h>\n\nSPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const\n{\n    return msg_level >= level_.load(std::memory_order_relaxed);\n}\n\nSPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level)\n{\n    level_.store(log_level, std::memory_order_relaxed);\n}\n\nSPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const\n{\n    return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed));\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/details/log_msg.h>\n#include <spdlog/formatter.h>\n\nnamespace spdlog {\n\nnamespace sinks {\nclass SPDLOG_API sink\n{\npublic:\n    virtual ~sink() = default;\n    virtual void log(const details::log_msg &msg) = 0;\n    virtual void flush() = 0;\n    virtual void set_pattern(const std::string &pattern) = 0;\n    virtual void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) = 0;\n\n    void set_level(level::level_enum log_level);\n    level::level_enum level() const;\n    bool should_log(level::level_enum msg_level) const;\n\nprotected:\n    // sink log level - default is all\n    level_t level_{level::trace};\n};\n\n} // namespace sinks\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"sink-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/stdout_color_sinks-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/sinks/stdout_color_sinks.h>\n#endif\n\n#include <spdlog/logger.h>\n#include <spdlog/common.h>\n\nnamespace spdlog {\n\ntemplate<typename Factory>\nSPDLOG_INLINE std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode)\n{\n    return Factory::template create<sinks::stdout_color_sink_mt>(logger_name, mode);\n}\n\ntemplate<typename Factory>\nSPDLOG_INLINE std::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode)\n{\n    return Factory::template create<sinks::stdout_color_sink_st>(logger_name, mode);\n}\n\ntemplate<typename Factory>\nSPDLOG_INLINE std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode)\n{\n    return Factory::template create<sinks::stderr_color_sink_mt>(logger_name, mode);\n}\n\ntemplate<typename Factory>\nSPDLOG_INLINE std::shared_ptr<logger> stderr_color_st(const std::string &logger_name, color_mode mode)\n{\n    return Factory::template create<sinks::stderr_color_sink_st>(logger_name, mode);\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/stdout_color_sinks.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifdef _WIN32\n#    include <spdlog/sinks/wincolor_sink.h>\n#else\n#    include <spdlog/sinks/ansicolor_sink.h>\n#endif\n\n#include <spdlog/details/synchronous_factory.h>\n\nnamespace spdlog {\nnamespace sinks {\n#ifdef _WIN32\nusing stdout_color_sink_mt = wincolor_stdout_sink_mt;\nusing stdout_color_sink_st = wincolor_stdout_sink_st;\nusing stderr_color_sink_mt = wincolor_stderr_sink_mt;\nusing stderr_color_sink_st = wincolor_stderr_sink_st;\n#else\nusing stdout_color_sink_mt = ansicolor_stdout_sink_mt;\nusing stdout_color_sink_st = ansicolor_stdout_sink_st;\nusing stderr_color_sink_mt = ansicolor_stderr_sink_mt;\nusing stderr_color_sink_st = ansicolor_stderr_sink_st;\n#endif\n} // namespace sinks\n\ntemplate<typename Factory = spdlog::synchronous_factory>\nstd::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic);\n\ntemplate<typename Factory = spdlog::synchronous_factory>\nstd::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic);\n\ntemplate<typename Factory = spdlog::synchronous_factory>\nstd::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic);\n\ntemplate<typename Factory = spdlog::synchronous_factory>\nstd::shared_ptr<logger> stderr_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic);\n\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"stdout_color_sinks-inl.h\"\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/stdout_sinks-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/sinks/stdout_sinks.h>\n#endif\n\n#include <spdlog/details/console_globals.h>\n#include <spdlog/pattern_formatter.h>\n#include <memory>\n\n#ifdef _WIN32\n// under windows using fwrite to non-binary stream results in \\r\\r\\n (see issue #1675)\n// so instead we use ::FileWrite\n#    include <spdlog/details/windows_include.h>\n\n#    ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp\n#        include <fileapi.h>   // WriteFile (..)\n#    endif\n\n#    include <io.h>    // _get_osfhandle(..)\n#    include <stdio.h> // _fileno(..)\n#endif                 // WIN32\n\nnamespace spdlog {\n\nnamespace sinks {\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE stdout_sink_base<ConsoleMutex>::stdout_sink_base(FILE *file)\n    : mutex_(ConsoleMutex::mutex())\n    , file_(file)\n    , formatter_(details::make_unique<spdlog::pattern_formatter>())\n{\n#ifdef _WIN32\n    // get windows handle from the FILE* object\n\n    handle_ = reinterpret_cast<HANDLE>(::_get_osfhandle(::_fileno(file_)));\n\n    // don't throw to support cases where no console is attached,\n    // and let the log method to do nothing if (handle_ == INVALID_HANDLE_VALUE).\n    // throw only if non stdout/stderr target is requested (probably regular file and not console).\n    if (handle_ == INVALID_HANDLE_VALUE && file != stdout && file != stderr)\n    {\n        throw_spdlog_ex(\"spdlog::stdout_sink_base: _get_osfhandle() failed\", errno);\n    }\n#endif // WIN32\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &msg)\n{\n#ifdef _WIN32\n    if (handle_ == INVALID_HANDLE_VALUE)\n    {\n        return;\n    }\n    std::lock_guard<mutex_t> lock(mutex_);\n    memory_buf_t formatted;\n    formatter_->format(msg, formatted);\n    ::fflush(file_); // flush in case there is something in this file_ already\n    auto size = static_cast<DWORD>(formatted.size());\n    DWORD bytes_written = 0;\n    bool ok = ::WriteFile(handle_, formatted.data(), size, &bytes_written, nullptr) != 0;\n    if (!ok)\n    {\n        throw_spdlog_ex(\"stdout_sink_base: WriteFile() failed. GetLastError(): \" + std::to_string(::GetLastError()));\n    }\n#else\n    std::lock_guard<mutex_t> lock(mutex_);\n    memory_buf_t formatted;\n    formatter_->format(msg, formatted);\n    ::fwrite(formatted.data(), sizeof(char), formatted.size(), file_);\n    ::fflush(file_); // flush every line to terminal\n#endif // WIN32\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::flush()\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    fflush(file_);\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_pattern(const std::string &pattern)\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern));\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter)\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    formatter_ = std::move(sink_formatter);\n}\n\n// stdout sink\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE stdout_sink<ConsoleMutex>::stdout_sink()\n    : stdout_sink_base<ConsoleMutex>(stdout)\n{}\n\n// stderr sink\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE stderr_sink<ConsoleMutex>::stderr_sink()\n    : stdout_sink_base<ConsoleMutex>(stderr)\n{}\n\n} // namespace sinks\n\n// factory methods\ntemplate<typename Factory>\nSPDLOG_INLINE std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name)\n{\n    return Factory::template create<sinks::stdout_sink_mt>(logger_name);\n}\n\ntemplate<typename Factory>\nSPDLOG_INLINE std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name)\n{\n    return Factory::template create<sinks::stdout_sink_st>(logger_name);\n}\n\ntemplate<typename Factory>\nSPDLOG_INLINE std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name)\n{\n    return Factory::template create<sinks::stderr_sink_mt>(logger_name);\n}\n\ntemplate<typename Factory>\nSPDLOG_INLINE std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name)\n{\n    return Factory::template create<sinks::stderr_sink_st>(logger_name);\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/stdout_sinks.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/details/console_globals.h>\n#include <spdlog/details/synchronous_factory.h>\n#include <spdlog/sinks/sink.h>\n#include <cstdio>\n\n#ifdef _WIN32\n#    include <spdlog/details/windows_include.h>\n#endif\n\nnamespace spdlog {\n\nnamespace sinks {\n\ntemplate<typename ConsoleMutex>\nclass stdout_sink_base : public sink\n{\npublic:\n    using mutex_t = typename ConsoleMutex::mutex_t;\n    explicit stdout_sink_base(FILE *file);\n    ~stdout_sink_base() override = default;\n\n    stdout_sink_base(const stdout_sink_base &other) = delete;\n    stdout_sink_base(stdout_sink_base &&other) = delete;\n\n    stdout_sink_base &operator=(const stdout_sink_base &other) = delete;\n    stdout_sink_base &operator=(stdout_sink_base &&other) = delete;\n\n    void log(const details::log_msg &msg) override;\n    void flush() override;\n    void set_pattern(const std::string &pattern) override;\n\n    void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) override;\n\nprotected:\n    mutex_t &mutex_;\n    FILE *file_;\n    std::unique_ptr<spdlog::formatter> formatter_;\n#ifdef _WIN32\n    HANDLE handle_;\n#endif // WIN32\n};\n\ntemplate<typename ConsoleMutex>\nclass stdout_sink : public stdout_sink_base<ConsoleMutex>\n{\npublic:\n    stdout_sink();\n};\n\ntemplate<typename ConsoleMutex>\nclass stderr_sink : public stdout_sink_base<ConsoleMutex>\n{\npublic:\n    stderr_sink();\n};\n\nusing stdout_sink_mt = stdout_sink<details::console_mutex>;\nusing stdout_sink_st = stdout_sink<details::console_nullmutex>;\n\nusing stderr_sink_mt = stderr_sink<details::console_mutex>;\nusing stderr_sink_st = stderr_sink<details::console_nullmutex>;\n\n} // namespace sinks\n\n// factory methods\ntemplate<typename Factory = spdlog::synchronous_factory>\nstd::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name);\n\ntemplate<typename Factory = spdlog::synchronous_factory>\nstd::shared_ptr<logger> stdout_logger_st(const std::string &logger_name);\n\ntemplate<typename Factory = spdlog::synchronous_factory>\nstd::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name);\n\ntemplate<typename Factory = spdlog::synchronous_factory>\nstd::shared_ptr<logger> stderr_logger_st(const std::string &logger_name);\n\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"stdout_sinks-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/syslog_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/sinks/base_sink.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/details/synchronous_factory.h>\n\n#include <array>\n#include <string>\n#include <syslog.h>\n\nnamespace spdlog {\nnamespace sinks {\n/**\n * Sink that write to syslog using the `syscall()` library call.\n */\ntemplate<typename Mutex>\nclass syslog_sink : public base_sink<Mutex>\n{\n\npublic:\n    syslog_sink(std::string ident, int syslog_option, int syslog_facility, bool enable_formatting)\n        : enable_formatting_{enable_formatting}\n        , syslog_levels_{{/* spdlog::level::trace      */ LOG_DEBUG,\n              /* spdlog::level::debug      */ LOG_DEBUG,\n              /* spdlog::level::info       */ LOG_INFO,\n              /* spdlog::level::warn       */ LOG_WARNING,\n              /* spdlog::level::err        */ LOG_ERR,\n              /* spdlog::level::critical   */ LOG_CRIT,\n              /* spdlog::level::off        */ LOG_INFO}}\n        , ident_{std::move(ident)}\n    {\n        // set ident to be program name if empty\n        ::openlog(ident_.empty() ? nullptr : ident_.c_str(), syslog_option, syslog_facility);\n    }\n\n    ~syslog_sink() override\n    {\n        ::closelog();\n    }\n\n    syslog_sink(const syslog_sink &) = delete;\n    syslog_sink &operator=(const syslog_sink &) = delete;\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        string_view_t payload;\n        memory_buf_t formatted;\n        if (enable_formatting_)\n        {\n            base_sink<Mutex>::formatter_->format(msg, formatted);\n            payload = string_view_t(formatted.data(), formatted.size());\n        }\n        else\n        {\n            payload = msg.payload;\n        }\n\n        size_t length = payload.size();\n        // limit to max int\n        if (length > static_cast<size_t>(std::numeric_limits<int>::max()))\n        {\n            length = static_cast<size_t>(std::numeric_limits<int>::max());\n        }\n\n        ::syslog(syslog_prio_from_level(msg), \"%.*s\", static_cast<int>(length), payload.data());\n    }\n\n    void flush_() override {}\n    bool enable_formatting_ = false;\n\nprivate:\n    using levels_array = std::array<int, 7>;\n    levels_array syslog_levels_;\n    // must store the ident because the man says openlog might use the pointer as\n    // is and not a string copy\n    const std::string ident_;\n\n    //\n    // Simply maps spdlog's log level to syslog priority level.\n    //\n    int syslog_prio_from_level(const details::log_msg &msg) const\n    {\n        return syslog_levels_.at(static_cast<levels_array::size_type>(msg.level));\n    }\n};\n\nusing syslog_sink_mt = syslog_sink<std::mutex>;\nusing syslog_sink_st = syslog_sink<details::null_mutex>;\n} // namespace sinks\n\n// Create and register a syslog logger\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> syslog_logger_mt(const std::string &logger_name, const std::string &syslog_ident = \"\", int syslog_option = 0,\n    int syslog_facility = LOG_USER, bool enable_formatting = false)\n{\n    return Factory::template create<sinks::syslog_sink_mt>(logger_name, syslog_ident, syslog_option, syslog_facility, enable_formatting);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> syslog_logger_st(const std::string &logger_name, const std::string &syslog_ident = \"\", int syslog_option = 0,\n    int syslog_facility = LOG_USER, bool enable_formatting = false)\n{\n    return Factory::template create<sinks::syslog_sink_st>(logger_name, syslog_ident, syslog_option, syslog_facility, enable_formatting);\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/systemd_sink.h",
    "content": "// Copyright(c) 2019 ZVYAGIN.Alexander@gmail.com\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/sinks/base_sink.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/details/synchronous_factory.h>\n\n#include <array>\n#ifndef SD_JOURNAL_SUPPRESS_LOCATION\n#    define SD_JOURNAL_SUPPRESS_LOCATION\n#endif\n#include <systemd/sd-journal.h>\n\nnamespace spdlog {\nnamespace sinks {\n\n/**\n * Sink that write to systemd journal using the `sd_journal_send()` library call.\n */\ntemplate<typename Mutex>\nclass systemd_sink : public base_sink<Mutex>\n{\npublic:\n    systemd_sink(std::string ident = \"\", bool enable_formatting = false)\n        : ident_{std::move(ident)}\n        , enable_formatting_{enable_formatting}\n        , syslog_levels_{{/* spdlog::level::trace      */ LOG_DEBUG,\n              /* spdlog::level::debug      */ LOG_DEBUG,\n              /* spdlog::level::info       */ LOG_INFO,\n              /* spdlog::level::warn       */ LOG_WARNING,\n              /* spdlog::level::err        */ LOG_ERR,\n              /* spdlog::level::critical   */ LOG_CRIT,\n              /* spdlog::level::off        */ LOG_INFO}}\n    {}\n\n    ~systemd_sink() override {}\n\n    systemd_sink(const systemd_sink &) = delete;\n    systemd_sink &operator=(const systemd_sink &) = delete;\n\nprotected:\n    const std::string ident_;\n    bool enable_formatting_ = false;\n    using levels_array = std::array<int, 7>;\n    levels_array syslog_levels_;\n\n    void sink_it_(const details::log_msg &msg) override\n    {\n        int err;\n        string_view_t payload;\n        memory_buf_t formatted;\n        if (enable_formatting_)\n        {\n            base_sink<Mutex>::formatter_->format(msg, formatted);\n            payload = string_view_t(formatted.data(), formatted.size());\n        }\n        else\n        {\n            payload = msg.payload;\n        }\n\n        size_t length = payload.size();\n        // limit to max int\n        if (length > static_cast<size_t>(std::numeric_limits<int>::max()))\n        {\n            length = static_cast<size_t>(std::numeric_limits<int>::max());\n        }\n\n        const string_view_t syslog_identifier = ident_.empty() ? msg.logger_name : ident_;\n\n        // Do not send source location if not available\n        if (msg.source.empty())\n        {\n            // Note: function call inside '()' to avoid macro expansion\n            err = (sd_journal_send)(\"MESSAGE=%.*s\", static_cast<int>(length), payload.data(), \"PRIORITY=%d\", syslog_level(msg.level),\n                \"SYSLOG_IDENTIFIER=%.*s\", static_cast<int>(syslog_identifier.size()), syslog_identifier.data(), nullptr);\n        }\n        else\n        {\n            err = (sd_journal_send)(\"MESSAGE=%.*s\", static_cast<int>(length), payload.data(), \"PRIORITY=%d\", syslog_level(msg.level),\n                \"SYSLOG_IDENTIFIER=%.*s\", static_cast<int>(syslog_identifier.size()), syslog_identifier.data(), \"CODE_FILE=%s\",\n                msg.source.filename, \"CODE_LINE=%d\", msg.source.line, \"CODE_FUNC=%s\", msg.source.funcname, nullptr);\n        }\n\n        if (err)\n        {\n            throw_spdlog_ex(\"Failed writing to systemd\", errno);\n        }\n    }\n\n    int syslog_level(level::level_enum l)\n    {\n        return syslog_levels_.at(static_cast<levels_array::size_type>(l));\n    }\n\n    void flush_() override {}\n};\n\nusing systemd_sink_mt = systemd_sink<std::mutex>;\nusing systemd_sink_st = systemd_sink<details::null_mutex>;\n} // namespace sinks\n\n// Create and register a syslog logger\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> systemd_logger_mt(\n    const std::string &logger_name, const std::string &ident = \"\", bool enable_formatting = false)\n{\n    return Factory::template create<sinks::systemd_sink_mt>(logger_name, ident, enable_formatting);\n}\n\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> systemd_logger_st(\n    const std::string &logger_name, const std::string &ident = \"\", bool enable_formatting = false)\n{\n    return Factory::template create<sinks::systemd_sink_st>(logger_name, ident, enable_formatting);\n}\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/tcp_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/common.h>\n#include <spdlog/sinks/base_sink.h>\n#include <spdlog/details/null_mutex.h>\n#ifdef _WIN32\n#    include <spdlog/details/tcp_client-windows.h>\n#else\n#    include <spdlog/details/tcp_client.h>\n#endif\n\n#include <mutex>\n#include <string>\n#include <chrono>\n#include <functional>\n\n#pragma once\n\n// Simple tcp client sink\n// Connects to remote address and send the formatted log.\n// Will attempt to reconnect if connection drops.\n// If more complicated behaviour is needed (i.e get responses), you can inherit it and override the sink_it_ method.\n\nnamespace spdlog {\nnamespace sinks {\n\nstruct tcp_sink_config\n{\n    std::string server_host;\n    int server_port;\n    bool lazy_connect = false; // if true connect on first log call instead of on construction\n\n    tcp_sink_config(std::string host, int port)\n        : server_host{std::move(host)}\n        , server_port{port}\n    {}\n};\n\ntemplate<typename Mutex>\nclass tcp_sink : public spdlog::sinks::base_sink<Mutex>\n{\npublic:\n    // connect to tcp host/port or throw if failed\n    // host can be hostname or ip address\n\n    explicit tcp_sink(tcp_sink_config sink_config)\n        : config_{std::move(sink_config)}\n    {\n        if (!config_.lazy_connect)\n        {\n            this->client_.connect(config_.server_host, config_.server_port);\n        }\n    }\n\n    ~tcp_sink() override = default;\n\nprotected:\n    void sink_it_(const spdlog::details::log_msg &msg) override\n    {\n        spdlog::memory_buf_t formatted;\n        spdlog::sinks::base_sink<Mutex>::formatter_->format(msg, formatted);\n        if (!client_.is_connected())\n        {\n            client_.connect(config_.server_host, config_.server_port);\n        }\n        client_.send(formatted.data(), formatted.size());\n    }\n\n    void flush_() override {}\n    tcp_sink_config config_;\n    details::tcp_client client_;\n};\n\nusing tcp_sink_mt = tcp_sink<std::mutex>;\nusing tcp_sink_st = tcp_sink<spdlog::details::null_mutex>;\n\n} // namespace sinks\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/udp_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/common.h>\n#include <spdlog/sinks/base_sink.h>\n#include <spdlog/details/null_mutex.h>\n#ifdef _WIN32\n#    include <spdlog/details/udp_client-windows.h>\n#else\n#    include <spdlog/details/udp_client.h>\n#endif\n\n#include <mutex>\n#include <string>\n#include <chrono>\n#include <functional>\n\n// Simple udp client sink\n// Sends formatted log via udp\n\nnamespace spdlog {\nnamespace sinks {\n\nstruct udp_sink_config\n{\n    std::string server_host;\n    uint16_t server_port;\n\n    udp_sink_config(std::string host, uint16_t port)\n        : server_host{std::move(host)}\n        , server_port{port}\n    {}\n};\n\ntemplate<typename Mutex>\nclass udp_sink : public spdlog::sinks::base_sink<Mutex>\n{\npublic:\n    // host can be hostname or ip address\n    explicit udp_sink(udp_sink_config sink_config)\n        : client_{sink_config.server_host, sink_config.server_port}\n    {}\n\n    ~udp_sink() override = default;\n\nprotected:\n    void sink_it_(const spdlog::details::log_msg &msg) override\n    {\n        spdlog::memory_buf_t formatted;\n        spdlog::sinks::base_sink<Mutex>::formatter_->format(msg, formatted);\n        client_.send(formatted.data(), formatted.size());\n    }\n\n    void flush_() override {}\n    details::udp_client client_;\n};\n\nusing udp_sink_mt = udp_sink<std::mutex>;\nusing udp_sink_st = udp_sink<spdlog::details::null_mutex>;\n\n} // namespace sinks\n\n//\n// factory functions\n//\ntemplate<typename Factory = spdlog::synchronous_factory>\ninline std::shared_ptr<logger> udp_logger_mt(const std::string &logger_name, sinks::udp_sink_config skin_config)\n{\n    return Factory::template create<sinks::udp_sink_mt>(logger_name, skin_config);\n}\n\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/win_eventlog_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n// Writing to Windows Event Log requires the registry entries below to be present, with the following modifications:\n// 1. <log_name>    should be replaced with your log name (e.g. your application name)\n// 2. <source_name> should be replaced with the specific source name and the key should be duplicated for\n//                  each source used in the application\n//\n// Since typically modifications of this kind require elevation, it's better to do it as a part of setup procedure.\n// The snippet below uses mscoree.dll as the message file as it exists on most of the Windows systems anyway and\n// happens to contain the needed resource.\n//\n// You can also specify a custom message file if needed.\n// Please refer to Event Log functions descriptions in MSDN for more details on custom message files.\n\n/*---------------------------------------------------------------------------------------\n\nWindows Registry Editor Version 5.00\n\n[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\<log_name>]\n\n[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\<log_name>\\<source_name>]\n\"TypesSupported\"=dword:00000007\n\"EventMessageFile\"=hex(2):25,00,73,00,79,00,73,00,74,00,65,00,6d,00,72,00,6f,\\\n  00,6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,\\\n  5c,00,6d,00,73,00,63,00,6f,00,72,00,65,00,65,00,2e,00,64,00,6c,00,6c,00,00,\\\n  00\n\n-----------------------------------------------------------------------------------------*/\n\n#pragma once\n\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/sinks/base_sink.h>\n\n#include <spdlog/details/windows_include.h>\n#include <winbase.h>\n\n#include <mutex>\n#include <string>\n#include <vector>\n\nnamespace spdlog {\nnamespace sinks {\n\nnamespace win_eventlog {\n\nnamespace internal {\n\nstruct local_alloc_t\n{\n    HLOCAL hlocal_;\n\n    SPDLOG_CONSTEXPR local_alloc_t() SPDLOG_NOEXCEPT : hlocal_(nullptr) {}\n\n    local_alloc_t(local_alloc_t const &) = delete;\n    local_alloc_t &operator=(local_alloc_t const &) = delete;\n\n    ~local_alloc_t() SPDLOG_NOEXCEPT\n    {\n        if (hlocal_)\n        {\n            LocalFree(hlocal_);\n        }\n    }\n};\n\n/** Windows error */\nstruct win32_error : public spdlog_ex\n{\n    /** Formats an error report line: \"user-message: error-code (system message)\" */\n    static std::string format(std::string const &user_message, DWORD error_code = GetLastError())\n    {\n        std::string system_message;\n\n        local_alloc_t format_message_result{};\n        auto format_message_succeeded =\n            ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,\n                error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result.hlocal_, 0, nullptr);\n\n        if (format_message_succeeded && format_message_result.hlocal_)\n        {\n            system_message = fmt_lib::format(\" ({})\", (LPSTR)format_message_result.hlocal_);\n        }\n\n        return fmt_lib::format(\"{}: {}{}\", user_message, error_code, system_message);\n    }\n\n    explicit win32_error(std::string const &func_name, DWORD error = GetLastError())\n        : spdlog_ex(format(func_name, error))\n    {}\n};\n\n/** Wrapper for security identifiers (SID) on Windows */\nstruct sid_t\n{\n    std::vector<char> buffer_;\n\npublic:\n    sid_t() {}\n\n    /** creates a wrapped SID copy */\n    static sid_t duplicate_sid(PSID psid)\n    {\n        if (!::IsValidSid(psid))\n        {\n            throw_spdlog_ex(\"sid_t::sid_t(): invalid SID received\");\n        }\n\n        auto const sid_length{::GetLengthSid(psid)};\n\n        sid_t result;\n        result.buffer_.resize(sid_length);\n        if (!::CopySid(sid_length, (PSID)result.as_sid(), psid))\n        {\n            SPDLOG_THROW(win32_error(\"CopySid\"));\n        }\n\n        return result;\n    }\n\n    /** Retrieves pointer to the internal buffer contents as SID* */\n    SID *as_sid() const\n    {\n        return buffer_.empty() ? nullptr : (SID *)buffer_.data();\n    }\n\n    /** Get SID for the current user */\n    static sid_t get_current_user_sid()\n    {\n        /* create and init RAII holder for process token */\n        struct process_token_t\n        {\n            HANDLE token_handle_ = INVALID_HANDLE_VALUE;\n            explicit process_token_t(HANDLE process)\n            {\n                if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle_))\n                {\n                    SPDLOG_THROW(win32_error(\"OpenProcessToken\"));\n                }\n            }\n\n            ~process_token_t()\n            {\n                ::CloseHandle(token_handle_);\n            }\n\n        } current_process_token(::GetCurrentProcess()); // GetCurrentProcess returns pseudohandle, no leak here!\n\n        // Get the required size, this is expected to fail with ERROR_INSUFFICIENT_BUFFER and return the token size\n        DWORD tusize = 0;\n        if (::GetTokenInformation(current_process_token.token_handle_, TokenUser, NULL, 0, &tusize))\n        {\n            SPDLOG_THROW(win32_error(\"GetTokenInformation should fail\"));\n        }\n\n        // get user token\n        std::vector<unsigned char> buffer(static_cast<size_t>(tusize));\n        if (!::GetTokenInformation(current_process_token.token_handle_, TokenUser, (LPVOID)buffer.data(), tusize, &tusize))\n        {\n            SPDLOG_THROW(win32_error(\"GetTokenInformation\"));\n        }\n\n        // create a wrapper of the SID data as stored in the user token\n        return sid_t::duplicate_sid(((TOKEN_USER *)buffer.data())->User.Sid);\n    }\n};\n\nstruct eventlog\n{\n    static WORD get_event_type(details::log_msg const &msg)\n    {\n        switch (msg.level)\n        {\n        case level::trace:\n        case level::debug:\n            return EVENTLOG_SUCCESS;\n\n        case level::info:\n            return EVENTLOG_INFORMATION_TYPE;\n\n        case level::warn:\n            return EVENTLOG_WARNING_TYPE;\n\n        case level::err:\n        case level::critical:\n        case level::off:\n            return EVENTLOG_ERROR_TYPE;\n\n        default:\n            return EVENTLOG_INFORMATION_TYPE;\n        }\n    }\n\n    static WORD get_event_category(details::log_msg const &msg)\n    {\n        return (WORD)msg.level;\n    }\n};\n\n} // namespace internal\n\n/*\n * Windows Event Log sink\n */\ntemplate<typename Mutex>\nclass win_eventlog_sink : public base_sink<Mutex>\n{\nprivate:\n    HANDLE hEventLog_{NULL};\n    internal::sid_t current_user_sid_;\n    std::string source_;\n    WORD event_id_;\n\n    HANDLE event_log_handle()\n    {\n        if (!hEventLog_)\n        {\n            hEventLog_ = ::RegisterEventSourceA(nullptr, source_.c_str());\n            if (!hEventLog_ || hEventLog_ == (HANDLE)ERROR_ACCESS_DENIED)\n            {\n                SPDLOG_THROW(internal::win32_error(\"RegisterEventSource\"));\n            }\n        }\n\n        return hEventLog_;\n    }\n\nprotected:\n    void sink_it_(const details::log_msg &msg) override\n    {\n        using namespace internal;\n\n        bool succeeded;\n        memory_buf_t formatted;\n        base_sink<Mutex>::formatter_->format(msg, formatted);\n        formatted.push_back('\\0');\n\n#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT\n        wmemory_buf_t buf;\n        details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), buf);\n\n        LPCWSTR lp_wstr = buf.data();\n        succeeded = ::ReportEventW(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,\n            current_user_sid_.as_sid(), 1, 0, &lp_wstr, nullptr);\n#else\n        LPCSTR lp_str = formatted.data();\n        succeeded = ::ReportEventA(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,\n            current_user_sid_.as_sid(), 1, 0, &lp_str, nullptr);\n#endif\n\n        if (!succeeded)\n        {\n            SPDLOG_THROW(win32_error(\"ReportEvent\"));\n        }\n    }\n\n    void flush_() override {}\n\npublic:\n    win_eventlog_sink(std::string const &source, WORD event_id = 1000 /* according to mscoree.dll */)\n        : source_(source)\n        , event_id_(event_id)\n    {\n        try\n        {\n            current_user_sid_ = internal::sid_t::get_current_user_sid();\n        }\n        catch (...)\n        {\n            // get_current_user_sid() is unlikely to fail and if it does, we can still proceed without\n            // current_user_sid but in the event log the record will have no user name\n        }\n    }\n\n    ~win_eventlog_sink()\n    {\n        if (hEventLog_)\n            DeregisterEventSource(hEventLog_);\n    }\n};\n\n} // namespace win_eventlog\n\nusing win_eventlog_sink_mt = win_eventlog::win_eventlog_sink<std::mutex>;\nusing win_eventlog_sink_st = win_eventlog::win_eventlog_sink<details::null_mutex>;\n\n} // namespace sinks\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/wincolor_sink-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/sinks/wincolor_sink.h>\n#endif\n\n#include <spdlog/details/windows_include.h>\n#include <wincon.h>\n\n#include <spdlog/common.h>\n#include <spdlog/pattern_formatter.h>\n\nnamespace spdlog {\nnamespace sinks {\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE wincolor_sink<ConsoleMutex>::wincolor_sink(void *out_handle, color_mode mode)\n    : out_handle_(out_handle)\n    , mutex_(ConsoleMutex::mutex())\n    , formatter_(details::make_unique<spdlog::pattern_formatter>())\n{\n\n    set_color_mode_impl(mode);\n    // set level colors\n    colors_[level::trace] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;     // white\n    colors_[level::debug] = FOREGROUND_GREEN | FOREGROUND_BLUE;                      // cyan\n    colors_[level::info] = FOREGROUND_GREEN;                                         // green\n    colors_[level::warn] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; // intense yellow\n    colors_[level::err] = FOREGROUND_RED | FOREGROUND_INTENSITY;                     // intense red\n    colors_[level::critical] =\n        BACKGROUND_RED | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; // intense white on red background\n    colors_[level::off] = 0;\n}\n\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE wincolor_sink<ConsoleMutex>::~wincolor_sink()\n{\n    this->flush();\n}\n\n// change the color for the given level\ntemplate<typename ConsoleMutex>\nvoid SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color(level::level_enum level, std::uint16_t color)\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    colors_[level] = color;\n}\n\ntemplate<typename ConsoleMutex>\nvoid SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg)\n{\n    if (out_handle_ == nullptr || out_handle_ == INVALID_HANDLE_VALUE)\n    {\n        return;\n    }\n\n    std::lock_guard<mutex_t> lock(mutex_);\n    msg.color_range_start = 0;\n    msg.color_range_end = 0;\n    memory_buf_t formatted;\n    formatter_->format(msg, formatted);\n    if (should_do_colors_ && msg.color_range_end > msg.color_range_start)\n    {\n        // before color range\n        print_range_(formatted, 0, msg.color_range_start);\n        // in color range\n        auto orig_attribs = static_cast<WORD>(set_foreground_color_(colors_[msg.level]));\n        print_range_(formatted, msg.color_range_start, msg.color_range_end);\n        // reset to orig colors\n        ::SetConsoleTextAttribute(static_cast<HANDLE>(out_handle_), orig_attribs);\n        print_range_(formatted, msg.color_range_end, formatted.size());\n    }\n    else // print without colors if color range is invalid (or color is disabled)\n    {\n        write_to_file_(formatted);\n    }\n}\n\ntemplate<typename ConsoleMutex>\nvoid SPDLOG_INLINE wincolor_sink<ConsoleMutex>::flush()\n{\n    // windows console always flushed?\n}\n\ntemplate<typename ConsoleMutex>\nvoid SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_pattern(const std::string &pattern)\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern));\n}\n\ntemplate<typename ConsoleMutex>\nvoid SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter)\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    formatter_ = std::move(sink_formatter);\n}\n\ntemplate<typename ConsoleMutex>\nvoid SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode(color_mode mode)\n{\n    std::lock_guard<mutex_t> lock(mutex_);\n    set_color_mode_impl(mode);\n}\n\ntemplate<typename ConsoleMutex>\nvoid SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode_impl(color_mode mode)\n{\n    if (mode == color_mode::automatic)\n    {\n        // should do colors only if out_handle_  points to actual console.\n        DWORD console_mode;\n        bool in_console = ::GetConsoleMode(static_cast<HANDLE>(out_handle_), &console_mode) != 0;\n        should_do_colors_ = in_console;\n    }\n    else\n    {\n        should_do_colors_ = mode == color_mode::always ? true : false;\n    }\n}\n\n// set foreground color and return the orig console attributes (for resetting later)\ntemplate<typename ConsoleMutex>\nstd::uint16_t SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_foreground_color_(std::uint16_t attribs)\n{\n    CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info;\n    if (!::GetConsoleScreenBufferInfo(static_cast<HANDLE>(out_handle_), &orig_buffer_info))\n    {\n        // just return white if failed getting console info\n        return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;\n    }\n\n    // change only the foreground bits (lowest 4 bits)\n    auto new_attribs = static_cast<WORD>(attribs) | (orig_buffer_info.wAttributes & 0xfff0);\n    auto ignored = ::SetConsoleTextAttribute(static_cast<HANDLE>(out_handle_), static_cast<WORD>(new_attribs));\n    (void)(ignored);\n    return static_cast<std::uint16_t>(orig_buffer_info.wAttributes); // return orig attribs\n}\n\n// print a range of formatted message to console\ntemplate<typename ConsoleMutex>\nvoid SPDLOG_INLINE wincolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end)\n{\n    if (end > start)\n    {\n        auto size = static_cast<DWORD>(end - start);\n        auto ignored = ::WriteConsoleA(static_cast<HANDLE>(out_handle_), formatted.data() + start, size, nullptr, nullptr);\n        (void)(ignored);\n    }\n}\n\ntemplate<typename ConsoleMutex>\nvoid SPDLOG_INLINE wincolor_sink<ConsoleMutex>::write_to_file_(const memory_buf_t &formatted)\n{\n    auto size = static_cast<DWORD>(formatted.size());\n    DWORD bytes_written = 0;\n    auto ignored = ::WriteFile(static_cast<HANDLE>(out_handle_), formatted.data(), size, &bytes_written, nullptr);\n    (void)(ignored);\n}\n\n// wincolor_stdout_sink\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE wincolor_stdout_sink<ConsoleMutex>::wincolor_stdout_sink(color_mode mode)\n    : wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_OUTPUT_HANDLE), mode)\n{}\n\n// wincolor_stderr_sink\ntemplate<typename ConsoleMutex>\nSPDLOG_INLINE wincolor_stderr_sink<ConsoleMutex>::wincolor_stderr_sink(color_mode mode)\n    : wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_ERROR_HANDLE), mode)\n{}\n} // namespace sinks\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/sinks/wincolor_sink.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/common.h>\n#include <spdlog/details/console_globals.h>\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/sinks/sink.h>\n\n#include <memory>\n#include <mutex>\n#include <string>\n#include <array>\n#include <cstdint>\n\nnamespace spdlog {\nnamespace sinks {\n/*\n * Windows color console sink. Uses WriteConsoleA to write to the console with\n * colors\n */\ntemplate<typename ConsoleMutex>\nclass wincolor_sink : public sink\n{\npublic:\n    wincolor_sink(void *out_handle, color_mode mode);\n    ~wincolor_sink() override;\n\n    wincolor_sink(const wincolor_sink &other) = delete;\n    wincolor_sink &operator=(const wincolor_sink &other) = delete;\n\n    // change the color for the given level\n    void set_color(level::level_enum level, std::uint16_t color);\n    void log(const details::log_msg &msg) final override;\n    void flush() final override;\n    void set_pattern(const std::string &pattern) override final;\n    void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) override final;\n    void set_color_mode(color_mode mode);\n\nprotected:\n    using mutex_t = typename ConsoleMutex::mutex_t;\n    void *out_handle_;\n    mutex_t &mutex_;\n    bool should_do_colors_;\n    std::unique_ptr<spdlog::formatter> formatter_;\n    std::array<std::uint16_t, level::n_levels> colors_;\n\n    // set foreground color and return the orig console attributes (for resetting later)\n    std::uint16_t set_foreground_color_(std::uint16_t attribs);\n\n    // print a range of formatted message to console\n    void print_range_(const memory_buf_t &formatted, size_t start, size_t end);\n\n    // in case we are redirected to file (not in console mode)\n    void write_to_file_(const memory_buf_t &formatted);\n\n    void set_color_mode_impl(color_mode mode);\n};\n\ntemplate<typename ConsoleMutex>\nclass wincolor_stdout_sink : public wincolor_sink<ConsoleMutex>\n{\npublic:\n    explicit wincolor_stdout_sink(color_mode mode = color_mode::automatic);\n};\n\ntemplate<typename ConsoleMutex>\nclass wincolor_stderr_sink : public wincolor_sink<ConsoleMutex>\n{\npublic:\n    explicit wincolor_stderr_sink(color_mode mode = color_mode::automatic);\n};\n\nusing wincolor_stdout_sink_mt = wincolor_stdout_sink<details::console_mutex>;\nusing wincolor_stdout_sink_st = wincolor_stdout_sink<details::console_nullmutex>;\n\nusing wincolor_stderr_sink_mt = wincolor_stderr_sink<details::console_mutex>;\nusing wincolor_stderr_sink_st = wincolor_stderr_sink<details::console_nullmutex>;\n} // namespace sinks\n} // namespace spdlog\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"wincolor_sink-inl.h\"\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/spdlog-inl.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#ifndef SPDLOG_HEADER_ONLY\n#    include <spdlog/spdlog.h>\n#endif\n\n#include <spdlog/common.h>\n#include <spdlog/pattern_formatter.h>\n\nnamespace spdlog {\n\nSPDLOG_INLINE void initialize_logger(std::shared_ptr<logger> logger)\n{\n    details::registry::instance().initialize_logger(std::move(logger));\n}\n\nSPDLOG_INLINE std::shared_ptr<logger> get(const std::string &name)\n{\n    return details::registry::instance().get(name);\n}\n\nSPDLOG_INLINE void set_formatter(std::unique_ptr<spdlog::formatter> formatter)\n{\n    details::registry::instance().set_formatter(std::move(formatter));\n}\n\nSPDLOG_INLINE void set_pattern(std::string pattern, pattern_time_type time_type)\n{\n    set_formatter(std::unique_ptr<spdlog::formatter>(new pattern_formatter(std::move(pattern), time_type)));\n}\n\nSPDLOG_INLINE void enable_backtrace(size_t n_messages)\n{\n    details::registry::instance().enable_backtrace(n_messages);\n}\n\nSPDLOG_INLINE void disable_backtrace()\n{\n    details::registry::instance().disable_backtrace();\n}\n\nSPDLOG_INLINE void dump_backtrace()\n{\n    default_logger_raw()->dump_backtrace();\n}\n\nSPDLOG_INLINE level::level_enum get_level()\n{\n    return default_logger_raw()->level();\n}\n\nSPDLOG_INLINE bool should_log(level::level_enum log_level)\n{\n    return default_logger_raw()->should_log(log_level);\n}\n\nSPDLOG_INLINE void set_level(level::level_enum log_level)\n{\n    details::registry::instance().set_level(log_level);\n}\n\nSPDLOG_INLINE void flush_on(level::level_enum log_level)\n{\n    details::registry::instance().flush_on(log_level);\n}\n\nSPDLOG_INLINE void flush_every(std::chrono::seconds interval)\n{\n    details::registry::instance().flush_every(interval);\n}\n\nSPDLOG_INLINE void set_error_handler(void (*handler)(const std::string &msg))\n{\n    details::registry::instance().set_error_handler(handler);\n}\n\nSPDLOG_INLINE void register_logger(std::shared_ptr<logger> logger)\n{\n    details::registry::instance().register_logger(std::move(logger));\n}\n\nSPDLOG_INLINE void apply_all(const std::function<void(std::shared_ptr<logger>)> &fun)\n{\n    details::registry::instance().apply_all(fun);\n}\n\nSPDLOG_INLINE void drop(const std::string &name)\n{\n    details::registry::instance().drop(name);\n}\n\nSPDLOG_INLINE void drop_all()\n{\n    details::registry::instance().drop_all();\n}\n\nSPDLOG_INLINE void shutdown()\n{\n    details::registry::instance().shutdown();\n}\n\nSPDLOG_INLINE void set_automatic_registration(bool automatic_registration)\n{\n    details::registry::instance().set_automatic_registration(automatic_registration);\n}\n\nSPDLOG_INLINE std::shared_ptr<spdlog::logger> default_logger()\n{\n    return details::registry::instance().default_logger();\n}\n\nSPDLOG_INLINE spdlog::logger *default_logger_raw()\n{\n    return details::registry::instance().get_default_raw();\n}\n\nSPDLOG_INLINE void set_default_logger(std::shared_ptr<spdlog::logger> default_logger)\n{\n    details::registry::instance().set_default_logger(std::move(default_logger));\n}\n\n} // namespace spdlog\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/spdlog.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n// spdlog main header file.\n// see example.cpp for usage example\n\n#ifndef SPDLOG_H\n#define SPDLOG_H\n\n#pragma once\n\n#include <spdlog/common.h>\n#include <spdlog/details/registry.h>\n#include <spdlog/logger.h>\n#include <spdlog/version.h>\n#include <spdlog/details/synchronous_factory.h>\n\n#include <chrono>\n#include <functional>\n#include <memory>\n#include <string>\n\nnamespace spdlog {\n\nusing default_factory = synchronous_factory;\n\n// Create and register a logger with a templated sink type\n// The logger's level, formatter and flush level will be set according the\n// global settings.\n//\n// Example:\n//   spdlog::create<daily_file_sink_st>(\"logger_name\", \"dailylog_filename\", 11, 59);\ntemplate<typename Sink, typename... SinkArgs>\ninline std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&... sink_args)\n{\n    return default_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);\n}\n\n// Initialize and register a logger,\n// formatter and flush level will be set according the global settings.\n//\n// Useful for initializing manually created loggers with the global settings.\n//\n// Example:\n//   auto mylogger = std::make_shared<spdlog::logger>(\"mylogger\", ...);\n//   spdlog::initialize_logger(mylogger);\nSPDLOG_API void initialize_logger(std::shared_ptr<logger> logger);\n\n// Return an existing logger or nullptr if a logger with such name doesn't\n// exist.\n// example: spdlog::get(\"my_logger\")->info(\"hello {}\", \"world\");\nSPDLOG_API std::shared_ptr<logger> get(const std::string &name);\n\n// Set global formatter. Each sink in each logger will get a clone of this object\nSPDLOG_API void set_formatter(std::unique_ptr<spdlog::formatter> formatter);\n\n// Set global format string.\n// example: spdlog::set_pattern(\"%Y-%m-%d %H:%M:%S.%e %l : %v\");\nSPDLOG_API void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local);\n\n// enable global backtrace support\nSPDLOG_API void enable_backtrace(size_t n_messages);\n\n// disable global backtrace support\nSPDLOG_API void disable_backtrace();\n\n// call dump backtrace on default logger\nSPDLOG_API void dump_backtrace();\n\n// Get global logging level\nSPDLOG_API level::level_enum get_level();\n\n// Set global logging level\nSPDLOG_API void set_level(level::level_enum log_level);\n\n// Determine whether the default logger should log messages with a certain level\nSPDLOG_API bool should_log(level::level_enum lvl);\n\n// Set global flush level\nSPDLOG_API void flush_on(level::level_enum log_level);\n\n// Start/Restart a periodic flusher thread\n// Warning: Use only if all your loggers are thread safe!\nSPDLOG_API void flush_every(std::chrono::seconds interval);\n\n// Set global error handler\nSPDLOG_API void set_error_handler(void (*handler)(const std::string &msg));\n\n// Register the given logger with the given name\nSPDLOG_API void register_logger(std::shared_ptr<logger> logger);\n\n// Apply a user defined function on all registered loggers\n// Example:\n// spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) {l->flush();});\nSPDLOG_API void apply_all(const std::function<void(std::shared_ptr<logger>)> &fun);\n\n// Drop the reference to the given logger\nSPDLOG_API void drop(const std::string &name);\n\n// Drop all references from the registry\nSPDLOG_API void drop_all();\n\n// stop any running threads started by spdlog and clean registry loggers\nSPDLOG_API void shutdown();\n\n// Automatic registration of loggers when using spdlog::create() or spdlog::create_async\nSPDLOG_API void set_automatic_registration(bool automatic_registration);\n\n// API for using default logger (stdout_color_mt),\n// e.g: spdlog::info(\"Message {}\", 1);\n//\n// The default logger object can be accessed using the spdlog::default_logger():\n// For example, to add another sink to it:\n// spdlog::default_logger()->sinks().push_back(some_sink);\n//\n// The default logger can replaced using spdlog::set_default_logger(new_logger).\n// For example, to replace it with a file logger.\n//\n// IMPORTANT:\n// The default API is thread safe (for _mt loggers), but:\n// set_default_logger() *should not* be used concurrently with the default API.\n// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another.\n\nSPDLOG_API std::shared_ptr<spdlog::logger> default_logger();\n\nSPDLOG_API spdlog::logger *default_logger_raw();\n\nSPDLOG_API void set_default_logger(std::shared_ptr<spdlog::logger> default_logger);\n\ntemplate<typename... Args>\ninline void log(source_loc source, level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->log(source, lvl, fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void log(level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void trace(format_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->trace(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void debug(format_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->debug(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void info(format_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->info(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void warn(format_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->warn(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void error(format_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->error(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void critical(format_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->critical(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename T>\ninline void log(source_loc source, level::level_enum lvl, const T &msg)\n{\n    default_logger_raw()->log(source, lvl, msg);\n}\n\ntemplate<typename T>\ninline void log(level::level_enum lvl, const T &msg)\n{\n    default_logger_raw()->log(lvl, msg);\n}\n\n#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT\ntemplate<typename... Args>\ninline void log(source_loc source, level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->log(source, lvl, fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void log(level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void trace(wformat_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->trace(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void debug(wformat_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->debug(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void info(wformat_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->info(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void warn(wformat_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->warn(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void error(wformat_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->error(fmt, std::forward<Args>(args)...);\n}\n\ntemplate<typename... Args>\ninline void critical(wformat_string_t<Args...> fmt, Args &&... args)\n{\n    default_logger_raw()->critical(fmt, std::forward<Args>(args)...);\n}\n#endif\n\ntemplate<typename T>\ninline void trace(const T &msg)\n{\n    default_logger_raw()->trace(msg);\n}\n\ntemplate<typename T>\ninline void debug(const T &msg)\n{\n    default_logger_raw()->debug(msg);\n}\n\ntemplate<typename T>\ninline void info(const T &msg)\n{\n    default_logger_raw()->info(msg);\n}\n\ntemplate<typename T>\ninline void warn(const T &msg)\n{\n    default_logger_raw()->warn(msg);\n}\n\ntemplate<typename T>\ninline void error(const T &msg)\n{\n    default_logger_raw()->error(msg);\n}\n\ntemplate<typename T>\ninline void critical(const T &msg)\n{\n    default_logger_raw()->critical(msg);\n}\n\n} // namespace spdlog\n\n//\n// enable/disable log calls at compile time according to global level.\n//\n// define SPDLOG_ACTIVE_LEVEL to one of those (before including spdlog.h):\n// SPDLOG_LEVEL_TRACE,\n// SPDLOG_LEVEL_DEBUG,\n// SPDLOG_LEVEL_INFO,\n// SPDLOG_LEVEL_WARN,\n// SPDLOG_LEVEL_ERROR,\n// SPDLOG_LEVEL_CRITICAL,\n// SPDLOG_LEVEL_OFF\n//\n\n#define SPDLOG_LOGGER_CALL(logger, level, ...) (logger)->log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__)\n\n#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE\n#    define SPDLOG_LOGGER_TRACE(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::trace, __VA_ARGS__)\n#    define SPDLOG_TRACE(...) SPDLOG_LOGGER_TRACE(spdlog::default_logger_raw(), __VA_ARGS__)\n#else\n#    define SPDLOG_LOGGER_TRACE(logger, ...) (void)0\n#    define SPDLOG_TRACE(...) (void)0\n#endif\n\n#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG\n#    define SPDLOG_LOGGER_DEBUG(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::debug, __VA_ARGS__)\n#    define SPDLOG_DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__)\n#else\n#    define SPDLOG_LOGGER_DEBUG(logger, ...) (void)0\n#    define SPDLOG_DEBUG(...) (void)0\n#endif\n\n#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_INFO\n#    define SPDLOG_LOGGER_INFO(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::info, __VA_ARGS__)\n#    define SPDLOG_INFO(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__)\n#else\n#    define SPDLOG_LOGGER_INFO(logger, ...) (void)0\n#    define SPDLOG_INFO(...) (void)0\n#endif\n\n#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_WARN\n#    define SPDLOG_LOGGER_WARN(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::warn, __VA_ARGS__)\n#    define SPDLOG_WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__)\n#else\n#    define SPDLOG_LOGGER_WARN(logger, ...) (void)0\n#    define SPDLOG_WARN(...) (void)0\n#endif\n\n#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_ERROR\n#    define SPDLOG_LOGGER_ERROR(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::err, __VA_ARGS__)\n#    define SPDLOG_ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__)\n#else\n#    define SPDLOG_LOGGER_ERROR(logger, ...) (void)0\n#    define SPDLOG_ERROR(...) (void)0\n#endif\n\n#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_CRITICAL\n#    define SPDLOG_LOGGER_CRITICAL(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::critical, __VA_ARGS__)\n#    define SPDLOG_CRITICAL(...) SPDLOG_LOGGER_CRITICAL(spdlog::default_logger_raw(), __VA_ARGS__)\n#else\n#    define SPDLOG_LOGGER_CRITICAL(logger, ...) (void)0\n#    define SPDLOG_CRITICAL(...) (void)0\n#endif\n\n#ifdef SPDLOG_HEADER_ONLY\n#    include \"spdlog-inl.h\"\n#endif\n\n#endif // SPDLOG_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/stopwatch.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#include <spdlog/fmt/fmt.h>\n\n// Stopwatch support for spdlog  (using std::chrono::steady_clock).\n// Displays elapsed seconds since construction as double.\n//\n// Usage:\n//\n// spdlog::stopwatch sw;\n// ...\n// spdlog::debug(\"Elapsed: {} seconds\", sw);    =>  \"Elapsed 0.005116733 seconds\"\n// spdlog::info(\"Elapsed: {:.6} seconds\", sw);  =>  \"Elapsed 0.005163 seconds\"\n//\n//\n// If other units are needed (e.g. millis instead of double), include \"fmt/chrono.h\" and use \"duration_cast<..>(sw.elapsed())\":\n//\n// #include <spdlog/fmt/chrono.h>\n//..\n// using std::chrono::duration_cast;\n// using std::chrono::milliseconds;\n// spdlog::info(\"Elapsed {}\", duration_cast<milliseconds>(sw.elapsed())); => \"Elapsed 5ms\"\n\nnamespace spdlog {\nclass stopwatch\n{\n    using clock = std::chrono::steady_clock;\n    std::chrono::time_point<clock> start_tp_;\n\npublic:\n    stopwatch()\n        : start_tp_{clock::now()}\n    {}\n\n    std::chrono::duration<double> elapsed() const\n    {\n        return std::chrono::duration<double>(clock::now() - start_tp_);\n    }\n\n    void reset()\n    {\n        start_tp_ = clock::now();\n    }\n};\n} // namespace spdlog\n\n// Support for fmt formatting  (e.g. \"{:012.9}\" or just \"{}\")\nnamespace\n#ifdef SPDLOG_USE_STD_FORMAT\n    std\n#else\n    fmt\n#endif\n{\n\ntemplate<>\nstruct formatter<spdlog::stopwatch> : formatter<double>\n{\n    template<typename FormatContext>\n    auto format(const spdlog::stopwatch &sw, FormatContext &ctx) -> decltype(ctx.out())\n    {\n        return formatter<double>::format(sw.elapsed().count(), ctx);\n    }\n};\n} // namespace std\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/tweakme.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n///////////////////////////////////////////////////////////////////////////////\n//\n// Edit this file to squeeze more performance, and to customize supported\n// features\n//\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used.\n// This clock is less accurate - can be off by dozens of millis - depending on\n// the kernel HZ.\n// Uncomment to use it instead of the regular clock.\n//\n// #define SPDLOG_CLOCK_COARSE\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment if thread id logging is not needed (i.e. no %t in the log pattern).\n// This will prevent spdlog from querying the thread id on each log call.\n//\n// WARNING: If the log pattern contains thread id (i.e, %t) while this flag is\n// on, zero will be logged as thread id.\n//\n// #define SPDLOG_NO_THREAD_ID\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to prevent spdlog from using thread local storage.\n//\n// WARNING: if your program forks, UNCOMMENT this flag to prevent undefined\n// thread ids in the children logs.\n//\n// #define SPDLOG_NO_TLS\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to avoid spdlog's usage of atomic log levels\n// Use only if your code never modifies a logger's log levels concurrently by\n// different threads.\n//\n// #define SPDLOG_NO_ATOMIC_LEVELS\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to enable usage of wchar_t for file names on Windows.\n//\n// #define SPDLOG_WCHAR_FILENAMES\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to override default eol (\"\\n\" or \"\\r\\n\" under Linux/Windows)\n//\n// #define SPDLOG_EOL \";-)\\n\"\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to override default folder separators (\"/\" or \"\\\\/\" under\n// Linux/Windows). Each character in the string is treated as a different\n// separator.\n//\n// #define SPDLOG_FOLDER_SEPS \"\\\\\"\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to use your own copy of the fmt library instead of spdlog's copy.\n// In this case spdlog will try to include <fmt/format.h> so set your -I flag\n// accordingly.\n//\n// #define SPDLOG_FMT_EXTERNAL\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to use C++20 std::format instead of fmt. This removes compile\n// time checking of format strings, but doesn't depend on the fmt library.\n//\n// #define SPDLOG_USE_STD_FORMAT\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to enable wchar_t support (convert to utf8)\n//\n// #define SPDLOG_WCHAR_TO_UTF8_SUPPORT\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to prevent child processes from inheriting log file descriptors\n//\n// #define SPDLOG_PREVENT_CHILD_FD\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to customize level names (e.g. \"MY TRACE\")\n//\n// #define SPDLOG_LEVEL_NAMES { \"MY TRACE\", \"MY DEBUG\", \"MY INFO\", \"MY WARNING\", \"MY ERROR\", \"MY CRITICAL\", \"OFF\" }\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to customize short level names (e.g. \"MT\")\n// These can be longer than one character.\n//\n// #define SPDLOG_SHORT_LEVEL_NAMES { \"T\", \"D\", \"I\", \"W\", \"E\", \"C\", \"O\" }\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment to disable default logger creation.\n// This might save some (very) small initialization time if no default logger is needed.\n//\n// #define SPDLOG_DISABLE_DEFAULT_LOGGER\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment and set to compile time level with zero cost (default is INFO).\n// Macros like SPDLOG_DEBUG(..), SPDLOG_INFO(..)  will expand to empty statements if not enabled\n//\n// #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Uncomment (and change if desired) macro to use for function names.\n// This is compiler dependent.\n// __PRETTY_FUNCTION__ might be nicer in clang/gcc, and __FUNCTION__ in msvc.\n// Defaults to __FUNCTION__ (should work on all compilers) if not defined.\n//\n// #ifdef __PRETTY_FUNCTION__\n// # define SPDLOG_FUNCTION __PRETTY_FUNCTION__\n// #else\n// # define SPDLOG_FUNCTION __FUNCTION__\n// #endif\n///////////////////////////////////////////////////////////////////////////////\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/include/spdlog/version.h",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#pragma once\n\n#define SPDLOG_VER_MAJOR 1\n#define SPDLOG_VER_MINOR 10\n#define SPDLOG_VER_PATCH 0\n\n#define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH)\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/scripts/extract_version.py",
    "content": "#!/usr/bin/env python3\n\nimport os\nimport re\n\nbase_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))\nconfig_h = os.path.join(base_path, 'include', 'spdlog', 'version.h')\ndata = {'MAJOR': 0, 'MINOR': 0, 'PATCH': 0}\nreg = re.compile(r'^\\s*#define\\s+SPDLOG_VER_([A-Z]+)\\s+([0-9]+).*$')\n\nwith open(config_h, 'r') as fp:\n    for l in fp:\n        m = reg.match(l)\n        if m:\n            data[m.group(1)] = int(m.group(2))\n\nprint(f\"{data['MAJOR']}.{data['MINOR']}.{data['PATCH']}\")\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/scripts/format.sh",
    "content": "#!/bin/bash\n\ncd \"$(dirname \"$0\")\"/..\npwd\necho -n \"Running dos2unix     \"\nfind . -name \"*\\.h\" -o -name \"*\\.cpp\"|grep -v bundled|xargs -I {} sh -c \"dos2unix '{}' 2>/dev/null; echo -n '.'\"\necho\necho -n \"Running clang-format \"\nfind . -name \"*\\.h\" -o -name \"*\\.cpp\"|grep -v bundled|xargs -I {} sh -c \"clang-format -i {}; echo -n '.'\"\necho\necho -n \"Running cmake-format \"\nfind . -name \"CMakeLists.txt\" -o -name \"*\\.cmake\"|grep -v bundled|xargs -I {} sh -c \"cmake-format --line-width 120 --tab-size 4 --max-subgroups-hwrap 4 -i {}; echo -n '.'\"\necho\n\n\n\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/src/async.cpp",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#ifndef SPDLOG_COMPILED_LIB\n#    error Please define SPDLOG_COMPILED_LIB to compile this file.\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4251)\n#endif\n\n#include <spdlog/async.h>\n#include <spdlog/async_logger-inl.h>\n#include <spdlog/details/periodic_worker-inl.h>\n#include <spdlog/details/thread_pool-inl.h>\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/src/cfg.cpp",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#ifndef SPDLOG_COMPILED_LIB\n#    error Please define SPDLOG_COMPILED_LIB to compile this file.\n#endif\n\n#include <spdlog/cfg/helpers-inl.h>\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/src/color_sinks.cpp",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#ifndef SPDLOG_COMPILED_LIB\n#    error Please define SPDLOG_COMPILED_LIB to compile this file.\n#endif\n\n#include <mutex>\n\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/async.h>\n//\n// color sinks\n//\n#ifdef _WIN32\n#    include <spdlog/sinks/wincolor_sink-inl.h>\ntemplate class SPDLOG_API spdlog::sinks::wincolor_sink<spdlog::details::console_mutex>;\ntemplate class SPDLOG_API spdlog::sinks::wincolor_sink<spdlog::details::console_nullmutex>;\ntemplate class SPDLOG_API spdlog::sinks::wincolor_stdout_sink<spdlog::details::console_mutex>;\ntemplate class SPDLOG_API spdlog::sinks::wincolor_stdout_sink<spdlog::details::console_nullmutex>;\ntemplate class SPDLOG_API spdlog::sinks::wincolor_stderr_sink<spdlog::details::console_mutex>;\ntemplate class SPDLOG_API spdlog::sinks::wincolor_stderr_sink<spdlog::details::console_nullmutex>;\n#else\n#    include \"spdlog/sinks/ansicolor_sink-inl.h\"\ntemplate class SPDLOG_API spdlog::sinks::ansicolor_sink<spdlog::details::console_mutex>;\ntemplate class SPDLOG_API spdlog::sinks::ansicolor_sink<spdlog::details::console_nullmutex>;\ntemplate class SPDLOG_API spdlog::sinks::ansicolor_stdout_sink<spdlog::details::console_mutex>;\ntemplate class SPDLOG_API spdlog::sinks::ansicolor_stdout_sink<spdlog::details::console_nullmutex>;\ntemplate class SPDLOG_API spdlog::sinks::ansicolor_stderr_sink<spdlog::details::console_mutex>;\ntemplate class SPDLOG_API spdlog::sinks::ansicolor_stderr_sink<spdlog::details::console_nullmutex>;\n#endif\n\n// factory methods for color loggers\n#include \"spdlog/sinks/stdout_color_sinks-inl.h\"\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt<spdlog::synchronous_factory>(\n    const std::string &logger_name, color_mode mode);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_color_st<spdlog::synchronous_factory>(\n    const std::string &logger_name, color_mode mode);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt<spdlog::synchronous_factory>(\n    const std::string &logger_name, color_mode mode);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_color_st<spdlog::synchronous_factory>(\n    const std::string &logger_name, color_mode mode);\n\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt<spdlog::async_factory>(\n    const std::string &logger_name, color_mode mode);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_color_st<spdlog::async_factory>(\n    const std::string &logger_name, color_mode mode);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt<spdlog::async_factory>(\n    const std::string &logger_name, color_mode mode);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_color_st<spdlog::async_factory>(\n    const std::string &logger_name, color_mode mode);\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/src/file_sinks.cpp",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#ifndef SPDLOG_COMPILED_LIB\n#    error Please define SPDLOG_COMPILED_LIB to compile this file.\n#endif\n\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/details/file_helper-inl.h>\n#include <spdlog/sinks/basic_file_sink-inl.h>\n#include <spdlog/sinks/base_sink-inl.h>\n\n#include <mutex>\n\ntemplate class SPDLOG_API spdlog::sinks::basic_file_sink<std::mutex>;\ntemplate class SPDLOG_API spdlog::sinks::basic_file_sink<spdlog::details::null_mutex>;\n\n#include <spdlog/sinks/rotating_file_sink-inl.h>\ntemplate class SPDLOG_API spdlog::sinks::rotating_file_sink<std::mutex>;\ntemplate class SPDLOG_API spdlog::sinks::rotating_file_sink<spdlog::details::null_mutex>;\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/src/fmt.cpp",
    "content": "// Slightly modified version of fmt lib's format.cc source file.\n// Copyright (c) 2012 - 2016, Victor Zverovich\n// All rights reserved.\n\n#ifndef SPDLOG_COMPILED_LIB\n#    error Please define SPDLOG_COMPILED_LIB to compile this file.\n#endif\n\n#if !defined(SPDLOG_FMT_EXTERNAL) && !defined(SPDLOG_USE_STD_FORMAT)\n#    include <spdlog/fmt/bundled/format-inl.h>\n\nFMT_BEGIN_NAMESPACE\nnamespace detail {\n\n// DEPRECATED!\ntemplate<typename T = void>\nstruct basic_data\n{\n    FMT_API static constexpr const char digits[100][2] = {{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},\n        {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'},\n        {'1', '7'}, {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'},\n        {'2', '8'}, {'2', '9'}, {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'},\n        {'3', '9'}, {'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},\n        {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'}, {'6', '0'},\n        {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},\n        {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'},\n        {'8', '3'}, {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'}, {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'},\n        {'9', '4'}, {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};\n    FMT_API static constexpr const char hex_digits[] = \"0123456789abcdef\";\n    FMT_API static constexpr const char signs[4] = {0, '-', '+', ' '};\n    FMT_API static constexpr const char left_padding_shifts[5] = {31, 31, 0, 1, 0};\n    FMT_API static constexpr const char right_padding_shifts[5] = {0, 31, 0, 1, 0};\n    FMT_API static constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+', 0x1000000u | ' '};\n};\n\n#    ifdef FMT_SHARED\n// Required for -flto, -fivisibility=hidden and -shared to work\nextern template struct basic_data<void>;\n#    endif\n\n#    if __cplusplus < 201703L\n// DEPRECATED! These are here only for ABI compatiblity.\ntemplate<typename T>\nconstexpr const char basic_data<T>::digits[][2];\ntemplate<typename T>\nconstexpr const char basic_data<T>::hex_digits[];\ntemplate<typename T>\nconstexpr const char basic_data<T>::signs[];\ntemplate<typename T>\nconstexpr const char basic_data<T>::left_padding_shifts[];\ntemplate<typename T>\nconstexpr const char basic_data<T>::right_padding_shifts[];\ntemplate<typename T>\nconstexpr const unsigned basic_data<T>::prefixes[];\n#    endif\n\ntemplate<typename T>\nint format_float(char *buf, std::size_t size, const char *format, int precision, T value)\n{\n#    ifdef FMT_FUZZ\n    if (precision > 100000)\n        throw std::runtime_error(\"fuzz mode - avoid large allocation inside snprintf\");\n#    endif\n    // Suppress the warning about nonliteral format string.\n    int (*snprintf_ptr)(char *, size_t, const char *, ...) = FMT_SNPRINTF;\n    return precision < 0 ? snprintf_ptr(buf, size, format, value) : snprintf_ptr(buf, size, format, precision, value);\n}\n\ntemplate FMT_API dragonbox::decimal_fp<float> dragonbox::to_decimal(float x) FMT_NOEXCEPT;\ntemplate FMT_API dragonbox::decimal_fp<double> dragonbox::to_decimal(double x) FMT_NOEXCEPT;\n} // namespace detail\n\n// Workaround a bug in MSVC2013 that prevents instantiation of format_float.\nint (*instantiate_format_float)(double, int, detail::float_specs, detail::buffer<char> &) = detail::format_float;\n\n#    ifndef FMT_STATIC_THOUSANDS_SEPARATOR\ntemplate FMT_API detail::locale_ref::locale_ref(const std::locale &loc);\ntemplate FMT_API std::locale detail::locale_ref::get<std::locale>() const;\n#    endif\n\n// Explicit instantiations for char.\n\ntemplate FMT_API auto detail::thousands_sep_impl(locale_ref) -> thousands_sep_result<char>;\ntemplate FMT_API char detail::decimal_point_impl(locale_ref);\n\ntemplate FMT_API void detail::buffer<char>::append(const char *, const char *);\n\n// DEPRECATED!\n// There is no correspondent extern template in format.h because of\n// incompatibility between clang and gcc (#2377).\ntemplate FMT_API void detail::vformat_to(\n    detail::buffer<char> &, string_view, basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);\n\ntemplate FMT_API int detail::snprintf_float(double, int, detail::float_specs, detail::buffer<char> &);\ntemplate FMT_API int detail::snprintf_float(long double, int, detail::float_specs, detail::buffer<char> &);\ntemplate FMT_API int detail::format_float(double, int, detail::float_specs, detail::buffer<char> &);\ntemplate FMT_API int detail::format_float(long double, int, detail::float_specs, detail::buffer<char> &);\n\n// Explicit instantiations for wchar_t.\n\ntemplate FMT_API auto detail::thousands_sep_impl(locale_ref) -> thousands_sep_result<wchar_t>;\ntemplate FMT_API wchar_t detail::decimal_point_impl(locale_ref);\n\ntemplate FMT_API void detail::buffer<wchar_t>::append(const wchar_t *, const wchar_t *);\n\ntemplate struct detail::basic_data<void>;\n\nFMT_END_NAMESPACE\n\n#endif // !SPDLOG_FMT_EXTERNAL\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/src/spdlog.cpp",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#ifndef SPDLOG_COMPILED_LIB\n#    error Please define SPDLOG_COMPILED_LIB to compile this file.\n#endif\n\n#include <spdlog/spdlog-inl.h>\n#include <spdlog/common-inl.h>\n#include <spdlog/details/backtracer-inl.h>\n#include <spdlog/details/registry-inl.h>\n#include <spdlog/details/os-inl.h>\n#include <spdlog/pattern_formatter-inl.h>\n#include <spdlog/details/log_msg-inl.h>\n#include <spdlog/details/log_msg_buffer-inl.h>\n#include <spdlog/logger-inl.h>\n#include <spdlog/sinks/sink-inl.h>\n#include <spdlog/sinks/base_sink-inl.h>\n#include <spdlog/details/null_mutex.h>\n\n#include <mutex>\n\n// template instantiate logger constructor with sinks init list\ntemplate SPDLOG_API spdlog::logger::logger(std::string name, sinks_init_list::iterator begin, sinks_init_list::iterator end);\ntemplate class SPDLOG_API spdlog::sinks::base_sink<std::mutex>;\ntemplate class SPDLOG_API spdlog::sinks::base_sink<spdlog::details::null_mutex>;\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/spdlog/src/stdout_sinks.cpp",
    "content": "// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.\n// Distributed under the MIT License (http://opensource.org/licenses/MIT)\n\n#ifndef SPDLOG_COMPILED_LIB\n#    error Please define SPDLOG_COMPILED_LIB to compile this file.\n#endif\n\n#include <mutex>\n\n#include <spdlog/details/null_mutex.h>\n#include <spdlog/async.h>\n#include <spdlog/sinks/stdout_sinks-inl.h>\n\ntemplate class SPDLOG_API spdlog::sinks::stdout_sink_base<spdlog::details::console_mutex>;\ntemplate class SPDLOG_API spdlog::sinks::stdout_sink_base<spdlog::details::console_nullmutex>;\ntemplate class SPDLOG_API spdlog::sinks::stdout_sink<spdlog::details::console_mutex>;\ntemplate class SPDLOG_API spdlog::sinks::stdout_sink<spdlog::details::console_nullmutex>;\ntemplate class SPDLOG_API spdlog::sinks::stderr_sink<spdlog::details::console_mutex>;\ntemplate class SPDLOG_API spdlog::sinks::stderr_sink<spdlog::details::console_nullmutex>;\n\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt<spdlog::synchronous_factory>(const std::string &logger_name);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st<spdlog::synchronous_factory>(const std::string &logger_name);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt<spdlog::synchronous_factory>(const std::string &logger_name);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st<spdlog::synchronous_factory>(const std::string &logger_name);\n\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt<spdlog::async_factory>(const std::string &logger_name);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st<spdlog::async_factory>(const std::string &logger_name);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt<spdlog::async_factory>(const std::string &logger_name);\ntemplate SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st<spdlog::async_factory>(const std::string &logger_name);\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/string-view-lite/LICENSE.txt",
    "content": "Boost Software License - Version 1.0 - August 17th, 2003\n\nPermission is hereby granted, free of charge, to any person or organization\nobtaining a copy of the software and accompanying documentation covered by\nthis license (the \"Software\") to use, reproduce, display, distribute,\nexecute, and transmit the Software, and to prepare derivative works of the\nSoftware, and to permit third-parties to whom the Software is furnished to\ndo so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including\nthe above license grant, this restriction and the following disclaimer,\nmust be included in all copies of the Software, in whole or in part, and\nall derivative works of the Software, unless such copies or derivative\nworks are solely in the form of machine-executable object code generated by\na source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\nSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\nFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/string-view-lite/README.md",
    "content": "# string_view lite: A single-file header-only version of a C++17-like string_view for C++98, C++11 and later\n\n[![Language](https://img.shields.io/badge/C%2B%2B-98/11/14/17-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-BSL-blue.svg)](https://opensource.org/licenses/BSL-1.0) [![Build Status](https://travis-ci.org/martinmoene/string-view-lite.svg?branch=master)](https://travis-ci.org/martinmoene/string-view-lite) [![Build status](https://ci.appveyor.com/api/projects/status/1ha3wnxtam547m8p?svg=true)](https://ci.appveyor.com/project/martinmoene/string-view-lite) [![Version](https://badge.fury.io/gh/martinmoene%2Fstring-view-lite.svg)](https://github.com/martinmoene/string-view-lite/releases) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://github.com/martinmoene/string-view-lite/blob/master/include/nonstd/string_view.hpp) [![Conan](https://img.shields.io/badge/on-conan-blue.svg)](https://bintray.com/agauniyal/nonstd-lite/) [![Try it on wandbox](https://img.shields.io/badge/on-wandbox-blue.svg)](https://wandbox.org/permlink/w2vUu56NVdVNyOiv) [![Try it on godbolt online](https://img.shields.io/badge/on-godbolt-blue.svg)](http://bit.ly/mm-string-view-lite-godbolt)\n\n**Contents**  \n- [Example usage](#example-usage)\n- [In a nutshell](#in-a-nutshell)\n- [License](#license)\n- [Dependencies](#dependencies)\n- [Installation](#installation)\n- [Synopsis](#synopsis)\n- [Reported to work with](#reported-to-work-with)\n- [Building the tests](#building-the-tests)\n- [Other implementations of string_view](#other-implementations-of-string_view)\n- [Notes and references](#notes-and-references)\n- [Appendix](#appendix)\n\n\nExample usage\n-------------\n\n```C++\n#include \"nonstd/string_view.hpp\"\n#include <iostream>\n\nusing namespace std::literals;\nusing namespace nonstd::literals;\nusing namespace nonstd;\n    \nvoid write( string_view sv )\n{\n    std::cout << sv;\n}\n\nint main()\n{\n    write( \"hello\"     );   // C-string\n    write( \", \"s       );   // std::string\n    write( \"world!\"_sv );   // nonstd::string_view\n}\n```\n\n### Compile and run\n```\nprompt> g++ -Wall -std=c++14 -I../include/ -o 01-basic.exe 01-basic.cpp && 01-basic.exe\nhello, world!\n```\n\nIn a nutshell\n---------------\n**string-view lite** is a single-file header-only library to provide a non-owning reference to a string. The library provides a [C++17-like string_view](http://en.cppreference.com/w/cpp/string/basic_string_view) for use with C++98 and later. If available, `std::string_view` is used, unless [configured otherwise](#configuration).\n\n**Features and properties of string-view lite** are ease of installation (single header), freedom of dependencies other than the standard library. To mimic C++17-like cooperation with `std::string`, `nonstd::string_view` provides several non-standard conversion functions. These functions may be [omitted via configuration](#configuration).\n\n\nLicense\n-------\n*string-view lite* is distributed under the [Boost Software License](LICENSE.txt).\n \n\nDependencies\n------------\n*string-view lite* has no other dependencies than the [C++ standard library](http://en.cppreference.com/w/cpp/header).\n\n\nInstallation\n------------\n\n*string-view lite* is a single-file header-only library. Put `string_view.hpp` in the [include](include) folder directly into the project source tree or somewhere reachable from your project.\n\nOr, if you use the [conan package manager](https://www.conan.io/), follow these steps:\n\n1. Add *nonstd-lite* to the conan remotes:\n\n        conan remote add nonstd-lite https://api.bintray.com/conan/martinmoene/nonstd-lite\n\n2. Add a reference to *string-view-lite* to the *requires* section of your project's `conanfile.txt` file:\n\n        [requires]\n        string-view-lite/[~=1]@nonstd-lite/testing\n\n3. Run conan's install command:\n\n        conan install\n\n\nSynopsis\n--------\n\n**Contents**  \n[Documentation of `std::string_view`](#stdstring_view)  \n[C++20 extensions](#c20-extensions)  \n[Non-standard extensions](#non-standard-extensions)  \n[Configuration](#configuration)    \n\nDocumentation of `std::string_view`\n-----------------------------------\nDepending on the compiler and C++-standard used, `nonstd::string_view` behaves less or more like `std::string_view`. To get an idea of the capabilities of `nonstd::string_view` with your configuration, look at the output of the [tests](test/string_view.t.cpp), issuing `string-view-lite.t --pass @`. For `std::string_view`, see its [documentation at cppreference](http://en.cppreference.com/w/cpp/string/basic_string_view).  \n\nC++20 extensions\n----------------\n*string_view-lite* provides the following C++20 *extensions*.\n\n- *[[nodiscard]]* constexpr bool **empty**() const noexcept;\n- constexpr bool ***starts_with***( basic_string_view v ) const noexcept;  // (1)\n- constexpr bool ***starts_with***( CharT c ) const noexcept;  // (2)\n- constexpr bool ***starts_with***( CharT const * s ) const;  // (3)\n- constexpr bool ***ends_with***( basic_string_view v ) const noexcept;  // (1)\n- constexpr bool ***ends_with***( CharT c ) const noexcept;  // (2)\n- constexpr bool ***ends_with***( CharT const * s ) const;  // (3)\n\nNote: [[nodiscard]], constexpr and noexcept if available.\n     \nNon-standard extensions\n-----------------------\n### `string_view` literals `sv` and `_sv`\nclang compilers do not allow to write `auto sv = \"...\"sv` with *string-view lite* under C++11. To still provide a literal operator that can be used in that case, *string-view lite* also provides `_sv`. See section [Configuration](#configuration) for how to control the presence of these operators.\n\nThe literal operators are declared in the namespace `nonstd::literals::string_view_literals`, where both `literals` and `string_view_literals` are inline namespaces, if supported. Access to these operators can be gained with using namespace `nonstd::literals`, using namespace `nonstd::string_view_literals`, and using namespace `nonstd::literals::string_view_literals`. If inline namespaces are not supported by the compiler, only the latter form is available.\n\n### Cooperation between `std::string` and `nonstd::string_view`\n*string-view lite* can provide several methods and free functions to mimic the cooperation between `std::string` and  `nonstd::string_view` that exists in C++17. See the table below. Several macros allow you to control the presence of these functions, see section [Configuration](#configuration).\n\n| Kind                  | Std   | Function or method |                                       \n|-----------------------|-------|--------------------|\n| **Free functions**    |&nbsp; | macro `nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS`|\n| **`std::string_view`**|&nbsp; | &nbsp; |\n| to_string()           |>=C++17| template&lt; class CharT, class Traits, class Allocator=std::allocator&lt;CharT> ><br>std::basic_string&lt;CharT, Traits, Allocator&gt;<br>**to_string**( std::basic_string_view&lt;CharT, Traits> v, Allocator const & a=Allocator() );|\n| to_string_view()      |>=C++17| template&lt; class CharT, class Traits, class Allocator ><br>std::basic_string_view&lt;CharT, Traits><br>**to_string_view**( std::basic_string&lt;CharT, Traits, Allocator> const & s );|\n| **`nonstd::string_view`**|&nbsp; | &nbsp;  |\n| to_string()<br>&nbsp;<br>*non-msvc14 (vs2015)* |>=C++11| template&lt; class CharT, class Traits, class Allocator = std::allocator&lt;CharT> ><br>std::basic_string&lt;CharT, Traits, Allocator><br>**to_string**( basic_string_view&lt;CharT, Traits> v, Allocator const & a = Allocator() );|\n| to_string()<br>&nbsp;<br>*msvc14 (vs2015)* |<C++11|template&lt; class CharT, class Traits ><br>std::basic_string&lt;CharT, Traits><br>**to_string**( basic_string_view&lt;CharT, Traits> v );|\n| to_string()<br>&nbsp;<br>*msvc14 (vs2015)* |<C++11|template&lt; class CharT, class Traits, class Allocator ><br>std::basic_string&lt;CharT, Traits, Allocator><br>**to_string**( basic_string_view&lt;CharT, Traits> v, Allocator const & a );|\n| to_string_view()      |>=C++98| template&lt; class CharT, class Traits, class Allocator ><br>basic_string_view&lt;CharT, Traits><br>**to_string_view**( std::basic_string&lt;CharT, Traits, Allocator> const & s );|\n| &nbsp;                |&nbsp; | &nbsp; |\n| **Class methods**     |&nbsp; | macro `nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS` |\n| **`nonstd::basic_string_view`**|&nbsp; |&nbsp; |\n| Constructor           |>=C++98| template&lt; class Allocator ><br>**basic_string_view**( std::basic_string&lt;CharT, Traits, Allocator> const & s ) nssv_noexcept;|\n| Converting operator   |>=C++11| template&lt; class Allocator ><br>explicit **operator std::basic_string**&lt;CharT, Traits, Allocator>() const;|\n| to_string()           |>=C++11| template&lt; class Allocator = std::allocator&lt;CharT> ><br>std::basic_string&lt;CharT, Traits, Allocator><br>**to_string**( Allocator const & a = Allocator() ) const;|\n| to_string()           |<C++11 | std::basic_string&lt;CharT, Traits><br>**to_string**() const;|\n| to_string()           |<C++11 | template&lt; class Allocator ><br>std::basic_string&lt;CharT, Traits, Allocator><br>**to_string**( Allocator const & a ) const;|\n| &nbsp;                |&nbsp; | &nbsp; |\n| **Literal operator `sv`**|>=C++11| macro `nssv_CONFIG_STD_SV_OPERATOR` |\n| &nbsp;                |&nbsp; | constexpr string_view operator \"\" **sv**( const char* str, size_t len ) noexcept; |\n| &nbsp;                |&nbsp; | constexpr u16string_view operator \"\" **sv**( const char16_t* str, size_t len ) noexcept; |\n| &nbsp;                |&nbsp; | constexpr u32string_view operator \"\" **sv**( const char32_t* str, size_t len ) noexcept; |\n| &nbsp;                |&nbsp; | constexpr wstring_view operator \"\" **sv**( const wchar_t* str, size_t len ) noexcept; |\n| &nbsp;                |&nbsp; | &nbsp; |\n| **Literal operator `_sv`**|>=C++11| macro `nssv_CONFIG_USR_SV_OPERATOR` |\n| &nbsp;                |&nbsp; | constexpr string_view operator \"\" **_sv**( const char* str, size_t len ) noexcept; |\n| &nbsp;                |&nbsp; | constexpr u16string_view operator \"\" **_sv**( const char16_t* str, size_t len ) noexcept; |\n| &nbsp;                |&nbsp; | constexpr u32string_view operator \"\" **_sv**( const char32_t* str, size_t len ) noexcept; |\n| &nbsp;                |&nbsp; | constexpr wstring_view operator \"\" **_sv**( const wchar_t* str, size_t len ) noexcept; |\n\n\nConfiguration\n-------------\n\n### Standard selection macro\n\n\\-D<b>nssv\\_CPLUSPLUS</b>=199711L  \nDefine this macro to override the auto-detection of the supported C++ standard, if your compiler does not set the `__cpluplus` macro correctly.\n\n### Select `std::string_view` or `nonstd::string_view`\nAt default, *string-view lite* uses `std::string_view` if it is available and lets you use it via namespace `nonstd`. You can however override this default and explicitly request to use `std::string_view` as `nonstd::string_view` or use string-view lite's `nonstd::string_view` via the following macros.\n\n-D<b>nssv\\_CONFIG\\_SELECT\\_STRING_VIEW</b>=nssv_STRING_VIEW_DEFAULT  \nDefine this to `nssv_STRING_VIEW_STD` to select `std::string_view` as `nonstd::string_view`. Define this to `nssv_STRING_VIEW_NONSTD` to select `nonstd::string_view` as `nonstd::string_view`. Default is undefined, which has the same effect as defining to `nssv_STRING_VIEW_DEFAULT`.\n\nNote: <b>nssv_CONFIG_SELECT_STD_STRING_VIEW</b> and <b>nssv_CONFIG_SELECT_NONSTD_STRING_VIEW</b> are deprecated and have been removed.\n\n### Disable exceptions\n-D<b>nssv\\_CONFIG\\_NO\\_EXCEPTIONS</b>=0\nDefine this to 1 if you want to compile without exceptions. If not defined, the header tries and detect if exceptions have been disabled (e.g. via `-fno-exceptions`). Default is undefined.\n\n### Add or omit literal operators `sv` and `_sv`\n\n-D<b>nssv_CONFIG_STD_SV_OPERATOR</b>=1  \nDefine this to 1 to provide literal operator `sv` to create a `string_view` from a literal string. Default is 0. Note that literal operators without leading underscore are reserved for the C++ standard.\n\n-D<b>nssv_CONFIG_USR_SV_OPERATOR</b>=0  \nDefine this to 0 to omit literal operator `_sv` to create a `string_view` from a literal string. Default is 1.\n\n### Omit cooperation between `std::string`&ndash;`nonstd::string_view`\nAt default, *string-view lite* provides several methods and free functions to mimic the cooperation between `std::string` and  `nonstd::string_view` (or `std::string_view`) that exists in C++17. See section [Non-standard extensions](#non-standard-extensions). The following macros allow you to control the presence of these functions.\n \n-D<b>nssv_CONFIG_CONVERSION_STD_STRING</b>=1  \nDefine this to 1 to provide `std::string`&ndash; `nonstd::string_view` interoperability via methods of `nonstd::basic_string_view` and free functions, define it to 0 to omit all said methods and functions. Default is undefined.\n\n-D<b>nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS</b>=1  \nDefine this to 1 to provide `std::string`&ndash; `nonstd::string_view` interoperability via methods of `nonstd::basic_string_view`, define it to 0 to omit all said methods. Default is undefined.\n\n-D<b>nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS</b>=1  \nDefine this to 1 to provide `std::string`&ndash; `nonstd::string_view` interoperability via free functions, define it to 0 to omit all said functions. This also controls the presence of these function if `std::string_view` is used. Default is undefined.\n\n\nReported to work with\n---------------------\nThe table below mentions the compiler versions *string-view lite* is reported to work with.\n\nOS        | Compiler   | Versions |\n---------:|:-----------|:---------|\nWindows   | Clang/LLVM | ?        |\n&nbsp;    | GCC        | 7.2.0    |\n&nbsp;    | Visual C++<br>(Visual Studio)| 8 (2005), 9 (2008), 10 (2010), 11 (2012),<br>12 (2013), 14 (2015), 15 (2017) |\nGNU/Linux | Clang/LLVM | 3.5 - 6.0  |\n&nbsp;    | GCC        | 4.8 - 8 |\nOS X      | Clang/LLVM | Xcode 6, Xcode 7, Xcode 8, Xcode 9 |\n\n\nBuilding the tests\n------------------\nTo build the tests you need:\n\n- [CMake](http://cmake.org), version 3.0 or later to be installed and in your PATH.\n- A [suitable compiler](#reported-to-work-with).\n\nThe [*lest* test framework](https://github.com/martinmoene/lest) is included in the [test folder](test).\n\nThe following steps assume that the [*string-view lite* source code](https://github.com/martinmoene/string-view-lite) has been cloned into a directory named `c:\\string-view-lite`.\n\n1. Create a directory for the build outputs for a particular architecture.\nHere we use c:\\string-view-lite\\build-win-x86-vc10.\n\n        cd c:\\string-view-lite\n        md build-win-x86-vc10\n        cd build-win-x86-vc10\n\n2. Configure CMake to use the compiler of your choice (run `cmake --help` for a list).\n\n        cmake -G \"Visual Studio 10 2010\" -DSTRINGVIEW_LITE_OPT_BUILD_TESTS=ON ..\n\n3. Build the test suite in the Debug configuration (alternatively use Release).    \n\n        cmake --build . --config Debug\n\n4. Run the test suite.    \n\n        ctest -V -C Debug\n\nAll tests should pass, indicating your platform is supported and you are ready to use *string-view lite*.\n\n\nOther implementations of string_view\n------------------------------------\n- Marshall Clow. [string_view implementation for libc++](https://github.com/mclow/string_view). GitHub.\n- LLVM libc++. [string_view](https://llvm.org/svn/llvm-project/libcxx/trunk/include/string_view). GitHub.\n- Matthew Rodusek's, @bitwizeshift. [string_view Standalone](https://github.com/bitwizeshift/string_view-standalone). GitHub.\n- @satoren. [string_view for C++03 C++11 C++14](https://github.com/satoren/string_view). GitHub.\n- Google Abseil [string_view](https://github.com/abseil/abseil-cpp/tree/master/absl/strings) (non-templated).\n- [Search _string view c++_ on GitHub](https://github.com/search?l=C%2B%2B&q=string+view+c%2B%2B&type=Repositories&utf8=%E2%9C%93).\n\n\nNotes and references\n--------------------\n*Interface and specification*\n- [string_view on cppreference](http://en.cppreference.com/w/cpp/string/basic_string_view).\n- [n4659 - C++17 Working Draft: string_view](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf#page=780).\n\n*Presentations*\n- Marshall Clow. [string_view - when to use it, and when not](https://cppcon2015.sched.com/event/3vch/stringview-when-to-use-it-and-when-not?iframe=yes&w=700&sidebar=yes&bg=no#). CppCon 2015. [video](https://youtu.be/H9gAaNRoon4), [slides](https://github.com/CppCon/CppCon2015/blob/master/Presentations/string_view/string_view%20-%20Marshall%20Clow%20-%20CppCon%202015.pdf).\n- Neil MacIntosh. [A few good types: Evolving array_view and string_view for safe C++ code](https://cppcon2015.sched.com/event/3vbQ/a-few-good-types-evolving-arrayview-and-stringview-for-safe-c-code). CppCon 2015. [video](https://youtu.be/C4Z3c4Sv52U), [slides](https://github.com/CppCon/CppCon2015/blob/master/Presentations/A%20Few%20Good%20Types/A%20Few%20Good%20Types%20-%20Neil%20MacIntosh%20-%20CppCon%202015.pdf).\n\n*Proposals*\n- Jeffrey Yasskin. [n3334 - Proposing array_ref<T> and string_ref](https://wg21.link/n3334). 2012.\n- Jeffrey Yasskin. [n3921 - string_view: a non-owning reference to a string, revision 7](http://wg21.link/n3921). **Adopted 2014-02**.\n- Alisdair Meredith. [n4288 - Strike string_view::clear from Library Fundamentals](http://wg21.link/n4288). **Adopted 2014-11**.\n- Neil MacIntosh. [p0123 - Unifying the interfaces of string_view and array_view](http://wg21.link/p0123). 2015.\n- Beman Dawes, Alisdair Meredith. [p0220 - Adopt Library Fundamentals V1 TS Components for C++17 (R1)](https://wg21.link/p0220r1). 2016.\n- Marshall Clow. [p0254 - Integrating std::string_view and std::string](http://wg21.link/p0254). **Adopted 2016-06**.\n- Nicolai Josuttis. [p0392 - Adapting string_view by filesystem paths](https://wg21.link/p0392r0). 2016.\n- Marshall Clow. [p0403 - Literal suffixes for basic_string_view](http://wg21.link/p0403). 2016.\n- Peter Sommerlad. [p0506 - use string_view for library function parameters instead of const string &/const char *](http://wg21.link/p0506). 2017.\n- Daniel Krugler. [wg2946 - LWG 2758's resolution missed further corrections](https://wg21.link/lwg2946). 2017.\n\n\nAppendix\n--------\n\n### A.1 Compile-time information\n\nThe version of *string-view lite* is available via tag `[.version]`. The following tags are available for information on the compiler and on the C++ standard library used: `[.compiler]`, `[.stdc++]`, `[.stdlanguage]` and `[.stdlibrary]`.\n\n### A.2 string-view lite test specification\n\n```\nstring_view: Allows to default construct an empty string_view\nstring_view: Allows to construct from pointer and size\nstring_view: Allows to construct from C-string\nstring_view: Allows to copy-construct from empty string_view\nstring_view: Allows to copy-construct from non-empty string_view\nstring_view: Allows to copy-assign from empty string_view\nstring_view: Allows to copy-assign from non-empty string_view\nstring_view: Allows forward iteration\nstring_view: Allows const forward iteration\nstring_view: Allows reverse iteration\nstring_view: Allows const reverse iteration\nstring_view: Allows to obtain the size of the view via size()\nstring_view: Allows to obtain the size of the view via length()\nstring_view: Allows to obtain the maximum size a view can be via max_size()\nstring_view: Allows to check for an empty string_view via empty()\nstring_view: Allows to observe an element via array indexing\nstring_view: Allows to observe an element via at()\nstring_view: Throws at observing an element via at() with an index of size() or larger\nstring_view: Allows to observe elements via data()\nstring_view: Yields nullptr (or NULL) with data() for an empty string_view\nstring_view: Allows to remove a prefix of n elements\nstring_view: Allows to remove a suffix of n elements\nstring_view: Allows to swap with other string_view\nstring_view: Allows to copy a substring of length n, starting at position pos (default: 0) via copy()\nstring_view: Throws if requested position of copy() exceeds string_view's size()\nstring_view: Allow to obtain a sub string, starting at position pos (default: 0) and of length n (default full), via substr()\nstring_view: Throws if requested position of substr() exceeds string_view's size()\nstring_view: Allows to lexically compare to another string_view via compare(), (1)\nstring_view: Allows to compare empty string_views as equal via compare(), (1)\nstring_view: Allows to compare a sub string to another string_view via compare(), (2)\nstring_view: Allows to compare a sub string to another string_view sub string via compare(), (3)\nstring_view: Allows to compare to a C-string via compare(), (4)\nstring_view: Allows to compare a sub string to a C-string via compare(), (5)\nstring_view: Allows to compare a sub string to a C-string prefix via compare(), (6)\nstring_view: Allows to check for a prefix string_view via starts_with(), (1)\nstring_view: Allows to check for a prefix character via starts_with(), (2)\nstring_view: Allows to check for a prefix C-string via starts_with(), (3)\nstring_view: Allows to check for a suffix string_view via ends_with(), (1)\nstring_view: Allows to check for a suffix character via ends_with(), (2)\nstring_view: Allows to check for a suffix C-string via ends_with(), (3)\nstring_view: Allows to search for a string_view substring, starting at position pos (default: 0) via find(), (1)\nstring_view: Allows to search for a character, starting at position pos (default: 0) via find(), (2)\nstring_view: Allows to search for a C-string substring, starting at position pos and of length n via find(), (3)\nstring_view: Allows to search for a C-string substring, starting at position pos (default: 0) via find(), (4)\nstring_view: Allows to search backwards for a string_view substring, starting at position pos (default: npos) via rfind(), (1)\nstring_view: Allows to search backwards for a character, starting at position pos (default: npos) via rfind(), (2)\nstring_view: Allows to search backwards for a C-string substring, starting at position pos and of length n via rfind(), (3)\nstring_view: Allows to search backwards for a C-string substring, starting at position pos (default: 0) via rfind(), (4)\nstring_view: Allows to search for the first occurrence of any of the characters specified in a string view, starting at position pos (default: 0) via find_first_of(), (1)\nstring_view: Allows to search for a character, starting at position pos (default: 0) via find_first_of(), (2)\nstring_view: Allows to search for the first occurrence of any of the characters specified in a C-string, starting at position pos and of length n via find_first_of(), (3)\nstring_view: Allows to search for the first occurrence of any of the characters specified in a C-string, starting at position pos via find_first_of(), (4)\nstring_view: Allows to search backwards for the last occurrence of any of the characters specified in a string view, starting at position pos (default: npos) via find_last_of(), (1)\nstring_view: Allows to search backwards for a character, starting at position pos (default: 0) via find_last_of(), (2)\nstring_view: Allows to search backwards for the first occurrence of any of the characters specified in a C-string, starting at position pos and of length n via find_last_of(), (3)\nstring_view: Allows to search backwards for the first occurrence of any of the characters specified in a C-string, starting at position pos via find_last_of(), (4)\nstring_view: Allows to search for the first character not specified in a string view, starting at position pos (default: 0) via find_first_not_of(), (1)\nstring_view: Allows to search for the first character not equal to the specified character, starting at position pos (default: 0) via find_first_not_of(), (2)\nstring_view: Allows to search for  the first character not equal to any of the characters specified in a C-string, starting at position pos and of length n via find_first_not_of(), (3)\nstring_view: Allows to search for  the first character not equal to any of the characters specified in a C-string, starting at position pos via find_first_not_of(), (4)\nstring_view: Allows to search backwards for the first character not specified in a string view, starting at position pos (default: npos) via find_last_not_of(), (1)\nstring_view: Allows to search backwards for the first character not equal to the specified character, starting at position pos (default: npos) via find_last_not_of(), (2)\nstring_view: Allows to search backwards for  the first character not equal to any of the characters specified in a C-string, starting at position pos and of length n via find_last_not_of(), (3)\nstring_view: Allows to search backwards for  the first character not equal to any of the characters specified in a C-string, starting at position pos via find_last_not_of(), (4)\nstring_view: Allows to create a string_view, wstring_view, u16string_view, u32string_view via literal \"sv\"\nstring_view: Allows to create a string_view via literal \"sv\", using namespace nonstd::literals::string_view_literals\nstring_view: Allows to create a string_view via literal \"sv\", using namespace nonstd::string_view_literals\nstring_view: Allows to create a string_view via literal \"sv\", using namespace nonstd::literals\nstring_view: Allows to create a string_view, wstring_view, u16string_view, u32string_view via literal \"_sv\"\nstring_view: Allows to create a string_view via literal \"_sv\", using namespace nonstd::literals::string_view_literals\nstring_view: Allows to create a string_view via literal \"_sv\", using namespace nonstd::string_view_literals\nstring_view: Allows to create a string_view via literal \"_sv\", using namespace nonstd::literals\nstring_view: Allows to compare a string_view with another string_view\nstring_view: Allows to compare empty string_view-s as equal\noperator<<: Allows printing a string_view to an output stream\nstd::hash<>: Hash value of string_view equals hash value of corresponding string object\nstd::hash<>: Hash value of wstring_view equals hash value of corresponding string object\nstd::hash<>: Hash value of u16string_view equals hash value of corresponding string object\nstd::hash<>: Hash value of u32string_view equals hash value of corresponding string object\nstring_view: construct from std::string [extension]\nstring_view: convert to std::string via explicit operator [extension]\nstring_view: convert to std::string via to_string() [extension]\nto_string(): convert to std::string via to_string() [extension]\nto_string_view(): convert from std::string via to_string_view() [extension]\n```\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/string-view-lite/cmake/string_view-lite-config.cmake.in",
    "content": "@PACKAGE_INIT@\n\n# Only include targets once:\n\nif( NOT TARGET @package_name@::@package_name@ )\n    include( \"${CMAKE_CURRENT_LIST_DIR}/@package_target@.cmake\" )\nendif()\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/string-view-lite/include/nonstd/string_view.hpp",
    "content": "// Copyright 2017-2019 by Martin Moene\n//\n// string-view lite, a C++17-like string_view for C++98 and later.\n// For more information see https://github.com/martinmoene/string-view-lite\n//\n// Distributed under the Boost Software License, Version 1.0.\n// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n\n#pragma once\n\n#ifndef NONSTD_SV_LITE_H_INCLUDED\n#define NONSTD_SV_LITE_H_INCLUDED\n\n#define string_view_lite_MAJOR  1\n#define string_view_lite_MINOR  1\n#define string_view_lite_PATCH  0\n\n#define string_view_lite_VERSION  nssv_STRINGIFY(string_view_lite_MAJOR) \".\" nssv_STRINGIFY(string_view_lite_MINOR) \".\" nssv_STRINGIFY(string_view_lite_PATCH)\n\n#define nssv_STRINGIFY(  x )  nssv_STRINGIFY_( x )\n#define nssv_STRINGIFY_( x )  #x\n\n// string-view lite configuration:\n\n#define nssv_STRING_VIEW_DEFAULT  0\n#define nssv_STRING_VIEW_NONSTD   1\n#define nssv_STRING_VIEW_STD      2\n\n#if !defined( nssv_CONFIG_SELECT_STRING_VIEW )\n# define nssv_CONFIG_SELECT_STRING_VIEW  ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD )\n#endif\n\n#if defined( nssv_CONFIG_SELECT_STD_STRING_VIEW ) || defined( nssv_CONFIG_SELECT_NONSTD_STRING_VIEW )\n# error nssv_CONFIG_SELECT_STD_STRING_VIEW and nssv_CONFIG_SELECT_NONSTD_STRING_VIEW are deprecated and removed, please use nssv_CONFIG_SELECT_STRING_VIEW=nssv_STRING_VIEW_...\n#endif\n\n#ifndef  nssv_CONFIG_STD_SV_OPERATOR\n# define nssv_CONFIG_STD_SV_OPERATOR  0\n#endif\n\n#ifndef  nssv_CONFIG_USR_SV_OPERATOR\n# define nssv_CONFIG_USR_SV_OPERATOR  1\n#endif\n\n#ifdef   nssv_CONFIG_CONVERSION_STD_STRING\n# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS   nssv_CONFIG_CONVERSION_STD_STRING\n# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS  nssv_CONFIG_CONVERSION_STD_STRING\n#endif\n\n#ifndef  nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS\n# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS  1\n#endif\n\n#ifndef  nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS\n# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS  1\n#endif\n\n// Control presence of exception handling (try and auto discover):\n\n#ifndef nssv_CONFIG_NO_EXCEPTIONS\n# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)\n#  define nssv_CONFIG_NO_EXCEPTIONS  0\n# else\n#  define nssv_CONFIG_NO_EXCEPTIONS  1\n# endif\n#endif\n\n// C++ language version detection (C++20 is speculative):\n// Note: VC14.0/1900 (VS2015) lacks too much from C++14.\n\n#ifndef   nssv_CPLUSPLUS\n# if defined(_MSVC_LANG ) && !defined(__clang__)\n#  define nssv_CPLUSPLUS  (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )\n# else\n#  define nssv_CPLUSPLUS  __cplusplus\n# endif\n#endif\n\n#define nssv_CPP98_OR_GREATER  ( nssv_CPLUSPLUS >= 199711L )\n#define nssv_CPP11_OR_GREATER  ( nssv_CPLUSPLUS >= 201103L )\n#define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L )\n#define nssv_CPP14_OR_GREATER  ( nssv_CPLUSPLUS >= 201402L )\n#define nssv_CPP17_OR_GREATER  ( nssv_CPLUSPLUS >= 201703L )\n#define nssv_CPP20_OR_GREATER  ( nssv_CPLUSPLUS >= 202000L )\n\n// use C++17 std::string_view if available and requested:\n\n#if nssv_CPP17_OR_GREATER && defined(__has_include )\n# if __has_include( <string_view> )\n#  define nssv_HAVE_STD_STRING_VIEW  1\n# else\n#  define nssv_HAVE_STD_STRING_VIEW  0\n# endif\n#else\n# define  nssv_HAVE_STD_STRING_VIEW  0\n#endif\n\n#define  nssv_USES_STD_STRING_VIEW  ( (nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW) )\n\n#define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW )\n#define nssv_HAVE_ENDS_WITH     nssv_HAVE_STARTS_WITH\n\n//\n// Use C++17 std::string_view:\n//\n\n#if nssv_USES_STD_STRING_VIEW\n\n#include <string_view>\n\n// Extensions for std::string:\n\n#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS\n\nnamespace nonstd {\n\ntemplate< class CharT, class Traits, class Allocator = std::allocator<CharT> >\nstd::basic_string<CharT, Traits, Allocator>\nto_string( std::basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )\n{\n    return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );\n}\n\ntemplate< class CharT, class Traits, class Allocator >\nstd::basic_string_view<CharT, Traits>\nto_string_view( std::basic_string<CharT, Traits, Allocator> const & s )\n{\n    return std::basic_string_view<CharT, Traits>( s.data(), s.size() );\n}\n\n// Literal operators sv and _sv:\n\n#if nssv_CONFIG_STD_SV_OPERATOR\n\nusing namespace std::literals::string_view_literals;\n\n#endif\n\n#if nssv_CONFIG_USR_SV_OPERATOR\n\ninline namespace literals {\ninline namespace string_view_literals {\n\n\nconstexpr std::string_view operator\"\"_sv( const char* str, size_t len ) noexcept  // (1)\n{\n    return std::string_view{ str, len };\n}\n\nconstexpr std::u16string_view operator\"\"_sv( const char16_t* str, size_t len ) noexcept  // (2)\n{\n    return std::u16string_view{ str, len };\n}\n\nconstexpr std::u32string_view operator\"\"_sv( const char32_t* str, size_t len ) noexcept  // (3)\n{\n    return std::u32string_view{ str, len };\n}\n\nconstexpr std::wstring_view operator\"\"_sv( const wchar_t* str, size_t len ) noexcept  // (4)\n{\n    return std::wstring_view{ str, len };\n}\n\n}} // namespace literals::string_view_literals\n\n#endif // nssv_CONFIG_USR_SV_OPERATOR\n\n} // namespace nonstd\n\n#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS\n\nnamespace nonstd {\n\nusing std::string_view;\nusing std::wstring_view;\nusing std::u16string_view;\nusing std::u32string_view;\nusing std::basic_string_view;\n\n// literal \"sv\" and \"_sv\", see above\n\nusing std::operator==;\nusing std::operator!=;\nusing std::operator<;\nusing std::operator<=;\nusing std::operator>;\nusing std::operator>=;\n\nusing std::operator<<;\n\n} // namespace nonstd\n\n#else // nssv_HAVE_STD_STRING_VIEW\n\n//\n// Before C++17: use string_view lite:\n//\n\n// Compiler versions:\n//\n// MSVC++ 6.0  _MSC_VER == 1200 (Visual Studio 6.0)\n// MSVC++ 7.0  _MSC_VER == 1300 (Visual Studio .NET 2002)\n// MSVC++ 7.1  _MSC_VER == 1310 (Visual Studio .NET 2003)\n// MSVC++ 8.0  _MSC_VER == 1400 (Visual Studio 2005)\n// MSVC++ 9.0  _MSC_VER == 1500 (Visual Studio 2008)\n// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)\n// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)\n// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)\n// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)\n// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)\n\n#if defined(_MSC_VER ) && !defined(__clang__)\n# define nssv_COMPILER_MSVC_VER      (_MSC_VER )\n# define nssv_COMPILER_MSVC_VERSION  (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )\n#else\n# define nssv_COMPILER_MSVC_VER      0\n# define nssv_COMPILER_MSVC_VERSION  0\n#endif\n\n#define nssv_COMPILER_VERSION( major, minor, patch )  (10 * ( 10 * major + minor) + patch)\n\n#if defined(__clang__)\n# define nssv_COMPILER_CLANG_VERSION  nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)\n#else\n# define nssv_COMPILER_CLANG_VERSION    0\n#endif\n\n#if defined(__GNUC__) && !defined(__clang__)\n# define nssv_COMPILER_GNUC_VERSION  nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)\n#else\n# define nssv_COMPILER_GNUC_VERSION    0\n#endif\n\n// half-open range [lo..hi):\n#define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )\n\n// Presence of language and library features:\n\n#ifdef _HAS_CPP0X\n# define nssv_HAS_CPP0X  _HAS_CPP0X\n#else\n# define nssv_HAS_CPP0X  0\n#endif\n\n// Unless defined otherwise below, consider VC14 as C++11 for variant-lite:\n\n#if nssv_COMPILER_MSVC_VER >= 1900\n# undef  nssv_CPP11_OR_GREATER\n# define nssv_CPP11_OR_GREATER  1\n#endif\n\n#define nssv_CPP11_90   (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)\n#define nssv_CPP11_100  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)\n#define nssv_CPP11_110  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)\n#define nssv_CPP11_120  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)\n#define nssv_CPP11_140  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)\n#define nssv_CPP11_141  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)\n\n#define nssv_CPP14_000  (nssv_CPP14_OR_GREATER)\n#define nssv_CPP17_000  (nssv_CPP17_OR_GREATER)\n\n// Presence of C++11 language features:\n\n#define nssv_HAVE_CONSTEXPR_11          nssv_CPP11_140\n#define nssv_HAVE_EXPLICIT_CONVERSION   nssv_CPP11_140\n#define nssv_HAVE_INLINE_NAMESPACE      nssv_CPP11_140\n#define nssv_HAVE_NOEXCEPT              nssv_CPP11_140\n#define nssv_HAVE_NULLPTR               nssv_CPP11_100\n#define nssv_HAVE_REF_QUALIFIER         nssv_CPP11_140\n#define nssv_HAVE_UNICODE_LITERALS      nssv_CPP11_140\n#define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140\n#define nssv_HAVE_WCHAR16_T             nssv_CPP11_100\n#define nssv_HAVE_WCHAR32_T             nssv_CPP11_100\n\n#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )\n# define nssv_HAVE_STD_DEFINED_LITERALS  nssv_CPP11_140\n#endif\n\n// Presence of C++14 language features:\n\n#define nssv_HAVE_CONSTEXPR_14          nssv_CPP14_000\n\n// Presence of C++17 language features:\n\n#define nssv_HAVE_NODISCARD             nssv_CPP17_000\n\n// Presence of C++ library features:\n\n#define nssv_HAVE_STD_HASH              nssv_CPP11_120\n\n// C++ feature usage:\n\n#if nssv_HAVE_CONSTEXPR_11\n# define nssv_constexpr  constexpr\n#else\n# define nssv_constexpr  /*constexpr*/\n#endif\n\n#if  nssv_HAVE_CONSTEXPR_14\n# define nssv_constexpr14  constexpr\n#else\n# define nssv_constexpr14  /*constexpr*/\n#endif\n\n#if nssv_HAVE_EXPLICIT_CONVERSION\n# define nssv_explicit  explicit\n#else\n# define nssv_explicit  /*explicit*/\n#endif\n\n#if nssv_HAVE_INLINE_NAMESPACE\n# define nssv_inline_ns  inline\n#else\n# define nssv_inline_ns  /*inline*/\n#endif\n\n#if nssv_HAVE_NOEXCEPT\n# define nssv_noexcept  noexcept\n#else\n# define nssv_noexcept  /*noexcept*/\n#endif\n\n//#if nssv_HAVE_REF_QUALIFIER\n//# define nssv_ref_qual  &\n//# define nssv_refref_qual  &&\n//#else\n//# define nssv_ref_qual  /*&*/\n//# define nssv_refref_qual  /*&&*/\n//#endif\n\n#if nssv_HAVE_NULLPTR\n# define nssv_nullptr  nullptr\n#else\n# define nssv_nullptr  NULL\n#endif\n\n#if nssv_HAVE_NODISCARD\n# define nssv_nodiscard  [[nodiscard]]\n#else\n# define nssv_nodiscard  /*[[nodiscard]]*/\n#endif\n\n// Additional includes:\n\n#include <algorithm>\n#include <cassert>\n#include <iterator>\n#include <limits>\n#include <ostream>\n#include <string>   // std::char_traits<>\n\n#if ! nssv_CONFIG_NO_EXCEPTIONS\n# include <stdexcept>\n#endif\n\n#if nssv_CPP11_OR_GREATER\n# include <type_traits>\n#endif\n\n// Clang, GNUC, MSVC warning suppression macros:\n\n#if defined(__clang__)\n# pragma clang diagnostic ignored \"-Wreserved-user-defined-literal\"\n# pragma clang diagnostic push\n# pragma clang diagnostic ignored \"-Wuser-defined-literals\"\n#elif defined(__GNUC__)\n# pragma  GCC  diagnostic push\n# pragma  GCC  diagnostic ignored \"-Wliteral-suffix\"\n#endif // __clang__\n\n#if nssv_COMPILER_MSVC_VERSION >= 140\n# define nssv_SUPPRESS_MSGSL_WARNING(expr)        [[gsl::suppress(expr)]]\n# define nssv_SUPPRESS_MSVC_WARNING(code, descr)  __pragma(warning(suppress: code) )\n# define nssv_DISABLE_MSVC_WARNINGS(codes)        __pragma(warning(push))  __pragma(warning(disable: codes))\n#else\n# define nssv_SUPPRESS_MSGSL_WARNING(expr)\n# define nssv_SUPPRESS_MSVC_WARNING(code, descr)\n# define nssv_DISABLE_MSVC_WARNINGS(codes)\n#endif\n\n#if defined(__clang__)\n# define nssv_RESTORE_WARNINGS()  _Pragma(\"clang diagnostic pop\")\n#elif defined(__GNUC__)\n# define nssv_RESTORE_WARNINGS()  _Pragma(\"GCC diagnostic pop\")\n#elif nssv_COMPILER_MSVC_VERSION >= 140\n# define nssv_RESTORE_WARNINGS()  __pragma(warning(pop ))\n#else\n# define nssv_RESTORE_WARNINGS()\n#endif\n\n// Suppress the following MSVC (GSL) warnings:\n// - C4455, non-gsl   : 'operator \"\"sv': literal suffix identifiers that do not\n//                      start with an underscore are reserved\n// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;\n//                      use brace initialization, gsl::narrow_cast or gsl::narow\n// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead\n\nnssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 )\n//nssv_DISABLE_CLANG_WARNINGS( \"-Wuser-defined-literals\" )\n//nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix )\n\nnamespace nonstd { namespace sv_lite {\n\ntemplate\n<\n    class CharT,\n    class Traits = std::char_traits<CharT>\n>\nclass basic_string_view;\n\n//\n// basic_string_view:\n//\n\ntemplate\n<\n    class CharT,\n    class Traits /* = std::char_traits<CharT> */\n>\nclass basic_string_view\n{\npublic:\n    // Member types:\n\n    typedef Traits traits_type;\n    typedef CharT  value_type;\n\n    typedef CharT       * pointer;\n    typedef CharT const * const_pointer;\n    typedef CharT       & reference;\n    typedef CharT const & const_reference;\n\n    typedef const_pointer iterator;\n    typedef const_pointer const_iterator;\n    typedef std::reverse_iterator< const_iterator > reverse_iterator;\n    typedef\tstd::reverse_iterator< const_iterator > const_reverse_iterator;\n\n    typedef std::size_t     size_type;\n    typedef std::ptrdiff_t  difference_type;\n\n    // 24.4.2.1 Construction and assignment:\n\n    nssv_constexpr basic_string_view() nssv_noexcept\n        : data_( nssv_nullptr )\n        , size_( 0 )\n    {}\n\n#if nssv_CPP11_OR_GREATER\n    nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept = default;\n#else\n    nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept\n        : data_( other.data_)\n        , size_( other.size_)\n    {}\n#endif\n\n    nssv_constexpr basic_string_view( CharT const * s, size_type count )\n        : data_( s )\n        , size_( count )\n    {}\n\n    /*nssv_constexpr basic_string_view( CharT const * s)\n        : data_( s )\n        , size_( Traits::length(s) )\n    {}*/\n\n\ttemplate<size_t N>\n\tnssv_constexpr basic_string_view(CharT const (&s)[N])\n\t\t\t: data_( s )\n\t\t\t, size_( N - 1 )\n\t{}\n\n    // Assignment:\n\n#if nssv_CPP11_OR_GREATER\n    nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept = default;\n#else\n    nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept\n    {\n        data_ = other.data_;\n        size_ = other.size_;\n        return *this;\n    }\n#endif\n\n    // 24.4.2.2 Iterator support:\n\n    nssv_constexpr const_iterator begin()  const nssv_noexcept { return data_;         }\n    nssv_constexpr const_iterator end()    const nssv_noexcept { return data_ + size_; }\n\n    nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); }\n    nssv_constexpr const_iterator cend()   const nssv_noexcept { return end();   }\n\n    nssv_constexpr const_reverse_iterator rbegin()  const nssv_noexcept { return const_reverse_iterator( end() );   }\n    nssv_constexpr const_reverse_iterator rend()    const nssv_noexcept { return const_reverse_iterator( begin() ); }\n\n    nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); }\n    nssv_constexpr const_reverse_iterator crend()   const nssv_noexcept { return rend();   }\n\n    // 24.4.2.3 Capacity:\n\n    nssv_constexpr size_type size()     const nssv_noexcept { return size_; }\n    nssv_constexpr size_type length()   const nssv_noexcept { return size_; }\n    nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); }\n\n    // since C++20\n    nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept\n    {\n        return 0 == size_;\n    }\n\n    // 24.4.2.4 Element access:\n\n    nssv_constexpr const_reference operator[]( size_type pos ) const\n    {\n        return data_at( pos );\n    }\n\n    nssv_constexpr14 const_reference at( size_type pos ) const\n    {\n#if nssv_CONFIG_NO_EXCEPTIONS\n        assert( pos < size() );\n#else\n        if ( pos >= size() )\n        {\n            throw std::out_of_range(\"nonst::string_view::at()\");\n        }\n#endif\n        return data_at( pos );\n    }\n\n    nssv_constexpr const_reference front() const { return data_at( 0 );          }\n    nssv_constexpr const_reference back()  const { return data_at( size() - 1 ); }\n\n    nssv_constexpr const_pointer   data()  const nssv_noexcept { return data_; }\n\n    // 24.4.2.5 Modifiers:\n\n    nssv_constexpr14 void remove_prefix( size_type n )\n    {\n        assert( n <= size() );\n        data_ += n;\n        size_ -= n;\n    }\n\n    nssv_constexpr14 void remove_suffix( size_type n )\n    {\n        assert( n <= size() );\n        size_ -= n;\n    }\n\n    nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept\n    {\n        using std::swap;\n        swap( data_, other.data_ );\n        swap( size_, other.size_ );\n    }\n\n    // 24.4.2.6 String operations:\n\n    size_type copy( CharT * dest, size_type n, size_type pos = 0 ) const\n    {\n#if nssv_CONFIG_NO_EXCEPTIONS\n        assert( pos <= size() );\n#else\n        if ( pos > size() )\n        {\n            throw std::out_of_range(\"nonst::string_view::copy()\");\n        }\n#endif\n        const size_type rlen = (std::min)( n, size() - pos );\n\n        (void) Traits::copy( dest, data() + pos, rlen );\n\n        return rlen;\n    }\n\n    nssv_constexpr14 basic_string_view substr( size_type pos = 0, size_type n = npos ) const\n    {\n#if nssv_CONFIG_NO_EXCEPTIONS\n        assert( pos <= size() );\n#else\n        if ( pos > size() )\n        {\n            throw std::out_of_range(\"nonst::string_view::substr()\");\n        }\n#endif\n        return basic_string_view( data() + pos, (std::min)( n, size() - pos ) );\n    }\n\n    // compare(), 6x:\n\n    nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1)\n    {\n        if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )\n            return result;\n\n        return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;\n    }\n\n    nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other ) const // (2)\n    {\n        return substr( pos1, n1 ).compare( other );\n    }\n\n    nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2 ) const // (3)\n    {\n        return substr( pos1, n1 ).compare( other.substr( pos2, n2 ) );\n    }\n\n    nssv_constexpr int compare( CharT const * s ) const // (4)\n    {\n        return compare( basic_string_view( s ) );\n    }\n\n    nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s ) const // (5)\n    {\n        return substr( pos1, n1 ).compare( basic_string_view( s ) );\n    }\n\n    nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s, size_type n2 ) const // (6)\n    {\n        return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) );\n    }\n\n    // 24.4.2.7 Searching:\n\n    // starts_with(), 3x, since C++20:\n\n    nssv_constexpr bool starts_with( basic_string_view v ) const nssv_noexcept  // (1)\n    {\n        return size() >= v.size() && compare( 0, v.size(), v ) == 0;\n    }\n\n    nssv_constexpr bool starts_with( CharT c ) const nssv_noexcept  // (2)\n    {\n        return starts_with( basic_string_view( &c, 1 ) );\n    }\n\n    nssv_constexpr bool starts_with( CharT const * s ) const  // (3)\n    {\n        return starts_with( basic_string_view( s ) );\n    }\n\n    // ends_with(), 3x, since C++20:\n\n    nssv_constexpr bool ends_with( basic_string_view v ) const nssv_noexcept  // (1)\n    {\n        return size() >= v.size() && compare( size() - v.size(), npos, v ) == 0;\n    }\n\n    nssv_constexpr bool ends_with( CharT c ) const nssv_noexcept  // (2)\n    {\n        return ends_with( basic_string_view( &c, 1 ) );\n    }\n\n    nssv_constexpr bool ends_with( CharT const * s ) const  // (3)\n    {\n        return ends_with( basic_string_view( s ) );\n    }\n\n    // find(), 4x:\n\n    nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept  // (1)\n    {\n        return assert( v.size() == 0 || v.data() != nssv_nullptr )\n            , pos >= size()\n            ? npos\n            : to_pos( std::search( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) );\n    }\n\n    nssv_constexpr14 size_type find( CharT c, size_type pos = 0 ) const nssv_noexcept  // (2)\n    {\n        return find( basic_string_view( &c, 1 ), pos );\n    }\n\n    nssv_constexpr14 size_type find( CharT const * s, size_type pos, size_type n ) const  // (3)\n    {\n        return find( basic_string_view( s, n ), pos );\n    }\n\n    nssv_constexpr14 size_type find( CharT const * s, size_type pos = 0 ) const  // (4)\n    {\n        return find( basic_string_view( s ), pos );\n    }\n\n    // rfind(), 4x:\n\n    nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept  // (1)\n    {\n        if ( size() < v.size() )\n            return npos;\n\n        if ( v.empty() )\n            return (std::min)( size(), pos );\n\n        const_iterator last   = cbegin() + (std::min)( size() - v.size(), pos ) + v.size();\n        const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq );\n\n        return result != last ? size_type( result - cbegin() ) : npos;\n    }\n\n    nssv_constexpr14 size_type rfind( CharT c, size_type pos = npos ) const nssv_noexcept  // (2)\n    {\n        return rfind( basic_string_view( &c, 1 ), pos );\n    }\n\n    nssv_constexpr14 size_type rfind( CharT const * s, size_type pos, size_type n ) const  // (3)\n    {\n        return rfind( basic_string_view( s, n ), pos );\n    }\n\n    nssv_constexpr14 size_type rfind( CharT const * s, size_type pos = npos ) const  // (4)\n    {\n        return rfind( basic_string_view( s ), pos );\n    }\n\n    // find_first_of(), 4x:\n\n    nssv_constexpr size_type find_first_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept  // (1)\n    {\n        return pos >= size()\n            ? npos\n            : to_pos( std::find_first_of( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) );\n    }\n\n    nssv_constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const nssv_noexcept  // (2)\n    {\n        return find_first_of( basic_string_view( &c, 1 ), pos );\n    }\n\n    nssv_constexpr size_type find_first_of( CharT const * s, size_type pos, size_type n ) const  // (3)\n    {\n        return find_first_of( basic_string_view( s, n ), pos );\n    }\n\n    nssv_constexpr size_type find_first_of(  CharT const * s, size_type pos = 0 ) const  // (4)\n    {\n        return find_first_of( basic_string_view( s ), pos );\n    }\n\n    // find_last_of(), 4x:\n\n    nssv_constexpr size_type find_last_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept  // (1)\n    {\n        return empty()\n            ? npos\n            : pos >= size()\n            ? find_last_of( v, size() - 1 )\n            : to_pos( std::find_first_of( const_reverse_iterator( cbegin() + pos + 1 ), crend(), v.cbegin(), v.cend(), Traits::eq ) );\n    }\n\n    nssv_constexpr size_type find_last_of( CharT c, size_type pos = npos ) const nssv_noexcept  // (2)\n    {\n        return find_last_of( basic_string_view( &c, 1 ), pos );\n    }\n\n    nssv_constexpr size_type find_last_of( CharT const * s, size_type pos, size_type count ) const  // (3)\n    {\n        return find_last_of( basic_string_view( s, count ), pos );\n    }\n\n    nssv_constexpr size_type find_last_of( CharT const * s, size_type pos = npos ) const  // (4)\n    {\n        return find_last_of( basic_string_view( s ), pos );\n    }\n\n    // find_first_not_of(), 4x:\n\n    nssv_constexpr size_type find_first_not_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept  // (1)\n    {\n        return pos >= size()\n            ? npos\n            : to_pos( std::find_if( cbegin() + pos, cend(), not_in_view( v ) ) );\n    }\n\n    nssv_constexpr size_type find_first_not_of( CharT c, size_type pos = 0 ) const nssv_noexcept  // (2)\n    {\n        return find_first_not_of( basic_string_view( &c, 1 ), pos );\n    }\n\n    nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos, size_type count ) const  // (3)\n    {\n        return find_first_not_of( basic_string_view( s, count ), pos );\n    }\n\n    nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos = 0 ) const  // (4)\n    {\n        return find_first_not_of( basic_string_view( s ), pos );\n    }\n\n    // find_last_not_of(), 4x:\n\n    nssv_constexpr size_type find_last_not_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept  // (1)\n    {\n        return empty()\n            ? npos\n            : pos >= size()\n            ? find_last_not_of( v, size() - 1 )\n            : to_pos( std::find_if( const_reverse_iterator( cbegin() + pos + 1 ), crend(), not_in_view( v ) ) );\n    }\n\n    nssv_constexpr size_type find_last_not_of( CharT c, size_type pos = npos ) const nssv_noexcept  // (2)\n    {\n        return find_last_not_of( basic_string_view( &c, 1 ), pos );\n    }\n\n    nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos, size_type count ) const  // (3)\n    {\n        return find_last_not_of( basic_string_view( s, count ), pos );\n    }\n\n    nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos = npos ) const  // (4)\n    {\n        return find_last_not_of( basic_string_view( s ), pos );\n    }\n\n    // Constants:\n\n#if nssv_CPP17_OR_GREATER\n    static nssv_constexpr size_type npos = size_type(-1);\n#elif nssv_CPP11_OR_GREATER\n    enum : size_type { npos = size_type(-1) };\n#else\n    enum { npos = size_type(-1) };\n#endif\n\nprivate:\n    struct not_in_view\n    {\n        const basic_string_view v;\n\n        nssv_constexpr not_in_view( basic_string_view v ) : v( v ) {}\n\n        nssv_constexpr bool operator()( CharT c ) const\n        {\n            return npos == v.find_first_of( c );\n        }\n    };\n\n    nssv_constexpr size_type to_pos( const_iterator it ) const\n    {\n        return it == cend() ? npos : size_type( it - cbegin() );\n    }\n\n    nssv_constexpr size_type to_pos( const_reverse_iterator it ) const\n    {\n        return it == crend() ? npos : size_type( crend() - it - 1 );\n    }\n\n    nssv_constexpr const_reference data_at( size_type pos ) const\n    {\n#if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 )\n        return data_[pos];\n#else\n        return data_[pos];\n#endif\n    }\n\nprivate:\n    const_pointer data_;\n    size_type     size_;\n\npublic:\n#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS\n\n    template< class Allocator >\n    basic_string_view( std::basic_string<CharT, Traits, Allocator> const & s ) nssv_noexcept\n        : data_( s.data() )\n        , size_( s.size() )\n    {}\n\n#if nssv_HAVE_EXPLICIT_CONVERSION\n\n    template< class Allocator >\n    explicit operator std::basic_string<CharT, Traits, Allocator>() const\n    {\n        return to_string( Allocator() );\n    }\n\n#endif // nssv_HAVE_EXPLICIT_CONVERSION\n\n#if nssv_CPP11_OR_GREATER\n\n    template< class Allocator = std::allocator<CharT> >\n    std::basic_string<CharT, Traits, Allocator>\n    to_string( Allocator const & a = Allocator() ) const\n    {\n        return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );\n    }\n\n#else\n\n    std::basic_string<CharT, Traits>\n    to_string() const\n    {\n        return std::basic_string<CharT, Traits>( begin(), end() );\n    }\n\n    template< class Allocator >\n    std::basic_string<CharT, Traits, Allocator>\n    to_string( Allocator const & a ) const\n    {\n        return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );\n    }\n\n#endif // nssv_CPP11_OR_GREATER\n\n#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS\n};\n\n//\n// Non-member functions:\n//\n\n// 24.4.3 Non-member comparison functions:\n// lexicographically compare two string views (function template):\n\ntemplate< class CharT, class Traits >\nnssv_constexpr bool operator== (\n    basic_string_view <CharT, Traits> lhs,\n    basic_string_view <CharT, Traits> rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) == 0 ; }\n\ntemplate< class CharT, class Traits >\nnssv_constexpr bool operator!= (\n    basic_string_view <CharT, Traits> lhs,\n    basic_string_view <CharT, Traits> rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) != 0 ; }\n\ntemplate< class CharT, class Traits >\nnssv_constexpr bool operator< (\n    basic_string_view <CharT, Traits> lhs,\n    basic_string_view <CharT, Traits> rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) < 0 ; }\n\ntemplate< class CharT, class Traits >\nnssv_constexpr bool operator<= (\n    basic_string_view <CharT, Traits> lhs,\n    basic_string_view <CharT, Traits> rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) <= 0 ; }\n\ntemplate< class CharT, class Traits >\nnssv_constexpr bool operator> (\n    basic_string_view <CharT, Traits> lhs,\n    basic_string_view <CharT, Traits> rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) > 0 ; }\n\ntemplate< class CharT, class Traits >\nnssv_constexpr bool operator>= (\n    basic_string_view <CharT, Traits> lhs,\n    basic_string_view <CharT, Traits> rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) >= 0 ; }\n\n// Let S be basic_string_view<CharT, Traits>, and sv be an instance of S.\n// Implementations shall provide sufficient additional overloads marked\n// constexpr and noexcept so that an object t with an implicit conversion\n// to S can be compared according to Table 67.\n\n#if nssv_CPP11_OR_GREATER && ! nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )\n\n#define nssv_BASIC_STRING_VIEW_I(T,U)  typename std::decay< basic_string_view<T,U> >::type\n\n#if nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 140, 150 )\n# define nssv_MSVC_ORDER(x)  , int=x\n#else\n# define nssv_MSVC_ORDER(x)  /*, int=x*/\n#endif\n\n// ==\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(1) >\nnssv_constexpr bool operator==(\n         basic_string_view  <CharT, Traits> lhs,\n    nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) == 0; }\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(2) >\nnssv_constexpr bool operator==(\n    nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,\n         basic_string_view  <CharT, Traits> rhs ) nssv_noexcept\n{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }\n\n// !=\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(1) >\nnssv_constexpr bool operator!= (\n         basic_string_view  < CharT, Traits > lhs,\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept\n{ return lhs.size() != rhs.size() || lhs.compare( rhs ) != 0 ; }\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(2) >\nnssv_constexpr bool operator!= (\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,\n         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) != 0 ; }\n\n// <\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(1) >\nnssv_constexpr bool operator< (\n         basic_string_view  < CharT, Traits > lhs,\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) < 0 ; }\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(2) >\nnssv_constexpr bool operator< (\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,\n         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) < 0 ; }\n\n// <=\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(1) >\nnssv_constexpr bool operator<= (\n         basic_string_view  < CharT, Traits > lhs,\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) <= 0 ; }\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(2) >\nnssv_constexpr bool operator<= (\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,\n         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) <= 0 ; }\n\n// >\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(1) >\nnssv_constexpr bool operator> (\n         basic_string_view  < CharT, Traits > lhs,\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) > 0 ; }\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(2) >\nnssv_constexpr bool operator> (\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,\n         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) > 0 ; }\n\n// >=\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(1) >\nnssv_constexpr bool operator>= (\n         basic_string_view  < CharT, Traits > lhs,\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) >= 0 ; }\n\ntemplate< class CharT, class Traits  nssv_MSVC_ORDER(2) >\nnssv_constexpr bool operator>= (\n    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,\n         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept\n{ return lhs.compare( rhs ) >= 0 ; }\n\n#undef nssv_MSVC_ORDER\n#undef nssv_BASIC_STRING_VIEW_I\n\n#endif // nssv_CPP11_OR_GREATER\n\n// 24.4.4 Inserters and extractors:\n\nnamespace detail {\n\ntemplate< class Stream >\nvoid write_padding( Stream & os, std::streamsize n )\n{\n    for ( std::streamsize i = 0; i < n; ++i )\n        os.rdbuf()->sputc( os.fill() );\n}\n\ntemplate< class Stream, class View >\nStream & write_to_stream( Stream & os, View const & sv )\n{\n    typename Stream::sentry sentry( os );\n\n    if ( !os )\n        return os;\n\n    const std::streamsize length = static_cast<std::streamsize>( sv.length() );\n\n    // Whether, and how, to pad:\n    const bool      pad = ( length < os.width() );\n    const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right;\n\n    if ( left_pad )\n        write_padding( os, os.width() - length );\n\n    // Write span characters:\n    os.rdbuf()->sputn( sv.begin(), length );\n\n    if ( pad && !left_pad )\n        write_padding( os, os.width() - length );\n\n    // Reset output stream width:\n    os.width( 0 );\n\n    return os;\n}\n\n} // namespace detail\n\ntemplate< class CharT, class Traits >\nstd::basic_ostream<CharT, Traits> &\noperator<<(\n    std::basic_ostream<CharT, Traits>& os,\n    basic_string_view <CharT, Traits> sv )\n{\n    return detail::write_to_stream( os, sv );\n}\n\n// Several typedefs for common character types are provided:\n\ntypedef basic_string_view<char>      string_view;\ntypedef basic_string_view<wchar_t>   wstring_view;\n#if nssv_HAVE_WCHAR16_T\ntypedef basic_string_view<char16_t>  u16string_view;\ntypedef basic_string_view<char32_t>  u32string_view;\n#endif\n\n}} // namespace nonstd::sv_lite\n\n//\n// 24.4.6 Suffix for basic_string_view literals:\n//\n\n#if nssv_HAVE_USER_DEFINED_LITERALS\n\nnamespace nonstd {\nnssv_inline_ns namespace literals {\nnssv_inline_ns namespace string_view_literals {\n\n#if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS\n\nnssv_constexpr nonstd::sv_lite::string_view operator\"\"sv( const char* str, size_t len ) nssv_noexcept  // (1)\n{\n    return nonstd::sv_lite::string_view{ str, len };\n}\n\nnssv_constexpr nonstd::sv_lite::u16string_view operator\"\"sv( const char16_t* str, size_t len ) nssv_noexcept  // (2)\n{\n    return nonstd::sv_lite::u16string_view{ str, len };\n}\n\nnssv_constexpr nonstd::sv_lite::u32string_view operator\"\"sv( const char32_t* str, size_t len ) nssv_noexcept  // (3)\n{\n    return nonstd::sv_lite::u32string_view{ str, len };\n}\n\nnssv_constexpr nonstd::sv_lite::wstring_view operator\"\"sv( const wchar_t* str, size_t len ) nssv_noexcept  // (4)\n{\n    return nonstd::sv_lite::wstring_view{ str, len };\n}\n\n#endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS\n\n#if nssv_CONFIG_USR_SV_OPERATOR\n\nnssv_constexpr nonstd::sv_lite::string_view operator\"\"_sv( const char* str, size_t len ) nssv_noexcept  // (1)\n{\n    return nonstd::sv_lite::string_view{ str, len };\n}\n\nnssv_constexpr nonstd::sv_lite::u16string_view operator\"\"_sv( const char16_t* str, size_t len ) nssv_noexcept  // (2)\n{\n    return nonstd::sv_lite::u16string_view{ str, len };\n}\n\nnssv_constexpr nonstd::sv_lite::u32string_view operator\"\"_sv( const char32_t* str, size_t len ) nssv_noexcept  // (3)\n{\n    return nonstd::sv_lite::u32string_view{ str, len };\n}\n\nnssv_constexpr nonstd::sv_lite::wstring_view operator\"\"_sv( const wchar_t* str, size_t len ) nssv_noexcept  // (4)\n{\n    return nonstd::sv_lite::wstring_view{ str, len };\n}\n\n#endif // nssv_CONFIG_USR_SV_OPERATOR\n\n}}} // namespace nonstd::literals::string_view_literals\n\n#endif\n\n//\n// Extensions for std::string:\n//\n\n#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS\n\nnamespace nonstd {\nnamespace sv_lite {\n\n// Exclude MSVC 14 (19.00): it yields ambiguous to_string():\n\n#if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140\n\ntemplate< class CharT, class Traits, class Allocator = std::allocator<CharT> >\nstd::basic_string<CharT, Traits, Allocator>\nto_string( basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )\n{\n    return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );\n}\n\n#else\n\ntemplate< class CharT, class Traits >\nstd::basic_string<CharT, Traits>\nto_string( basic_string_view<CharT, Traits> v )\n{\n    return std::basic_string<CharT, Traits>( v.begin(), v.end() );\n}\n\ntemplate< class CharT, class Traits, class Allocator >\nstd::basic_string<CharT, Traits, Allocator>\nto_string( basic_string_view<CharT, Traits> v, Allocator const & a )\n{\n    return std::basic_string<CharT, Traits, Allocator>( v.begin(), v.end(), a );\n}\n\n#endif // nssv_CPP11_OR_GREATER\n\ntemplate< class CharT, class Traits, class Allocator >\nbasic_string_view<CharT, Traits>\nto_string_view( std::basic_string<CharT, Traits, Allocator> const & s )\n{\n    return basic_string_view<CharT, Traits>( s.data(), s.size() );\n}\n\n}} // namespace nonstd::sv_lite\n\n#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS\n\n//\n// make types and algorithms available in namespace nonstd:\n//\n\nnamespace nonstd {\n\nusing sv_lite::basic_string_view;\nusing sv_lite::string_view;\nusing sv_lite::wstring_view;\n\n#if nssv_HAVE_WCHAR16_T\nusing sv_lite::u16string_view;\n#endif\n#if nssv_HAVE_WCHAR32_T\nusing sv_lite::u32string_view;\n#endif\n\n// literal \"sv\"\n\nusing sv_lite::operator==;\nusing sv_lite::operator!=;\nusing sv_lite::operator<;\nusing sv_lite::operator<=;\nusing sv_lite::operator>;\nusing sv_lite::operator>=;\n\nusing sv_lite::operator<<;\n\n#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS\nusing sv_lite::to_string;\nusing sv_lite::to_string_view;\n#endif\n\n} // namespace nonstd\n\n// 24.4.5 Hash support (C++11):\n\n// Note: The hash value of a string view object is equal to the hash value of\n// the corresponding string object.\n\n#if nssv_HAVE_STD_HASH\n\n#include <functional>\n\nnamespace std {\n\ntemplate<>\nstruct hash< nonstd::string_view >\n{\npublic:\n    std::size_t operator()( nonstd::string_view v ) const nssv_noexcept\n    {\n        return std::hash<std::string>()( std::string( v.data(), v.size() ) );\n    }\n};\n\ntemplate<>\nstruct hash< nonstd::wstring_view >\n{\npublic:\n    std::size_t operator()( nonstd::wstring_view v ) const nssv_noexcept\n    {\n        return std::hash<std::wstring>()( std::wstring( v.data(), v.size() ) );\n    }\n};\n\ntemplate<>\nstruct hash< nonstd::u16string_view >\n{\npublic:\n    std::size_t operator()( nonstd::u16string_view v ) const nssv_noexcept\n    {\n        return std::hash<std::u16string>()( std::u16string( v.data(), v.size() ) );\n    }\n};\n\ntemplate<>\nstruct hash< nonstd::u32string_view >\n{\npublic:\n    std::size_t operator()( nonstd::u32string_view v ) const nssv_noexcept\n    {\n        return std::hash<std::u32string>()( std::u32string( v.data(), v.size() ) );\n    }\n};\n\n} // namespace std\n\n#endif // nssv_HAVE_STD_HASH\n\nnssv_RESTORE_WARNINGS()\n\n#endif // nssv_HAVE_STD_STRING_VIEW\n#endif // NONSTD_SV_LITE_H_INCLUDED\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/thirdparty.cpp",
    "content": ""
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/thirdparty.hpp",
    "content": "#ifndef RD_CPP_THIRDPARTY_HPP\n#define RD_CPP_THIRDPARTY_HPP\n\n#include \"tsl/ordered_set.h\"\n#include \"tsl/ordered_map.h\"\n\n#if __cplusplus >= 201703L\n\n#include <optional>\n#include <variant>\n#include <string_view>\n\nnamespace rd\n{\nusing std::get;\nusing std::make_optional;\nusing std::nullopt;\nusing std::nullopt_t;\nusing std::optional;\nusing std::variant;\nusing std::visit;\n}\t // namespace rd\n\n#else\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4583)\n#pragma warning(disable : 4582)\n#endif\n#include \"optional.hpp\"\n#include \"mpark/variant.hpp\"\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\nnamespace rd\n{\nusing mpark::get;\nusing mpark::variant;\nusing mpark::visit;\nusing tl::make_optional;\nusing tl::nullopt;\nusing tl::nullopt_t;\nusing tl::optional;\n}\t // namespace rd\n\n#endif\n\n#include \"nonstd/string_view.hpp\"\nnamespace rd\n{\nusing nonstd::string_view;\nusing nonstd::wstring_view;\nusing namespace std::literals;\nusing namespace nonstd::literals;\n}\t // namespace rd\n\nnamespace rd\n{\nusing tsl::ordered_map;\nusing tsl::ordered_set;\n}\t // namespace rd\n\n#endif\t  // RD_CPP_THIRDPARTY_H\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2017 Mikhail Pilin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/README.md",
    "content": "# UTF-8/16/32 C++ library\nThis is the C++11 template based header only library under Windows/Linux/MacOs to convert UFT-8/16/32 symbols and strings. The library transparently support `wchar_t` as UTF-16 for Windows and UTF-32 for Linux and MacOs.\n\nUTF-8 and UTF-32 (UCS-32) both support 31 bit wide code points `[0‥0x7FFFFFFF]`with no restriction. UTF-16 supports only unicode code points `[0‥0x10FFFF]`, where high `[0xD800‥0xDBFF]` and low `[0xDC00‥0xDFFF]` surrogate regions are prohibited.\n\nThe maximum UTF-16 symbol size is 2 words (4 bytes, both words should be in the surrogate region). UFT-32 (UCS-32) is always 1 word (4 bytes). UTF-8 has the maximum symbol size (see [conversion table](#utf-8-conversion-table) for details):\n- 4 bytes for unicode code points\n- 6 bytes for 31bit code points\n\n###### UTF-16 surrogate decoder:\n|High\\Low|DC00|DC01|…|DFFF|\n|:-:|:-:|:-:|:-:|:-:|\n|**D800**|010000|010001|…|0103FF|\n|**D801**|010400|010401|…|0107FF|\n|**⋮**|⋮|⋮|⋱|⋮|\n|**DBFF**|10FC00|10FC01|…|10FFFF|\n\n![UTF-16 Surrogates](https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Utf-16.svg/512px-Utf-16.svg.png)\n\n## Supported compilers\n\nTested on following compilers:\n- [Visual Studio 2013 v12.0.40629.00 Update 5](perf/vc120_win.md)\n- [Visual Studio 2015 v14.0.25431.01 Update 3](perf/vc140_win.md)\n- [Visual Studio 2017 v15.6.7](perf/vc141_win.md)\n- [Visual Studio 2019 v16.0.3](perf/vc142_win.md)\n- [GNU v5.4.0](perf/gnu_linux.md)\n- [Clang v6.0.1](perf/clang_linux.md)\n- [Apple Clang v10.0.1](perf/clang_mac.md)\n\n## Usage example\n\n```cpp\n    // यूनिकोड\n    static char const u8s[] = \"\\xE0\\xA4\\xAF\\xE0\\xA5\\x82\\xE0\\xA4\\xA8\\xE0\\xA4\\xBF\\xE0\\xA4\\x95\\xE0\\xA5\\x8B\\xE0\\xA4\\xA1\";\n    using namespace ww898::utf;\n    std::u16string u16;\n    convz<utf_selector_t<decltype(*u8s)>, utf16>(u8s, std::back_inserter(u16));\n    std::u32string u32;\n    conv<utf16, utf_selector_t<decltype(u32)::value_type>>(u16.begin(), u16.end(), std::back_inserter(u32));\n    std::vector<char> u8;\n    convz<utf32, utf8>(u32.data(), std::back_inserter(u8));\n    std::wstring uw;\n    conv<utf8, utfw>(u8s, u8s + sizeof(u8s), std::back_inserter(uw));\n    auto u8r = conv<char>(uw);\n    auto u16r = conv<char16_t>(u16);\n    auto uwr = convz<wchar_t>(u8s);\n\n    auto u32r = conv<char32_t>(std::string_view(u8r.data(), u8r.size())); // C++17 only\n\n    static_assert(std::is_same<utf_selector<decltype(*u8s)>, utf_selector<decltype(u8)::value_type>>::value, \"Fail\");\n    static_assert(\n        std::is_same<utf_selector_t<decltype(u16)::value_type>, utf_selector_t<decltype(uw)::value_type>>::value !=\n        std::is_same<utf_selector_t<decltype(u32)::value_type>, utf_selector_t<decltype(uw)::value_type>>::value, \"Fail\");\n```\n\n## UTF-8 Conversion table\n![UTF-8/32 table](https://upload.wikimedia.org/wikipedia/commons/3/38/UTF-8_Encoding_Scheme.png)\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/include/ww898/cp_utf16.hpp",
    "content": "﻿/*\n * MIT License\n * \n * Copyright (c) 2017-2019 Mikhail Pilin\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#pragma once\n\n#include <cstdint>\n#include <stdexcept>\n\nnamespace ww898 {\nnamespace utf {\n\n//                1         0\n//       98765432109876543210\n//       ||||||||||||||||||||\n// 110110xxxxxxxxxx|||||||||| high surrogate\n//           110111xxxxxxxxxx low  surrogate\nstruct utf16 final\n{\n    static size_t const max_unicode_symbol_size = 2;\n    static size_t const max_supported_symbol_size = max_unicode_symbol_size;\n\n    static uint32_t const max_supported_code_point = 0x10FFFF;\n\n    using char_type = uint16_t;\n\n    static char_type const min_surrogate = 0xD800;\n    static char_type const max_surrogate = 0xDFFF;\n\n    static char_type const min_surrogate_high = 0xD800;\n    static char_type const max_surrogate_high = 0xDBFF;\n\n    static char_type const min_surrogate_low = 0xDC00;\n    static char_type const max_surrogate_low = 0xDFFF;\n\n    template<typename PeekFn>\n    static size_t char_size(PeekFn && peek_fn)\n    {\n        char_type const ch0 = std::forward<PeekFn>(peek_fn)();\n        if (ch0 < 0xD800) // [0x0000‥0xD7FF]\n            return 1;\n        if (ch0 < 0xDC00) // [0xD800‥0xDBFF] [0xDC00‥0xDFFF]\n            return 2;\n        if (ch0 < 0xE000)\n            throw std::runtime_error(\"The high utf16 surrogate char is expected\");\n        // [0xE000‥0xFFFF]\n        return 1;\n    }\n\n    template<typename ReadFn>\n    static uint32_t read(ReadFn && read_fn)\n    {\n        char_type const ch0 = read_fn();\n        if (ch0 < 0xD800) // [0x0000‥0xD7FF]\n            return ch0;\n        if (ch0 < 0xDC00) // [0xD800‥0xDBFF] [0xDC00‥0xDFFF]\n        {\n            char_type const ch1 = read_fn(); if (ch1 >> 10 != 0x37) throw std::runtime_error(\"The low utf16 surrogate char is expected\");\n            return static_cast<uint32_t>((ch0 << 10) + ch1 - 0x35FDC00);\n        }\n        if (ch0 < 0xE000)\n            throw std::runtime_error(\"The high utf16 surrogate char is expected\");\n        // [0xE000‥0xFFFF]\n        return ch0;\n    }\n\n    template<typename WriteFn>\n    static void write(uint32_t const cp, WriteFn && write_fn)\n    {\n        if (cp < 0xD800) // [0x0000‥0xD7FF]\n            write_fn(static_cast<char_type>(cp));\n        else if (cp < 0x10000)\n        {\n            if (cp < 0xE000)\n                throw std::runtime_error(\"The utf16 code point can not be in surrogate range\");\n            // [0xE000‥0xFFFF]\n            write_fn(static_cast<char_type>(cp));\n        }\n        else if (cp < 0x110000) // [0xD800‥0xDBFF] [0xDC00‥0xDFFF]\n        {\n            write_fn(static_cast<char_type>(0xD7C0 + (cp >> 10        )));\n            write_fn(static_cast<char_type>(0xDC00 + (cp       & 0x3FF)));\n        }\n        else\n            throw std::runtime_error(\"Too large the utf16 code point\");\n    }\n};\n\n}}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/include/ww898/cp_utf32.hpp",
    "content": "﻿/*\n * MIT License\n * \n * Copyright (c) 2017-2019 Mikhail Pilin\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#pragma once\n\n#include <cstdint>\n#include <stdexcept>\n\nnamespace ww898 {\nnamespace utf {\n\nstruct utf32 final\n{\n    static size_t const max_unicode_symbol_size = 1;\n    static size_t const max_supported_symbol_size = 1;\n\n    static uint32_t const max_supported_code_point = 0x7FFFFFFF;\n\n    using char_type = uint32_t;\n\n    template<typename PeekFn>\n    static size_t char_size(PeekFn &&)\n    {\n        return 1;\n    }\n\n    template<typename ReadFn>\n    static uint32_t read(ReadFn && read_fn)\n    {\n        char_type const ch = std::forward<ReadFn>(read_fn)();\n        if (ch < 0x80000000)\n            return ch;\n        throw std::runtime_error(\"Too large utf32 char\");\n    }\n\n    template<typename WriteFn>\n    static void write(uint32_t const cp, WriteFn && write_fn)\n    {\n        if (cp < 0x80000000)\n            std::forward<WriteFn>(write_fn)(static_cast<char_type>(cp));\n        else\n            throw std::runtime_error(\"Too large utf32 code point\");\n    }\n};\n\n}}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/include/ww898/cp_utf8.hpp",
    "content": "﻿/*\n * MIT License\n * \n * Copyright (c) 2017-2019 Mikhail Pilin\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#pragma once\n\n#include <cstdint>\n#include <stdexcept>\n\nnamespace ww898 {\nnamespace utf {\n\n// Supported combinations:\n//   0xxx_xxxx\n//   110x_xxxx 10xx_xxxx\n//   1110_xxxx 10xx_xxxx 10xx_xxxx\n//   1111_0xxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n//   1111_10xx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n//   1111_110x 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\nstruct utf8 final\n{\n    static size_t const max_unicode_symbol_size = 4;\n    static size_t const max_supported_symbol_size = 6;\n\n    static uint32_t const max_supported_code_point = 0x7FFFFFFF;\n\n    using char_type = uint8_t;\n\n    template<typename PeekFn>\n    static size_t char_size(PeekFn && peek_fn)\n    {\n        char_type const ch0 = std::forward<PeekFn>(peek_fn)();\n        if (ch0 < 0x80) // 0xxx_xxxx\n            return 1;\n        if (ch0 < 0xC0)\n            throw std::runtime_error(\"The utf8 first char in sequence is incorrect\");\n        if (ch0 < 0xE0) // 110x_xxxx 10xx_xxxx\n            return 2;\n        if (ch0 < 0xF0) // 1110_xxxx 10xx_xxxx 10xx_xxxx\n            return 3;\n        if (ch0 < 0xF8) // 1111_0xxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n            return 4;\n        if (ch0 < 0xFC) // 1111_10xx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n            return 5;\n        if (ch0 < 0xFE) // 1111_110x 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n            return 6;\n        throw std::runtime_error(\"The utf8 first char in sequence is incorrect\");\n    }\n\n    template<typename ReadFn>\n    static uint32_t read(ReadFn && read_fn)\n    {\n        char_type const ch0 = read_fn();\n        if (ch0 < 0x80) // 0xxx_xxxx\n            return ch0;\n        if (ch0 < 0xC0)\n            throw std::runtime_error(\"The utf8 first char in sequence is incorrect\");\n        if (ch0 < 0xE0) // 110x_xxxx 10xx_xxxx\n        {\n            char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;\n            return (ch0 << 6) + ch1 - 0x3080;\n        }\n        if (ch0 < 0xF0) // 1110_xxxx 10xx_xxxx 10xx_xxxx\n        {\n            char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;\n            char_type const ch2 = read_fn(); if (ch2 >> 6 != 2) goto _err;\n            return (ch0 << 12) + (ch1 << 6) + ch2 - 0xE2080;\n        }\n        if (ch0 < 0xF8) // 1111_0xxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n        {\n            char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;\n            char_type const ch2 = read_fn(); if (ch2 >> 6 != 2) goto _err;\n            char_type const ch3 = read_fn(); if (ch3 >> 6 != 2) goto _err;\n            return (ch0 << 18) + (ch1 << 12) + (ch2 << 6) + ch3 - 0x3C82080;\n        }\n        if (ch0 < 0xFC) // 1111_10xx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n        {\n            char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;\n            char_type const ch2 = read_fn(); if (ch2 >> 6 != 2) goto _err;\n            char_type const ch3 = read_fn(); if (ch3 >> 6 != 2) goto _err;\n            char_type const ch4 = read_fn(); if (ch4 >> 6 != 2) goto _err;\n            return (ch0 << 24) + (ch1 << 18) + (ch2 << 12) + (ch3 << 6) + ch4 - 0xFA082080;\n        }\n        if (ch0 < 0xFE) // 1111_110x 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n        {\n            char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;\n            char_type const ch2 = read_fn(); if (ch2 >> 6 != 2) goto _err;\n            char_type const ch3 = read_fn(); if (ch3 >> 6 != 2) goto _err;\n            char_type const ch4 = read_fn(); if (ch4 >> 6 != 2) goto _err;\n            char_type const ch5 = read_fn(); if (ch5 >> 6 != 2) goto _err;\n            return (ch0 << 30) + (ch1 << 24) + (ch2 << 18) + (ch3 << 12) + (ch4 << 6) + ch5 - 0x82082080;\n        }\n        throw std::runtime_error(\"The utf8 first char in sequence is incorrect\");\n        _err: throw std::runtime_error(\"The utf8 slave char in sequence is incorrect\");\n    }\n\n    template<typename WriteFn>\n    static void write(uint32_t const cp, WriteFn && write_fn)\n    {\n        if (cp < 0x80)          // 0xxx_xxxx\n            write_fn(static_cast<char_type>(cp));\n        else if (cp < 0x800)    // 110x_xxxx 10xx_xxxx\n        {\n            write_fn(static_cast<char_type>(0xC0 | cp >>  6));\n            goto _1;\n        }\n        else if (cp < 0x10000)  // 1110_xxxx 10xx_xxxx 10xx_xxxx\n        {\n            write_fn(static_cast<char_type>(0xE0 | cp >> 12));\n            goto _2;\n        }\n        else if (cp < 0x200000) // 1111_0xxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n        {\n            write_fn(static_cast<char_type>(0xF0 | cp >> 18));\n            goto _3;\n        }\n        else if (cp < 0x4000000) // 1111_10xx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n        {\n            write_fn(static_cast<char_type>(0xF8 | cp >> 24));\n            goto _4;\n        }\n        else if (cp < 0x80000000) // 1111_110x 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx\n        {\n            write_fn(static_cast<char_type>(0xFC | cp >> 30));\n            goto _5;\n        }\n        else\n            throw std::runtime_error(\"Tool large UTF8 code point\");\n        return;\n        _5: write_fn(static_cast<char_type>(0x80 | (cp >> 24 & 0x3F)));\n        _4: write_fn(static_cast<char_type>(0x80 | (cp >> 18 & 0x3F)));\n        _3: write_fn(static_cast<char_type>(0x80 | (cp >> 12 & 0x3F)));\n        _2: write_fn(static_cast<char_type>(0x80 | (cp >>  6 & 0x3F)));\n        _1: write_fn(static_cast<char_type>(0x80 | (cp       & 0x3F)));\n    }\n};\n\n}}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/include/ww898/cp_utfw.hpp",
    "content": "﻿/*\n * MIT License\n * \n * Copyright (c) 2017-2019 Mikhail Pilin\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#pragma once\n\n#if defined(_WIN32)\n\n#include <ww898/cp_utf16.hpp>\n\nnamespace ww898 {\nnamespace utf {\nusing utfw = utf16;\n}}\n\n#elif defined(__linux__) || defined(__APPLE__)\n\n#include <ww898/cp_utf32.hpp>\n\nnamespace ww898 {\nnamespace utf {\nusing utfw = utf32;\n}}\n\n#else\n#error Unsupported platform\n#endif\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/include/ww898/utf_config.hpp",
    "content": "/*\n * MIT License\n * \n * Copyright (c) 2017-2019 Mikhail Pilin\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#pragma once\n\n// Normally `__cpp_lib_string_view` should be defined in string header\n#include <string>\n\n#if !defined(__cpp_lib_string_view)\n#if defined(_MSVC_LANG)\n#define __cpp_lib_string_view _MSVC_LANG\n#else\n#define __cpp_lib_string_view __cplusplus\n#endif\n#endif\n\nnamespace ww898 {\nnamespace utf {\nstatic uint32_t const max_unicode_code_point = 0x10FFFF;\n}}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/include/ww898/utf_converters.hpp",
    "content": "﻿/*\n * MIT License\n * \n * Copyright (c) 2017-2019 Mikhail Pilin\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#pragma once\n\n#include <ww898/utf_selector.hpp>\n#include <ww898/utf_config.hpp>\n\n#include <cstdint>\n#include <iterator>\n#include <string>\n\n#if __cpp_lib_string_view >= 201606\n#include <string_view>\n#endif\n\nnamespace ww898 {\nnamespace utf {\n\nnamespace detail {\n\nenum struct convz_impl { normal, binary_copy };\n\ntemplate<\n    typename Utf,\n    typename Outf,\n    typename It,\n    typename Oit,\n    convz_impl>\nstruct convz_strategy\n{\n    Oit operator()(It it, Oit oit) const\n    {\n        auto const read_fn = [&it] { return *it++; };\n        auto const write_fn = [&oit] (typename Outf::char_type const ch) { *oit++ = ch; };\n        while (true)\n        {\n            auto const cp = Utf::read(read_fn);\n            if (!cp)\n                return oit;\n            Outf::write(cp, write_fn);\n        }\n    }\n};\n\ntemplate<\n    typename Utf,\n    typename Outf,\n    typename It,\n    typename Oit>\nstruct convz_strategy<Utf, Outf, It, Oit, convz_impl::binary_copy>\n{\n    Oit operator()(It it, Oit oit) const\n    {\n        while (true)\n        {\n            auto const ch = *it++;\n            if (!ch)\n                return oit;\n            *oit++ = ch;\n        }\n    }\n};\n\n}\n\ntemplate<\n    typename Utf,\n    typename Outf,\n    typename It,\n    typename Oit>\nOit convz(It && it, Oit && oit)\n{\n    return detail::convz_strategy<Utf, Outf,\n            typename std::decay<It>::type,\n            typename std::decay<Oit>::type,\n            std::is_same<Utf, Outf>::value\n                ? detail::convz_impl::binary_copy\n                : detail::convz_impl::normal>()(\n        std::forward<It>(it),\n        std::forward<Oit>(oit));\n}\n\nnamespace detail {\n\nenum struct conv_impl { normal, random_interator, binary_copy };\n\ntemplate<\n    typename Utf,\n    typename Outf,\n    typename It,\n    typename Oit,\n    conv_impl>\nstruct conv_strategy final\n{\n    Oit operator()(It it, It const eit, Oit oit) const\n    {\n        auto const read_fn = [&it, &eit]\n            {\n                if (it == eit)\n                    throw std::runtime_error(\"Not enough input\");\n                return *it++;\n            };\n        auto const write_fn = [&oit] (typename Outf::char_type const ch) { *oit++ = ch; };\n        while (it != eit)\n            Outf::write(Utf::read(read_fn), write_fn);\n        return oit;\n    }\n};\n\ntemplate<\n    typename Utf,\n    typename Outf,\n    typename It,\n    typename Oit>\nstruct conv_strategy<Utf, Outf, It, Oit, conv_impl::random_interator> final\n{\n    Oit operator()(It it, It const eit, Oit oit) const\n    {\n        auto const write_fn = [&oit] (typename Outf::char_type const ch) { *oit++ = ch; };\n        if (eit - it >= static_cast<typename std::iterator_traits<It>::difference_type>(Utf::max_supported_symbol_size))\n        {\n            auto const fast_read_fn = [&it] { return *it++; };\n            auto const fast_eit = eit - Utf::max_supported_symbol_size;\n            while (it < fast_eit)\n                Outf::write(Utf::read(fast_read_fn), write_fn);\n        }\n        auto const read_fn = [&it, &eit]\n            {\n                if (it == eit)\n                    throw std::runtime_error(\"Not enough input\");\n                return *it++;\n            };\n        while (it != eit)\n            Outf::write(Utf::read(read_fn), write_fn);\n        return oit;\n    }\n};\n\ntemplate<\n    typename Utf,\n    typename Outf,\n    typename It,\n    typename Oit>\nstruct conv_strategy<Utf, Outf, It, Oit, conv_impl::binary_copy> final\n{\n    Oit operator()(It it, It const eit, Oit oit) const\n    {\n        while (it != eit)\n            *oit++ = *it++;\n        return oit;\n    }\n};\n\n}\n\ntemplate<\n    typename Utf,\n    typename Outf,\n    typename It,\n    typename Eit,\n    typename Oit>\nOit conv(It && it, Eit && eit, Oit && oit)\n{\n    return detail::conv_strategy<Utf, Outf,\n            typename std::decay<It>::type,\n            typename std::decay<Oit>::type,\n            std::is_same<Utf, Outf>::value\n                ? detail::conv_impl::binary_copy\n                : std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<typename std::decay<It>::type>::iterator_category>::value\n                    ? detail::conv_impl::random_interator\n                    : detail::conv_impl::normal>()(\n        std::forward<It>(it),\n        std::forward<Eit>(eit),\n        std::forward<Oit>(oit));\n}\n\ntemplate<\n    typename Outf,\n    typename Ch,\n    typename Oit>\nOit convz(Ch const * const str, Oit && oit)\n{\n    return convz<utf_selector_t<Ch>, Outf>(str, std::forward<Oit>(oit));\n}\n\ntemplate<\n    typename Och,\n    typename Str>\nstd::basic_string<Och> convz(Str && str)\n{\n    std::basic_string<Och> res;\n    convz<utf_selector_t<Och>>(std::forward<Str>(str), std::back_inserter(res));\n    return res;\n}\n\ntemplate<\n    typename Outf,\n    typename Ch,\n    typename Oit>\nOit conv(std::basic_string<Ch> const & str, Oit && oit)\n{\n    return conv<utf_selector_t<Ch>, Outf>(str.cbegin(), str.cend(), std::forward<Oit>(oit));\n}\n\n#if __cpp_lib_string_view >= 201606\ntemplate<\n    typename Outf,\n    typename Ch,\n    typename Oit>\nOit conv(std::basic_string_view<Ch> const & str, Oit && oit)\n{\n    return conv<utf_selector_t<Ch>, Outf>(str.cbegin(), str.cend(), std::forward<Oit>(oit));\n}\n#endif\n\ntemplate<\n    typename Och,\n    typename Str,\n    typename std::enable_if<!std::is_same<typename std::decay<Str>::type, std::basic_string<Och>>::value, void *>::type = nullptr>\nstd::basic_string<Och> conv(Str && str)\n{\n    std::basic_string<Och> res;\n    conv<utf_selector_t<Och>>(std::forward<Str>(str), std::back_inserter(res));\n    return res;\n}\n\ntemplate<\n    typename Ch>\nstd::basic_string<Ch> conv(std::basic_string<Ch> str) throw()\n{\n    return str;\n}\n\n}}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/include/ww898/utf_selector.hpp",
    "content": "﻿/*\n * MIT License\n * \n * Copyright (c) 2017-2019 Mikhail Pilin\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#pragma once\n\n#include <ww898/cp_utf8.hpp>\n#include <ww898/cp_utf16.hpp>\n#include <ww898/cp_utf32.hpp>\n#include <ww898/cp_utfw.hpp>\n\nnamespace ww898 {\nnamespace utf {\nnamespace detail {\n\ntemplate<typename Ch>\nstruct utf_selector final {};\n\ntemplate<> struct utf_selector<         char> final { using type = utf8 ; };\ntemplate<> struct utf_selector<unsigned char> final { using type = utf8 ; };\ntemplate<> struct utf_selector<signed   char> final { using type = utf8 ; };\ntemplate<> struct utf_selector<char16_t     > final { using type = utf16; };\ntemplate<> struct utf_selector<char32_t     > final { using type = utf32; };\ntemplate<> struct utf_selector<wchar_t      > final { using type = utfw ; };\n\n}\n\ntemplate<typename Ch>\nusing utf_selector = detail::utf_selector<typename std::decay<Ch>::type>;\n\ntemplate<typename Ch>\nusing utf_selector_t = typename utf_selector<Ch>::type;\n\n}}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/utf-cpp/include/ww898/utf_sizes.hpp",
    "content": "﻿/*\n * MIT License\n * \n * Copyright (c) 2017-2019 Mikhail Pilin\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#pragma once\n\n#include <ww898/utf_selector.hpp>\n#include <ww898/utf_config.hpp>\n\n#include <cstddef>\n#include <iterator>\n#include <string>\n\n#if __cpp_lib_string_view >= 201606\n#include <string_view>\n#endif\n\nnamespace ww898 {\nnamespace utf {\n\ntemplate<\n    typename Utf,\n    typename It>\nsize_t char_size(It it)\n{\n    return Utf::char_size([&it] { return *it; });\n}\n\ntemplate<\n    typename Utf,\n    typename It>\nsize_t size(It it)\n{\n    size_t total_cp = 0;\n    while (*it)\n    {\n        size_t size = Utf::char_size([&it] { return *it; });\n        while (++it, --size > 0)\n            if (!*it)\n                throw std::runtime_error(\"Not enough input for the null-terminated string\");\n        ++total_cp;\n    }\n    return total_cp;\n}\n\nnamespace detail {\n\nenum struct iterator_impl { forward, random_access };\n\ntemplate<\n    typename It,\n    iterator_impl>\nstruct next_strategy final\n{\n    void operator()(It & it, It const & eit, size_t size)\n    {\n        while (++it, --size > 0)\n            if (it == eit)\n                throw std::runtime_error(\"Not enough input for the forward iterator\");\n    }\n};\n\ntemplate<typename It>\nstruct next_strategy<It, iterator_impl::random_access> final\n{\n    void operator()(It & it, It const & eit, typename std::iterator_traits<It>::difference_type const size)\n    {\n        if (eit - it < size)\n            throw std::runtime_error(\"Not enough input for the random access iterator\");\n        it += size;\n    }\n};\n\n}\n\ntemplate<\n    typename Utf,\n    typename It,\n    typename Eit>\nsize_t size(It it, Eit const eit)\n{\n    size_t total_cp = 0;\n    while (it != eit)\n    {\n        size_t const size = Utf::char_size([&it] { return *it; });\n        detail::next_strategy<\n            typename std::decay<It>::type,\n            std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<typename std::decay<It>::type>::iterator_category>::value\n                    ? detail::iterator_impl::random_access\n                    : detail::iterator_impl::forward>()(it, eit, size);\n        ++total_cp;\n    }\n    return total_cp;\n}\n\ntemplate<typename Ch>\nsize_t size(Ch const * str)\n{\n    return size<utf_selector_t<Ch>>(str);\n}\n\ntemplate<typename Ch>\nsize_t size(std::basic_string<Ch> str)\n{\n    return size<utf_selector_t<Ch>>(str.cbegin(), str.cend());\n}\n\n#if __cpp_lib_string_view >= 201606\ntemplate<typename Ch>\nsize_t size(std::basic_string_view<Ch> str)\n{\n    return size<utf_selector_t<Ch>>(str.cbegin(), str.cend());\n}\n#endif\n\n}}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/variant/LICENSE.md",
    "content": "Boost Software License - Version 1.0 - August 17th, 2003\n\nPermission is hereby granted, free of charge, to any person or organization\nobtaining a copy of the software and accompanying documentation covered by\nthis license (the \"Software\") to use, reproduce, display, distribute,\nexecute, and transmit the Software, and to prepare derivative works of the\nSoftware, and to permit third-parties to whom the Software is furnished to\ndo so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including\nthe above license grant, this restriction and the following disclaimer,\nmust be included in all copies of the Software, in whole or in part, and\nall derivative works of the Software, unless such copies or derivative\nworks are solely in the form of machine-executable object code generated by\na source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\nSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\nFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/variant/README.md",
    "content": "# MPark.Variant\n\n> __C++17__ `std::variant` for __C++11__/__14__/__17__\n\n[![release][badge.release]][release]\n[![header][badge.header]][header]\n[![travis][badge.travis]][travis]\n[![appveyor][badge.appveyor]][appveyor]\n[![license][badge.license]][license]\n[![godbolt][badge.godbolt]][godbolt]\n[![wandbox][badge.wandbox]][wandbox]\n\n[badge.release]: https://img.shields.io/github/release/mpark/variant.svg\n[badge.header]: https://img.shields.io/badge/single%20header-master-blue.svg\n[badge.travis]: https://travis-ci.org/mpark/variant.svg?branch=master\n[badge.appveyor]: https://ci.appveyor.com/api/projects/status/github/mpark/variant?branch=master&svg=true\n[badge.license]: https://img.shields.io/badge/license-boost-blue.svg\n[badge.godbolt]: https://img.shields.io/badge/try%20it-on%20godbolt-222266.svg\n[badge.wandbox]: https://img.shields.io/badge/try%20it-on%20wandbox-5cb85c.svg\n\n[release]: https://github.com/mpark/variant/releases/latest\n[header]: https://github.com/mpark/variant/blob/single-header/master/variant.hpp\n[travis]: https://travis-ci.org/mpark/variant\n[appveyor]: https://ci.appveyor.com/project/mpark/variant\n[license]: https://github.com/mpark/variant/blob/master/LICENSE.md\n[godbolt]: https://godbolt.org/z/4r7hEy\n[wandbox]: https://wandbox.org/permlink/dTZxf85MVhehOqx1\n\n## Introduction\n\n__MPark.Variant__ is an implementation of __C++17__ `std::variant` for __C++11__/__14__/__17__.\n\n  - Based on [my implementation of `std::variant` for __libc++__][libcxx-impl]\n  - Continuously tested against __libc++__'s `std::variant` test suite.\n\n[libcxx-impl]: https://reviews.llvm.org/rL288547\n\n## Documentation\n\n  - [cppreference.com](http://en.cppreference.com/w/cpp/utility/variant)\n  - [eel.is/c++draft](http://eel.is/c++draft/variant)\n\n## Integration\n\n### Single Header\n\nThe [single-header] branch provides a standalone `variant.hpp`\nfile for each [release](https://github.com/mpark/variant/releases).\nCopy it and `#include` away!\n\n[single-header]: https://github.com/mpark/variant/tree/single-header\n\n### Submodule\n\nYou can add `mpark/variant` as a submodule to your project.\n\n```bash\ngit submodule add https://github.com/mpark/variant.git 3rdparty/variant\n```\n\nAdd the `include` directory to your include path with\n`-I3rdparty/variant/include` then `#include` the `variant.hpp` header\nwith `#include <mpark/variant.hpp>`.\n\nIf you use CMake, you can simply use `add_subdirectory(3rdparty/variant)`:\n\n```cmake\ncmake_minimum_required(VERSION 3.6.3)\n\nproject(HelloWorld CXX)\n\nadd_subdirectory(3rdparty/variant)\n\nadd_executable(hello-world hello_world.cpp)\ntarget_link_libraries(hello-world mpark_variant)\n```\n\n### Installation / CMake `find_package`\n\n```bash\ngit clone https://github.com/mpark/variant.git\nmkdir variant/build && cd variant/build\ncmake ..\ncmake --build . --target install\n```\n\nThis will install `mpark/variant` to the default install-directory for\nyour platform (`/usr/local` for Unix, `C:\\Program Files` for Windows).\nYou can also install at a custom location via the `CMAKE_INSTALL_PREFIX`\nvariable, (e.g., `cmake .. -DCMAKE_INSTALL_PREFIX=/opt`).\n\nThe installed `mpark/variant` can then be found by CMake via `find_package`:\n\n```cmake\ncmake_minimum_required(VERSION 3.6.3)\n\nproject(HelloWorld CXX)\n\nfind_package(mpark_variant 1.3.0 REQUIRED)\n\nadd_executable(hello-world hello_world.cpp)\ntarget_link_libraries(hello-world mpark_variant)\n```\n\nCMake will search for `mpark/variant` in its default set of\ninstallation prefixes. If `mpark/variant` is installed in\na custom location via the `CMAKE_INSTALL_PREFIX` variable,\nyou'll likely need to use the `CMAKE_PREFIX_PATH` to specify\nthe location (e.g., `cmake .. -DCMAKE_PREFIX_PATH=/opt`).\n\n## Requirements\n\nThis library requires a standard conformant __C++11__ compiler.\nThe following compilers are continously tested:\n\n| Compiler                               | Operating System                            | Version String                                                                     |\n| -------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------- |\n| GCC 4.8.5                              | Ubuntu 16.04.5 LTS                          | g++-4.8 (Ubuntu 4.8.5-4ubuntu8~16.04.1) 4.8.5                                      |\n| GCC 4.9.4                              | Ubuntu 16.04.5 LTS                          | g++-4.9 (Ubuntu 4.9.4-2ubuntu1~16.04) 4.9.4                                        |\n| GCC 5.5.0                              | Ubuntu 16.04.5 LTS                          | g++-5 (Ubuntu 5.5.0-12ubuntu1~16.04) 5.5.0 20171010                                |\n| GCC 6.5.0                              | Ubuntu 16.04.5 LTS                          | g++-6 (Ubuntu 6.5.0-2ubuntu1~16.04) 6.5.0 20181026                                 |\n| GCC 7.4.0                              | Ubuntu 16.04.5 LTS                          | g++-7 (Ubuntu 7.4.0-1ubuntu1\\~16.04\\~ppa1) 7.4.0                                   |\n| GCC 8.1.0                              | Ubuntu 16.04.5 LTS                          | g++-8 (Ubuntu 8.1.0-5ubuntu1~16.04) 8.1.0                                          |\n| Clang 3.6.2                            | Ubuntu 16.04.5 LTS                          | Ubuntu clang version 3.6.2-3ubuntu2 (tags/RELEASE_362/final) (based on LLVM 3.6.2) |\n| Clang 3.7.1                            | Ubuntu 16.04.5 LTS                          | Ubuntu clang version 3.7.1-2ubuntu2 (tags/RELEASE_371/final) (based on LLVM 3.7.1) |\n| Clang 3.8.0                            | Ubuntu 16.04.5 LTS                          | clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)                              |\n| Clang 3.9.1                            | Ubuntu 16.04.5 LTS                          | clang version 3.9.1-4ubuntu3~16.04.2 (tags/RELEASE_391/rc2)                        |\n| Clang 4.0.0                            | Ubuntu 16.04.5 LTS                          | clang version 4.0.0-1ubuntu1~16.04.2 (tags/RELEASE_400/rc1)                        |\n| Clang 5.0.0                            | Ubuntu 16.04.5 LTS                          | clang version 5.0.0-3~16.04.1 (tags/RELEASE_500/final)                             |\n| Clang 6.0.0                            | Ubuntu 16.04.5 LTS                          | clang version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)                      |\n| Clang 7.0.1                            | Ubuntu 16.04.5 LTS                          | clang version 7.0.1-svn347285-1\\~exp1\\~20181124105320.40 (branches/release_70)     |\n| Clang Xcode 8.3                        | Darwin Kernel Version 16.7.0 (OS X 10.12.6) | Apple LLVM version 8.1.0 (clang-802.0.42)                                          |\n| Clang Xcode 9.4                        | Darwin Kernel Version 17.4.0 (OS X 10.13.3) | Apple LLVM version 9.1.0 (clang-902.0.39.2)                                        |\n| Clang Xcode 10.1                       | Darwin Kernel Version 17.7.0 (OS X 10.13.6) | Apple LLVM version 10.0.0 (clang-1000.11.45.5)                                     |\n| Visual Studio 14 2015                  | Visual Studio 2015 with Update 3            | MSVC 19.0.24241.7                                                                  |\n| Visual Studio 15 2017                  | Visual Studio 2017 with Update 8            | MSVC 19.15.26732.1                                                                 |\n| Visual Studio 15 2017                  | Visual Studio 2017 with Update 9            | MSVC 19.16.27025.1                                                                 |\n| Visual Studio 15 2017 (__Clang/LLVM__) | Visual Studio 2017                          | Clang 7.0.0                                                                        |\n\n#### NOTES\n  - __GCC 4.8__/__4.9__: `constexpr` support is not available for `visit` and relational operators.\n  - Enabling __libc++__ `std::variant` tests require `-std=c++17` support.\n\n## CMake Variables\n\n  -  __`MPARK_VARIANT_INCLUDE_TESTS`__:`STRING` (__default__: `\"\"`)\n\n     Semicolon-separated list of tests to build.\n     Possible values are `mpark`, and `libc++`.\n\n     __NOTE__: The __libc++__ `std::variant` tests are built with `-std=c++17`.\n\n## Unit Tests\n\nRefer to [test/README.md](test/README.md).\n\n## License\n\nDistributed under the [Boost Software License, Version 1.0](LICENSE.md).\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/variant/cmake/mpark_variant-config.cmake.in",
    "content": "# MPark.Variant\n#\n# Copyright Michael Park, 2015-2017\n#\n# Distributed under the Boost Software License, Version 1.0.\n# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)\n\n# Config file for MPark.Variant\n#\n#   `MPARK_VARIANT_INCLUDE_DIRS` - include directories\n#   `MPARK_VARIANT_LIBRARIES`    - libraries to link against\n#\n# The following `IMPORTED` target is also defined:\n#\n#   `mpark_variant`\n\n@PACKAGE_INIT@\n\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/mpark_variant-targets.cmake\")\n\nget_target_property(\n  MPARK_VARIANT_INCLUDE_DIRS\n  mpark_variant INTERFACE_INCLUDE_DIRECTORIES)\n\nset_and_check(MPARK_VARIANT_INCLUDE_DIRS \"${MPARK_VARIANT_INCLUDE_DIRS}\")\nset(MPARK_VARIANT_LIBRARIES mpark_variant)\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/variant/include/mpark/config.hpp",
    "content": "// MPark.Variant\n//\n// Copyright Michael Park, 2015-2017\n//\n// Distributed under the Boost Software License, Version 1.0.\n// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)\n\n#ifndef MPARK_CONFIG_HPP\n#define MPARK_CONFIG_HPP\n\n// MSVC 2015 Update 3.\n#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210)\n#error \"MPark.Variant requires C++11 support.\"\n#endif\n\n#ifndef __has_attribute\n#define __has_attribute(x) 0\n#endif\n\n#ifndef __has_builtin\n#define __has_builtin(x) 0\n#endif\n\n#ifndef __has_include\n#define __has_include(x) 0\n#endif\n\n#ifndef __has_feature\n#define __has_feature(x) 0\n#endif\n\n#if __has_attribute(always_inline) || defined(__GNUC__)\n#define MPARK_ALWAYS_INLINE __attribute__((__always_inline__)) inline\n#elif defined(_MSC_VER)\n#define MPARK_ALWAYS_INLINE __forceinline\n#else\n#define MPARK_ALWAYS_INLINE inline\n#endif\n\n#if __has_builtin(__builtin_addressof) || \\\n    (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER)\n#define MPARK_BUILTIN_ADDRESSOF\n#endif\n\n#if __has_builtin(__builtin_unreachable) || defined(__GNUC__)\n#define MPARK_BUILTIN_UNREACHABLE __builtin_unreachable()\n#elif defined(_MSC_VER)\n#define MPARK_BUILTIN_UNREACHABLE __assume(false)\n#else\n#define MPARK_BUILTIN_UNREACHABLE\n#endif\n\n#if __has_builtin(__type_pack_element)\n#define MPARK_TYPE_PACK_ELEMENT\n#endif\n\n#if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \\\n    !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9)\n#define MPARK_CPP11_CONSTEXPR\n#endif\n\n#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304\n#define MPARK_CPP14_CONSTEXPR\n#endif\n\n#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \\\n    (defined(_MSC_VER) && defined(_CPPUNWIND))\n#define MPARK_EXCEPTIONS\n#endif\n\n#if defined(__cpp_generic_lambdas) || defined(_MSC_VER)\n#define MPARK_GENERIC_LAMBDAS\n#endif\n\n#if defined(__cpp_lib_integer_sequence)\n#define MPARK_INTEGER_SEQUENCE\n#endif\n\n#if defined(__cpp_return_type_deduction) || defined(_MSC_VER)\n#define MPARK_RETURN_TYPE_DEDUCTION\n#endif\n\n#if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER)\n#define MPARK_TRANSPARENT_OPERATORS\n#endif\n\n#if defined(__cpp_variable_templates) || defined(_MSC_VER)\n#define MPARK_VARIABLE_TEMPLATES\n#endif\n\n#if !defined(__GLIBCXX__) || __has_include(<codecvt>)  // >= libstdc++-5\n#define MPARK_TRIVIALITY_TYPE_TRAITS\n#define MPARK_INCOMPLETE_TYPE_TRAITS\n#endif\n\n#endif  // MPARK_CONFIG_HPP\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/variant/include/mpark/in_place.hpp",
    "content": "// MPark.Variant\n//\n// Copyright Michael Park, 2015-2017\n//\n// Distributed under the Boost Software License, Version 1.0.\n// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)\n\n#ifndef MPARK_IN_PLACE_HPP\n#define MPARK_IN_PLACE_HPP\n\n#include <cstddef>\n\n#include \"config.hpp\"\n\nnamespace mpark {\n\n  struct in_place_t { explicit in_place_t() = default; };\n\n  template <std::size_t I>\n  struct in_place_index_t { explicit in_place_index_t() = default; };\n\n  template <typename T>\n  struct in_place_type_t { explicit in_place_type_t() = default; };\n\n#ifdef MPARK_VARIABLE_TEMPLATES\n  constexpr in_place_t in_place{};\n\n  template <std::size_t I> constexpr in_place_index_t<I> in_place_index{};\n\n  template <typename T> constexpr in_place_type_t<T> in_place_type{};\n#endif\n\n}  // namespace mpark\n\n#endif  // MPARK_IN_PLACE_HPP\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/variant/include/mpark/lib.hpp",
    "content": "// MPark.Variant\n//\n// Copyright Michael Park, 2015-2017\n//\n// Distributed under the Boost Software License, Version 1.0.\n// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)\n\n#ifndef MPARK_LIB_HPP\n#define MPARK_LIB_HPP\n\n#include <memory>\n#include <functional>\n#include <type_traits>\n#include <utility>\n\n#include \"config.hpp\"\n\n#define MPARK_RETURN(...) \\\n  noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }\n\nnamespace mpark {\n  namespace lib {\n    template <typename T>\n    struct identity { using type = T; };\n\n    inline namespace cpp14 {\n      template <typename T, std::size_t N>\n      struct array {\n        constexpr const T &operator[](std::size_t index) const {\n          return data[index];\n        }\n\n        T data[N == 0 ? 1 : N];\n      };\n\n      template <typename T>\n      using add_pointer_t = typename std::add_pointer<T>::type;\n\n      template <typename... Ts>\n      using common_type_t = typename std::common_type<Ts...>::type;\n\n      template <typename T>\n      using decay_t = typename std::decay<T>::type;\n\n      template <bool B, typename T = void>\n      using enable_if_t = typename std::enable_if<B, T>::type;\n\n      template <typename T>\n      using remove_const_t = typename std::remove_const<T>::type;\n\n      template <typename T>\n      using remove_reference_t = typename std::remove_reference<T>::type;\n\n      template <typename T>\n      inline constexpr T &&forward(remove_reference_t<T> &t) noexcept {\n        return static_cast<T &&>(t);\n      }\n\n      template <typename T>\n      inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept {\n        static_assert(!std::is_lvalue_reference<T>::value,\n                      \"can not forward an rvalue as an lvalue\");\n        return static_cast<T &&>(t);\n      }\n\n      template <typename T>\n      inline constexpr remove_reference_t<T> &&move(T &&t) noexcept {\n        return static_cast<remove_reference_t<T> &&>(t);\n      }\n\n#ifdef MPARK_INTEGER_SEQUENCE\n      using std::integer_sequence;\n      using std::index_sequence;\n      using std::make_index_sequence;\n      using std::index_sequence_for;\n#else\n      template <typename T, T... Is>\n      struct integer_sequence {\n        using value_type = T;\n        static constexpr std::size_t size() noexcept { return sizeof...(Is); }\n      };\n\n      template <std::size_t... Is>\n      using index_sequence = integer_sequence<std::size_t, Is...>;\n\n      template <typename Lhs, typename Rhs>\n      struct make_index_sequence_concat;\n\n      template <std::size_t... Lhs, std::size_t... Rhs>\n      struct make_index_sequence_concat<index_sequence<Lhs...>,\n                                        index_sequence<Rhs...>>\n          : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {};\n\n      template <std::size_t N>\n      struct make_index_sequence_impl;\n\n      template <std::size_t N>\n      using make_index_sequence = typename make_index_sequence_impl<N>::type;\n\n      template <std::size_t N>\n      struct make_index_sequence_impl\n          : make_index_sequence_concat<make_index_sequence<N / 2>,\n                                       make_index_sequence<N - (N / 2)>> {};\n\n      template <>\n      struct make_index_sequence_impl<0> : identity<index_sequence<>> {};\n\n      template <>\n      struct make_index_sequence_impl<1> : identity<index_sequence<0>> {};\n\n      template <typename... Ts>\n      using index_sequence_for = make_index_sequence<sizeof...(Ts)>;\n#endif\n\n      // <functional>\n#ifdef MPARK_TRANSPARENT_OPERATORS\n      using equal_to = std::equal_to<>;\n#else\n      struct equal_to {\n        template <typename Lhs, typename Rhs>\n        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const\n          MPARK_RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))\n      };\n#endif\n\n#ifdef MPARK_TRANSPARENT_OPERATORS\n      using not_equal_to = std::not_equal_to<>;\n#else\n      struct not_equal_to {\n        template <typename Lhs, typename Rhs>\n        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const\n          MPARK_RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))\n      };\n#endif\n\n#ifdef MPARK_TRANSPARENT_OPERATORS\n      using less = std::less<>;\n#else\n      struct less {\n        template <typename Lhs, typename Rhs>\n        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const\n          MPARK_RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))\n      };\n#endif\n\n#ifdef MPARK_TRANSPARENT_OPERATORS\n      using greater = std::greater<>;\n#else\n      struct greater {\n        template <typename Lhs, typename Rhs>\n        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const\n          MPARK_RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))\n      };\n#endif\n\n#ifdef MPARK_TRANSPARENT_OPERATORS\n      using less_equal = std::less_equal<>;\n#else\n      struct less_equal {\n        template <typename Lhs, typename Rhs>\n        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const\n          MPARK_RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))\n      };\n#endif\n\n#ifdef MPARK_TRANSPARENT_OPERATORS\n      using greater_equal = std::greater_equal<>;\n#else\n      struct greater_equal {\n        template <typename Lhs, typename Rhs>\n        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const\n          MPARK_RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))\n      };\n#endif\n    }  // namespace cpp14\n\n    inline namespace cpp17 {\n\n      // <type_traits>\n      template <bool B>\n      using bool_constant = std::integral_constant<bool, B>;\n\n      template <typename...>\n      struct voider : identity<void> {};\n\n      template <typename... Ts>\n      using void_t = typename voider<Ts...>::type;\n\n      namespace detail {\n        namespace swappable {\n\n          using std::swap;\n\n          template <typename T>\n          struct is_swappable {\n            private:\n            template <typename U,\n                      typename = decltype(swap(std::declval<U &>(),\n                                               std::declval<U &>()))>\n            inline static std::true_type test(int);\n\n            template <typename U>\n            inline static std::false_type test(...);\n\n            public:\n            static constexpr bool value = decltype(test<T>(0))::value;\n          };\n\n          template <bool IsSwappable, typename T>\n          struct is_nothrow_swappable {\n            static constexpr bool value =\n                noexcept(swap(std::declval<T &>(), std::declval<T &>()));\n          };\n\n          template <typename T>\n          struct is_nothrow_swappable<false, T> : std::false_type {};\n\n        }  // namespace swappable\n      }  // namespace detail\n\n      using detail::swappable::is_swappable;\n\n      template <typename T>\n      using is_nothrow_swappable =\n          detail::swappable::is_nothrow_swappable<is_swappable<T>::value, T>;\n\n      // <functional>\n      namespace detail {\n\n        template <typename T>\n        struct is_reference_wrapper : std::false_type {};\n\n        template <typename T>\n        struct is_reference_wrapper<std::reference_wrapper<T>>\n            : std::true_type {};\n\n        template <bool, int>\n        struct Invoke;\n\n        template <>\n        struct Invoke<true /* pmf */, 0 /* is_base_of */> {\n          template <typename R, typename T, typename Arg, typename... Args>\n          inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)\n            MPARK_RETURN((lib::forward<Arg>(arg).*pmf)(lib::forward<Args>(args)...))\n        };\n\n        template <>\n        struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> {\n          template <typename R, typename T, typename Arg, typename... Args>\n          inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)\n            MPARK_RETURN((lib::forward<Arg>(arg).get().*pmf)(lib::forward<Args>(args)...))\n        };\n\n        template <>\n        struct Invoke<true /* pmf */, 2 /* otherwise */> {\n          template <typename R, typename T, typename Arg, typename... Args>\n          inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)\n            MPARK_RETURN(((*lib::forward<Arg>(arg)).*pmf)(lib::forward<Args>(args)...))\n        };\n\n        template <>\n        struct Invoke<false /* pmo */, 0 /* is_base_of */> {\n          template <typename R, typename T, typename Arg>\n          inline static constexpr auto invoke(R T::*pmo, Arg &&arg)\n            MPARK_RETURN(lib::forward<Arg>(arg).*pmo)\n        };\n\n        template <>\n        struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> {\n          template <typename R, typename T, typename Arg>\n          inline static constexpr auto invoke(R T::*pmo, Arg &&arg)\n            MPARK_RETURN(lib::forward<Arg>(arg).get().*pmo)\n        };\n\n        template <>\n        struct Invoke<false /* pmo */, 2 /* otherwise */> {\n          template <typename R, typename T, typename Arg>\n          inline static constexpr auto invoke(R T::*pmo, Arg &&arg)\n              MPARK_RETURN((*lib::forward<Arg>(arg)).*pmo)\n        };\n\n        template <typename R, typename T, typename Arg, typename... Args>\n        inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args)\n          MPARK_RETURN(\n              Invoke<std::is_function<R>::value,\n                     (std::is_base_of<T, lib::decay_t<Arg>>::value\n                          ? 0\n                          : is_reference_wrapper<lib::decay_t<Arg>>::value\n                                ? 1\n                                : 2)>::invoke(f,\n                                              lib::forward<Arg>(arg),\n                                              lib::forward<Args>(args)...))\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4100)\n#endif\n        template <typename F, typename... Args>\n        inline constexpr auto invoke(F &&f, Args &&... args)\n          MPARK_RETURN(lib::forward<F>(f)(lib::forward<Args>(args)...))\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n      }  // namespace detail\n\n      template <typename F, typename... Args>\n      inline constexpr auto invoke(F &&f, Args &&... args)\n        MPARK_RETURN(detail::invoke(lib::forward<F>(f),\n                                    lib::forward<Args>(args)...))\n\n      namespace detail {\n\n        template <typename Void, typename, typename...>\n        struct invoke_result {};\n\n        template <typename F, typename... Args>\n        struct invoke_result<void_t<decltype(lib::invoke(\n                                 std::declval<F>(), std::declval<Args>()...))>,\n                             F,\n                             Args...>\n            : identity<decltype(\n                  lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};\n\n      }  // namespace detail\n\n      template <typename F, typename... Args>\n      using invoke_result = detail::invoke_result<void, F, Args...>;\n\n      template <typename F, typename... Args>\n      using invoke_result_t = typename invoke_result<F, Args...>::type;\n\n      namespace detail {\n\n        template <typename Void, typename, typename...>\n        struct is_invocable : std::false_type {};\n\n        template <typename F, typename... Args>\n        struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>\n            : std::true_type {};\n\n        template <typename Void, typename, typename, typename...>\n        struct is_invocable_r : std::false_type {};\n\n        template <typename R, typename F, typename... Args>\n        struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,\n                              R,\n                              F,\n                              Args...>\n            : std::is_convertible<invoke_result_t<F, Args...>, R> {};\n\n      }  // namespace detail\n\n      template <typename F, typename... Args>\n      using is_invocable = detail::is_invocable<void, F, Args...>;\n\n      template <typename R, typename F, typename... Args>\n      using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;\n\n      // <memory>\n#ifdef MPARK_BUILTIN_ADDRESSOF\n      template <typename T>\n      inline constexpr T *addressof(T &arg) noexcept {\n        return __builtin_addressof(arg);\n      }\n#else\n      namespace detail {\n\n        namespace has_addressof_impl {\n\n          struct fail;\n\n          template <typename T>\n          inline fail operator&(T &&);\n\n          template <typename T>\n          inline static constexpr bool impl() {\n            return (std::is_class<T>::value || std::is_union<T>::value) &&\n                   !std::is_same<decltype(&std::declval<T &>()), fail>::value;\n          }\n\n        }  // namespace has_addressof_impl\n\n        template <typename T>\n        using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;\n\n        template <typename T>\n        inline constexpr T *addressof(T &arg, std::true_type) noexcept {\n          return std::addressof(arg);\n        }\n\n        template <typename T>\n        inline constexpr T *addressof(T &arg, std::false_type) noexcept {\n          return &arg;\n        }\n\n      }  // namespace detail\n\n      template <typename T>\n      inline constexpr T *addressof(T &arg) noexcept {\n        return detail::addressof(arg, detail::has_addressof<T>{});\n      }\n#endif\n\n      template <typename T>\n      inline constexpr T *addressof(const T &&) = delete;\n\n    }  // namespace cpp17\n\n    template <typename T>\n    struct remove_all_extents : identity<T> {};\n\n    template <typename T, std::size_t N>\n    struct remove_all_extents<array<T, N>> : remove_all_extents<T> {};\n\n    template <typename T>\n    using remove_all_extents_t = typename remove_all_extents<T>::type;\n\n    template <std::size_t N>\n    using size_constant = std::integral_constant<std::size_t, N>;\n\n    template <std::size_t I, typename T>\n    struct indexed_type : size_constant<I> { using type = T; };\n\n    template <bool... Bs>\n    using all = std::is_same<integer_sequence<bool, true, Bs...>,\n                             integer_sequence<bool, Bs..., true>>;\n\n#ifdef MPARK_TYPE_PACK_ELEMENT\n    template <std::size_t I, typename... Ts>\n    using type_pack_element_t = __type_pack_element<I, Ts...>;\n#else\n    template <std::size_t I, typename... Ts>\n    struct type_pack_element_impl {\n      private:\n      template <typename>\n      struct set;\n\n      template <std::size_t... Is>\n      struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {};\n\n      template <typename T>\n      inline static std::enable_if<true, T> impl(indexed_type<I, T>);\n\n      inline static std::enable_if<false> impl(...);\n\n      public:\n      using type = decltype(impl(set<index_sequence_for<Ts...>>{}));\n    };\n\n    template <std::size_t I, typename... Ts>\n    using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;\n\n    template <std::size_t I, typename... Ts>\n    using type_pack_element_t = typename type_pack_element<I, Ts...>::type;\n#endif\n\n#ifdef MPARK_TRIVIALITY_TYPE_TRAITS\n    using std::is_trivially_copy_constructible;\n    using std::is_trivially_move_constructible;\n    using std::is_trivially_copy_assignable;\n    using std::is_trivially_move_assignable;\n#else\n    template <typename T>\n    struct is_trivially_copy_constructible\n        : bool_constant<\n              std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};\n\n    template <typename T>\n    struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};\n\n    template <typename T>\n    struct is_trivially_copy_assignable\n        : bool_constant<\n              std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};\n\n    template <typename T>\n    struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};\n#endif\n\n    template <typename T, bool>\n    struct dependent_type : T {};\n\n    template <typename Is, std::size_t J>\n    struct push_back;\n\n    template <typename Is, std::size_t J>\n    using push_back_t = typename push_back<Is, J>::type;\n\n    template <std::size_t... Is, std::size_t J>\n    struct push_back<index_sequence<Is...>, J> {\n      using type = index_sequence<Is..., J>;\n    };\n\n  }  // namespace lib\n}  // namespace mpark\n\n#undef MPARK_RETURN\n\n#endif  // MPARK_LIB_HPP\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RD/thirdparty/variant/include/mpark/variant.hpp",
    "content": "// MPark.Variant\n//\n// Copyright Michael Park, 2015-2017\n//\n// Distributed under the Boost Software License, Version 1.0.\n// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)\n\n#ifndef MPARK_VARIANT_HPP\n#define MPARK_VARIANT_HPP\n\n/*\n   variant synopsis\n\nnamespace std {\n\n  // 20.7.2, class template variant\n  template <class... Types>\n  class variant {\n  public:\n\n    // 20.7.2.1, constructors\n    constexpr variant() noexcept(see below);\n    variant(const variant&);\n    variant(variant&&) noexcept(see below);\n\n    template <class T> constexpr variant(T&&) noexcept(see below);\n\n    template <class T, class... Args>\n    constexpr explicit variant(in_place_type_t<T>, Args&&...);\n\n    template <class T, class U, class... Args>\n    constexpr explicit variant(\n        in_place_type_t<T>, initializer_list<U>, Args&&...);\n\n    template <size_t I, class... Args>\n    constexpr explicit variant(in_place_index_t<I>, Args&&...);\n\n    template <size_t I, class U, class... Args>\n    constexpr explicit variant(\n        in_place_index_t<I>, initializer_list<U>, Args&&...);\n\n    // 20.7.2.2, destructor\n    ~variant();\n\n    // 20.7.2.3, assignment\n    variant& operator=(const variant&);\n    variant& operator=(variant&&) noexcept(see below);\n\n    template <class T> variant& operator=(T&&) noexcept(see below);\n\n    // 20.7.2.4, modifiers\n    template <class T, class... Args>\n    T& emplace(Args&&...);\n\n    template <class T, class U, class... Args>\n    T& emplace(initializer_list<U>, Args&&...);\n\n    template <size_t I, class... Args>\n    variant_alternative<I, variant>& emplace(Args&&...);\n\n    template <size_t I, class U, class...  Args>\n    variant_alternative<I, variant>& emplace(initializer_list<U>, Args&&...);\n\n    // 20.7.2.5, value status\n    constexpr bool valueless_by_exception() const noexcept;\n    constexpr size_t index() const noexcept;\n\n    // 20.7.2.6, swap\n    void swap(variant&) noexcept(see below);\n  };\n\n  // 20.7.3, variant helper classes\n  template <class T> struct variant_size; // undefined\n\n  template <class T>\n  constexpr size_t variant_size_v = variant_size<T>::value;\n\n  template <class T> struct variant_size<const T>;\n  template <class T> struct variant_size<volatile T>;\n  template <class T> struct variant_size<const volatile T>;\n\n  template <class... Types>\n  struct variant_size<variant<Types...>>;\n\n  template <size_t I, class T> struct variant_alternative; // undefined\n\n  template <size_t I, class T>\n  using variant_alternative_t = typename variant_alternative<I, T>::type;\n\n  template <size_t I, class T> struct variant_alternative<I, const T>;\n  template <size_t I, class T> struct variant_alternative<I, volatile T>;\n  template <size_t I, class T> struct variant_alternative<I, const volatile T>;\n\n  template <size_t I, class... Types>\n  struct variant_alternative<I, variant<Types...>>;\n\n  constexpr size_t variant_npos = -1;\n\n  // 20.7.4, value access\n  template <class T, class... Types>\n  constexpr bool holds_alternative(const variant<Types...>&) noexcept;\n\n  template <size_t I, class... Types>\n  constexpr variant_alternative_t<I, variant<Types...>>&\n  get(variant<Types...>&);\n\n  template <size_t I, class... Types>\n  constexpr variant_alternative_t<I, variant<Types...>>&&\n  get(variant<Types...>&&);\n\n  template <size_t I, class... Types>\n  constexpr variant_alternative_t<I, variant<Types...>> const&\n  get(const variant<Types...>&);\n\n  template <size_t I, class... Types>\n  constexpr variant_alternative_t<I, variant<Types...>> const&&\n  get(const variant<Types...>&&);\n\n  template <class T, class...  Types>\n  constexpr T& get(variant<Types...>&);\n\n  template <class T, class... Types>\n  constexpr T&& get(variant<Types...>&&);\n\n  template <class T, class... Types>\n  constexpr const T& get(const variant<Types...>&);\n\n  template <class T, class... Types>\n  constexpr const T&& get(const variant<Types...>&&);\n\n  template <size_t I, class... Types>\n  constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>\n  get_if(variant<Types...>*) noexcept;\n\n  template <size_t I, class... Types>\n  constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>\n  get_if(const variant<Types...>*) noexcept;\n\n  template <class T, class... Types>\n  constexpr add_pointer_t<T>\n  get_if(variant<Types...>*) noexcept;\n\n  template <class T, class... Types>\n  constexpr add_pointer_t<const T>\n  get_if(const variant<Types...>*) noexcept;\n\n  // 20.7.5, relational operators\n  template <class... Types>\n  constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);\n\n  template <class... Types>\n  constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);\n\n  template <class... Types>\n  constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);\n\n  template <class... Types>\n  constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);\n\n  template <class... Types>\n  constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);\n\n  template <class... Types>\n  constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);\n\n  // 20.7.6, visitation\n  template <class Visitor, class... Variants>\n  constexpr see below visit(Visitor&&, Variants&&...);\n\n  // 20.7.7, class monostate\n  struct monostate;\n\n  // 20.7.8, monostate relational operators\n  constexpr bool operator<(monostate, monostate) noexcept;\n  constexpr bool operator>(monostate, monostate) noexcept;\n  constexpr bool operator<=(monostate, monostate) noexcept;\n  constexpr bool operator>=(monostate, monostate) noexcept;\n  constexpr bool operator==(monostate, monostate) noexcept;\n  constexpr bool operator!=(monostate, monostate) noexcept;\n\n  // 20.7.9, specialized algorithms\n  template <class... Types>\n  void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);\n\n  // 20.7.10, class bad_variant_access\n  class bad_variant_access;\n\n  // 20.7.11, hash support\n  template <class T> struct hash;\n  template <class... Types> struct hash<variant<Types...>>;\n  template <> struct hash<monostate>;\n\n} // namespace std\n\n*/\n\n#include <cstddef>\n#include <exception>\n#include <functional>\n#include <initializer_list>\n#include <limits>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include \"config.hpp\"\n#include \"in_place.hpp\"\n#include \"lib.hpp\"\n\nnamespace mpark {\n\n#ifdef MPARK_RETURN_TYPE_DEDUCTION\n\n#define AUTO auto\n#define AUTO_RETURN(...) { return __VA_ARGS__; }\n\n#define AUTO_REFREF auto &&\n#define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; }\n\n#define DECLTYPE_AUTO decltype(auto)\n#define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; }\n\n#else\n\n#define AUTO auto\n#define AUTO_RETURN(...) \\\n  -> lib::decay_t<decltype(__VA_ARGS__)> { return __VA_ARGS__; }\n\n#define AUTO_REFREF auto\n#define AUTO_REFREF_RETURN(...)                                           \\\n  -> decltype((__VA_ARGS__)) {                                            \\\n    static_assert(std::is_reference<decltype((__VA_ARGS__))>::value, \"\"); \\\n    return __VA_ARGS__;                                                   \\\n  }\n\n#define DECLTYPE_AUTO auto\n#define DECLTYPE_AUTO_RETURN(...) \\\n  -> decltype(__VA_ARGS__) { return __VA_ARGS__; }\n\n#endif\n\n  class bad_variant_access : public std::exception {\n    public:\n    virtual const char *what() const noexcept override { return \"bad_variant_access\"; }\n  };\n\n  [[noreturn]] inline void throw_bad_variant_access() {\n#ifdef MPARK_EXCEPTIONS\n    throw bad_variant_access{};\n#else\n    std::terminate();\n    MPARK_BUILTIN_UNREACHABLE;\n#endif\n  }\n\n  template <typename... Ts>\n  class variant;\n\n  template <typename T>\n  struct variant_size;\n\n#ifdef MPARK_VARIABLE_TEMPLATES\n  template <typename T>\n  constexpr std::size_t variant_size_v = variant_size<T>::value;\n#endif\n\n  template <typename T>\n  struct variant_size<const T> : variant_size<T> {};\n\n  template <typename T>\n  struct variant_size<volatile T> : variant_size<T> {};\n\n  template <typename T>\n  struct variant_size<const volatile T> : variant_size<T> {};\n\n  template <typename... Ts>\n  struct variant_size<variant<Ts...>> : lib::size_constant<sizeof...(Ts)> {};\n\n  template <std::size_t I, typename T>\n  struct variant_alternative;\n\n  template <std::size_t I, typename T>\n  using variant_alternative_t = typename variant_alternative<I, T>::type;\n\n  template <std::size_t I, typename T>\n  struct variant_alternative<I, const T>\n      : std::add_const<variant_alternative_t<I, T>> {};\n\n  template <std::size_t I, typename T>\n  struct variant_alternative<I, volatile T>\n      : std::add_volatile<variant_alternative_t<I, T>> {};\n\n  template <std::size_t I, typename T>\n  struct variant_alternative<I, const volatile T>\n      : std::add_cv<variant_alternative_t<I, T>> {};\n\n  template <std::size_t I, typename... Ts>\n  struct variant_alternative<I, variant<Ts...>> {\n    static_assert(I < sizeof...(Ts),\n                  \"index out of bounds in `std::variant_alternative<>`\");\n    using type = lib::type_pack_element_t<I, Ts...>;\n  };\n\n  constexpr std::size_t variant_npos = static_cast<std::size_t>(-1);\n\n  namespace detail {\n\n    constexpr std::size_t not_found = static_cast<std::size_t>(-1);\n    constexpr std::size_t ambiguous = static_cast<std::size_t>(-2);\n\n#ifdef MPARK_CPP14_CONSTEXPR\n    template <typename T, typename... Ts>\n    inline constexpr std::size_t find_index() {\n      constexpr lib::array<bool, sizeof...(Ts)> matches = {\n          {std::is_same<T, Ts>::value...}\n      };\n      std::size_t result = not_found;\n      for (std::size_t i = 0; i < sizeof...(Ts); ++i) {\n        if (matches[i]) {\n          if (result != not_found) {\n            return ambiguous;\n          }\n          result = i;\n        }\n      }\n      return result;\n    }\n#else\n    inline constexpr std::size_t find_index_impl(std::size_t result,\n                                                 std::size_t) {\n      return result;\n    }\n\n    template <typename... Bs>\n    inline constexpr std::size_t find_index_impl(std::size_t result,\n                                                 std::size_t idx,\n                                                 bool b,\n                                                 Bs... bs) {\n      return b ? (result != not_found ? ambiguous\n                                      : find_index_impl(idx, idx + 1, bs...))\n               : find_index_impl(result, idx + 1, bs...);\n    }\n\n    template <typename T, typename... Ts>\n    inline constexpr std::size_t find_index() {\n      return find_index_impl(not_found, 0, std::is_same<T, Ts>::value...);\n    }\n#endif\n\n    template <std::size_t I>\n    using find_index_sfinae_impl =\n        lib::enable_if_t<I != not_found && I != ambiguous,\n                         lib::size_constant<I>>;\n\n    template <typename T, typename... Ts>\n    using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>;\n\n    template <std::size_t I>\n    struct find_index_checked_impl : lib::size_constant<I> {\n      static_assert(I != not_found, \"the specified type is not found.\");\n      static_assert(I != ambiguous, \"the specified type is ambiguous.\");\n    };\n\n    template <typename T, typename... Ts>\n    using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>;\n\n    struct valueless_t {};\n\n    enum class Trait { TriviallyAvailable, Available, Unavailable };\n\n    template <typename T,\n              template <typename> class IsTriviallyAvailable,\n              template <typename> class IsAvailable>\n    inline constexpr Trait trait() {\n      return IsTriviallyAvailable<T>::value\n                 ? Trait::TriviallyAvailable\n                 : IsAvailable<T>::value ? Trait::Available\n                                         : Trait::Unavailable;\n    }\n\n#ifdef MPARK_CPP14_CONSTEXPR\n    template <typename... Traits>\n    inline constexpr Trait common_trait(Traits... traits_) {\n      Trait result = Trait::TriviallyAvailable;\n      lib::array<Trait, sizeof...(Traits)> traits = {{traits_...}};\n      for (std::size_t i = 0; i < sizeof...(Traits); ++i) {\n        Trait t = traits[i];\n        if (static_cast<int>(t) > static_cast<int>(result)) {\n          result = t;\n        }\n      }\n      return result;\n    }\n#else\n    inline constexpr Trait common_trait_impl(Trait result) { return result; }\n\n    template <typename... Traits>\n    inline constexpr Trait common_trait_impl(Trait result,\n                                             Trait t,\n                                             Traits... ts) {\n      return static_cast<int>(t) > static_cast<int>(result)\n                 ? common_trait_impl(t, ts...)\n                 : common_trait_impl(result, ts...);\n    }\n\n    template <typename... Traits>\n    inline constexpr Trait common_trait(Traits... ts) {\n      return common_trait_impl(Trait::TriviallyAvailable, ts...);\n    }\n#endif\n\n    template <typename... Ts>\n    struct traits {\n      static constexpr Trait copy_constructible_trait =\n          common_trait(trait<Ts,\n                             lib::is_trivially_copy_constructible,\n                             std::is_copy_constructible>()...);\n\n      static constexpr Trait move_constructible_trait =\n          common_trait(trait<Ts,\n                             lib::is_trivially_move_constructible,\n                             std::is_move_constructible>()...);\n\n      static constexpr Trait copy_assignable_trait =\n          common_trait(copy_constructible_trait,\n                       trait<Ts,\n                             lib::is_trivially_copy_assignable,\n                             std::is_copy_assignable>()...);\n\n      static constexpr Trait move_assignable_trait =\n          common_trait(move_constructible_trait,\n                       trait<Ts,\n                             lib::is_trivially_move_assignable,\n                             std::is_move_assignable>()...);\n\n      static constexpr Trait destructible_trait =\n          common_trait(trait<Ts,\n                             std::is_trivially_destructible,\n                             std::is_destructible>()...);\n    };\n\n    namespace access {\n\n      struct recursive_union {\n#ifdef MPARK_RETURN_TYPE_DEDUCTION\n        template <typename V>\n        inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) {\n          return lib::forward<V>(v).head_;\n        }\n\n        template <typename V, std::size_t I>\n        inline static constexpr auto &&get_alt(V &&v, in_place_index_t<I>) {\n          return get_alt(lib::forward<V>(v).tail_, in_place_index_t<I - 1>{});\n        }\n#else\n        template <std::size_t I, bool Dummy = true>\n        struct get_alt_impl {\n          template <typename V>\n          inline constexpr AUTO_REFREF operator()(V &&v) const\n            AUTO_REFREF_RETURN(get_alt_impl<I - 1>{}(lib::forward<V>(v).tail_))\n        };\n\n        template <bool Dummy>\n        struct get_alt_impl<0, Dummy> {\n          template <typename V>\n          inline constexpr AUTO_REFREF operator()(V &&v) const\n            AUTO_REFREF_RETURN(lib::forward<V>(v).head_)\n        };\n\n        template <typename V, std::size_t I>\n        inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t<I>)\n          AUTO_REFREF_RETURN(get_alt_impl<I>{}(lib::forward<V>(v)))\n#endif\n      };\n\n      struct base {\n        template <std::size_t I, typename V>\n        inline static constexpr AUTO_REFREF get_alt(V &&v)\n#ifdef _MSC_VER\n          AUTO_REFREF_RETURN(recursive_union::get_alt(\n              lib::forward<V>(v).data_, in_place_index_t<I>{}))\n#else\n          AUTO_REFREF_RETURN(recursive_union::get_alt(\n              data(lib::forward<V>(v)), in_place_index_t<I>{}))\n#endif\n      };\n\n      struct variant {\n        template <std::size_t I, typename V>\n        inline static constexpr AUTO_REFREF get_alt(V &&v)\n          AUTO_REFREF_RETURN(base::get_alt<I>(lib::forward<V>(v).impl_))\n      };\n\n    }  // namespace access\n\n    namespace visitation {\n\n#if defined(MPARK_CPP14_CONSTEXPR) && !defined(_MSC_VER)\n#define MPARK_VARIANT_SWITCH_VISIT\n#endif\n\n      struct base {\n        template <typename Visitor, typename... Vs>\n        using dispatch_result_t = decltype(\n            lib::invoke(std::declval<Visitor>(),\n                        access::base::get_alt<0>(std::declval<Vs>())...));\n\n        template <typename Expected>\n        struct expected {\n          template <typename Actual>\n          inline static constexpr bool but_got() {\n            return std::is_same<Expected, Actual>::value;\n          }\n        };\n\n        template <typename Expected, typename Actual>\n        struct visit_return_type_check {\n          static_assert(\n              expected<Expected>::template but_got<Actual>(),\n              \"`visit` requires the visitor to have a single return type\");\n\n          template <typename Visitor, typename... Alts>\n          inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor,\n                                                       Alts &&... alts)\n            DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),\n                                             lib::forward<Alts>(alts)...))\n        };\n\n#ifdef MPARK_VARIANT_SWITCH_VISIT\n        template <bool B, typename R, typename... ITs>\n        struct dispatcher;\n\n        template <typename R, typename... ITs>\n        struct dispatcher<false, R, ITs...> {\n          template <std::size_t B, typename F, typename... Vs>\n          MPARK_ALWAYS_INLINE static constexpr R dispatch(\n              F &&, typename ITs::type &&..., Vs &&...) {\n            MPARK_BUILTIN_UNREACHABLE;\n          }\n\n          template <std::size_t I, typename F, typename... Vs>\n          MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&, Vs &&...) {\n            MPARK_BUILTIN_UNREACHABLE;\n          }\n\n          template <std::size_t B, typename F, typename... Vs>\n          MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t,\n                                                             F &&,\n                                                             Vs &&...) {\n            MPARK_BUILTIN_UNREACHABLE;\n          }\n        };\n\n        template <typename R, typename... ITs>\n        struct dispatcher<true, R, ITs...> {\n          template <std::size_t B, typename F>\n          MPARK_ALWAYS_INLINE static constexpr R dispatch(\n              F &&f, typename ITs::type &&... visited_vs) {\n            using Expected = R;\n            using Actual = decltype(lib::invoke(\n                lib::forward<F>(f),\n                access::base::get_alt<ITs::value>(\n                    lib::forward<typename ITs::type>(visited_vs))...));\n            return visit_return_type_check<Expected, Actual>::invoke(\n                lib::forward<F>(f),\n                access::base::get_alt<ITs::value>(\n                    lib::forward<typename ITs::type>(visited_vs))...);\n          }\n\n          template <std::size_t B, typename F, typename V, typename... Vs>\n          MPARK_ALWAYS_INLINE static constexpr R dispatch(\n              F &&f, typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) {\n#define MPARK_DISPATCH(I)                                                   \\\n  dispatcher<(I < lib::decay_t<V>::size()),                                 \\\n             R,                                                             \\\n             ITs...,                                                        \\\n             lib::indexed_type<I, V>>::                                     \\\n      template dispatch<0>(lib::forward<F>(f),                              \\\n                           lib::forward<typename ITs::type>(visited_vs)..., \\\n                           lib::forward<V>(v),                              \\\n                           lib::forward<Vs>(vs)...)\n\n#define MPARK_DEFAULT(I)                                                      \\\n  dispatcher<(I < lib::decay_t<V>::size()), R, ITs...>::template dispatch<I>( \\\n      lib::forward<F>(f),                                                     \\\n      lib::forward<typename ITs::type>(visited_vs)...,                        \\\n      lib::forward<V>(v),                                                     \\\n      lib::forward<Vs>(vs)...)\n\n            switch (v.index()) {\n              case B + 0: return MPARK_DISPATCH(B + 0);\n              case B + 1: return MPARK_DISPATCH(B + 1);\n              case B + 2: return MPARK_DISPATCH(B + 2);\n              case B + 3: return MPARK_DISPATCH(B + 3);\n              case B + 4: return MPARK_DISPATCH(B + 4);\n              case B + 5: return MPARK_DISPATCH(B + 5);\n              case B + 6: return MPARK_DISPATCH(B + 6);\n              case B + 7: return MPARK_DISPATCH(B + 7);\n              case B + 8: return MPARK_DISPATCH(B + 8);\n              case B + 9: return MPARK_DISPATCH(B + 9);\n              case B + 10: return MPARK_DISPATCH(B + 10);\n              case B + 11: return MPARK_DISPATCH(B + 11);\n              case B + 12: return MPARK_DISPATCH(B + 12);\n              case B + 13: return MPARK_DISPATCH(B + 13);\n              case B + 14: return MPARK_DISPATCH(B + 14);\n              case B + 15: return MPARK_DISPATCH(B + 15);\n              case B + 16: return MPARK_DISPATCH(B + 16);\n              case B + 17: return MPARK_DISPATCH(B + 17);\n              case B + 18: return MPARK_DISPATCH(B + 18);\n              case B + 19: return MPARK_DISPATCH(B + 19);\n              case B + 20: return MPARK_DISPATCH(B + 20);\n              case B + 21: return MPARK_DISPATCH(B + 21);\n              case B + 22: return MPARK_DISPATCH(B + 22);\n              case B + 23: return MPARK_DISPATCH(B + 23);\n              case B + 24: return MPARK_DISPATCH(B + 24);\n              case B + 25: return MPARK_DISPATCH(B + 25);\n              case B + 26: return MPARK_DISPATCH(B + 26);\n              case B + 27: return MPARK_DISPATCH(B + 27);\n              case B + 28: return MPARK_DISPATCH(B + 28);\n              case B + 29: return MPARK_DISPATCH(B + 29);\n              case B + 30: return MPARK_DISPATCH(B + 30);\n              case B + 31: return MPARK_DISPATCH(B + 31);\n              default: return MPARK_DEFAULT(B + 32);\n            }\n\n#undef MPARK_DEFAULT\n#undef MPARK_DISPATCH\n          }\n\n          template <std::size_t I, typename F, typename... Vs>\n          MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&f,\n                                                               Vs &&... vs) {\n            using Expected = R;\n            using Actual = decltype(\n                lib::invoke(lib::forward<F>(f),\n                            access::base::get_alt<I>(lib::forward<Vs>(vs))...));\n            return visit_return_type_check<Expected, Actual>::invoke(\n                lib::forward<F>(f),\n                access::base::get_alt<I>(lib::forward<Vs>(vs))...);\n          }\n\n          template <std::size_t B, typename F, typename V, typename... Vs>\n          MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t index,\n                                                             F &&f,\n                                                             V &&v,\n                                                             Vs &&... vs) {\n            static_assert(lib::all<(lib::decay_t<V>::size() ==\n                                    lib::decay_t<Vs>::size())...>::value,\n                          \"all of the variants must be the same size.\");\n#define MPARK_DISPATCH_AT(I)                                               \\\n  dispatcher<(I < lib::decay_t<V>::size()), R>::template dispatch_case<I>( \\\n      lib::forward<F>(f), lib::forward<V>(v), lib::forward<Vs>(vs)...)\n\n#define MPARK_DEFAULT(I)                                                 \\\n  dispatcher<(I < lib::decay_t<V>::size()), R>::template dispatch_at<I>( \\\n      index, lib::forward<F>(f), lib::forward<V>(v), lib::forward<Vs>(vs)...)\n\n            switch (index) {\n              case B + 0: return MPARK_DISPATCH_AT(B + 0);\n              case B + 1: return MPARK_DISPATCH_AT(B + 1);\n              case B + 2: return MPARK_DISPATCH_AT(B + 2);\n              case B + 3: return MPARK_DISPATCH_AT(B + 3);\n              case B + 4: return MPARK_DISPATCH_AT(B + 4);\n              case B + 5: return MPARK_DISPATCH_AT(B + 5);\n              case B + 6: return MPARK_DISPATCH_AT(B + 6);\n              case B + 7: return MPARK_DISPATCH_AT(B + 7);\n              case B + 8: return MPARK_DISPATCH_AT(B + 8);\n              case B + 9: return MPARK_DISPATCH_AT(B + 9);\n              case B + 10: return MPARK_DISPATCH_AT(B + 10);\n              case B + 11: return MPARK_DISPATCH_AT(B + 11);\n              case B + 12: return MPARK_DISPATCH_AT(B + 12);\n              case B + 13: return MPARK_DISPATCH_AT(B + 13);\n              case B + 14: return MPARK_DISPATCH_AT(B + 14);\n              case B + 15: return MPARK_DISPATCH_AT(B + 15);\n              case B + 16: return MPARK_DISPATCH_AT(B + 16);\n              case B + 17: return MPARK_DISPATCH_AT(B + 17);\n              case B + 18: return MPARK_DISPATCH_AT(B + 18);\n              case B + 19: return MPARK_DISPATCH_AT(B + 19);\n              case B + 20: return MPARK_DISPATCH_AT(B + 20);\n              case B + 21: return MPARK_DISPATCH_AT(B + 21);\n              case B + 22: return MPARK_DISPATCH_AT(B + 22);\n              case B + 23: return MPARK_DISPATCH_AT(B + 23);\n              case B + 24: return MPARK_DISPATCH_AT(B + 24);\n              case B + 25: return MPARK_DISPATCH_AT(B + 25);\n              case B + 26: return MPARK_DISPATCH_AT(B + 26);\n              case B + 27: return MPARK_DISPATCH_AT(B + 27);\n              case B + 28: return MPARK_DISPATCH_AT(B + 28);\n              case B + 29: return MPARK_DISPATCH_AT(B + 29);\n              case B + 30: return MPARK_DISPATCH_AT(B + 30);\n              case B + 31: return MPARK_DISPATCH_AT(B + 31);\n              default: return MPARK_DEFAULT(B + 32);\n            }\n\n#undef MPARK_DEFAULT\n#undef MPARK_DISPATCH_AT\n          }\n        };\n#else\n        template <typename T>\n        inline static constexpr const T &at(const T &elem) noexcept {\n          return elem;\n        }\n\n        template <typename T, std::size_t N, typename... Is>\n        inline static constexpr const lib::remove_all_extents_t<T> &at(\n            const lib::array<T, N> &elems, std::size_t i, Is... is) noexcept {\n          return at(elems[i], is...);\n        }\n\n        template <typename F, typename... Fs>\n        inline static constexpr lib::array<lib::decay_t<F>, sizeof...(Fs) + 1>\n        make_farray(F &&f, Fs &&... fs) {\n          return {{lib::forward<F>(f), lib::forward<Fs>(fs)...}};\n        }\n\n        template <typename F, typename... Vs>\n        struct make_fmatrix_impl {\n\n          template <std::size_t... Is>\n          inline static constexpr dispatch_result_t<F, Vs...> dispatch(\n              F &&f, Vs &&... vs) {\n            using Expected = dispatch_result_t<F, Vs...>;\n            using Actual = decltype(lib::invoke(\n                lib::forward<F>(f),\n                access::base::get_alt<Is>(lib::forward<Vs>(vs))...));\n            return visit_return_type_check<Expected, Actual>::invoke(\n                lib::forward<F>(f),\n                access::base::get_alt<Is>(lib::forward<Vs>(vs))...);\n          }\n\n#ifdef MPARK_RETURN_TYPE_DEDUCTION\n          template <std::size_t... Is>\n          inline static constexpr auto impl(lib::index_sequence<Is...>) {\n            return &dispatch<Is...>;\n          }\n\n          template <typename Is, std::size_t... Js, typename... Ls>\n          inline static constexpr auto impl(Is,\n                                            lib::index_sequence<Js...>,\n                                            Ls... ls) {\n            return make_farray(impl(lib::push_back_t<Is, Js>{}, ls...)...);\n          }\n#else\n          template <typename...>\n          struct impl;\n\n          template <std::size_t... Is>\n          struct impl<lib::index_sequence<Is...>> {\n            inline constexpr AUTO operator()() const\n              AUTO_RETURN(&dispatch<Is...>)\n          };\n\n          template <typename Is, std::size_t... Js, typename... Ls>\n          struct impl<Is, lib::index_sequence<Js...>, Ls...> {\n            inline constexpr AUTO operator()() const\n              AUTO_RETURN(\n                  make_farray(impl<lib::push_back_t<Is, Js>, Ls...>{}()...))\n          };\n#endif\n        };\n\n#ifdef MPARK_RETURN_TYPE_DEDUCTION\n        template <typename F, typename... Vs>\n        inline static constexpr auto make_fmatrix() {\n          return make_fmatrix_impl<F, Vs...>::impl(\n              lib::index_sequence<>{},\n              lib::make_index_sequence<lib::decay_t<Vs>::size()>{}...);\n        }\n#else\n        template <typename F, typename... Vs>\n        inline static constexpr AUTO make_fmatrix()\n          AUTO_RETURN(\n              typename make_fmatrix_impl<F, Vs...>::template impl<\n                  lib::index_sequence<>,\n                  lib::make_index_sequence<lib::decay_t<Vs>::size()>...>{}())\n#endif\n\n        template <typename F, typename... Vs>\n        struct make_fdiagonal_impl {\n          template <std::size_t I>\n          inline static constexpr dispatch_result_t<F, Vs...> dispatch(\n              F &&f, Vs &&... vs) {\n            using Expected = dispatch_result_t<F, Vs...>;\n            using Actual = decltype(\n                lib::invoke(lib::forward<F>(f),\n                            access::base::get_alt<I>(lib::forward<Vs>(vs))...));\n            return visit_return_type_check<Expected, Actual>::invoke(\n                lib::forward<F>(f),\n                access::base::get_alt<I>(lib::forward<Vs>(vs))...);\n          }\n\n          template <std::size_t... Is>\n          inline static constexpr AUTO impl(lib::index_sequence<Is...>)\n            AUTO_RETURN(make_farray(&dispatch<Is>...))\n        };\n\n        template <typename F, typename V, typename... Vs>\n        inline static constexpr auto make_fdiagonal()\n            -> decltype(make_fdiagonal_impl<F, V, Vs...>::impl(\n                lib::make_index_sequence<lib::decay_t<V>::size()>{})) {\n          static_assert(lib::all<(lib::decay_t<V>::size() ==\n                                  lib::decay_t<Vs>::size())...>::value,\n                        \"all of the variants must be the same size.\");\n          return make_fdiagonal_impl<F, V, Vs...>::impl(\n              lib::make_index_sequence<lib::decay_t<V>::size()>{});\n        }\n#endif\n      };\n\n#if !defined(MPARK_VARIANT_SWITCH_VISIT) && \\\n    (!defined(_MSC_VER) || _MSC_VER >= 1910)\n      template <typename F, typename... Vs>\n      using fmatrix_t = decltype(base::make_fmatrix<F, Vs...>());\n\n      template <typename F, typename... Vs>\n      struct fmatrix {\n        static constexpr fmatrix_t<F, Vs...> value =\n            base::make_fmatrix<F, Vs...>();\n      };\n\n      template <typename F, typename... Vs>\n      constexpr fmatrix_t<F, Vs...> fmatrix<F, Vs...>::value;\n\n      template <typename F, typename... Vs>\n      using fdiagonal_t = decltype(base::make_fdiagonal<F, Vs...>());\n\n      template <typename F, typename... Vs>\n      struct fdiagonal {\n        static constexpr fdiagonal_t<F, Vs...> value =\n            base::make_fdiagonal<F, Vs...>();\n      };\n\n      template <typename F, typename... Vs>\n      constexpr fdiagonal_t<F, Vs...> fdiagonal<F, Vs...>::value;\n#endif\n\n      struct alt {\n        template <typename Visitor, typename... Vs>\n        inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,\n                                                        Vs &&... vs)\n#ifdef MPARK_VARIANT_SWITCH_VISIT\n          DECLTYPE_AUTO_RETURN(\n              base::dispatcher<\n                  true,\n                  base::dispatch_result_t<Visitor,\n                                          decltype(as_base(\n                                              lib::forward<Vs>(vs)))...>>::\n                  template dispatch<0>(lib::forward<Visitor>(visitor),\n                                       as_base(lib::forward<Vs>(vs))...))\n#elif !defined(_MSC_VER) || _MSC_VER >= 1910\n          DECLTYPE_AUTO_RETURN(base::at(\n              fmatrix<Visitor &&,\n                      decltype(as_base(lib::forward<Vs>(vs)))...>::value,\n              vs.index()...)(lib::forward<Visitor>(visitor),\n                             as_base(lib::forward<Vs>(vs))...))\n#else\n          DECLTYPE_AUTO_RETURN(base::at(\n              base::make_fmatrix<Visitor &&,\n                      decltype(as_base(lib::forward<Vs>(vs)))...>(),\n              vs.index()...)(lib::forward<Visitor>(visitor),\n                             as_base(lib::forward<Vs>(vs))...))\n#endif\n\n        template <typename Visitor, typename... Vs>\n        inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,\n                                                           Visitor &&visitor,\n                                                           Vs &&... vs)\n#ifdef MPARK_VARIANT_SWITCH_VISIT\n          DECLTYPE_AUTO_RETURN(\n              base::dispatcher<\n                  true,\n                  base::dispatch_result_t<Visitor,\n                                          decltype(as_base(\n                                              lib::forward<Vs>(vs)))...>>::\n                  template dispatch_at<0>(index,\n                                          lib::forward<Visitor>(visitor),\n                                          as_base(lib::forward<Vs>(vs))...))\n#elif !defined(_MSC_VER) || _MSC_VER >= 1910\n          DECLTYPE_AUTO_RETURN(base::at(\n              fdiagonal<Visitor &&,\n                        decltype(as_base(lib::forward<Vs>(vs)))...>::value,\n              index)(lib::forward<Visitor>(visitor),\n                     as_base(lib::forward<Vs>(vs))...))\n#else\n          DECLTYPE_AUTO_RETURN(base::at(\n              base::make_fdiagonal<Visitor &&,\n                        decltype(as_base(lib::forward<Vs>(vs)))...>(),\n              index)(lib::forward<Visitor>(visitor),\n                     as_base(lib::forward<Vs>(vs))...))\n#endif\n      };\n\n      struct variant {\n        private:\n        template <typename Visitor>\n        struct visitor {\n          template <typename... Values>\n          inline static constexpr bool does_not_handle() {\n            return lib::is_invocable<Visitor, Values...>::value;\n          }\n        };\n\n        template <typename Visitor, typename... Values>\n        struct visit_exhaustiveness_check {\n          static_assert(visitor<Visitor>::template does_not_handle<Values...>(),\n                        \"`visit` requires the visitor to be exhaustive.\");\n\n          inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor,\n                                                       Values &&... values)\n            DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),\n                                             lib::forward<Values>(values)...))\n        };\n\n        template <typename Visitor>\n        struct value_visitor {\n          Visitor &&visitor_;\n\n          template <typename... Alts>\n          inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const\n            DECLTYPE_AUTO_RETURN(\n                visit_exhaustiveness_check<\n                    Visitor,\n                    decltype((lib::forward<Alts>(alts).value))...>::\n                    invoke(lib::forward<Visitor>(visitor_),\n                           lib::forward<Alts>(alts).value...))\n        };\n\n        template <typename Visitor>\n        inline static constexpr AUTO make_value_visitor(Visitor &&visitor)\n          AUTO_RETURN(value_visitor<Visitor>{lib::forward<Visitor>(visitor)})\n\n        public:\n        template <typename Visitor, typename... Vs>\n        inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,\n                                                        Vs &&... vs)\n          DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward<Visitor>(visitor),\n                                              lib::forward<Vs>(vs).impl_...))\n\n        template <typename Visitor, typename... Vs>\n        inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,\n                                                           Visitor &&visitor,\n                                                           Vs &&... vs)\n          DECLTYPE_AUTO_RETURN(\n              alt::visit_alt_at(index,\n                                lib::forward<Visitor>(visitor),\n                                lib::forward<Vs>(vs).impl_...))\n\n        template <typename Visitor, typename... Vs>\n        inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor,\n                                                          Vs &&... vs)\n          DECLTYPE_AUTO_RETURN(\n              visit_alt(make_value_visitor(lib::forward<Visitor>(visitor)),\n                        lib::forward<Vs>(vs)...))\n\n        template <typename Visitor, typename... Vs>\n        inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index,\n                                                             Visitor &&visitor,\n                                                             Vs &&... vs)\n          DECLTYPE_AUTO_RETURN(\n              visit_alt_at(index,\n                           make_value_visitor(lib::forward<Visitor>(visitor)),\n                           lib::forward<Vs>(vs)...))\n      };\n\n    }  // namespace visitation\n\n    template <std::size_t Index, typename T>\n    struct alt {\n      using value_type = T;\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4244)\n#endif\n      template <typename... Args>\n      inline explicit constexpr alt(in_place_t, Args &&... args)\n          : value(lib::forward<Args>(args)...) {}\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n      T value;\n    };\n\n    template <Trait DestructibleTrait, std::size_t Index, typename... Ts>\n    union recursive_union;\n\n    template <Trait DestructibleTrait, std::size_t Index>\n    union recursive_union<DestructibleTrait, Index> {};\n\n#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor)      \\\n  template <std::size_t Index, typename T, typename... Ts>                 \\\n  union recursive_union<destructible_trait, Index, T, Ts...> {             \\\n    public:                                                                \\\n    inline explicit constexpr recursive_union(valueless_t) noexcept        \\\n        : dummy_{} {}                                                      \\\n                                                                           \\\n    template <typename... Args>                                            \\\n    inline explicit constexpr recursive_union(in_place_index_t<0>,         \\\n                                              Args &&... args)             \\\n        : head_(in_place_t{}, lib::forward<Args>(args)...) {}              \\\n                                                                           \\\n    template <std::size_t I, typename... Args>                             \\\n    inline explicit constexpr recursive_union(in_place_index_t<I>,         \\\n                                              Args &&... args)             \\\n        : tail_(in_place_index_t<I - 1>{}, lib::forward<Args>(args)...) {} \\\n                                                                           \\\n    recursive_union(const recursive_union &) = default;                    \\\n    recursive_union(recursive_union &&) = default;                         \\\n                                                                           \\\n    destructor                                                             \\\n                                                                           \\\n    recursive_union &operator=(const recursive_union &) = default;         \\\n    recursive_union &operator=(recursive_union &&) = default;              \\\n                                                                           \\\n    private:                                                               \\\n    char dummy_;                                                           \\\n    alt<Index, T> head_;                                                   \\\n    recursive_union<destructible_trait, Index + 1, Ts...> tail_;           \\\n                                                                           \\\n    friend struct access::recursive_union;                                 \\\n  }\n\n    MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable,\n                                  ~recursive_union() = default;);\n    MPARK_VARIANT_RECURSIVE_UNION(Trait::Available,\n                                  ~recursive_union() {});\n    MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable,\n                                  ~recursive_union() = delete;);\n\n#undef MPARK_VARIANT_RECURSIVE_UNION\n\n    template <typename... Ts>\n    using index_t = typename std::conditional<\n            sizeof...(Ts) < std::numeric_limits<unsigned char>::max(),\n            unsigned char,\n            typename std::conditional<\n                sizeof...(Ts) < std::numeric_limits<unsigned short>::max(),\n                unsigned short,\n                unsigned int>::type\n            >::type;\n\n    template <Trait DestructibleTrait, typename... Ts>\n    class base {\n      public:\n      inline explicit constexpr base(valueless_t tag) noexcept\n          : data_(tag), index_(static_cast<index_t<Ts...>>(-1)) {}\n\n      template <std::size_t I, typename... Args>\n      inline explicit constexpr base(in_place_index_t<I>, Args &&... args)\n          : data_(in_place_index_t<I>{}, lib::forward<Args>(args)...),\n            index_(I) {}\n\n      inline constexpr bool valueless_by_exception() const noexcept {\n        return index_ == static_cast<index_t<Ts...>>(-1);\n      }\n\n      inline constexpr std::size_t index() const noexcept {\n        return valueless_by_exception() ? variant_npos : index_;\n      }\n\n      protected:\n      using data_t = recursive_union<DestructibleTrait, 0, Ts...>;\n\n      friend inline constexpr base &as_base(base &b) { return b; }\n      friend inline constexpr const base &as_base(const base &b) { return b; }\n      friend inline constexpr base &&as_base(base &&b) { return lib::move(b); }\n      friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); }\n\n      friend inline constexpr data_t &data(base &b) { return b.data_; }\n      friend inline constexpr const data_t &data(const base &b) { return b.data_; }\n      friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; }\n      friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; }\n\n      inline static constexpr std::size_t size() { return sizeof...(Ts); }\n\n      data_t data_;\n      index_t<Ts...> index_;\n\n      friend struct access::base;\n      friend struct visitation::base;\n    };\n\n    struct dtor {\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4100)\n#endif\n      template <typename Alt>\n      inline void operator()(Alt &alt) const noexcept { alt.~Alt(); }\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n    };\n\n#if !defined(_MSC_VER) || _MSC_VER >= 1910\n#define MPARK_INHERITING_CTOR(type, base) using base::base;\n#else\n#define MPARK_INHERITING_CTOR(type, base)         \\\n  template <typename... Args>                     \\\n  inline explicit constexpr type(Args &&... args) \\\n      : base(lib::forward<Args>(args)...) {}\n#endif\n\n    template <typename Traits, Trait = Traits::destructible_trait>\n    class destructor;\n\n#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \\\n  template <typename... Ts>                                               \\\n  class destructor<traits<Ts...>, destructible_trait>                     \\\n      : public base<destructible_trait, Ts...> {                          \\\n    using super = base<destructible_trait, Ts...>;                        \\\n                                                                          \\\n    public:                                                               \\\n    MPARK_INHERITING_CTOR(destructor, super)                              \\\n    using super::operator=;                                               \\\n                                                                          \\\n    destructor(const destructor &) = default;                             \\\n    destructor(destructor &&) = default;                                  \\\n    definition                                                            \\\n    destructor &operator=(const destructor &) = default;                  \\\n    destructor &operator=(destructor &&) = default;                       \\\n                                                                          \\\n    protected:                                                            \\\n    destroy                                                               \\\n  }\n\n    MPARK_VARIANT_DESTRUCTOR(\n        Trait::TriviallyAvailable,\n        ~destructor() = default;,\n        inline void destroy() noexcept {\n          this->index_ = static_cast<index_t<Ts...>>(-1);\n        });\n\n    MPARK_VARIANT_DESTRUCTOR(\n        Trait::Available,\n        ~destructor() { destroy(); },\n        inline void destroy() noexcept {\n          if (!this->valueless_by_exception()) {\n            visitation::alt::visit_alt(dtor{}, *this);\n          }\n          this->index_ = static_cast<index_t<Ts...>>(-1);\n        });\n\n    MPARK_VARIANT_DESTRUCTOR(\n        Trait::Unavailable,\n        ~destructor() = delete;,\n        inline void destroy() noexcept = delete;);\n\n#undef MPARK_VARIANT_DESTRUCTOR\n\n    template <typename Traits>\n    class constructor : public destructor<Traits> {\n      using super = destructor<Traits>;\n\n      public:\n      MPARK_INHERITING_CTOR(constructor, super)\n      using super::operator=;\n\n      protected:\n#ifndef MPARK_GENERIC_LAMBDAS\n      struct ctor {\n        template <typename LhsAlt, typename RhsAlt>\n        inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const {\n          constructor::construct_alt(lhs_alt,\n                                     lib::forward<RhsAlt>(rhs_alt).value);\n        }\n      };\n#endif\n\n      template <std::size_t I, typename T, typename... Args>\n      inline static T &construct_alt(alt<I, T> &a, Args &&... args) {\n        auto *result = ::new (static_cast<void *>(lib::addressof(a)))\n            alt<I, T>(in_place_t{}, lib::forward<Args>(args)...);\n        return result->value;\n      }\n\n      template <typename Rhs>\n      inline static void generic_construct(constructor &lhs, Rhs &&rhs) {\n        lhs.destroy();\n        if (!rhs.valueless_by_exception()) {\n          visitation::alt::visit_alt_at(\n              rhs.index(),\n#ifdef MPARK_GENERIC_LAMBDAS\n              [](auto &lhs_alt, auto &&rhs_alt) {\n                constructor::construct_alt(\n                    lhs_alt, lib::forward<decltype(rhs_alt)>(rhs_alt).value);\n              }\n#else\n              ctor{}\n#endif\n              ,\n              lhs,\n              lib::forward<Rhs>(rhs));\n          lhs.index_ = rhs.index_;\n        }\n      }\n    };\n\n    template <typename Traits, Trait = Traits::move_constructible_trait>\n    class move_constructor;\n\n#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \\\n  template <typename... Ts>                                                  \\\n  class move_constructor<traits<Ts...>, move_constructible_trait>            \\\n      : public constructor<traits<Ts...>> {                                  \\\n    using super = constructor<traits<Ts...>>;                                \\\n                                                                             \\\n    public:                                                                  \\\n    MPARK_INHERITING_CTOR(move_constructor, super)                           \\\n    using super::operator=;                                                  \\\n                                                                             \\\n    move_constructor(const move_constructor &) = default;                    \\\n    definition                                                               \\\n    ~move_constructor() = default;                                           \\\n    move_constructor &operator=(const move_constructor &) = default;         \\\n    move_constructor &operator=(move_constructor &&) = default;              \\\n  }\n\n    MPARK_VARIANT_MOVE_CONSTRUCTOR(\n        Trait::TriviallyAvailable,\n        move_constructor(move_constructor &&that) = default;);\n\n    MPARK_VARIANT_MOVE_CONSTRUCTOR(\n        Trait::Available,\n        move_constructor(move_constructor &&that) noexcept(\n            lib::all<std::is_nothrow_move_constructible<Ts>::value...>::value)\n            : move_constructor(valueless_t{}) {\n          this->generic_construct(*this, lib::move(that));\n        });\n\n    MPARK_VARIANT_MOVE_CONSTRUCTOR(\n        Trait::Unavailable,\n        move_constructor(move_constructor &&) = delete;);\n\n#undef MPARK_VARIANT_MOVE_CONSTRUCTOR\n\n    template <typename Traits, Trait = Traits::copy_constructible_trait>\n    class copy_constructor;\n\n#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \\\n  template <typename... Ts>                                                  \\\n  class copy_constructor<traits<Ts...>, copy_constructible_trait>            \\\n      : public move_constructor<traits<Ts...>> {                             \\\n    using super = move_constructor<traits<Ts...>>;                           \\\n                                                                             \\\n    public:                                                                  \\\n    MPARK_INHERITING_CTOR(copy_constructor, super)                           \\\n    using super::operator=;                                                  \\\n                                                                             \\\n    definition                                                               \\\n    copy_constructor(copy_constructor &&) = default;                         \\\n    ~copy_constructor() = default;                                           \\\n    copy_constructor &operator=(const copy_constructor &) = default;         \\\n    copy_constructor &operator=(copy_constructor &&) = default;              \\\n  }\n\n    MPARK_VARIANT_COPY_CONSTRUCTOR(\n        Trait::TriviallyAvailable,\n        copy_constructor(const copy_constructor &that) = default;);\n\n    MPARK_VARIANT_COPY_CONSTRUCTOR(\n        Trait::Available,\n        copy_constructor(const copy_constructor &that)\n            : copy_constructor(valueless_t{}) {\n          this->generic_construct(*this, that);\n        });\n\n    MPARK_VARIANT_COPY_CONSTRUCTOR(\n        Trait::Unavailable,\n        copy_constructor(const copy_constructor &) = delete;);\n\n#undef MPARK_VARIANT_COPY_CONSTRUCTOR\n\n    template <typename Traits>\n    class assignment : public copy_constructor<Traits> {\n      using super = copy_constructor<Traits>;\n\n      public:\n      MPARK_INHERITING_CTOR(assignment, super)\n      using super::operator=;\n\n      template <std::size_t I, typename... Args>\n      inline /* auto & */ auto emplace(Args &&... args)\n          -> decltype(this->construct_alt(access::base::get_alt<I>(*this),\n                                          lib::forward<Args>(args)...)) {\n        this->destroy();\n        auto &result = this->construct_alt(access::base::get_alt<I>(*this),\n                                           lib::forward<Args>(args)...);\n        this->index_ = I;\n        return result;\n      }\n\n      protected:\n#ifndef MPARK_GENERIC_LAMBDAS\n      template <typename That>\n      struct assigner {\n        template <typename ThisAlt, typename ThatAlt>\n        inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const {\n          self->assign_alt(this_alt, lib::forward<ThatAlt>(that_alt).value);\n        }\n        assignment *self;\n      };\n#endif\n\n      template <std::size_t I, typename T, typename Arg>\n      inline void assign_alt(alt<I, T> &a, Arg &&arg) {\n        if (this->index() == I) {\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4244)\n#endif\n          a.value = lib::forward<Arg>(arg);\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n        } else {\n          struct {\n            void operator()(std::true_type) const {\n              this_->emplace<I>(lib::forward<Arg>(arg_));\n            }\n            void operator()(std::false_type) const {\n              this_->emplace<I>(T(lib::forward<Arg>(arg_)));\n            }\n            assignment *this_;\n            Arg &&arg_;\n          } impl{this, lib::forward<Arg>(arg)};\n          impl(lib::bool_constant<\n                   std::is_nothrow_constructible<T, Arg>::value ||\n                   !std::is_nothrow_move_constructible<T>::value>{});\n        }\n      }\n\n      template <typename That>\n      inline void generic_assign(That &&that) {\n        if (this->valueless_by_exception() && that.valueless_by_exception()) {\n          // do nothing.\n        } else if (that.valueless_by_exception()) {\n          this->destroy();\n        } else {\n          visitation::alt::visit_alt_at(\n              that.index(),\n#ifdef MPARK_GENERIC_LAMBDAS\n              [this](auto &this_alt, auto &&that_alt) {\n                this->assign_alt(\n                    this_alt, lib::forward<decltype(that_alt)>(that_alt).value);\n              }\n#else\n              assigner<That>{this}\n#endif\n              ,\n              *this,\n              lib::forward<That>(that));\n        }\n      }\n    };\n\n    template <typename Traits, Trait = Traits::move_assignable_trait>\n    class move_assignment;\n\n#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \\\n  template <typename... Ts>                                              \\\n  class move_assignment<traits<Ts...>, move_assignable_trait>            \\\n      : public assignment<traits<Ts...>> {                               \\\n    using super = assignment<traits<Ts...>>;                             \\\n                                                                         \\\n    public:                                                              \\\n    MPARK_INHERITING_CTOR(move_assignment, super)                        \\\n    using super::operator=;                                              \\\n                                                                         \\\n    move_assignment(const move_assignment &) = default;                  \\\n    move_assignment(move_assignment &&) = default;                       \\\n    ~move_assignment() = default;                                        \\\n    move_assignment &operator=(const move_assignment &) = default;       \\\n    definition                                                           \\\n  }\n\n    MPARK_VARIANT_MOVE_ASSIGNMENT(\n        Trait::TriviallyAvailable,\n        move_assignment &operator=(move_assignment &&that) = default;);\n\n    MPARK_VARIANT_MOVE_ASSIGNMENT(\n        Trait::Available,\n        move_assignment &\n        operator=(move_assignment &&that) noexcept(\n            lib::all<(std::is_nothrow_move_constructible<Ts>::value &&\n                      std::is_nothrow_move_assignable<Ts>::value)...>::value) {\n          this->generic_assign(lib::move(that));\n          return *this;\n        });\n\n    MPARK_VARIANT_MOVE_ASSIGNMENT(\n        Trait::Unavailable,\n        move_assignment &operator=(move_assignment &&) = delete;);\n\n#undef MPARK_VARIANT_MOVE_ASSIGNMENT\n\n    template <typename Traits, Trait = Traits::copy_assignable_trait>\n    class copy_assignment;\n\n#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \\\n  template <typename... Ts>                                              \\\n  class copy_assignment<traits<Ts...>, copy_assignable_trait>            \\\n      : public move_assignment<traits<Ts...>> {                          \\\n    using super = move_assignment<traits<Ts...>>;                        \\\n                                                                         \\\n    public:                                                              \\\n    MPARK_INHERITING_CTOR(copy_assignment, super)                        \\\n    using super::operator=;                                              \\\n                                                                         \\\n    copy_assignment(const copy_assignment &) = default;                  \\\n    copy_assignment(copy_assignment &&) = default;                       \\\n    ~copy_assignment() = default;                                        \\\n    definition                                                           \\\n    copy_assignment &operator=(copy_assignment &&) = default;            \\\n  }\n\n    MPARK_VARIANT_COPY_ASSIGNMENT(\n        Trait::TriviallyAvailable,\n        copy_assignment &operator=(const copy_assignment &that) = default;);\n\n    MPARK_VARIANT_COPY_ASSIGNMENT(\n        Trait::Available,\n        copy_assignment &operator=(const copy_assignment &that) {\n          this->generic_assign(that);\n          return *this;\n        });\n\n    MPARK_VARIANT_COPY_ASSIGNMENT(\n        Trait::Unavailable,\n        copy_assignment &operator=(const copy_assignment &) = delete;);\n\n#undef MPARK_VARIANT_COPY_ASSIGNMENT\n\n    template <typename... Ts>\n    class impl : public copy_assignment<traits<Ts...>> {\n      using super = copy_assignment<traits<Ts...>>;\n\n      public:\n      MPARK_INHERITING_CTOR(impl, super)\n      using super::operator=;\n\n      template <std::size_t I, typename Arg>\n      inline void assign(Arg &&arg) {\n        this->assign_alt(access::base::get_alt<I>(*this),\n                         lib::forward<Arg>(arg));\n      }\n\n      inline void swap(impl &that) {\n        if (this->valueless_by_exception() && that.valueless_by_exception()) {\n          // do nothing.\n        } else if (this->index() == that.index()) {\n          visitation::alt::visit_alt_at(this->index(),\n#ifdef MPARK_GENERIC_LAMBDAS\n                                        [](auto &this_alt, auto &that_alt) {\n                                          using std::swap;\n                                          swap(this_alt.value,\n                                               that_alt.value);\n                                        }\n#else\n                                        swapper{}\n#endif\n                                        ,\n                                        *this,\n                                        that);\n        } else {\n          impl *lhs = this;\n          impl *rhs = lib::addressof(that);\n          if (lhs->move_nothrow() && !rhs->move_nothrow()) {\n            std::swap(lhs, rhs);\n          }\n          impl tmp(lib::move(*rhs));\n#ifdef MPARK_EXCEPTIONS\n          // EXTENSION: When the move construction of `lhs` into `rhs` throws\n          // and `tmp` is nothrow move constructible then we move `tmp` back\n          // into `rhs` and provide the strong exception safety guarantee.\n          try {\n            this->generic_construct(*rhs, lib::move(*lhs));\n          } catch (...) {\n            if (tmp.move_nothrow()) {\n              this->generic_construct(*rhs, lib::move(tmp));\n            }\n            throw;\n          }\n#else\n          this->generic_construct(*rhs, lib::move(*lhs));\n#endif\n          this->generic_construct(*lhs, lib::move(tmp));\n        }\n      }\n\n      private:\n#ifndef MPARK_GENERIC_LAMBDAS\n      struct swapper {\n        template <typename ThisAlt, typename ThatAlt>\n        inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const {\n          using std::swap;\n          swap(this_alt.value, that_alt.value);\n        }\n      };\n#endif\n\n      inline constexpr bool move_nothrow() const {\n        return this->valueless_by_exception() ||\n               lib::array<bool, sizeof...(Ts)>{\n                   {std::is_nothrow_move_constructible<Ts>::value...}\n               }[this->index()];\n      }\n    };\n\n#undef MPARK_INHERITING_CTOR\n\n    template <std::size_t I, typename T>\n    struct overload_leaf {\n      using F = lib::size_constant<I> (*)(T);\n      operator F() const { return nullptr; }\n    };\n\n    template <typename... Ts>\n    struct overload_impl {\n      private:\n      template <typename>\n      struct impl;\n\n      template <std::size_t... Is>\n      struct impl<lib::index_sequence<Is...>> : overload_leaf<Is, Ts>... {};\n\n      public:\n      using type = impl<lib::index_sequence_for<Ts...>>;\n    };\n\n    template <typename... Ts>\n    using overload = typename overload_impl<Ts...>::type;\n\n    template <typename T, typename... Ts>\n    using best_match = lib::invoke_result_t<overload<Ts...>, T &&>;\n\n    template <typename T>\n    struct is_in_place_index : std::false_type {};\n\n    template <std::size_t I>\n    struct is_in_place_index<in_place_index_t<I>> : std::true_type {};\n\n    template <typename T>\n    struct is_in_place_type : std::false_type {};\n\n    template <typename T>\n    struct is_in_place_type<in_place_type_t<T>> : std::true_type {};\n\n  }  // detail\n\n  template <typename... Ts>\n  class variant {\n    static_assert(0 < sizeof...(Ts),\n                  \"variant must consist of at least one alternative.\");\n\n    static_assert(lib::all<!std::is_array<Ts>::value...>::value,\n                  \"variant can not have an array type as an alternative.\");\n\n    static_assert(lib::all<!std::is_reference<Ts>::value...>::value,\n                  \"variant can not have a reference type as an alternative.\");\n\n    static_assert(lib::all<!std::is_void<Ts>::value...>::value,\n                  \"variant can not have a void type as an alternative.\");\n\n    public:\n    template <\n        typename Front = lib::type_pack_element_t<0, Ts...>,\n        lib::enable_if_t<std::is_default_constructible<Front>::value, int> = 0>\n    inline constexpr variant() noexcept(\n        std::is_nothrow_default_constructible<Front>::value)\n        : impl_(in_place_index_t<0>{}) {}\n\n    variant(const variant &) = default;\n    variant(variant &&) = default;\n\n    template <\n        typename Arg,\n        typename Decayed = lib::decay_t<Arg>,\n        lib::enable_if_t<!std::is_same<Decayed, variant>::value, int> = 0,\n        lib::enable_if_t<!detail::is_in_place_index<Decayed>::value, int> = 0,\n        lib::enable_if_t<!detail::is_in_place_type<Decayed>::value, int> = 0,\n        std::size_t I = detail::best_match<Arg, Ts...>::value,\n        typename T = lib::type_pack_element_t<I, Ts...>,\n        lib::enable_if_t<std::is_constructible<T, Arg>::value, int> = 0>\n    inline constexpr variant(Arg &&arg) noexcept(\n        std::is_nothrow_constructible<T, Arg>::value)\n        : impl_(in_place_index_t<I>{}, lib::forward<Arg>(arg)) {}\n\n    template <\n        std::size_t I,\n        typename... Args,\n        typename T = lib::type_pack_element_t<I, Ts...>,\n        lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>\n    inline explicit constexpr variant(\n        in_place_index_t<I>,\n        Args &&... args) noexcept(std::is_nothrow_constructible<T,\n                                                                Args...>::value)\n        : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}\n\n    template <\n        std::size_t I,\n        typename Up,\n        typename... Args,\n        typename T = lib::type_pack_element_t<I, Ts...>,\n        lib::enable_if_t<std::is_constructible<T,\n                                               std::initializer_list<Up> &,\n                                               Args...>::value,\n                         int> = 0>\n    inline explicit constexpr variant(\n        in_place_index_t<I>,\n        std::initializer_list<Up> il,\n        Args &&... args) noexcept(std::\n                                      is_nothrow_constructible<\n                                          T,\n                                          std::initializer_list<Up> &,\n                                          Args...>::value)\n        : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {}\n\n    template <\n        typename T,\n        typename... Args,\n        std::size_t I = detail::find_index_sfinae<T, Ts...>::value,\n        lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>\n    inline explicit constexpr variant(\n        in_place_type_t<T>,\n        Args &&... args) noexcept(std::is_nothrow_constructible<T,\n                                                                Args...>::value)\n        : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}\n\n    template <\n        typename T,\n        typename Up,\n        typename... Args,\n        std::size_t I = detail::find_index_sfinae<T, Ts...>::value,\n        lib::enable_if_t<std::is_constructible<T,\n                                               std::initializer_list<Up> &,\n                                               Args...>::value,\n                         int> = 0>\n    inline explicit constexpr variant(\n        in_place_type_t<T>,\n        std::initializer_list<Up> il,\n        Args &&... args) noexcept(std::\n                                      is_nothrow_constructible<\n                                          T,\n                                          std::initializer_list<Up> &,\n                                          Args...>::value)\n        : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {}\n\n    ~variant() = default;\n\n    variant &operator=(const variant &) = default;\n    variant &operator=(variant &&) = default;\n\n    template <typename Arg,\n              lib::enable_if_t<!std::is_same<lib::decay_t<Arg>, variant>::value,\n                               int> = 0,\n              std::size_t I = detail::best_match<Arg, Ts...>::value,\n              typename T = lib::type_pack_element_t<I, Ts...>,\n              lib::enable_if_t<(std::is_assignable<T &, Arg>::value &&\n                                std::is_constructible<T, Arg>::value),\n                               int> = 0>\n    inline variant &operator=(Arg &&arg) noexcept(\n        (std::is_nothrow_assignable<T &, Arg>::value &&\n         std::is_nothrow_constructible<T, Arg>::value)) {\n      impl_.template assign<I>(lib::forward<Arg>(arg));\n      return *this;\n    }\n\n    template <\n        std::size_t I,\n        typename... Args,\n        typename T = lib::type_pack_element_t<I, Ts...>,\n        lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>\n    inline T &emplace(Args &&... args) {\n      return impl_.template emplace<I>(lib::forward<Args>(args)...);\n    }\n\n    template <\n        std::size_t I,\n        typename Up,\n        typename... Args,\n        typename T = lib::type_pack_element_t<I, Ts...>,\n        lib::enable_if_t<std::is_constructible<T,\n                                               std::initializer_list<Up> &,\n                                               Args...>::value,\n                         int> = 0>\n    inline T &emplace(std::initializer_list<Up> il, Args &&... args) {\n      return impl_.template emplace<I>(il, lib::forward<Args>(args)...);\n    }\n\n    template <\n        typename T,\n        typename... Args,\n        std::size_t I = detail::find_index_sfinae<T, Ts...>::value,\n        lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>\n    inline T &emplace(Args &&... args) {\n      return impl_.template emplace<I>(lib::forward<Args>(args)...);\n    }\n\n    template <\n        typename T,\n        typename Up,\n        typename... Args,\n        std::size_t I = detail::find_index_sfinae<T, Ts...>::value,\n        lib::enable_if_t<std::is_constructible<T,\n                                               std::initializer_list<Up> &,\n                                               Args...>::value,\n                         int> = 0>\n    inline T &emplace(std::initializer_list<Up> il, Args &&... args) {\n      return impl_.template emplace<I>(il, lib::forward<Args>(args)...);\n    }\n\n    inline constexpr bool valueless_by_exception() const noexcept {\n      return impl_.valueless_by_exception();\n    }\n\n    inline constexpr std::size_t index() const noexcept {\n      return impl_.index();\n    }\n\n    template <bool Dummy = true,\n              lib::enable_if_t<\n                  lib::all<Dummy,\n                           (lib::dependent_type<std::is_move_constructible<Ts>,\n                                                Dummy>::value &&\n                            lib::dependent_type<lib::is_swappable<Ts>,\n                                                Dummy>::value)...>::value,\n                  int> = 0>\n    inline void swap(variant &that) noexcept(\n        lib::all<(std::is_nothrow_move_constructible<Ts>::value &&\n                  lib::is_nothrow_swappable<Ts>::value)...>::value) {\n      impl_.swap(that.impl_);\n    }\n\n    private:\n    detail::impl<Ts...> impl_;\n\n    friend struct detail::access::variant;\n    friend struct detail::visitation::variant;\n  };\n\n  template <std::size_t I, typename... Ts>\n  inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {\n    return v.index() == I;\n  }\n\n  template <typename T, typename... Ts>\n  inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {\n    return holds_alternative<detail::find_index_checked<T, Ts...>::value>(v);\n  }\n\n  namespace detail {\n    template <std::size_t I, typename V>\n    struct generic_get_impl {\n      constexpr generic_get_impl(int) noexcept {}\n\n      constexpr AUTO_REFREF operator()(V &&v) const\n        AUTO_REFREF_RETURN(\n            access::variant::get_alt<I>(lib::forward<V>(v)).value)\n    };\n\n    template <std::size_t I, typename V>\n    inline constexpr AUTO_REFREF generic_get(V &&v)\n      AUTO_REFREF_RETURN(generic_get_impl<I, V>(\n          holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))(\n          lib::forward<V>(v)))\n  }  // namespace detail\n\n  template <std::size_t I, typename... Ts>\n  inline constexpr variant_alternative_t<I, variant<Ts...>> &get(\n      variant<Ts...> &v) {\n    return detail::generic_get<I>(v);\n  }\n\n  template <std::size_t I, typename... Ts>\n  inline constexpr variant_alternative_t<I, variant<Ts...>> &&get(\n      variant<Ts...> &&v) {\n    return detail::generic_get<I>(lib::move(v));\n  }\n\n  template <std::size_t I, typename... Ts>\n  inline constexpr const variant_alternative_t<I, variant<Ts...>> &get(\n      const variant<Ts...> &v) {\n    return detail::generic_get<I>(v);\n  }\n\n  template <std::size_t I, typename... Ts>\n  inline constexpr const variant_alternative_t<I, variant<Ts...>> &&get(\n      const variant<Ts...> &&v) {\n    return detail::generic_get<I>(lib::move(v));\n  }\n\n  template <typename T, typename... Ts>\n  inline constexpr T &get(variant<Ts...> &v) {\n    return get<detail::find_index_checked<T, Ts...>::value>(v);\n  }\n\n  template <typename T, typename... Ts>\n  inline constexpr T &&get(variant<Ts...> &&v) {\n    return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));\n  }\n\n  template <typename T, typename... Ts>\n  inline constexpr const T &get(const variant<Ts...> &v) {\n    return get<detail::find_index_checked<T, Ts...>::value>(v);\n  }\n\n  template <typename T, typename... Ts>\n  inline constexpr const T &&get(const variant<Ts...> &&v) {\n    return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));\n  }\n\n  namespace detail {\n\n    template <std::size_t I, typename V>\n    inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept\n      AUTO_RETURN(v && holds_alternative<I>(*v)\n                      ? lib::addressof(access::variant::get_alt<I>(*v).value)\n                      : nullptr)\n\n  }  // namespace detail\n\n  template <std::size_t I, typename... Ts>\n  inline constexpr lib::add_pointer_t<variant_alternative_t<I, variant<Ts...>>>\n  get_if(variant<Ts...> *v) noexcept {\n    return detail::generic_get_if<I>(v);\n  }\n\n  template <std::size_t I, typename... Ts>\n  inline constexpr lib::add_pointer_t<\n      const variant_alternative_t<I, variant<Ts...>>>\n  get_if(const variant<Ts...> *v) noexcept {\n    return detail::generic_get_if<I>(v);\n  }\n\n  template <typename T, typename... Ts>\n  inline constexpr lib::add_pointer_t<T>\n  get_if(variant<Ts...> *v) noexcept {\n    return get_if<detail::find_index_checked<T, Ts...>::value>(v);\n  }\n\n  template <typename T, typename... Ts>\n  inline constexpr lib::add_pointer_t<const T>\n  get_if(const variant<Ts...> *v) noexcept {\n    return get_if<detail::find_index_checked<T, Ts...>::value>(v);\n  }\n\n  namespace detail {\n    template <typename RelOp>\n    struct convert_to_bool {\n      template <typename Lhs, typename Rhs>\n      inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const {\n        static_assert(std::is_convertible<lib::invoke_result_t<RelOp, Lhs, Rhs>,\n                                          bool>::value,\n                      \"relational operators must return a type\"\n                      \" implicitly convertible to bool\");\n        return lib::invoke(\n            RelOp{}, lib::forward<Lhs>(lhs), lib::forward<Rhs>(rhs));\n      }\n    };\n  }  // namespace detail\n\n  template <typename... Ts>\n  inline constexpr bool operator==(const variant<Ts...> &lhs,\n                                   const variant<Ts...> &rhs) {\n    using detail::visitation::variant;\n    using equal_to = detail::convert_to_bool<lib::equal_to>;\n#ifdef MPARK_CPP14_CONSTEXPR\n    if (lhs.index() != rhs.index()) return false;\n    if (lhs.valueless_by_exception()) return true;\n    return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs);\n#else\n    return lhs.index() == rhs.index() &&\n           (lhs.valueless_by_exception() ||\n            variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs));\n#endif\n  }\n\n  template <typename... Ts>\n  inline constexpr bool operator!=(const variant<Ts...> &lhs,\n                                   const variant<Ts...> &rhs) {\n    using detail::visitation::variant;\n    using not_equal_to = detail::convert_to_bool<lib::not_equal_to>;\n#ifdef MPARK_CPP14_CONSTEXPR\n    if (lhs.index() != rhs.index()) return true;\n    if (lhs.valueless_by_exception()) return false;\n    return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs);\n#else\n    return lhs.index() != rhs.index() ||\n           (!lhs.valueless_by_exception() &&\n            variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs));\n#endif\n  }\n\n  template <typename... Ts>\n  inline constexpr bool operator<(const variant<Ts...> &lhs,\n                                  const variant<Ts...> &rhs) {\n    using detail::visitation::variant;\n    using less = detail::convert_to_bool<lib::less>;\n#ifdef MPARK_CPP14_CONSTEXPR\n    if (rhs.valueless_by_exception()) return false;\n    if (lhs.valueless_by_exception()) return true;\n    if (lhs.index() < rhs.index()) return true;\n    if (lhs.index() > rhs.index()) return false;\n    return variant::visit_value_at(lhs.index(), less{}, lhs, rhs);\n#else\n    return !rhs.valueless_by_exception() &&\n           (lhs.valueless_by_exception() || lhs.index() < rhs.index() ||\n            (lhs.index() == rhs.index() &&\n             variant::visit_value_at(lhs.index(), less{}, lhs, rhs)));\n#endif\n  }\n\n  template <typename... Ts>\n  inline constexpr bool operator>(const variant<Ts...> &lhs,\n                                  const variant<Ts...> &rhs) {\n    using detail::visitation::variant;\n    using greater = detail::convert_to_bool<lib::greater>;\n#ifdef MPARK_CPP14_CONSTEXPR\n    if (lhs.valueless_by_exception()) return false;\n    if (rhs.valueless_by_exception()) return true;\n    if (lhs.index() > rhs.index()) return true;\n    if (lhs.index() < rhs.index()) return false;\n    return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs);\n#else\n    return !lhs.valueless_by_exception() &&\n           (rhs.valueless_by_exception() || lhs.index() > rhs.index() ||\n            (lhs.index() == rhs.index() &&\n             variant::visit_value_at(lhs.index(), greater{}, lhs, rhs)));\n#endif\n  }\n\n  template <typename... Ts>\n  inline constexpr bool operator<=(const variant<Ts...> &lhs,\n                                   const variant<Ts...> &rhs) {\n    using detail::visitation::variant;\n    using less_equal = detail::convert_to_bool<lib::less_equal>;\n#ifdef MPARK_CPP14_CONSTEXPR\n    if (lhs.valueless_by_exception()) return true;\n    if (rhs.valueless_by_exception()) return false;\n    if (lhs.index() < rhs.index()) return true;\n    if (lhs.index() > rhs.index()) return false;\n    return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs);\n#else\n    return lhs.valueless_by_exception() ||\n           (!rhs.valueless_by_exception() &&\n            (lhs.index() < rhs.index() ||\n             (lhs.index() == rhs.index() &&\n              variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs))));\n#endif\n  }\n\n  template <typename... Ts>\n  inline constexpr bool operator>=(const variant<Ts...> &lhs,\n                                   const variant<Ts...> &rhs) {\n    using detail::visitation::variant;\n    using greater_equal = detail::convert_to_bool<lib::greater_equal>;\n#ifdef MPARK_CPP14_CONSTEXPR\n    if (rhs.valueless_by_exception()) return true;\n    if (lhs.valueless_by_exception()) return false;\n    if (lhs.index() > rhs.index()) return true;\n    if (lhs.index() < rhs.index()) return false;\n    return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs);\n#else\n    return rhs.valueless_by_exception() ||\n           (!lhs.valueless_by_exception() &&\n            (lhs.index() > rhs.index() ||\n             (lhs.index() == rhs.index() &&\n              variant::visit_value_at(\n                  lhs.index(), greater_equal{}, lhs, rhs))));\n#endif\n  }\n\n  struct monostate {};\n\n  inline constexpr bool operator<(monostate, monostate) noexcept {\n    return false;\n  }\n\n  inline constexpr bool operator>(monostate, monostate) noexcept {\n    return false;\n  }\n\n  inline constexpr bool operator<=(monostate, monostate) noexcept {\n    return true;\n  }\n\n  inline constexpr bool operator>=(monostate, monostate) noexcept {\n    return true;\n  }\n\n  inline constexpr bool operator==(monostate, monostate) noexcept {\n    return true;\n  }\n\n  inline constexpr bool operator!=(monostate, monostate) noexcept {\n    return false;\n  }\n\n#ifdef MPARK_CPP14_CONSTEXPR\n  namespace detail {\n\n    inline constexpr bool all(std::initializer_list<bool> bs) {\n      for (bool b : bs) {\n        if (!b) {\n          return false;\n        }\n      }\n      return true;\n    }\n\n  }  // namespace detail\n\n  template <typename Visitor, typename... Vs>\n  inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) {\n    return (detail::all({!vs.valueless_by_exception()...})\n                ? (void)0\n                : throw_bad_variant_access()),\n           detail::visitation::variant::visit_value(\n               lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...);\n  }\n#else\n  namespace detail {\n\n    template <std::size_t N>\n    inline constexpr bool all_impl(const lib::array<bool, N> &bs,\n                                   std::size_t idx) {\n      return idx >= N || (bs[idx] && all_impl(bs, idx + 1));\n    }\n\n    template <std::size_t N>\n    inline constexpr bool all(const lib::array<bool, N> &bs) {\n      return all_impl(bs, 0);\n    }\n\n  }  // namespace detail\n\n  template <typename Visitor, typename... Vs>\n  inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs)\n    DECLTYPE_AUTO_RETURN(\n        (detail::all(\n             lib::array<bool, sizeof...(Vs)>{{!vs.valueless_by_exception()...}})\n             ? (void)0\n             : throw_bad_variant_access()),\n        detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor),\n                                                 lib::forward<Vs>(vs)...))\n#endif\n\n  template <typename... Ts>\n  inline auto swap(variant<Ts...> &lhs,\n                   variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs)))\n      -> decltype(lhs.swap(rhs)) {\n    lhs.swap(rhs);\n  }\n\n  namespace detail {\n\n    template <typename T, typename...>\n    using enabled_type = T;\n\n    namespace hash {\n\n      template <typename H, typename K>\n      constexpr bool meets_requirements() noexcept {\n        return std::is_copy_constructible<H>::value &&\n               std::is_move_constructible<H>::value &&\n               lib::is_invocable_r<std::size_t, H, const K &>::value;\n      }\n\n      template <typename K>\n      constexpr bool is_enabled() noexcept {\n        using H = std::hash<K>;\n        return meets_requirements<H, K>() &&\n               std::is_default_constructible<H>::value &&\n               std::is_copy_assignable<H>::value &&\n               std::is_move_assignable<H>::value;\n      }\n\n    }  // namespace hash\n\n  }  // namespace detail\n\n#undef AUTO\n#undef AUTO_RETURN\n\n#undef AUTO_REFREF\n#undef AUTO_REFREF_RETURN\n\n#undef DECLTYPE_AUTO\n#undef DECLTYPE_AUTO_RETURN\n\n}  // namespace mpark\n\nnamespace std {\n\n  template <typename... Ts>\n  struct hash<mpark::detail::enabled_type<\n      mpark::variant<Ts...>,\n      mpark::lib::enable_if_t<mpark::lib::all<mpark::detail::hash::is_enabled<\n          mpark::lib::remove_const_t<Ts>>()...>::value>>> {\n    using argument_type = mpark::variant<Ts...>;\n    using result_type = std::size_t;\n\n    inline result_type operator()(const argument_type &v) const {\n      using mpark::detail::visitation::variant;\n      std::size_t result =\n          v.valueless_by_exception()\n              ? 299792458  // Random value chosen by the universe upon creation\n              : variant::visit_alt(\n#ifdef MPARK_GENERIC_LAMBDAS\n                    [](const auto &alt) {\n                      using alt_type = mpark::lib::decay_t<decltype(alt)>;\n                      using value_type = mpark::lib::remove_const_t<\n                          typename alt_type::value_type>;\n                      return hash<value_type>{}(alt.value);\n                    }\n#else\n                    hasher{}\n#endif\n                    ,\n                    v);\n      return hash_combine(result, hash<std::size_t>{}(v.index()));\n    }\n\n    private:\n#ifndef MPARK_GENERIC_LAMBDAS\n    struct hasher {\n      template <typename Alt>\n      inline std::size_t operator()(const Alt &alt) const {\n        using alt_type = mpark::lib::decay_t<Alt>;\n        using value_type =\n            mpark::lib::remove_const_t<typename alt_type::value_type>;\n        return hash<value_type>{}(alt.value);\n      }\n    };\n#endif\n\n    static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {\n      return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);\n    }\n  };\n\n  template <>\n  struct hash<mpark::monostate> {\n    using argument_type = mpark::monostate;\n    using result_type = std::size_t;\n\n    inline result_type operator()(const argument_type &) const noexcept {\n      return 66740831;  // return a fundamentally attractive random value.\n    }\n  };\n\n}  // namespace std\n\n#endif  // MPARK_VARIANT_HPP\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderBlueprint/Private/BlueprintProvider.cpp",
    "content": "#include \"BlueprintProvider.hpp\"\n\n#include \"Async/Async.h\"\n\n#include \"AssetEditorMessages.h\"\n#include \"BlueprintEditor.h\"\n#include \"MessageEndpointBuilder.h\"\n#include \"MessageEndpoint.h\"\n#include \"Kismet2/KismetEditorUtilities.h\"\n#include \"Runtime/Launch/Resources/Version.h\"\n\n#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION <= 23\n#include \"Toolkits/AssetEditorManager.h\"\n#endif\n#include \"Kismet2/BlueprintEditorUtils.h\"\n#include \"Model/RdEditorProtocol/RdEditorModel/RdEditorModel.Pregenerated.h\"\n\n#if ENGINE_MAJOR_VERSION < 5\n#include \"AssetData.h\"\n#else\n#include \"AssetRegistry/AssetData.h\"\n#endif\n\nvoid BluePrintProvider::AddAsset(FAssetData const& AssetData) {\n#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION <= 23\n    UObject* cls = AssetData.GetAsset();\n#else\n    UObject* cls = AssetData.FastGetAsset();\n#endif\n    if (cls) {\n        UBlueprint* Blueprint = Cast<UBlueprint>(cls);\n        if (Blueprint && Blueprint->IsValidLowLevel()) {\n\n        }\n    }\n}\n\nbool BluePrintProvider::IsBlueprint(FString const& pathName) {\n    return FPackageName::IsValidObjectPath(pathName);\n}\n\nvoid BluePrintProvider::OpenBlueprint(JetBrains::EditorPlugin::BlueprintReference const& BlueprintReference, TSharedPtr<FMessageEndpoint, ESPMode::ThreadSafe> const& messageEndpoint) {\n    // Just to create asset manager if it wasn't created already\n    const FString AssetPathName = BlueprintReference.get_pathName();\n    FGuid AssetGuid;\n    bool bIsValidGuid = FGuid::Parse(BlueprintReference.get_guid(), AssetGuid);\n#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION <= 23\n    FAssetEditorManager::Get();\n    messageEndpoint->Publish(new FAssetEditorRequestOpenAsset(AssetPathName), EMessageScope::Process);\n#else\n    AsyncTask(ENamedThreads::GameThread, [AssetPathName, AssetGuid, bIsValidGuid]()\n    {\n        // An asset needs loading\n        UPackage* Package = LoadPackage(nullptr, *AssetPathName, LOAD_NoRedirects);\n\n        if (Package)\n        {\n            Package->FullyLoad();\n\n            const FString AssetName = FPaths::GetBaseFilename(AssetPathName);\n            UObject* Object = FindObject<UObject>(Package, *AssetName);\n            const UBlueprint* Blueprint = Cast<UBlueprint>(Object);\n\n            if(bIsValidGuid && Blueprint != nullptr)\n            {\n                UEdGraphNode* EdGraphNode = FBlueprintEditorUtils::GetNodeByGUID(Blueprint, AssetGuid);\n                if(EdGraphNode != nullptr)\n                {\n                    FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(EdGraphNode); \n                }\n                else\n                {\n                    FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(Blueprint);\n                }\n            }\n            else if(Object != nullptr)\n            {      \n                GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->OpenEditorForAsset(Object);         \n            }\n        }\n    });\n#endif\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderBlueprint/Private/RiderBlueprint.cpp",
    "content": "#include \"RiderBlueprint.hpp\"\n\n#include \"BlueprintProvider.hpp\"\n#include \"IRiderLink.hpp\"\n#include \"Model/RdEditorProtocol/RdEditorModel/RdEditorModel.Pregenerated.h\"\n\n\n#include \"Engine/Blueprint.h\"\n#include \"Framework/Docking/TabManager.h\"\n#include \"HAL/PlatformProcess.h\"\n#include \"MessageEndpoint.h\"\n#include \"MessageEndpointBuilder.h\"\n#include \"Modules/ModuleManager.h\"\n#include \"Runtime/Launch/Resources/Version.h\"\n\n#if ENGINE_MAJOR_VERSION < 5\n#include \"AssetRegistryModule.h\"\n#else\n#include \"AssetRegistry/AssetRegistryModule.h\"\n#endif\n\n#define LOCTEXT_NAMESPACE \"RiderBlueprint\"\n\nDEFINE_LOG_CATEGORY(FLogRiderBlueprintModule);\n\nIMPLEMENT_MODULE(FRiderBlueprintModule, RiderBlueprint);\n\nstatic void AllowSetForeGroundForEditor(JetBrains::EditorPlugin::RdEditorModel const & unrealToBackendModel) {\n    static const int32 CurrentProcessId = FPlatformProcess::GetCurrentProcessId();\n    try {\n        const rd::WiredRdTask<bool> Task = unrealToBackendModel.get_allowSetForegroundWindow().sync(CurrentProcessId);\n        if (Task.is_faulted()) {\n            UE_LOG(FLogRiderBlueprintModule, Error, TEXT(\"AllowSetForeGroundForEditor failed: %hs \"), rd::to_string(Task.value_or_throw()).c_str());\n        }\n        else if (Task.is_succeeded()) {\n            if (!(Task.value_or_throw().unwrap())) {\n                UE_LOG(FLogRiderBlueprintModule, Error, TEXT(\"AllowSetForeGroundForEditor failed: %hs \"), rd::to_string(Task.value_or_throw()).c_str());\n            }\n        }\n    }\n    catch (std::exception const &e) {\n        UE_LOG(FLogRiderBlueprintModule, Error, TEXT(\"AllowSetForeGroundForEditor failed: %hs \"), rd::to_string(e).c_str());\n    }\n}\n\nvoid FRiderBlueprintModule::StartupModule()\n{\n    UE_LOG(FLogRiderBlueprintModule, Verbose, TEXT(\"STARTUP START\"));\n    IRiderLinkModule& RiderLinkModule = IRiderLinkModule::Get();\n    ModuleLifetimeDef = RiderLinkModule.CreateNestedLifetimeDefinition();\n\n    const FAssetRegistryModule* AssetRegistryModule = &FModuleManager::LoadModuleChecked<FAssetRegistryModule>\n        (AssetRegistryConstants::ModuleName);\n\n    MessageEndpoint = FMessageEndpoint::Builder(FName(\"FAssetEditorManager\")).Build();\n\n    AssetRegistryModule->Get().OnAssetAdded().AddLambda([](const FAssetData& AssetData) {\n        // TO-DO: Fix loading uasset's on 4.23-\n        // BluePrintProvider::AddAsset(AssetData);\n    });\n\n    RiderLinkModule.ViewModel(ModuleLifetimeDef.lifetime, [this] (rd::Lifetime ModelLifetime, JetBrains::EditorPlugin::RdEditorModel const& UnrealToBackendModel)\n    {\n        UnrealToBackendModel.get_openBlueprint().advise(\n            ModelLifetime,\n            [this, &UnrealToBackendModel](\n            JetBrains::EditorPlugin::BlueprintReference const& s)\n            {\n                try\n                {\n                    AllowSetForeGroundForEditor(UnrealToBackendModel);\n\n                    auto Window = FGlobalTabmanager::Get()->GetRootWindow();\n                    if (!Window.IsValid()) return;\n\n                    if (Window->IsWindowMinimized())\n                    {\n                        Window->Restore();\n                    }\n                    else\n                    {\n                        Window->HACK_ForceToFront();\n                    }\n                    BluePrintProvider::OpenBlueprint(s, MessageEndpoint);\n                }\n                catch (std::exception const& e)\n                {\n                    std::cerr << rd::to_string(e);\n                }\n            }\n        );\n\n        UnrealToBackendModel.get_isBlueprintPathName().set([](FString const& pathName) -> bool\n        {\n            return BluePrintProvider::IsBlueprint(pathName);\n        });\n    });\n    UE_LOG(FLogRiderBlueprintModule, Verbose, TEXT(\"STARTUP FINISH\"));\n}\n\nvoid FRiderBlueprintModule::ShutdownModule()\n{\n    UE_LOG(FLogRiderBlueprintModule, Verbose, TEXT(\"SHUTDOWN START\"));\n    ModuleLifetimeDef.terminate();\n    UE_LOG(FLogRiderBlueprintModule, Verbose, TEXT(\"SHUTDOWN FINISH\"));\n}\n\n#undef LOCTEXT_NAMESPACE"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderBlueprint/Public/BlueprintProvider.hpp",
    "content": "#pragma once\n\n#include \"Delegates/Delegate.h\"\n\nnamespace JetBrains\n{\n    namespace EditorPlugin\n    {\n        class BlueprintReference;\n    }\n}\n\nstruct FAssetData;\nclass FMessageEndpoint;\nclass UBlueprint;\n\nclass RIDERBLUEPRINT_API BluePrintProvider {\npublic:\n\n    static void AddAsset(FAssetData const& AssetData);\n\n    static bool IsBlueprint(FString const& pathName);\n\n    static void OpenBlueprint(JetBrains::EditorPlugin::BlueprintReference const& path, TSharedPtr<FMessageEndpoint, ESPMode::ThreadSafe> const& messageEndpoint);\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderBlueprint/Public/RiderBlueprint.hpp",
    "content": "#pragma once\n\n#include \"lifetime/LifetimeDefinition.h\"\n\n#include \"Logging/LogMacros.h\"\n#include \"Logging/LogVerbosity.h\"\n#include \"MessageEndpoint.h\"\n#include \"Modules/ModuleInterface.h\"\n#include \"Templates/SharedPointer.h\"\n\nDECLARE_LOG_CATEGORY_EXTERN(FLogRiderBlueprintModule, Log, All);\n\nclass FRiderBlueprintModule : public IModuleInterface\n{\npublic:\n    FRiderBlueprintModule() = default;\n    virtual ~FRiderBlueprintModule() override = default;\n\n    /** IModuleInterface implementation */\n    virtual void StartupModule() override;\n    virtual void ShutdownModule() override;\n    virtual bool SupportsDynamicReloading() override { return true; };\nprivate:\n    TSharedPtr<FMessageEndpoint, ESPMode::ThreadSafe> MessageEndpoint;\n    rd::LifetimeDefinition ModuleLifetimeDef;\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderBlueprint/RiderBlueprint.Build.cs",
    "content": "using UnrealBuildTool;\n\npublic class RiderBlueprint : ModuleRules\n{\n\tpublic RiderBlueprint(ReadOnlyTargetRules Target) : base(Target)\n\t{\n#if UE_4_22_OR_LATER\n\t\tPCHUsage = PCHUsageMode.NoPCHs;\n#else\n\t\tPCHUsage = PCHUsageMode.NoSharedPCHs;\n#endif\n\t\t\n\t\tbUseRTTI = true;\n\n#if UE_5_2_OR_LATER\n\t\tbDisableStaticAnalysis = true;\n#endif\n\t\t\n\t\tPublicDependencyModuleNames.Add(\"RD\");\n\n\t\tPrivateDependencyModuleNames.AddRange(new []\n\t\t{\n\t\t\t\"Core\",\n\t\t\t\"SlateCore\",\n\t\t\t\"RiderLink\",\n\t\t\t\"Slate\",\n\t\t\t\"AssetRegistry\",\n\t\t\t\"MessagingCommon\",\n\t\t\t\"UnrealEd\",\n\t\t\t\"UnrealEdMessages\",\n\t\t\t\"Engine\",\n\t\t\t\"CoreUObject\"\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/Private/BlueprintStackGetter.cpp",
    "content": "﻿#include \"UObject/Class.h\"\n#include \"DebugLogger.h\"\n#include \"UnrealFunctions.h\"\n#include \"UObject/UObjectBaseUtility.h\"\n#include \"WideStringWrapper.h\"\n#include \"EdGraph/EdGraphNode.h\"\n\nnamespace RiderDebuggerSupport\n{\n    constexpr int StringBufferSizeInWideChars = 1024;\n    constexpr int GWideCharSizeInBytes = sizeof(wchar_t);\n    constexpr int GStringSizeInBytes = StringBufferSizeInWideChars * GWideCharSizeInBytes;\n    constexpr int GLengthSizeInBytes = sizeof(uint32_t);\n    constexpr int GResultCodeSizeInBytes = sizeof(uint32_t);\n    constexpr int GStringEntrySizeInBytes = GStringSizeInBytes + GLengthSizeInBytes;\n    constexpr int GFirstStringOffset = GLengthSizeInBytes;\n    constexpr int GSecondStringOffset = GFirstStringOffset + GStringEntrySizeInBytes;\n    constexpr int GThirdStringOffset = GSecondStringOffset + GStringEntrySizeInBytes;\n    constexpr int GBufferSizeInBytes = GResultCodeSizeInBytes + 3 * GStringEntrySizeInBytes;\n}\n\n/* Start Identifiers available from IDEA */\n\nextern \"C\" DLLEXPORT void __stdcall RiderDebuggerSupport_GetBlueprintFunction(void* PFunction, void* PContext);\n\nstruct FJbCallContextModule\n{\n    void* Context;\n    void* Function;\n} RiderDebuggerSupportBlueprintFunctionCallContext;\n\nint RiderDebuggerSupportModuleVersion = 1346;\n\nchar RiderDebuggerSupportBlueprintFunctionBuffer[RiderDebuggerSupport::GBufferSizeInBytes] = {0};\nint RiderDebuggerSupportBlueprintBufferSizeInBytes = RiderDebuggerSupport::GBufferSizeInBytes;\nint RiderDebuggerSupportBlueprintStringBufferSizeInChars = RiderDebuggerSupport::StringBufferSizeInWideChars;\nint RiderDebuggerSupportBlueprintWideCharSizeInBytes = RiderDebuggerSupport::GWideCharSizeInBytes;\n\n/* End Identifiers available from IDEA */\n\nnamespace RiderDebuggerSupport\n{\n    static FWideStringWrapper GJbFullNameWrapper(RiderDebuggerSupportBlueprintFunctionBuffer + GFirstStringOffset, GStringEntrySizeInBytes);\n    static FWideStringWrapper GJbScopeDisplayNameWrapper(RiderDebuggerSupportBlueprintFunctionBuffer + GSecondStringOffset, GStringEntrySizeInBytes);\n    static FWideStringWrapper GJbFunctionDisplayNameWrapper(RiderDebuggerSupportBlueprintFunctionBuffer + GThirdStringOffset, GStringEntrySizeInBytes);\n\n    uint32_t* GJbPOperationResultCode = reinterpret_cast<uint32_t*>(RiderDebuggerSupportBlueprintFunctionBuffer);\n\n    static void SetLastExecutedLine(const uint16 LineNumber)\n    {\n        *GJbPOperationResultCode = (*GJbPOperationResultCode & 0xFFFF0000) | LineNumber;\n    }\n\n    static void SetResultCodeFlag(const uint8 FlagOffset)\n    {\n        *GJbPOperationResultCode |= 1 << FlagOffset;\n    }\n}\n\nvoid RiderDebuggerSupport_GetBlueprintFunction(void* PFunction, void* PContext)\n{\n    using namespace RiderDebuggerSupport;\n\n    SendLogToDebugger(\"Called %s: Context=%p Function=%p\", __func__, PContext, PFunction);\n    *GJbPOperationResultCode = 0;\n\n    const UObject* Context = static_cast<UObject*>(PContext);\n    UFunction* Function = static_cast<UFunction*>(PFunction);\n\n    if (nullptr == Context)\n    {\n        SendLogToDebugger(\"Context is null\");\n        SetLastExecutedLine(__LINE__);\n        return;\n    }\n\n    if (nullptr == Function)\n    {\n        SendLogToDebugger(\"Function is null\");\n        SetLastExecutedLine(__LINE__);\n        return;\n    }\n    SetLastExecutedLine(__LINE__);\n\n    FString FullName;\n    SetLastExecutedLine(__LINE__);\n\n    Function->GetFullName(nullptr, FullName, EObjectFullNameFlags::None);\n    GJbFullNameWrapper.CopyFromNullTerminatedStr(\n        GetData(FullName), FullName.Len());\n    SetLastExecutedLine(__LINE__);\n\n    const auto Outer = Function->GetOuter();\n\n    SendLogToDebugger(\"Trying to get SourceClass\");\n\n    const UClass* SourceClass = CastToUClass(Outer);\n\n    SendLogToDebugger(\"SourceClass=%p\", SourceClass);\n\n    SetLastExecutedLine(__LINE__);\n    if (nullptr != SourceClass)\n    {\n        constexpr int SourceCodeNotNullFlag = 16;\n        SetResultCodeFlag(SourceCodeNotNullFlag);\n    }\n\n    FString SourceClassDisplayName = GetClassNameWithoutSuffix(SourceClass);\n    SendLogToDebugger(\n        \"SourceClassDisplayName length=%u, str_ptr=%p\",\n        SourceClassDisplayName.Len(), GetData(SourceClassDisplayName));\n    SetLastExecutedLine(__LINE__);\n\n    SendLogToDebugger(\"Trying to get outerDisplayName\");\n    FString OuterDisplayName = FText::FromName(Outer->GetFName()).ToString();\n    SendLogToDebugger(\n        \"OuterDisplayName length=%u, str_ptr=%p\",\n        OuterDisplayName.Len(), GetData(OuterDisplayName));\n\n    const auto ScopeDisplayName = SourceClass ? &SourceClassDisplayName : &OuterDisplayName;\n    GJbScopeDisplayNameWrapper.CopyFromNullTerminatedStr(\n        GetData(*ScopeDisplayName), ScopeDisplayName->Len());\n    SetLastExecutedLine(__LINE__);\n\n    auto FunctionDisplayName = FText::FromName(Function->GetFName()).ToString();\n    GJbFunctionDisplayNameWrapper.CopyFromNullTerminatedStr(GetData(FunctionDisplayName), FunctionDisplayName.Len());\n    SetLastExecutedLine(__LINE__);\n\n#if WITH_EDITORONLY_DATA\n    if (SourceClass)\n    {\n        const auto GraphNode = FindSourceNodeForCodeLocation(Context, Function);\n        SetLastExecutedLine(__LINE__);\n\n        if (nullptr != GraphNode)\n        {\n            constexpr int SourceCodeNotNullFlag = 17;\n            SetResultCodeFlag(SourceCodeNotNullFlag);\n\n            const FText NodeTitle = GraphNode->GetNodeTitle(ENodeTitleType::Type::ListView);\n            SetLastExecutedLine(__LINE__);\n\n            FString NodeTitleStr = NodeTitle.ToString();\n            SetLastExecutedLine(__LINE__);\n\n            GJbFunctionDisplayNameWrapper.CopyFromNullTerminatedStr(\n                GetData(NodeTitleStr), NodeTitleStr.Len());\n            SetLastExecutedLine(__LINE__);\n        }\n    }\n#endif\n}"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/Private/DebugLogger.cpp",
    "content": "﻿#include \"DebugLogger.h\"\n\n#define JB_DEBUG_MODE 0\n#define LOG_DBG_PREFIX \"JB_UNR_BP_DBG_MSG>\"\n#define LOG_DBG_PREFIX_LENGTH (sizeof(LOG_DBG_PREFIX) - 1)\n\n#if JB_DEBUG_MODE\n#include \"UObject/UnrealType.h\"\n\n// Avoid including windows.h\nextern \"C\" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* LpOutputString);\n\n#endif\n\nvoid RiderDebuggerSupport::SendLogToDebugger(\n#if !JB_DEBUG_MODE && __cplusplus >= 201703L\n    [[maybe_unused]]\n#endif\n    const char* FormatStr, ...)\n{\n#if JB_DEBUG_MODE\n\n    va_list Args;\n    va_start(Args, FormatStr);\n\n    char OutputBuffer[1024] = {LOG_DBG_PREFIX};\n\n    char* FormatBuffer = OutputBuffer + LOG_DBG_PREFIX_LENGTH;\n    constexpr int FormatBufferSize = sizeof(OutputBuffer) - LOG_DBG_PREFIX_LENGTH;\n\n    const auto Res = vsprintf_s(FormatBuffer, FormatBufferSize, FormatStr, Args);\n\n    if (Res > 0)\n        OutputDebugStringA(OutputBuffer);\n    else\n        OutputDebugStringA(\"Error in SendLogToDebugger\");\n\n    va_end(Args);\n#endif\n}"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/Private/DebugLogger.h",
    "content": "﻿#pragma once\n\nnamespace RiderDebuggerSupport\n{\n    void SendLogToDebugger(const char* FormatStr, ...);\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/Private/RiderDebuggerSupport.cpp",
    "content": "﻿#include \"RiderDebuggerSupport.h\"\n\n#define LOCTEXT_NAMESPACE \"FRiderDebuggerSupportModule\"\n\n\nvoid FRiderDebuggerSupportModule::StartupModule()\n{\n}\n\nvoid FRiderDebuggerSupportModule::ShutdownModule()\n{\n}\n\n#undef LOCTEXT_NAMESPACE\n\nIMPLEMENT_MODULE(FRiderDebuggerSupportModule, RiderDebuggerSupport)\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/Private/RiderDebuggerSupport.h",
    "content": "﻿#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Modules/ModuleManager.h\"\n\nclass FRiderDebuggerSupportModule : public IModuleInterface\n{\npublic:\n    virtual void StartupModule() override;\n    virtual void ShutdownModule() override;\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/Private/UnrealFunctions.cpp",
    "content": "﻿#include \"UnrealFunctions.h\"\n#include \"Engine/BlueprintGeneratedClass.h\"\n#include \"Templates/Casts.h\"\n\nUClass* RiderDebuggerSupport::FindClassForNode(const UObject* Object, const UFunction* Function)\n{\n    if (nullptr != Function) return Function->GetOwnerClass();\n\n    if (nullptr != Object) return Object->GetClass();\n    return nullptr;\n}\n\nUEdGraphNode* RiderDebuggerSupport::FindSourceNodeForCodeLocation(const UObject* Object, UFunction* Function)\n{\n#if WITH_EDITORONLY_DATA\n\n    if (nullptr == Object) return nullptr;\n\n    if (UBlueprintGeneratedClass* Class = Cast<UBlueprintGeneratedClass>(FindClassForNode(Object, Function)))\n    {\n        return Class->GetDebugData().\n                      FindSourceNodeFromCodeLocation(Function, 0, true);\n    }\n\n#endif\n    return nullptr;\n}\n\nFString RiderDebuggerSupport::GetClassNameWithoutSuffix(const UClass* Class)\n{\n    FString Result = TEXT(\"Null\");\n    if (nullptr == Class) return Result;\n\n    Result = Class->GetName();\n    if (nullptr != Class->ClassGeneratedBy)\n    {\n        Result.RemoveFromEnd(TEXT(\"_C\"), ESearchCase::CaseSensitive);\n    }\n\n    return Result;\n}\n\nconst UClass* RiderDebuggerSupport::CastToUClass(const UObject* Object)\n{\n    if (nullptr == Object) return nullptr;\n\n    const auto& TypeOfObject = Object->GetClass();\n    if (nullptr == TypeOfObject) return nullptr;\n\n    const auto& TypeOfTypeOfObject = TypeOfObject->GetClass();\n    if (nullptr == TypeOfTypeOfObject) return nullptr;\n\n    const auto& TypeOfClass = TypeOfTypeOfObject->GetClass();\n    if (nullptr == TypeOfClass) return nullptr;\n\n    if (TypeOfClass != TypeOfTypeOfObject) return nullptr;\n\n    return static_cast<const UClass*>(Object);\n}"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/Private/UnrealFunctions.h",
    "content": "﻿#pragma once\n\n\nclass UEdGraphNode;\nclass UFunction;\nclass UObject;\nclass UClass;\nclass FString;\n\nnamespace RiderDebuggerSupport\n{\n    UClass* FindClassForNode(const UObject* Object, const UFunction* Function);\n    UEdGraphNode* FindSourceNodeForCodeLocation(const UObject* Object, UFunction* Function);\n    FString GetClassNameWithoutSuffix(const UClass* Class);\n    const UClass* CastToUClass(const UObject* Object);\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/Private/WideStringWrapper.cpp",
    "content": "﻿#include \"WideStringWrapper.h\"\n\n#include \"HAL/UnrealMemory.h\"\n\n\nRiderDebuggerSupport::FWideStringWrapper::FWideStringWrapper(char* Buf, uint32 BufLen):\n    AllocatedBuffer(Buf),\n    AllocatedBufferLength(BufLen)\n{\n    if (AllocatedBuffer != nullptr && AllocatedBufferLength > LengthPrefixSize)\n    {\n        WideStringLength = reinterpret_cast<uint32*>(AllocatedBuffer);\n        *WideStringLength = 0;\n        PointerToString = reinterpret_cast<wchar_t*>(AllocatedBuffer + LengthPrefixSize);\n        AvailableStringSpaceInBytes = AllocatedBufferLength - LengthPrefixSize;\n    }\n    else\n    {\n        WideStringLength = nullptr;\n        PointerToString = nullptr;\n        AvailableStringSpaceInBytes = 0;\n    }\n}\n\nuint32 RiderDebuggerSupport::FWideStringWrapper::CopyFromNullTerminatedStr(const wchar_t* SourceStr, uint32 SourceStrLength) const\n{\n    if (nullptr == SourceStr || 0 == SourceStrLength) return 0;\n    if (PointerToString == nullptr || AllocatedBufferLength <= LengthPrefixSize) return 0;\n\n    uint32 LocalDataLength = SourceStrLength;\n\n    while (LocalDataLength > 0 && SourceStr[LocalDataLength - 1] == L'\\0')\n    {\n        --LocalDataLength;\n    }\n\n    uint32 BytesToCopy = LocalDataLength * sizeof(wchar_t);\n\n    if (BytesToCopy > AvailableStringSpaceInBytes)\n    {\n        BytesToCopy = AvailableStringSpaceInBytes;\n        LocalDataLength = BytesToCopy / sizeof(wchar_t);\n    }\n\n    *WideStringLength = LocalDataLength;\n\n    FMemory::Memcpy(PointerToString, SourceStr, BytesToCopy);\n\n    return LocalDataLength;\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/Private/WideStringWrapper.h",
    "content": "﻿#pragma once\n\n#include \"HAL/Platform.h\"\n\nnamespace RiderDebuggerSupport\n{\n    class FWideStringWrapper\n    {\n        char* AllocatedBuffer; // Raw buffer to store data as bytes\n        uint32 AllocatedBufferLength; // Total buffer length in bytes, including space for length prefix\n        uint32* WideStringLength;\n        uint32 AvailableStringSpaceInBytes;\n        wchar_t* PointerToString; // Pointer to the start of the string within AllocatedBuffer\n\n        static constexpr uint32 LengthPrefixSize = sizeof(uint32); // Size of the length prefix in bytes\n    public:\n        FWideStringWrapper(char* Buf, uint32 BufLen);\n        uint32 CopyFromNullTerminatedStr(const wchar_t* SourceStr, uint32 SourceStrLength) const;\n    };\n}"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderDebuggerSupport/RiderDebuggerSupport.Build.cs",
    "content": "﻿using UnrealBuildTool;\n\npublic class RiderDebuggerSupport : ModuleRules\n{\n    public RiderDebuggerSupport(ReadOnlyTargetRules Target) : base(Target)\n    {\n#if UE_4_22_OR_LATER\n        PCHUsage = PCHUsageMode.NoPCHs;\n#else\n        PCHUsage = PCHUsageMode.NoSharedPCHs;\n#endif\n\n#if UE_5_2_OR_LATER\n        bDisableStaticAnalysis = true;\n#endif\n\n        PrivateDependencyModuleNames.AddRange(\n            new string[]\n            {\n                \"Core\",\n                \"CoreUObject\",\n                \"Engine\"\n            }\n        );\n    }\n}"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderGameControl/Private/RiderGameControl.cpp",
    "content": "#include \"RiderGameControl.hpp\"\n\n\n#include \"IRiderLink.hpp\"\n\n#include \"Model/Library/UE4Library/PlayState.Pregenerated.h\"\n#include \"Model/Library/UE4Library/RequestFailed.Pregenerated.h\"\n#include \"Model/Library/UE4Library/RequestSucceed.Pregenerated.h\"\n#include \"RdEditorModel/RdEditorModel.Pregenerated.h\"\n\n#include \"Async/Async.h\"\n#include \"Editor/UnrealEdEngine.h\"\n#include \"Framework/Application/SlateApplication.h\"\n#include \"Kismet2/DebuggerCommands.h\"\n#include \"LevelEditor.h\"\n#include \"LevelEditorActions.h\"\n#include \"Misc/FeedbackContext.h\"\n#include \"Modules/ModuleManager.h\"\n#include \"Settings/LevelEditorPlaySettings.h\"\n#include \"Editor.h\"\n\n#include \"Runtime/Launch/Resources/Version.h\"\n#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION <= 23\n#include \"ILevelViewport.h\"\n#include \"LevelEditorViewport.h\"\n#else\n#include \"IAssetViewport.h\"\n#include \"EditorViewportClient.h\"\n#endif\n\n#define LOCTEXT_NAMESPACE \"RiderGameControl\"\n\nDEFINE_LOG_CATEGORY(FLogRiderGameControlModule);\n\nIMPLEMENT_MODULE(FRiderGameControlModule, RiderGameControl);\n\nextern UNREALED_API class UUnrealEdEngine* GUnrealEd;\n\nstatic int NumberOfPlayers(int Mode) { return (Mode & 3) + 1; }\n\nstatic bool SpawnAtPlayerStart(int Mode) { return (Mode & 4) != 0; }\n\nstatic bool DedicatedServer(int Mode) { return (Mode & 8) != 0; }\n\nenum class Compile\n{\n    Yes,\n    No\n};\n\nstatic Compile CompileBeforeRun(int Mode) { return (Mode & 128) != 0 ? Compile::Yes : Compile::No; }\n\nstatic EPlayModeType PlayModeFromInt(int ModeNumber)\n{\n    switch (ModeNumber)\n    {\n    default: break;\n    case 1: return PlayMode_InMobilePreview;\n    case 2: return PlayMode_InEditorFloating;\n    case 3: return PlayMode_InVR;\n    case 4: return PlayMode_InNewProcess;\n    case 5: return PlayMode_Simulate;\n#if ENGINE_MAJOR_VERSION < 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 7)\n    case 6: return PlayMode_InVulkanPreview;\n#endif\n    }\n    return PlayMode_InViewPort;\n}\n\nstatic int PlayModeToInt(EPlayModeType modeType)\n{\n    switch (modeType)\n    {\n    default: break;\n#if ENGINE_MAJOR_VERSION < 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 8)\n    case PlayMode_InTargetedMobilePreview:\n#endif\n    case PlayMode_InMobilePreview:\n        return 1;\n    case PlayMode_InEditorFloating: return 2;\n    case PlayMode_InVR: return 3;\n    case PlayMode_InNewProcess: return 4;\n    case PlayMode_Simulate: return 5;\n#if ENGINE_MAJOR_VERSION < 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 7)\n    case PlayMode_InVulkanPreview: return 6;\n#endif\n    }\n    return 0;\n}\n\nFSlateApplication* SlateApplication = nullptr;\n\nstruct FPlaySettings\n{\n    EPlayModeType PlayMode;\n    int32 NumberOfClients;\n    bool bNetDedicated;\n    bool bSpawnAtPlayerStart;\n\n    static FPlaySettings UnpackFromMode(int32_t mode)\n    {\n        FPlaySettings settings = {\n            PlayModeFromInt((mode & (16 + 32 + 64)) >> 4),\n            NumberOfPlayers(mode),\n            DedicatedServer(mode),\n            SpawnAtPlayerStart(mode),\n        };\n        return settings;\n    }\n\n    static int32_t PackToMode(const FPlaySettings& settings)\n    {\n        return (settings.NumberOfClients - 1) +\n            (settings.bSpawnAtPlayerStart ? (1 << 2) : 0) +\n            (settings.bNetDedicated ? (1 << 3) : 0) +\n            (PlayModeToInt(settings.PlayMode) << 4);\n    }\n};\n\n\nstatic FPlaySettings RetrieveSettings(const ULevelEditorPlaySettings* PlayInSettings)\n{\n    check(PlayInSettings);\n\n    FPlaySettings settings;\n    settings.PlayMode = PlayInSettings->LastExecutedPlayModeType;\n    PlayInSettings->GetPlayNumberOfClients(settings.NumberOfClients);\n#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION <= 24\n    PlayInSettings->GetPlayNetDedicated(settings.bNetDedicated);\n#else\n    settings.bNetDedicated = PlayInSettings->bLaunchSeparateServer;\n#endif\n    settings.bSpawnAtPlayerStart = PlayInSettings->LastExecutedPlayModeLocation == PlayLocation_DefaultPlayerStart;\n\n    return settings;\n}\n\nstatic void UpdateSettings(ULevelEditorPlaySettings* PlayInSettings, const FPlaySettings& settings)\n{\n    check(PlayInSettings);\n    \n    PlayInSettings->SetPlayNumberOfClients(settings.NumberOfClients);\n#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION <= 24\n    PlayInSettings->SetPlayNetDedicated(settings.bNetDedicated);\n#else\n    PlayInSettings->bLaunchSeparateServer = settings.bNetDedicated;\n#endif\n    PlayInSettings->LastExecutedPlayModeLocation =\n        settings.bSpawnAtPlayerStart\n            ? PlayLocation_DefaultPlayerStart\n            : PlayLocation_CurrentCameraLocation;\n    PlayInSettings->LastExecutedPlayModeType = settings.PlayMode;\n\n    PlayInSettings->PostEditChange();\n    PlayInSettings->SaveConfig();\n}\n\n\nstruct FCachedCommandInfo\n{\n    FName CommandName;\n    TSharedPtr<FUICommandInfo> Command;\n};\n\nclass FRiderGameControlActionsCache\n{\npublic:\n    FRiderGameControlActionsCache();\n    ~FRiderGameControlActionsCache();\n\nprivate:\n    void UpdatePlayWorldCommandsCache();\n\npublic:\n    FCachedCommandInfo PlayModeCommands[PlayMode_Count] = {\n        {TEXT(\"PlayInViewport\")},\n        {TEXT(\"PlayInEditorFloating\")},\n        {TEXT(\"PlayInMobilePreview\")},\n        {FName()},\n#if ENGINE_MAJOR_VERSION < 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 7)\n        {TEXT(\"PlayInVulkanPreview\")},\n#else\n        {FName()},\n#endif\n        {TEXT(\"PlayInNewProcess\")},\n        {TEXT(\"PlayInVR\")},\n        {TEXT(\"Simulate\")},\n    };\n    FCachedCommandInfo ResumePlaySession = {TEXT(\"ResumePlaySession\")};\n    FCachedCommandInfo PausePlaySession = {TEXT(\"PausePlaySession\")};\n    FCachedCommandInfo StopPlaySession = {TEXT(\"StopPlaySession\")};\n    FCachedCommandInfo SingleFrameAdvance = {TEXT(\"SingleFrameAdvance\")};\n\nprivate:\n    FDelegateHandle CommandsChangedHandle;\n};\n\nFRiderGameControlActionsCache::FRiderGameControlActionsCache()\n{\n    const FName PlayWorldContextName = FName(\"PlayWorld\");\n\n    TSharedPtr<FBindingContext> PlayWorldContext = FInputBindingManager::Get().GetContextByName(PlayWorldContextName);\n    if (PlayWorldContext.IsValid())\n    {\n        UpdatePlayWorldCommandsCache();\n    }\n\n    CommandsChangedHandle = FBindingContext::CommandsChanged.AddLambda(\n        [this, PlayWorldContextName](const FBindingContext& Ctx)\n        {\n            if (Ctx.GetContextName() == PlayWorldContextName)\n            {\n                UpdatePlayWorldCommandsCache();\n            }\n        }\n    );\n}\n\nFRiderGameControlActionsCache::~FRiderGameControlActionsCache()\n{\n    FBindingContext::CommandsChanged.Remove(CommandsChangedHandle);\n}\n\nvoid FRiderGameControlActionsCache::UpdatePlayWorldCommandsCache()\n{\n    FInputBindingManager& BindingManager = FInputBindingManager::Get();\n    auto CacheCommand = [&] (FCachedCommandInfo &Cmd, const FName &ContextName)\n    {\n        Cmd.Command = BindingManager.FindCommandInContext(ContextName, Cmd.CommandName);\n    };\n\n    const FName PlayWorldContextName = FName(\"PlayWorld\");\n    for (FCachedCommandInfo& PlayModeCommand : PlayModeCommands)\n    {\n        if (PlayModeCommand.CommandName.IsNone()) continue;\n        CacheCommand(PlayModeCommand, PlayWorldContextName);\n    }\n    CacheCommand(ResumePlaySession, PlayWorldContextName);\n    CacheCommand(PausePlaySession, PlayWorldContextName);\n    CacheCommand(StopPlaySession, PlayWorldContextName);\n    CacheCommand(SingleFrameAdvance, PlayWorldContextName);\n}\n\n\nclass FRiderGameControl\n{\npublic:\n    FRiderGameControl(rd::Lifetime Lifetime, JetBrains::EditorPlugin::RdEditorModel const &Model, FRiderGameControlActionsCache& ActionsCache);\n    ~FRiderGameControl();\nprivate:\n    void RequestPlayWorldCommand(const FCachedCommandInfo& CommandInfo, int RequestID);\n\n    void SendRequestSucceed(int RequestID);\n    void SendRequestFailed(int RequestID, JetBrains::EditorPlugin::NotificationType Type, const FString& Message);\n\n    void ScheduleModelAction(TFunction<void(JetBrains::EditorPlugin::RdEditorModel const&)> Action);\n\nprivate:\n    FRiderGameControlActionsCache& Actions;\n    JetBrains::EditorPlugin::RdEditorModel const &Model;\n\n    int32_t playMode;\n\n    FDelegateHandle BeginPIEHandle;\n    FDelegateHandle EndPIEHandle;\n    FDelegateHandle PausePIEHandle;\n    FDelegateHandle ResumePIEHandle;\n    FDelegateHandle SingleStepPIEHandle;\n    FDelegateHandle OnObjectPropertyChangedHandle;\n};\n\n\nvoid FRiderGameControl::SendRequestSucceed(int RequestID)\n{\n    using namespace JetBrains::EditorPlugin;\n    ScheduleModelAction([=](RdEditorModel const& EditorModel)\n    {\n        EditorModel.get_notificationReplyFromEditor().fire(RequestSucceed(RequestID));\n    });\n}\n\nvoid FRiderGameControl::SendRequestFailed(int RequestID, JetBrains::EditorPlugin::NotificationType Type,\n                                          const FString& Message)\n{\n    using namespace JetBrains::EditorPlugin;\n    ScheduleModelAction([=](RdEditorModel const& EditorModel)\n    {\n        EditorModel.get_notificationReplyFromEditor().fire(RequestFailed(Type, Message, RequestID));\n    });\n}\n\nvoid FRiderGameControl::RequestPlayWorldCommand(const FCachedCommandInfo& CommandInfo, int RequestID)\n{\n    using namespace JetBrains::EditorPlugin;\n    if (!CommandInfo.Command.IsValid())\n    {\n        const FString Message = FString::Format(TEXT(\"Command '{0}' was not executed.\\nCommand was not registered in Unreal Engine\"),\n                                                {CommandInfo.CommandName.ToString()});\n        SendRequestFailed(RequestID, NotificationType::Error, Message);\n        return;\n    }\n    AsyncTask(ENamedThreads::GameThread, [this, RequestID, CommandInfo]()\n    {\n        if (FPlayWorldCommands::GlobalPlayWorldActions->TryExecuteAction(CommandInfo.Command.ToSharedRef()))\n        {\n            SendRequestSucceed(RequestID);\n        }\n        else\n        {\n            const FString Message = FString::Format(TEXT(\"Command '{0}' was not executed.\\nRejected by Unreal Engine\"),\n                                                    {CommandInfo.CommandName.ToString()});\n            SendRequestFailed(RequestID, NotificationType::Message, Message);\n        }\n    });\n}\n\nvoid FRiderGameControl::ScheduleModelAction(TFunction<void(JetBrains::EditorPlugin::RdEditorModel const&)> Action)\n{\n    IRiderLinkModule& RiderLinkModule = IRiderLinkModule::Get();\n    RiderLinkModule.QueueAction([Action, this]()\n    {\n        Action(Model);\n    });\n}\n\nFRiderGameControl::FRiderGameControl(rd::Lifetime Lifetime, JetBrains::EditorPlugin::RdEditorModel const &Model, FRiderGameControlActionsCache& ActionsCache) :\n    Actions(ActionsCache), Model(Model)\n{\n    using namespace JetBrains::EditorPlugin;\n    \n    // Subscribe to Editor events\n    Lifetime->bracket(\n        [this]()\n        {\n            BeginPIEHandle = FEditorDelegates::BeginPIE.AddLambda([this](const bool)\n            {\n                ScheduleModelAction([](RdEditorModel const& model)\n                {\n                    model.get_playStateFromEditor().fire(PlayState::Play);\n                });\n            });\n            EndPIEHandle = FEditorDelegates::EndPIE.AddLambda([this](const bool)\n            {\n                ScheduleModelAction([](RdEditorModel const& model)\n                {\n                    model.get_playStateFromEditor().fire(PlayState::Idle);\n                });\n            });\n            PausePIEHandle = FEditorDelegates::PausePIE.AddLambda([this](const bool)\n            {\n                ScheduleModelAction([](RdEditorModel const& model)\n                {\n                    model.get_playStateFromEditor().fire(PlayState::Pause);\n                });\n            });\n            ResumePIEHandle = FEditorDelegates::ResumePIE.AddLambda([this](const bool)\n            {\n                ScheduleModelAction([](RdEditorModel const& model)\n                {\n                    model.get_playStateFromEditor().fire(PlayState::Play);\n                });\n            });\n            SingleStepPIEHandle = FEditorDelegates::SingleStepPIE.AddLambda([this](const bool)\n            {\n                ScheduleModelAction([](RdEditorModel const& model)\n                {\n                    model.get_playStateFromEditor().fire(PlayState::Play);\n                    model.get_playStateFromEditor().fire(PlayState::Pause);\n                });\n            });\n\n            OnObjectPropertyChangedHandle = FCoreUObjectDelegates::OnObjectPropertyChanged.AddLambda(\n                [this](UObject* obj, FPropertyChangedEvent& ev)\n                {\n                    ULevelEditorPlaySettings* PlayInSettings = GetMutableDefault<ULevelEditorPlaySettings>();\n                    if (!PlayInSettings || obj != PlayInSettings) return;\n\n                    const FPlaySettings Settings = RetrieveSettings(PlayInSettings);\n                    int PlayModeNew = FPlaySettings::PackToMode(Settings);\n                    if (PlayModeNew == playMode) return;\n\n                    playMode = PlayModeNew;\n                    ScheduleModelAction([PlayModeNew](RdEditorModel const& Model)\n                    {\n                        Model.get_playModeFromEditor().fire(PlayModeNew);\n                    });\n                }\n            );\n        },\n        [this]()\n        {\n            FCoreUObjectDelegates::OnObjectPropertyChanged.Remove(OnObjectPropertyChangedHandle);\n            FEditorDelegates::SingleStepPIE.Remove(SingleStepPIEHandle);\n            FEditorDelegates::ResumePIE.Remove(ResumePIEHandle);\n            FEditorDelegates::PausePIE.Remove(PausePIEHandle);\n            FEditorDelegates::EndPIE.Remove(EndPIEHandle);\n            FEditorDelegates::BeginPIE.Remove(BeginPIEHandle);\n        }\n    );\n\n    // Subscribe to model\n    ScheduleModelAction([Lifetime, this](RdEditorModel const& Model)\n    {\n        Model.get_requestPlayFromRider()\n             .advise(Lifetime, [this](int requestID)\n                     {\n                         const ULevelEditorPlaySettings* PlayInSettings\n                             = GetDefault<ULevelEditorPlaySettings>();\n                         check(PlayInSettings);\n                         const EPlayModeType PlayMode = PlayInSettings->LastExecutedPlayModeType;\n\n                         RequestPlayWorldCommand(Actions.PlayModeCommands[PlayMode], requestID);\n                     }\n             );\n        Model.get_requestPauseFromRider()\n             .advise(Lifetime, [this](int requestID)\n                     {\n                         RequestPlayWorldCommand(Actions.PausePlaySession, requestID);\n                     }\n             );\n        Model.get_requestResumeFromRider()\n             .advise(Lifetime, [this](int requestID)\n                     {\n                         RequestPlayWorldCommand(Actions.ResumePlaySession, requestID);\n                     }\n             );\n        Model.get_requestStopFromRider()\n             .advise(Lifetime, [this](int requestID)\n                     {\n                         RequestPlayWorldCommand(Actions.StopPlaySession, requestID);\n                     }\n             );\n        Model.get_requestFrameSkipFromRider()\n             .advise(Lifetime, [this](int requestID)\n                     {\n                         RequestPlayWorldCommand(Actions.SingleFrameAdvance, requestID);\n                     }\n             );\n\n        Model.get_playModeFromRider()\n             .advise(Lifetime, [this](int32_t mode)\n                     {\n                         ULevelEditorPlaySettings* PlayInSettings\n                             = GetMutableDefault<ULevelEditorPlaySettings>();\n                         check(PlayInSettings);\n                         const FPlaySettings NewSettings = FPlaySettings::UnpackFromMode(mode);\n                         UpdateSettings(PlayInSettings, NewSettings);\n                     }\n             );\n    });\n\n    // Initial sync.\n    const ULevelEditorPlaySettings* PlayInSettings = GetDefault<ULevelEditorPlaySettings>();\n    check(PlayInSettings);\n    const FPlaySettings Settings = RetrieveSettings(PlayInSettings);\n    playMode = FPlaySettings::PackToMode(Settings);\n\n    ScheduleModelAction([lambdaPlayMode=playMode](RdEditorModel const &Model)\n    {\n        Model.get_playModeFromEditor().fire(lambdaPlayMode);\n    });\n\n    // After all initialization finished/scheduled - mark that module was initialized\n    Lifetime->bracket(\n        [this]()\n        {\n            ScheduleModelAction([](RdEditorModel const& Model)\n            {\n                Model.get_isGameControlModuleInitialized().set(true);\n            });\n        },\n        [this]()\n        {\n            ScheduleModelAction([](RdEditorModel const& Model)\n            {\n                Model.get_isGameControlModuleInitialized().set(false);\n            });\n        }\n    );\n}\n\nFRiderGameControl::~FRiderGameControl()\n{\n}\n\n\nvoid FRiderGameControlModule::StartupModule()\n{\n    using namespace JetBrains::EditorPlugin;\n    \n    UE_LOG(FLogRiderGameControlModule, Verbose, TEXT(\"STARTUP START\"));\n\n    // Actions cache is not related to connection and its lifetimes\n    ActionsCache = MakeUnique<FRiderGameControlActionsCache>();\n\n    IRiderLinkModule& RiderLinkModule = IRiderLinkModule::Get();\n    ModuleLifetimeDefinition = RiderLinkModule.CreateNestedLifetimeDefinition();\n    rd::Lifetime ModuleLifetime = ModuleLifetimeDefinition.lifetime;\n\n    RiderLinkModule.ViewModel(\n        ModuleLifetime,\n        [&](rd::Lifetime ModelLifetime, RdEditorModel const& Model)\n        {\n            ModelLifetime->add_action([&]() { GameControl.Reset(); });\n            GameControl = MakeUnique<FRiderGameControl>(ModelLifetime, Model, *ActionsCache);\n        }\n    );\n\n    UE_LOG(FLogRiderGameControlModule, Verbose, TEXT(\"STARTUP FINISH\"));\n}\n\nvoid FRiderGameControlModule::ShutdownModule()\n{\n    UE_LOG(FLogRiderGameControlModule, Verbose, TEXT(\"SHUTDOWN START\"));\n    ModuleLifetimeDefinition.terminate();\n    ActionsCache.Reset();\n    UE_LOG(FLogRiderGameControlModule, Verbose, TEXT(\"SHUTDOWN FINISH\"));\n}\n\n#undef LOCTEXT_NAMESPACE"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderGameControl/Public/RiderGameControl.hpp",
    "content": "#pragma once\n\n#include \"lifetime/LifetimeDefinition.h\"\n\n#include \"Logging/LogMacros.h\"\n#include \"Logging/LogVerbosity.h\"\n#include \"Modules/ModuleInterface.h\"\n#include \"Templates/UniquePtr.h\"\n\nDECLARE_LOG_CATEGORY_EXTERN(FLogRiderGameControlModule, Log, All);\n\nclass FRiderGameControl;\nclass FRiderGameControlActionsCache;\n\nclass FRiderGameControlModule : public IModuleInterface\n{\npublic:\n    FRiderGameControlModule() = default;\n    virtual ~FRiderGameControlModule() override = default;\n\n    /** IModuleInterface implementation */\n    virtual void StartupModule() override;\n    virtual void ShutdownModule() override;\n    virtual bool SupportsDynamicReloading() override { return true; }\n\nprivate:\n    rd::LifetimeDefinition ModuleLifetimeDefinition;\n    TUniquePtr<FRiderGameControl> GameControl;\n    TUniquePtr<FRiderGameControlActionsCache> ActionsCache;\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderGameControl/RiderGameControl.Build.cs",
    "content": "using UnrealBuildTool;\n\npublic class RiderGameControl : ModuleRules\n{\n\tpublic RiderGameControl(ReadOnlyTargetRules Target) : base(Target)\n\t{\n#if UE_4_22_OR_LATER\n\t\tPCHUsage = PCHUsageMode.NoPCHs;\n#else\n\t\tPCHUsage = PCHUsageMode.NoSharedPCHs;\n#endif\n\t\t\n\t\tbUseRTTI = true;\n\n#if UE_5_2_OR_LATER\n\t\tbDisableStaticAnalysis = true;\n#endif\n\n\t\tPublicDependencyModuleNames.Add(\"Core\");\n\n\t\tPrivateDependencyModuleNames.AddRange(new []\n\t\t{\n\t\t\t\"RD\",\n\t\t\t\"RiderLink\",\n\t\t\t\"HeadMountedDisplay\",\n\t\t\t\"LevelEditor\",\n\t\t\t\"UnrealEd\",\n\t\t\t\"Slate\",\n\t\t\t\"CoreUObject\",\n\t\t\t\"Engine\"\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLC/Private/RiderLC.cpp",
    "content": "﻿#include \"RiderLC.hpp\"\n\n#include \"IRiderLink.hpp\"\n#include \"RdEditorModel/RdEditorModel.Pregenerated.h\"\n\n#include \"Async/Async.h\"\n#if WITH_LIVE_CODING\n#include \"ILiveCodingModule.h\"\n#endif\n#include \"Misc/HotReloadInterface.h\"\n\n#define LOCTEXT_NAMESPACE \"FRiderLCModule\"\n\nDEFINE_LOG_CATEGORY(FLogRiderLCModule);\n\nIMPLEMENT_MODULE(FRiderLCModule, RiderLC)\n\nconst FName HotReloadModule(\"HotReload\");\n\nvoid FRiderLCModule::SetupLiveCodingBinds()\n{\n\tIRiderLinkModule& RiderLinkModule = IRiderLinkModule::Get();\n\tRiderLinkModule.ViewModel(ModuleLifetimeDef.lifetime, [](const rd::Lifetime& Lifetime, JetBrains::EditorPlugin::RdEditorModel const& RdEditorModel)\n\t{\n\t\tRdEditorModel.get_triggerHotReload().advise(Lifetime, []\n\t\t{\n\t\t\tAsyncTask(ENamedThreads::GameThread, []\n\t\t\t{\n#if WITH_LIVE_CODING\n\t\t\t\tILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);\n\t\t\t\tif (LiveCoding != nullptr && LiveCoding->IsEnabledByDefault())\n\t\t\t\t{\n\t\t\t\t\tLiveCoding->EnableForSession(true);\n\t\t\t\t\tif (LiveCoding->IsEnabledForSession())\n\t\t\t\t\t{\n\t\t\t\t\t\tLiveCoding->Compile();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n#endif\n\t\t\t\t{\n#if WITH_HOT_RELOAD\n\t\t\t\t\tIHotReloadInterface* HotReload = FModuleManager::GetModulePtr<IHotReloadInterface>(HotReloadModule);\n\t\t\t\t\tif (HotReload != nullptr && !HotReload->IsCurrentlyCompiling())\n\t\t\t\t\t{\n\t\t\t\t\t\tHotReload->DoHotReloadFromEditor(EHotReloadFlags::None);\n\t\t\t\t\t}\n#endif\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t});\n}\n\nbool FRiderLCModule::Tick(float DeltaTime)\n{\n\tbool bIsAvailable = false;\n\tbool bIsCompiling = false;\n#if WITH_LIVE_CODING\n\tconst ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);\n\tif (LiveCoding != nullptr && LiveCoding->IsEnabledByDefault())\n\t{\n\t\tbIsAvailable = true;\n\t\tbIsCompiling = LiveCoding->IsCompiling();\n\t}\n\telse\n#endif\n\t{\n#if WITH_HOT_RELOAD\n\t\tconst IHotReloadInterface* HotReload = FModuleManager::GetModulePtr<IHotReloadInterface>(HotReloadModule);\n\t\tif (HotReload != nullptr)\n\t\t{\n\t\t\tbIsAvailable = true;\n\t\t\tbIsCompiling = HotReload->IsCurrentlyCompiling();\n\t\t}\n#endif\n\t}\n\tIRiderLinkModule& RiderLinkModule = IRiderLinkModule::Get();\n\tRiderLinkModule.QueueModelAction([bIsAvailable, bIsCompiling](JetBrains::EditorPlugin::RdEditorModel const& RdEditorModel)\n\t{\n\t\tRdEditorModel.get_isHotReloadAvailable().set(bIsAvailable);\n\t\tRdEditorModel.get_isHotReloadCompiling().set(bIsCompiling);\n\t});\n\n\treturn true;\n}\n\nvoid FRiderLCModule::StartupModule()\n{\n\tUE_LOG(FLogRiderLCModule, Verbose, TEXT(\"RiderLC STARTUP START\"));\n\t\n\tconst IRiderLinkModule& RiderLinkModule = IRiderLinkModule::Get();\n\tModuleLifetimeDef = RiderLinkModule.CreateNestedLifetimeDefinition();\n\tSetupLiveCodingBinds();\n\tTickDelegate = FTickerDelegate::CreateRaw(this, &FRiderLCModule::Tick);\n#if ENGINE_MAJOR_VERSION < 5\n\tTickDelegateHandle = FTicker::GetCoreTicker().AddTicker(TickDelegate);\n#else\n\tTickDelegateHandle = FTSTicker::GetCoreTicker().AddTicker(TickDelegate);\n#endif\n\t\n\tUE_LOG(FLogRiderLCModule, Verbose, TEXT(\"RiderLC STARTUP FINISH\"));\n}\n\nvoid FRiderLCModule::ShutdownModule()\n{\n\tUE_LOG(FLogRiderLCModule, Verbose, TEXT(\"RiderLC SHUTDOWN START\"));\n\n#if ENGINE_MAJOR_VERSION < 5\n\tFTicker::GetCoreTicker().RemoveTicker(TickDelegateHandle);\n#else\n\tFTSTicker::GetCoreTicker().RemoveTicker(TickDelegateHandle);\n#endif\n\tModuleLifetimeDef.terminate();\n\t\n\tUE_LOG(FLogRiderLCModule, Verbose, TEXT(\"RiderLC SHUTDOWN FINISH\"));\n}\n\n#undef LOCTEXT_NAMESPACE"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLC/Private/RiderLC.hpp",
    "content": "﻿#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Containers/Ticker.h\"\n#include \"lifetime/LifetimeDefinition.h\"\n#include \"Modules/ModuleManager.h\"\n#include \"Runtime/Launch/Resources/Version.h\"\n\nDECLARE_LOG_CATEGORY_EXTERN(FLogRiderLCModule, Log, All);\n\nclass FRiderLCModule : public IModuleInterface\n{\npublic:\n    virtual void StartupModule() override;\n    virtual void ShutdownModule() override;\n\tvirtual bool SupportsDynamicReloading() override { return true; }\n\tvoid SetupLiveCodingBinds();\n\t\nprivate:\n\tbool Tick(float DeltaTime);\n\t\n\trd::LifetimeDefinition ModuleLifetimeDef;\n\tFTickerDelegate TickDelegate;\n#if ENGINE_MAJOR_VERSION < 5\n\tFDelegateHandle TickDelegateHandle;\n#else\n\tFTSTicker::FDelegateHandle TickDelegateHandle;\n#endif\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLC/RiderLC.Build.cs",
    "content": "﻿using UnrealBuildTool;\n\npublic class RiderLC : ModuleRules\n{\n    public RiderLC(ReadOnlyTargetRules Target) : base(Target)\n    {\n#if UE_4_22_OR_LATER\n        PCHUsage = PCHUsageMode.NoPCHs;\n#else\n\t\tPCHUsage = PCHUsageMode.NoSharedPCHs;\n#endif\n\n        bUseRTTI = true;\n\n#if UE_5_2_OR_LATER\n\t\tbDisableStaticAnalysis = true;\n#endif\n\n        PrivateDefinitions.Add(\"_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING\");\n        PrivateDefinitions.Add(\"_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS\");\n        PrivateDependencyModuleNames.AddRange(\n            new string[]\n            {\n                \"Core\",\n                \"Engine\",\n                \"RiderLink\",\n                \"RD\"\n            }\n        );\n        \n        if (Target.bWithLiveCoding)\n        {\n            PrivateIncludePathModuleNames.Add(\"LiveCoding\");\n        }\n    }\n}"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLink/Private/ProtocolFactory.cpp",
    "content": "#include \"ProtocolFactory.h\"\n\n#include \"scheduler/base/IScheduler.h\"\n#include \"wire/SocketWire.h\"\n\n#include \"Runtime/Launch/Resources/Version.h\"\n\n#if ENGINE_MAJOR_VERSION >= 5\n#include \"HAL/PlatformFileManager.h\"\n#else\n#include \"HAL/PlatformFilemanager.h\"\n#endif\n#include \"Misc/App.h\"\n#include \"Misc/FileHelper.h\"\n#include \"Misc/Paths.h\"\n\n#if PLATFORM_WINDOWS\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"Windows/AllowWindowsPlatformTypes.h\"\n\n#if ENGINE_MAJOR_VERSION <5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 4)\n#include \"Windows/PreWindowsApi.h\"\n#endif\n\n#include \"Windows/WindowsPlatformMisc.h\"\n\n#if ENGINE_MAJOR_VERSION <5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 4)\n#include \"Windows/PostWindowsApi.h\"\n#endif\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"Windows/HideWindowsPlatformTypes.h\"\n#endif\n\n#include \"spdlog/sinks/daily_file_sink.h\"\n\nstatic FString GetLocalAppdataFolder()\n{\n    const FString EnvironmentVarName =\n#if PLATFORM_WINDOWS\nTEXT(\"LOCALAPPDATA\");\n#else\n    TEXT(\"HOME\");\n#endif\n#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION <= 20\n    TCHAR CAppDataLocalPath[4096];\n    FPlatformMisc::GetEnvironmentVariable(*EnvironmentVarName, CAppDataLocalPath, ARRAY_COUNT(CAppDataLocalPath));\n    return CAppDataLocalPath;\n#else\n    return FPlatformMisc::GetEnvironmentVariable(*EnvironmentVarName);\n#endif\n}\n\nstatic FString GetMiscFilesFolder()\n{    \n    FString FAppDataLocalPath = GetLocalAppdataFolder();\n    FPaths::NormalizeFilename(FAppDataLocalPath);\n    return FPaths::Combine(*FAppDataLocalPath,\n#if PLATFORM_WINDOWS\n        TEXT(\"Jetbrains\"), TEXT(\"Rider\"), TEXT(\"Unreal\")\n#elif PLATFORM_MAC\n        TEXT(\"Library\"), TEXT(\"Logs\"), TEXT(\"Unreal Engine\")\n#else\n        TEXT(\".config\"), TEXT(\"unrealEngine\")\n#endif\n    );\n}\n\nstatic FString GetPathToPortsFolder()\n{\n    const FString MiscFilesFolder = GetMiscFilesFolder();\n    return FPaths::Combine(*MiscFilesFolder, TEXT(\"Ports\"));\n}\n\nstatic FString GetLogFile(const FString& projectName)\n{\n    const FString MiscFilesFolder = GetMiscFilesFolder();\n    return FPaths::Combine(*MiscFilesFolder, TEXT(\"Logs\"), projectName + TEXT(\".uproject\"));\n}\n\nProtocolFactory::ProtocolFactory(const FString& ProjectName): ProjectName(ProjectName)\n{\n    InitRdLogging();\n}\n\nvoid ProtocolFactory::InitRdLogging()\n{\n    spdlog::set_level(spdlog::level::err);\n#if defined(ENABLE_LOG_FILE) && ENABLE_LOG_FILE == 1\n    const FString LogFile = GetLogFile(ProjectName);\n    const FString Msg = TEXT(\"[RiderLink] Path to log file: \") + LogFile;\n    auto FileLogger = std::make_shared<spdlog::sinks::daily_file_sink_mt>(*LogFile, 23, 59);\n    FileLogger->set_level(spdlog::level::trace);\n    spdlog::apply_all([FileLogger](std::shared_ptr<spdlog::logger> Logger)\n    {\n        Logger->sinks().push_back(FileLogger);\n    });\n#endif\n}\n\nstd::shared_ptr<rd::SocketWire::Server> ProtocolFactory::CreateWire(rd::IScheduler* Scheduler, rd::Lifetime SocketLifetime)\n{\n    return std::make_shared<rd::SocketWire::Server>(SocketLifetime, Scheduler, 0,\n                                                         TCHAR_TO_UTF8(*FString::Printf(TEXT(\"UnrealEditorServer-%s\"),\n                                                             *ProjectName)));\n}\n\n\nTUniquePtr<rd::Protocol> ProtocolFactory::CreateProtocol(rd::IScheduler* Scheduler, rd::Lifetime SocketLifetime, std::shared_ptr<rd::SocketWire::Server> wire)\n{\n    auto protocol = MakeUnique<rd::Protocol>(rd::Identities::SERVER, Scheduler, wire, SocketLifetime);\n\n    auto& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();\n    const FString PortFullDirectoryPath = GetPathToPortsFolder();\n    if (PlatformFile.CreateDirectoryTree(*PortFullDirectoryPath) && !IsRunningCommandlet())\n    {\n        const FString ProjectFileName = ProjectName + TEXT(\".uproject\");\n        const FString TmpPortFile = TEXT(\"~\") + ProjectFileName;\n        const FString TmpPortFileFullPath = FPaths::Combine(*PortFullDirectoryPath, *TmpPortFile);\n        FFileHelper::SaveStringToFile(FString::FromInt(wire->port), *TmpPortFileFullPath);\n        const FString PortFileFullPath = FPaths::Combine(*PortFullDirectoryPath, *ProjectFileName);\n        IFileManager::Get().Move(*PortFileFullPath, *TmpPortFileFullPath, true, true);\n    }\n    return protocol;\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLink/Private/ProtocolFactory.h",
    "content": "﻿#pragma once\n\n#include <protocol/Protocol.h>\n#include \"wire/SocketWire.h\"\n\n#include \"Containers/UnrealString.h\"\n#include \"Templates/UniquePtr.h\"\n\nclass ProtocolFactory\n{\npublic:\n\texplicit ProtocolFactory(const FString& ProjectName);\n\n\tstd::shared_ptr<rd::SocketWire::Server> CreateWire(rd::IScheduler* Scheduler, rd::Lifetime SocketLifetime);\n\tTUniquePtr<rd::Protocol> CreateProtocol(rd::IScheduler* Scheduler, rd::Lifetime SocketLifetime,\n\t                                        std::shared_ptr<rd::SocketWire::Server> wire);\n\nprivate:\n\tvoid InitRdLogging();\n\nprivate:\n\tFString ProjectName;\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLink/Private/RiderLink.cpp",
    "content": "#include \"RiderLink.hpp\"\n\n#include \"ProtocolFactory.h\"\n#include \"UE4Library/UE4Library.Pregenerated.h\"\n\n#include \"Async/Async.h\"\n#include \"Misc/App.h\"\n#include \"Misc/ScopeRWLock.h\"\n#include \"Modules/ModuleManager.h\"\n#include \"HAL/Platform.h\"\n\n#define LOCTEXT_NAMESPACE \"RiderLink\"\n\nDEFINE_LOG_CATEGORY(FLogRiderLinkModule);\n\nIMPLEMENT_MODULE(FRiderLinkModule, RiderLink);\n\nstatic FString GetProjectName()\n{\n\tFString ProjectNameNoExtension = FApp::GetProjectName();\n\tif (ProjectNameNoExtension.IsEmpty())\n\t\tProjectNameNoExtension = TEXT(\"<ENGINE>\");\n\treturn ProjectNameNoExtension;\n}\n\nvoid FRiderLinkModule::ShutdownModule()\n{\n\tUE_LOG(FLogRiderLinkModule, Verbose, TEXT(\"RiderLink SHUTDOWN START\"));\n\t\n\tModuleLifetimeDef.terminate();\n\tProtocolFactory.Reset();\n\tUE_LOG(FLogRiderLinkModule, Verbose, TEXT(\"RiderLink SHUTDOWN FINISH\"));\n}\n\nvoid FRiderLinkModule::StartupModule()\n{\n\tUE_LOG(FLogRiderLinkModule, Verbose, TEXT(\"RiderLink STARTUP START\"));\n\t\n\tProtocolFactory = MakeUnique<class ProtocolFactory>(GetProjectName());\n\tScheduler.queue([this]()\n\t{\n\t\tInitProtocol();\n\t});\n\tUE_LOG(FLogRiderLinkModule, Verbose, TEXT(\"RiderLink STARTUP FINISH\"));\n}\n\nvoid FRiderLinkModule::InitProtocol()\n{\n\tWireLifetimeDef = MakeUnique<rd::LifetimeDefinition>(ModuleLifetimeDef.lifetime);\n\trd::Lifetime WireLifetime = WireLifetimeDef->lifetime;\n\tstd::shared_ptr<rd::SocketWire::Server> Wire = ProtocolFactory->CreateWire(&Scheduler, WireLifetime);\n\tProtocol = ProtocolFactory->CreateProtocol(&Scheduler, WireLifetime.create_nested(), Wire);\n\t// Exception fired for Server::Base::~Base() when trying to invoke it this way\n//\tWireLifetime->add_action([this]()\n//\t{\n//\t\tif (!ModuleLifetimeDef.is_terminated())\n//\t\t{\n//\t\t\tScheduler.queue([this]()\n//\t\t\t{\n//\t\t\t\tInitProtocol();\n//\t\t\t});\n//\t\t}\n//\t});\n\tProtocol->wire->connected.view(WireLifetime, [this](rd::Lifetime ConnectionLifetime, bool const& IsConnected)\n\t{\n\t\tScheduler.queue([this, ConnectionLifetime, IsConnected]()\n\t\t{\n\t\t\tif (!IsConnected) return;\n\n\t\t\tFRWScopeLock LockOnConnect(ModelLock, SLT_Write);\n\t\t\tEditorModel = MakeUnique<JetBrains::EditorPlugin::RdEditorModel>();\n\t\t\tEditorModel->connect(ConnectionLifetime, Protocol.Get());\n\t\t\tJetBrains::EditorPlugin::UE4Library::serializersOwner.registerSerializersCore(\n\t\t\t\tEditorModel->get_serialization_context().get_serializers()\n\t\t\t);\n\t\t\tConnectionLifetime->add_action([&]() mutable\n\t\t\t{\n\t\t\t\tScheduler.queue([&]()mutable\n\t\t\t\t{\n                    FRWScopeLock LockOnDisconnect(ModelLock, SLT_Write);\n                    RdIsModelAlive.set(false);\n\t\t\t\t});\n\t\t\t});\n\t\t\tRdIsModelAlive.set(true);\n\t\t\t\n\t\t\tFString projectName = GetProjectName();\n\t\t\tFString executableName = FPlatformProcess::ExecutableName(false);\n\t\t\tuint32_t pid = FPlatformProcess::GetCurrentProcessId();\n\t\t\t\n\t\t\tstd::wstring projectNameWstr = TCHAR_TO_WCHAR(GetData(projectName));\n\t\t\tstd::wstring executableNameWstr = TCHAR_TO_WCHAR(GetData(executableName));\n\t\t\tauto connectionInfo = JetBrains::EditorPlugin::ConnectionInfo(projectNameWstr, executableNameWstr, pid);\n\t\t\tEditorModel->get_connectionInfo().set(connectionInfo);\n\t\t});\n\t});\n}\n\nbool FRiderLinkModule::SupportsDynamicReloading() { return true; }\n\n\n// Can't place RdEditorModel or TUniquePtr<RdEditorModel> into RdProperty.\n// Have to resort to RdProperty<bool> and change it before creating new RdEditorModel\nvoid FRiderLinkModule::ViewModel(rd::Lifetime Lifetime,\n                                 TFunction<void(rd::Lifetime, JetBrains::EditorPlugin::RdEditorModel const&)> Handler)\n{\n\tScheduler.invoke_or_queue([this, Lifetime, Handler]\n\t{\n\t\tRdIsModelAlive.view(Lifetime, [this, Handler](rd::Lifetime ModelLifetime, bool const& Cond)\n\t\t{\n\t\t\tif (Cond) Handler(ModelLifetime, *EditorModel.Get());\n\t\t});\n\t});\n}\n\nvoid FRiderLinkModule::QueueModelAction(TFunction<void(JetBrains::EditorPlugin::RdEditorModel const&)> Handler)\n{\t\n\tScheduler.invoke_or_queue([this, Handler]\n\t{\n\t\tif(!RdIsModelAlive.has_value() || !RdIsModelAlive.get()) return;\n\t\t\n\t\tHandler(*EditorModel.Get());\n\t});\n}\n\nvoid FRiderLinkModule::QueueAction(TFunction<void()> Handler)\n{\n\tScheduler.invoke_or_queue([this, Handler]\n\t{\n\t\tHandler();\n\t});\n}\n\nbool FRiderLinkModule::FireAsyncAction(TFunction<void(JetBrains::EditorPlugin::RdEditorModel const&)> Handler)\n{\n\tFRWScopeLock Lock(ModelLock, SLT_ReadOnly);\n\tif(!RdIsModelAlive.has_value()) return false;\n\t\n\tif(RdIsModelAlive.get())\n\t{\n\t\tHandler(*EditorModel.Get());\n\t}\n\treturn RdIsModelAlive.get();\n}\n\n#undef LOCTEXT_NAMESPACE\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLink/Private/RiderLink.hpp",
    "content": "#pragma once\n\n#include \"IRiderLink.hpp\"\n#include \"impl/RdProperty.h\"\n#include \"lifetime/LifetimeDefinition.h\"\n#include \"scheduler/SingleThreadScheduler.h\"\n#include \"wire/SocketWire.h\"\n\n#include \"Logging/LogMacros.h\"\n#include \"Logging/LogVerbosity.h\"\n#include \"Modules/ModuleManager.h\"\n\n#include \"RdEditorModel/RdEditorModel.Pregenerated.h\"\n\nclass ProtocolFactory;\n\nnamespace rd\n{\n\tclass Protocol;\n}\n\nDECLARE_LOG_CATEGORY_EXTERN(FLogRiderLinkModule, Log, All);\n\nclass RIDERLINK_API FRiderLinkModule : public IRiderLinkModule\n{\npublic:\n\tFRiderLinkModule() = default;\n\tvirtual ~FRiderLinkModule() override = default;\n\n\t/** IModuleInterface implementation */\n\tvirtual void StartupModule() override;\n\tvirtual void ShutdownModule() override;\n\tvirtual bool SupportsDynamicReloading() override;\n\n\tvirtual rd::LifetimeDefinition CreateNestedLifetimeDefinition() const override\n\t{\n\t\treturn rd::LifetimeDefinition{ModuleLifetimeDef.lifetime};\n\t}\n\n\tvirtual void ViewModel(rd::Lifetime Lifetime,\n\t                       TFunction<void(rd::Lifetime,\n\t                                      JetBrains::EditorPlugin::RdEditorModel const&)> Handler) override;\n\tvirtual void QueueModelAction(TFunction<void(JetBrains::EditorPlugin::RdEditorModel const&)> Handler) override;\n\tvirtual void QueueAction(TFunction<void()> Handler) override;\n\tvirtual bool FireAsyncAction(TFunction<void(JetBrains::EditorPlugin::RdEditorModel const&)> Handler) override;\n\nprivate:\n\tvoid InitProtocol();\n\n\trd::LifetimeDefinition ModuleLifetimeDef{rd::Lifetime::Eternal()};\n\trd::SingleThreadScheduler Scheduler{ModuleLifetimeDef.lifetime, \"MainScheduler\"};\n\tTUniquePtr<rd::LifetimeDefinition> WireLifetimeDef;\n\tTUniquePtr<ProtocolFactory> ProtocolFactory;\n\tTUniquePtr<rd::Protocol> Protocol;\n\trd::RdProperty<bool> RdIsModelAlive;\n\tTUniquePtr<JetBrains::EditorPlugin::RdEditorModel> EditorModel;\n\tFRWLock ModelLock;\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLink/Private/UE4TypesMarshallers.cpp",
    "content": "#include \"UE4TypesMarshallers.h\"\n\n#include \"Containers/StringConv.h\"\n#include \"serialization/ArraySerializer.h\"\n#include \"Templates/UniquePtr.h\"\n\n//region FString\n\nnamespace rd {\n\n    FString Polymorphic<FString, void>::read(SerializationCtx& ctx, Buffer& buffer) {\n        UCS2CHAR * str = buffer.read_char16_string();\n        FString tmp{str};\n        delete str;\n        return tmp;\n    }\n\n    void Polymorphic<FString, void>::write(SerializationCtx& ctx, Buffer& buffer, FString const& value) {\n        buffer.write_char16_string(reinterpret_cast<const uint16_t*>(GetData(value)), value.Len());\n    }\n\n\n    size_t hash<FString>::operator()(const FString& value) const noexcept {\n        return GetTypeHash(value);\n    }\n\n\n}\n\ntemplate class rd::Polymorphic<FString>;\ntemplate class rd::Polymorphic<rd::Wrapper<FString>>;\ntemplate struct rd::hash<FString>;\n// template class rd::Polymorphic<TArray<FString>, void>;\n\n//endregion\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLink/Public/IRiderLink.hpp",
    "content": "﻿#pragma once\n\n#include \"RdEditorModel/RdEditorModel.Pregenerated.h\"\n#include \"lifetime/LifetimeDefinition.h\"\n\n#include \"Modules/ModuleInterface.h\"\n#include \"Modules/ModuleManager.h\"\n\nclass RIDERLINK_API IRiderLinkModule : public IModuleInterface\n{\npublic:\n\tstatic IRiderLinkModule& Get()\n\t{\t\t\n\t\treturn FModuleManager::GetModuleChecked<IRiderLinkModule>(GetModuleName());\n\t}\n\n\tstatic FName GetModuleName()\n\t{\n\t\tstatic const FName ModuleName = TEXT(\"RiderLink\");\n\t\treturn ModuleName;\n\t}\n\n    // RiderLink API\n\tvirtual rd::LifetimeDefinition CreateNestedLifetimeDefinition() const = 0;\n\tvirtual void ViewModel(rd::Lifetime Lifetime, TFunction<void(rd::Lifetime, JetBrains::EditorPlugin::RdEditorModel const&)> Handler) = 0;\n\tvirtual void QueueAction(TFunction<void()> Handler) = 0;\n\tvirtual bool FireAsyncAction(TFunction<void(JetBrains::EditorPlugin::RdEditorModel const&)> Handler) = 0;\n\tvirtual void QueueModelAction(TFunction<void(JetBrains::EditorPlugin::RdEditorModel const&)> Handler) = 0;\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLink/Public/UE4TypesMarshallers.h",
    "content": "#pragma once\n\n#include \"serialization/Polymorphic.h\"\n#include \"std/hash.h\"\n\n#include \"Containers/UnrealString.h\"\n#include \"Containers/StringConv.h\"\n#include \"Templates/UniquePtr.h\"\n\n\n//region FString\n\ninline std::string to_string(FString const& val) {\n    return TCHAR_TO_UTF8(*val);\n}\n\ntemplate <typename T, typename A>\nint32_t size(TArray<T, A> const& value) {\n    return static_cast<int32_t>(value.Num());\n}\n\ntemplate <typename T, typename A>\nvoid resize(TArray<T, A>& value, int32_t size) {\n    value.Reserve(size);\n}\n\nnamespace rd {\n    template <>\n    class Polymorphic<FString> {\n    public:\n        static FString read(SerializationCtx& ctx, Buffer& buffer);\n\n        static void write(SerializationCtx& ctx, Buffer& buffer, FString const& value);\n    };\n\n    template <>\n    class Polymorphic<Wrapper<FString>> {\n    public:\n        static void write(SerializationCtx& ctx, Buffer& buffer, Wrapper<FString> const& value);\n    };\n\n    template <>\n    struct hash<FString> {\n        size_t operator()(const FString& value) const noexcept;\n    };\n\n    // template <typename T>\n    // std::string to_string(TArray<T> const& val);\n\n    template <typename T>\n    struct hash<TArray<T>> {\n        size_t operator()(const TArray<T>& value) const noexcept;\n    };\n\n    template <typename T>\n    Wrapper<T> ToRdWrapper(TUniquePtr<T>&& Ptr) {\n        Wrapper<T> Result;\n        Result.reset(std::move(Ptr).Release());\n        return Result;\n    }\n}\n\nextern template class rd::Polymorphic<FString>;\nextern template class rd::Polymorphic<rd::Wrapper<FString>>;\nextern template struct rd::hash<FString>;\n// extern template class rd::Polymorphic<TArray<FString>, void>;\n\n//endregion\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLink/RiderLink.Build.cs",
    "content": "using System.IO;\nusing UnrealBuildTool;\n\npublic class RiderLink : ModuleRules\n{\n\tpublic RiderLink(ReadOnlyTargetRules Target) : base(Target)\n\t{\n#if UE_4_22_OR_LATER\n\t\tPCHUsage = PCHUsageMode.NoPCHs;\n#else\n\t\tPCHUsage = PCHUsageMode.NoSharedPCHs;\n#endif\n\t\t\n\t\tbUseRTTI = true;\n\n#if UE_5_2_OR_LATER\n\t\tbDisableStaticAnalysis = true;\n#endif\n\n\t\tPublicDependencyModuleNames.Add(\"Core\");\n\t\tPublicDependencyModuleNames.Add(\"RD\");\n\t\tstring[] Paths = {\n\t\t\t\"Public/Model/Library\",\n\t\t\t\"Public/Model/RdEditorProtocol\",\n\t\t};\n\t\t\n\t\tPrivateDefinitions.Add(\"ENABLE_LOG_FILE=0\");\n\n\t\tforeach(var Item in Paths)\n\t\t{\n\t\t\tPublicIncludePaths.Add(Path.Combine(ModuleDirectory, Item));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLogging/Private/RiderLogging.cpp",
    "content": "#include \"RiderLogging.hpp\"\n\n#include \"BlueprintProvider.hpp\"\n#include \"IRiderLink.hpp\"\n#include \"Model/Library/UE4Library/LogMessageInfo.Pregenerated.h\"\n#include \"Model/Library/UE4Library/StringRange.Pregenerated.h\"\n#include \"Model/Library/UE4Library/UnrealLogEvent.Pregenerated.h\"\n\n#include \"Internationalization/Regex.h\"\n#include \"Misc/DateTime.h\"\n#include \"Modules/ModuleManager.h\"\n\n#define LOCTEXT_NAMESPACE \"RiderLogging\"\n\nDEFINE_LOG_CATEGORY(FLogRiderLoggingModule);\n\nIMPLEMENT_MODULE(FRiderLoggingModule, RiderLogging);\n\nnamespace LoggingExtensionImpl\n{\nstatic TArray<rd::Wrapper<JetBrains::EditorPlugin::StringRange>> GetPathRanges(\n\tconst FRegexPattern& Pattern,\n\tconst FString& Str)\n{\n\tusing JetBrains::EditorPlugin::StringRange;\n\tFRegexMatcher Matcher(Pattern, Str);\n\tTArray<rd::Wrapper<StringRange>> Ranges;\n\twhile (Matcher.FindNext())\n\t{\n\t\tconst int Start = Matcher.GetMatchBeginning();\n\t\tconst int End = Matcher.GetMatchEnding();\n\t\tFString PathName = Str.Mid(Start, End - Start);\n\t\tif (BluePrintProvider::IsBlueprint(PathName))\n\t\t\tRanges.Emplace(StringRange(Start, End));\n\t}\n\treturn Ranges;\n}\n\nstatic TArray<rd::Wrapper<JetBrains::EditorPlugin::StringRange>> GetMethodRanges(\n\tconst FRegexPattern& Pattern,\n\tconst FString& Str)\n{\n\tusing JetBrains::EditorPlugin::StringRange;\n\tFRegexMatcher Matcher(Pattern, Str);\n\tTArray<rd::Wrapper<StringRange>> Ranges;\n\twhile (Matcher.FindNext())\n\t{\n\t\tRanges.Emplace(StringRange(Matcher.GetMatchBeginning(), Matcher.GetMatchEnding()));\n\t}\n\treturn Ranges;\n}\n\nstatic bool SendMessageToRider(const JetBrains::EditorPlugin::LogMessageInfo& MessageInfo, const FString& Message)\n{\n\tstatic const FRegexPattern PathPattern = FRegexPattern(TEXT(\"(/[\\\\w\\\\.]+)+\"));\n\tstatic const FRegexPattern MethodPattern = FRegexPattern(TEXT(\"[0-9a-z_A-Z]+::~?[0-9a-z_A-Z]+\"));\n\t\n\treturn IRiderLinkModule::Get().FireAsyncAction(\n\t[&MessageInfo, &Message] (JetBrains::EditorPlugin::RdEditorModel const& RdEditorModel)\n\t{\n\t\trd::ISignal<JetBrains::EditorPlugin::UnrealLogEvent> const& UnrealLog = RdEditorModel.get_unrealLog();\n\t\tUnrealLog.fire({\n\t\t\tMessageInfo,\n\t\t\tMessage,\n\t\t\tGetPathRanges(PathPattern, Message),\n\t\t\tGetMethodRanges(MethodPattern, Message)\n\t\t});\n\t});\n}\n\nvoid SendMessageInChunks(FString* Msg, const JetBrains::EditorPlugin::LogMessageInfo& MessageInfo)\n{\n\tstatic int NUMBER_OF_CHUNKS = 1024;\n\twhile (!Msg->IsEmpty())\n\t{\n\t\tSendMessageToRider(MessageInfo, Msg->Left(NUMBER_OF_CHUNKS));\n\t\t*Msg = Msg->RightChop(NUMBER_OF_CHUNKS);\n\t}\n}\n\nvoid ScheduledSendMessage(FString* Msg, const JetBrains::EditorPlugin::LogMessageInfo& MessageInfo)\n{\n\tFString ToSend;\n\twhile (Msg->Split(\"\\n\", &ToSend, Msg))\n\t{\n\t\tSendMessageInChunks(&ToSend, MessageInfo);\n\t}\n\n\tSendMessageInChunks(Msg, MessageInfo);\n}\n}\n\n\nvoid FRiderLoggingModule::StartupModule()\n{\n\tUE_LOG(FLogRiderLoggingModule, Verbose, TEXT(\"STARTUP START\"));\n\n\tstatic const auto START_TIME = FDateTime::UtcNow().ToUnixTimestamp();\n\tstatic const auto GetTimeNow = [](double Time) -> rd::DateTime\n\t{\n\t\treturn rd::DateTime(START_TIME + static_cast<int64>(Time));\n\t};\n\n\tModuleLifetimeDef = IRiderLinkModule::Get().CreateNestedLifetimeDefinition();\n\tLoggingScheduler = MakeUnique<rd::SingleThreadScheduler>(ModuleLifetimeDef.lifetime, \"LoggingScheduler\");\n\tModuleLifetimeDef.lifetime->bracket(\n\t[this]()\n\t{\n\t\tOutputDevice.Setup([this](const TCHAR* msg, ELogVerbosity::Type Type, const FName& Name, TOptional<double> Time)\n\t\t{\n\t\t\tif (Type > ELogVerbosity::All) return;\n\n\t\t\trd::optional<rd::DateTime> DateTime;\n\t\t\tif (Time)\n\t\t\t{\n\t\t\t\tDateTime = GetTimeNow(Time.GetValue());\n\t\t\t}\n\t\t\tconst FString PlainName = Name.GetPlainNameString();\n\t\t\tconst JetBrains::EditorPlugin::LogMessageInfo MessageInfo{Type, PlainName, DateTime};\n\t\t\t\n\t\t\tLoggingScheduler->queue([Msg = FString(msg), MessageInfo]() mutable\n\t\t\t{\n\t\t\t\tLoggingExtensionImpl::ScheduledSendMessage(&Msg, MessageInfo);\n\t\t\t});\n\t\t});\n\t},\n\t[this]()\n\t{\n\t\tOutputDevice.TearDown();\n\t});\n\n\tUE_LOG(FLogRiderLoggingModule, Verbose, TEXT(\"STARTUP FINISH\"));\n}\n\nvoid FRiderLoggingModule::ShutdownModule()\n{\n\tUE_LOG(FLogRiderLoggingModule, Verbose, TEXT(\"SHUTDOWN START\"));\n\tModuleLifetimeDef.terminate();\n\tUE_LOG(FLogRiderLoggingModule, Verbose, TEXT(\"SHUTDOWN FINISH\"));\n}\n\n#undef LOCTEXT_NAMESPACE"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLogging/Private/RiderLogging.hpp",
    "content": "#pragma once\n\n#include \"RiderOutputDevice.hpp\"\n\n#include \"Templates/UniquePtr.h\"\n\n#include \"lifetime/LifetimeDefinition.h\"\n\n#include \"Logging/LogMacros.h\"\n#include \"Logging/LogVerbosity.h\"\n#include \"Modules/ModuleInterface.h\"\n#include \"scheduler/SingleThreadScheduler.h\"\n\nDECLARE_LOG_CATEGORY_EXTERN(FLogRiderLoggingModule, Log, All);\n\nclass FRiderLoggingModule : public IModuleInterface\n{\npublic:\n    FRiderLoggingModule() = default;\n    virtual ~FRiderLoggingModule() override = default;\n\n    /** IModuleInterface implementation */\n    virtual void StartupModule() override;\n    virtual void ShutdownModule() override;\n    virtual bool SupportsDynamicReloading() override { return true; }\n\nprivate:\n    TUniquePtr<rd::SingleThreadScheduler> LoggingScheduler;\n    FRiderOutputDevice OutputDevice;\n    rd::LifetimeDefinition ModuleLifetimeDef;\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLogging/Private/RiderOutputDevice.cpp",
    "content": "#include \"RiderOutputDevice.hpp\"\n\n#include \"CoreGlobals.h\"\n#include \"Misc/ScopeLock.h\"\n#include \"Misc/OutputDeviceRedirector.h\"\n\nvoid FRiderOutputDevice::Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category)\n{\n\tSerialize(V, Verbosity, Category, {});\n}\n\nvoid FRiderOutputDevice::Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category,\n                                   const double Time)\n{\n\tFScopeLock Lock{&CriticalSection};\n\t\n\tonSerializeMessage.ExecuteIfBound(V, Verbosity, Category, {Time});\n}\n\nFRiderOutputDevice::~FRiderOutputDevice()\n{\n\t// At shutdown, GLog may already be null\n\t// This should be out of scoped lock, because it'll implicitly try take a lock in OutputDeviceRedirector\n\t// And Serialize is already holding that lock, so we'll have a deadlock here\n\tif (GLog != nullptr)\n\t{\n\t\tGLog->RemoveOutputDevice(this);\n\t}\n}\n\nvoid FRiderOutputDevice::Setup(TFunction<FOnSerializeMessage::TFuncType> Callback)\n{\n\tFScopeLock Lock{&CriticalSection};\n\n\tif(onSerializeMessage.IsBound()) return;\n\t\n\tonSerializeMessage.BindLambda(Callback);\n\tGLog->AddOutputDevice(this);\n#if ENGINE_MAJOR_VERSION < 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 7)\n\tGLog->SerializeBacklog(this);\n#endif\n}\n\nvoid FRiderOutputDevice::TearDown()\n{\n\tFScopeLock Lock{&CriticalSection};\n\n\tif(onSerializeMessage.IsBound() == false) return;\n\n\tonSerializeMessage.Unbind();\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLogging/Private/RiderOutputDevice.hpp",
    "content": "#pragma once\n\n#include \"Misc/OutputDevice.h\"\n#include \"Delegates/Delegate.h\"\n#include \"Logging/LogVerbosity.h\"\n#include \"Runtime/Launch/Resources/Version.h\"\n\nusing FOnSerializeMessage =\n#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 26\n\tTBaseDelegate<void, const TCHAR*, ELogVerbosity::Type, const FName&, TOptional<double>>;\n#elif ENGINE_MAJOR_VERSION < 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 3)\n\tTDelegate<void(const TCHAR*, ELogVerbosity::Type, const FName&, TOptional<double>)>;\n#else\n\tTDelegate<void(const TCHAR*, ELogVerbosity::Type, const FName&, TOptional<double>), FDefaultTSDelegateUserPolicy>;\n#endif\n\nclass FRiderOutputDevice : public FOutputDevice {\npublic:\n\t~FRiderOutputDevice();\n\tvoid Setup(TFunction<FOnSerializeMessage::TFuncType>);\n\tvirtual void TearDown() override;\n\nprotected:\n\tvirtual void Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category) override;\n\tvirtual void Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category, double Time) override;\n\t\nprivate:\n\tFOnSerializeMessage onSerializeMessage;\n\tFCriticalSection CriticalSection;\n};\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderLogging/RiderLogging.Build.cs",
    "content": "using UnrealBuildTool;\n\npublic class RiderLogging : ModuleRules\n{\n\tpublic RiderLogging(ReadOnlyTargetRules Target) : base(Target)\n\t{\n#if UE_4_22_OR_LATER\n\t\tPCHUsage = PCHUsageMode.NoPCHs;\n#else\n\t\tPCHUsage = PCHUsageMode.NoSharedPCHs;\n#endif\n\n#if UE_5_2_OR_LATER\n\t\tif(Target.Platform == UnrealTargetPlatform.Linux || Target.Platform == UnrealTargetPlatform.Mac)\n\t\t{\n\t\t\tbUseRTTI = false;\n\t\t}\n\t\telse\n#endif\n        {\n\t\t    bUseRTTI = true;\n        }\n\n#if UE_5_2_OR_LATER\n\t\tbDisableStaticAnalysis = true;\n#endif\n\n\t\tPrivateDependencyModuleNames.AddRange(new []\n\t\t{\n\t\t\t\"Core\",\n\t\t\t\"RD\",\n\t\t\t\"RiderLink\",\n\t\t\t\"RiderBlueprint\"\n\t\t});\n\t}\n}"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderShaderInfo/RiderShaderInfo.Build.cs",
    "content": "﻿using UnrealBuildTool;\n\npublic class RiderShaderInfo : ModuleRules\n{\n\tpublic RiderShaderInfo(ReadOnlyTargetRules Target) : base(Target)\n\t{\n#if UE_4_22_OR_LATER\n\t\tPCHUsage = PCHUsageMode.NoPCHs;\n#else\n\t\tPCHUsage = PCHUsageMode.NoSharedPCHs;\n#endif\n\n#if UE_5_2_OR_LATER\n\t\tbDisableStaticAnalysis = true;\n#endif\n\n\t\tPrivateDependencyModuleNames.AddRange(new string[] { \"Core\",  \"Projects\", \"RenderCore\" });\n\t}\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderShaderInfo/RiderShaderInfo.cpp",
    "content": "﻿#include \"RiderShaderInfo.h\"\n\n#include \"HAL/FileManager.h\"\n#include \"Interfaces/IPluginManager.h\"\n#include \"Misc/FileHelper.h\"\n#include \"Modules/ModuleManager.h\"\n#include \"ShaderCore.h\"\n\nIMPLEMENT_MODULE(FRiderShaderInfoModule, RiderShaderInfo);\n\nvoid FRiderShaderInfoModule::StartupModule()\n{\n\tconst TSharedPtr<IPlugin> Plugin = IPluginManager::Get().FindPlugin(TEXT(\"RiderLink\"));\n\tif(!Plugin.IsValid()) return;\n\t\n\tconst FString MappingFile = FPaths::Combine(Plugin->GetBaseDir(), TEXT(\"Intermediate\"), TEXT(\"FileSystemMappings.ini\"));\n\tconst FString TmpMappingFile = FPaths::Combine(Plugin->GetBaseDir(), TEXT(\"Intermediate\"), TEXT(\"~FileSystemMappings.ini\"));\n\n\tconst TMap<FString, FString> ShaderMappings = AllShaderSourceDirectoryMappings();\n\tconst TArray<FString> Mappings = [&ShaderMappings]()->TArray<FString>\n\t{\n\t\tTArray<FString> Result;\n\t\tfor(const TTuple<FString, FString>& Pair : ShaderMappings)\n\t\t{\n\t\t\tResult.Add(FString::Printf(TEXT(\"%s=%s\"), *Pair.Key,  *FPaths::ConvertRelativePathToFull(Pair.Value)));\n\t\t}\n\t\treturn Result;\n\t}();\n\tif(IFileManager::Get().FileExists(*MappingFile))\n\t{\n\t\tTArray<FString> Result;\n\t\tFFileHelper::LoadFileToStringArray(Result, *MappingFile);\n\t\tif(Mappings == Result) return;\n\t}\n\tFFileHelper::SaveStringArrayToFile(Mappings, *TmpMappingFile);\n\tIFileManager::Get().Move(*MappingFile, *TmpMappingFile, true, true);\n}\n"
  },
  {
    "path": "src/cpp/RiderLink/Source/RiderShaderInfo/RiderShaderInfo.h",
    "content": "﻿#pragma once\n\n#include \"Modules/ModuleInterface.h\"\n\nclass RIDERSHADERINFO_API FRiderShaderInfoModule : public IModuleInterface\n{\npublic:\n\tvirtual void StartupModule() override;\n};\n"
  },
  {
    "path": "src/cpp/Subplatform.Root",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<SubplatformInfo xmlns=\"urn:schemas-jetbrains-com:build-subplatform-info\" CompanyNameHuman=\"JetBrains\" IsGitSubplatform=\"true\">\n</SubplatformInfo>"
  },
  {
    "path": "src/dotnet/BuildScript/DefineUnrealLinkConstants.cs",
    "content": "using System.Collections.Generic;\nusing System.Linq;\nusing JetBrains.Application.BuildScript.PreCompile.Autofix;\nusing JetBrains.Application.BuildScript.Solution;\nusing JetBrains.Build;\n\nnamespace JetBrains.ReSharper.Plugins.UnrealLink.BuildScript\n{\n\tpublic static class DefineUnrealLinkConstants\n\t{\n\t\t[BuildStep]\n\t\tpublic static IEnumerable<AutofixAllowedDefineConstant> YieldAllowedDefineConstantsForUnrealLink()\n\t\t{\n\t\t\tvar constants = new List<string>();\n\n\t\t\tconstants.AddRange(new[] {\"$(DefineConstants)\", \"RIDER\"});\n\n\t\t\treturn constants.SelectMany(s => new []\n\t\t\t{\n\t\t\t\tnew AutofixAllowedDefineConstant(new SubplatformName(\"Plugins\\\\UnrealLink\\\\src\\\\dotnet\"), s)\n            });\n\t\t}\n\t}\n}"
  },
  {
    "path": "src/dotnet/Directory.Build.props",
    "content": "<Project>\n  <Sdk Name=\"JetBrains.Build.VersionLockFileTargets\" Version=\"0.0.4\" />\n  <PropertyGroup>\n    <PackageLockFilePath>$(MSBuildThisFileDirectory)PackagesLock.targets</PackageLockFilePath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <LangVersion>latest</LangVersion>\n\n    <NoPackageAnalysis>true</NoPackageAnalysis>\n    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>\n    <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>\n    \n    <BaseIntermediateOutputPath>obj\\$(MSBuildProjectName)\\</BaseIntermediateOutputPath>\n    <DefaultItemExcludes>$(DefaultItemExcludes);obj\\**</DefaultItemExcludes>\n    <OutputPath>bin\\$(MSBuildProjectName)\\$(Configuration)\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\"'$(Configuration)'=='Debug'\">\n    <DefineConstants>TRACE;DEBUG;JET_MODE_ASSERT</DefineConstants>\n  </PropertyGroup>\n\n  <Import Project=\"Plugin.props\" />\n  <Import Project=\"Versions.props\" />\n  <Import Project=\"$(MSBuildThisFileDirectory)..\\..\\build\\DotNetSdkPath.generated.props\" Condition=\"Exists('$(MSBuildThisFileDirectory)..\\..\\build\\DotNetSdkPath.generated.props')\" />\n\n</Project>\n"
  },
  {
    "path": "src/dotnet/PackagesLock.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <PackageLock Include=\"JetBrains.Annotations\" Version=\"2025.2.0\" />\n    <PackageLock Include=\"JetBrains.HabitatDetector\" Version=\"1.5.0\" />\n    <PackageLock Include=\"JetBrains.Lifetimes\" Version=\"2026.1.3\" />\n    <PackageLock Include=\"JetBrains.RdFramework\" Version=\"2026.1.3\" />\n    <PackageLock Include=\"Newtonsoft.Json\" Version=\"13.0.3\" />\n    <PackageLock Include=\"System.Memory\" Version=\"4.6.0\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "src/dotnet/Plugin.props",
    "content": "<Project>\n   <PropertyGroup>\n       <SdkVersion>201.0.20200217.155048-eap01d</SdkVersion>\n       <Title>UnrealLink</Title>\n   </PropertyGroup>\n</Project>"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/BuildScript/UnrealLinkInRiderProduct.cs",
    "content": "using System;\nusing System.Linq;\nusing JetBrains.Application.BuildScript.Compile;\nusing JetBrains.Application.BuildScript.PackageSpecification;\nusing JetBrains.Application.BuildScript.Solution;\nusing JetBrains.Build;\nusing JetBrains.Rider.Backend.BuildScript;\nusing JetBrains.Util;\n\nnamespace RiderPlugin.UnrealLink.BuildScript\n{\n  /// <summary>\n  ///   Defines a bundled plugin which drives adding the referenced packages as a plugin for Rider.\n  /// </summary>\n  public class UnrealLinkInRiderProduct\n  {\n    public static readonly SubplatformName ThisSubplatformName = new((RelativePath)\"Plugins\" / \"UnrealLink\" / \"src\" / \"dotnet\");\n\n    public static readonly RelativePath DotFilesFolder = @\"plugins\\UnrealLink\\dotnet\";\n\n    public const string ProductTechnicalName = \"UnrealLink\";\n\n    [BuildStep]\n    public static SubplatformComponentForPackagingFast[] ProductMetaDependency(AllAssembliesOnSources allassSrc)\n    {\n      if (allassSrc.Subplatforms.All(sub => sub.Name != ThisSubplatformName))\n        return Array.Empty<SubplatformComponentForPackagingFast>();\n\n      return new[]\n      {\n        new SubplatformComponentForPackagingFast\n        (\n          ThisSubplatformName,\n          new JetPackageMetadata\n          {\n            Spec = new JetSubplatformSpec\n            {\n              ComplementedProductName = RiderConstants.ProductTechnicalName\n            }\n          }\n        )\n      };\n    }\n\n    public class EditorPlugin\n    {\n      public static readonly SubplatformName EditorSubplatformName = new((RelativePath)\"Plugins\" / \"UnrealLink\" / \"src\" / \"cpp\");\n\n      public static readonly RelativePath EditorFolder = @\"plugins\\UnrealLink\\EditorPlugin\";\n\n      public const string ProductTechnicalName = \"UnrealLink.EditorPlugin\";\n\n      [BuildStep]\n      public static SubplatformComponentForPackagingFast[] ProductMetaDependency(AllAssembliesOnSources allassSrc)\n      {\n        if (allassSrc.Subplatforms.All(sub => sub.Name != EditorSubplatformName))\n          return Array.Empty<SubplatformComponentForPackagingFast>();\n\n        return new[]\n        {\n          new SubplatformComponentForPackagingFast\n          (\n            EditorSubplatformName,\n            new JetPackageMetadata\n            {\n              Spec = new JetSubplatformSpec\n              {\n                ComplementedProductName = RiderConstants.ProductTechnicalName\n              }\n            }\n          )\n        };\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/EditorNavigator.cs",
    "content": "using System.Linq;\nusing JetBrains.Application.Parts;\nusing JetBrains.Metadata.Reader.API;\nusing JetBrains.ProjectModel;\nusing JetBrains.ReSharper.Feature.Services.Navigation;\nusing JetBrains.ReSharper.Psi;\nusing JetBrains.ReSharper.Psi.Cpp.Caches;\nusing JetBrains.ReSharper.Psi.Cpp.Language;\nusing JetBrains.ReSharper.Psi.Cpp.Symbols;\nusing JetBrains.ReSharper.Psi.Cpp.Util;\nusing JetBrains.ReSharper.Resources.Shell;\nusing JetBrains.Util.Caches;\nusing RiderPlugin.UnrealLink.Model;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\n\nnamespace RiderPlugin.UnrealLink\n{\n    [SolutionComponent(Instantiation.DemandAnyThreadUnsafe)]\n    public class EditorNavigator\n    {\n        private readonly CppGlobalSymbolCache _cppSymbolNameCache;\n        private readonly IPsiServices _psiServices;\n        private const int MaxSizeOfCache = 1 << 6;\n        private readonly DirectMappedCache<string, CppClassSymbol> _classCache = new DirectMappedCache<string, CppClassSymbol>(MaxSizeOfCache);\n        private readonly DirectMappedCache<string, CppDeclaratorSymbol> _methodCache = new DirectMappedCache<string, CppDeclaratorSymbol>(MaxSizeOfCache);\n\n\n        public EditorNavigator(CppGlobalSymbolCache cppSymbolNameCache, IPsiServices psiServices)\n        {\n            _cppSymbolNameCache = cppSymbolNameCache;\n            _psiServices = psiServices;\n        }\n\n        private CppClassSymbol GetClassSymbol(string name) =>\n            _classCache.GetOrCreate(name, s =>\n            {\n                var symbolsByShortName = _cppSymbolNameCache.SymbolNameCache.GetSymbolsByShortName(s);\n                var classSymbol = symbolsByShortName.ToEnumerable().OfType<CppClassSymbol>().SingleOrNull();\n                return classSymbol;\n            });\n\n        private CppDeclaratorSymbol GetMethodSymbol(CppClassSymbol classSymbol, string method) =>\n            _methodCache.GetOrCreate(method, s =>\n            {\n                return classSymbol.Children.ToEnumerable().OfType<CppDeclaratorSymbol>()\n                    .Where(symbol => s == symbol.Name.Name.ToString()).SingleOrNull();\n            });\n\n        public void NavigateToClass(UClass uClass)\n        {\n            var classSymbol = GetClassSymbol(uClass.Name.Data);\n            if (classSymbol == null)\n                return;\n            var declaredElement = new CppParserSymbolDeclaredElement(_psiServices, classSymbol);\n\n            using (NonCSharpInteropReadLockCookie.Create()) // todo: change to ordinary after updating to C# 13\n            {\n                using (CompilationContextCookie.GetOrCreate(UniversalModuleReferenceContext.Instance))\n                {\n                    declaredElement.Navigate(true);\n                }\n            }\n        }\n\n        public void NavigateToMethod(MethodReference methodReference)\n        {\n            var declaredElement = MethodDeclaredElement(methodReference);\n            using (NonCSharpInteropReadLockCookie.Create()) // todo: change to ordinary after updating to C# 13\n            {\n                using (CompilationContextCookie.GetOrCreate(UniversalModuleReferenceContext.Instance))\n                {\n                    declaredElement.Navigate(true);\n                }\n            }\n        }\n\n        private CppParserSymbolDeclaredElement MethodDeclaredElement(MethodReference methodReference)\n        {\n            var (uClass, method) = methodReference;\n            var classSymbol = GetClassSymbol(uClass.Name.Data);\n            if (classSymbol == null)\n                return null;\n            var methodSymbol = GetMethodSymbol(classSymbol, method.Data);\n            return new CppParserSymbolDeclaredElement(_psiServices, methodSymbol);\n        }\n\n        public bool IsMethodReference(MethodReference methodReference)\n        {\n            return MethodDeclaredElement(methodReference) != null;\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/Install/AdvertiseRiderBundledPlugin.cs",
    "content": "using JetBrains.Build;\nusing RiderPlugin.UnrealLink.BuildScript;\nusing JetBrains.Rider.Backend.Install;\n\nnamespace RiderPlugin.UnrealLink.Install\n{\n  public static class AdvertiseRiderBundledPlugin\n  {\n    [BuildStep]\n    public static RiderBundledProductArtifact[] ShipUnrealLinkWithRider()\n    {\n      return new[]\n      {\n        new RiderBundledProductArtifact(\n          UnrealLinkInRiderProduct.ProductTechnicalName,\n          UnrealLinkInRiderProduct.ThisSubplatformName,\n          UnrealLinkInRiderProduct.DotFilesFolder,\n          allowCommonPluginFiles: false),\n        new RiderBundledProductArtifact(\n          UnrealLinkInRiderProduct.EditorPlugin.ProductTechnicalName,\n          UnrealLinkInRiderProduct.EditorPlugin.EditorSubplatformName,\n          UnrealLinkInRiderProduct.EditorPlugin.EditorFolder,\n          allowCommonPluginFiles: false)\n      };\n    }\n  }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/LinkResolver.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing JetBrains.Annotations;\nusing JetBrains.Application.Parts;\nusing JetBrains.Diagnostics;\nusing JetBrains.ProjectModel;\nusing JetBrains.Rd.Tasks;\nusing JetBrains.ReSharper.Psi.Cpp.UE4;\nusing JetBrains.Util.DataStructures;\nusing JetBrains.Util;\nusing RiderPlugin.UnrealLink.Model;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\n\nnamespace RiderPlugin.UnrealLink\n{\n    [SolutionComponent(InstantiationEx.LegacyDefault)]\n    public class UnrealLinkResolver\n    {\n        private readonly ISolution _solution;\n        private readonly ILogger _logger;\n        private static readonly CompactMap<char, char> PairSymbol = new();\n        private readonly Lazy<VirtualFileSystemPath> _ue4SourcesPath;\n        private readonly Lazy<List<VirtualFileSystemPath>> _possiblePaths;\n\n        static UnrealLinkResolver()\n        {\n            PairSymbol.Add(')', '(');\n            PairSymbol.Add(']', '[');\n            PairSymbol.Add('\\'', '\\'');\n            PairSymbol.Add('\"', '\"');\n        }\n\n        public UnrealLinkResolver(ISolution solution, ILogger logger,\n            ICppUE4SolutionDetector unrealEngineSolutionDetector)\n        {\n            _solution = solution;\n            _logger = logger;\n            var solutionDirectory = _solution.SolutionDirectory;\n            _ue4SourcesPath = new Lazy<VirtualFileSystemPath>(() =>\n                unrealEngineSolutionDetector.UnrealContext.Value.UnrealEngineSourcePath);\n\n            _possiblePaths = new Lazy<List<VirtualFileSystemPath>>(() =>\n                new List<VirtualFileSystemPath>\n                {\n                    _ue4SourcesPath.Value,\n                    _ue4SourcesPath.Value.Parent,\n                    _ue4SourcesPath.Value / \"Content\",\n                    _ue4SourcesPath.Value / \"Content\" / \"Editor\",\n                    _ue4SourcesPath.Value / \"Content\" / \"Editor\" / \"Slate\", // FSlateStyleSet::ContentRootDir\n                    _ue4SourcesPath.Value / \"Plugins\",\n\n                    solutionDirectory,\n                    solutionDirectory / \"Content\",\n                    solutionDirectory / \"Plugins\"\n                });\n        }\n\n        [CanBeNull]\n        private VirtualFileSystemPath ConvertToAbsolutePath(VirtualFileSystemPath path)\n        {\n            if (path.IsAbsolute)\n            {\n                return path;\n            }\n\n            return _possiblePaths\n                .Value.SelectNotNull(possibleDir =>\n                {\n                    var relativePath = path.AsRelative();\n                    if (relativePath == null || relativePath.IsEmpty)\n                    {\n                        return null;\n                    }\n\n                    var candidate = possibleDir / relativePath;\n                    return candidate.Exists == FileSystemPath.Existence.Missing ? null : candidate;\n                })\n                .FirstOrDefault(null);\n        }\n\n        [CanBeNull]\n        private ILinkResponse TryParseFullPath([NotNull] string input, [NotNull] StringRange range)\n        {\n            try\n            {\n                var path = ConvertToAbsolutePath(VirtualFileSystemPath.Parse(input, InteractionContext.SolutionContext));\n                if (path == null)\n                {\n                    return null;\n                }\n\n                if (path.ExtensionNoDot == \"umap\")\n                {\n                    //TO-DO\n                    return null;\n                }\n\n                if (path.ExtensionNoDot == \"uasset\")\n                {\n                    return new LinkResponseBlueprint(new FString(path.ToUri().AbsolutePath), range);\n                }\n\n                return new LinkResponseFilePath(new FString(path.ToUri().AbsolutePath), range);\n            }\n            catch (InvalidPathException e)\n            {\n                _logger.Warn(e);\n            }\n            catch (Exception e)\n            {\n                _logger.Error(e, \"occured while trying parse full path\");\n            }\n\n            return null;\n        }\n\n        [CanBeNull]\n        private ILinkResponse TryParseFullName([NotNull] string s, [NotNull] StringRange range,\n            IRdCall<FString, bool> isBlueprintPathName)\n        {\n            var path = new FString(s);\n            try\n            {\n                return isBlueprintPathName.Sync(path)\n                    ? new LinkResponseBlueprint(path, range)\n                    : null;\n            }\n            catch (Exception e)\n            {\n                _logger.Warn(e, \"[UnrealLink]: Failed to parse Blueprint string\");\n                return null;\n            }\n        }\n\n        [NotNull]\n        internal ILinkResponse ResolveLink(LinkRequest @struct, IRdCall<FString, bool> isBlueprintPathName)\n        {\n            // ReSharper disable once LocalFunctionCanBeMadeStatic\n            string SqueezeBorders(string s, out int l, out int r)\n            {\n                l = 0;\n                r = s.Length;\n                if (s.EndsWith(\".\"))\n                {\n                    --r;\n                }\n\n                if (PairSymbol.TryGetValue(s[r - 1], out var value))\n                {\n                    l = s.AsSpan(l, r - l - 1).LastIndexOf(value) + 1;\n                    --r;\n                }\n\n                return s.Substring(l, r - l);\n            }\n\n            var link = @struct.Data.Data;\n            var squeezed = SqueezeBorders(link, out var left, out var right);\n            var range = new StringRange(left, right);\n\n            var fullPath = TryParseFullPath(squeezed, range);\n            if (fullPath != null)\n            {\n                return fullPath;\n            }\n\n            var fullName = TryParseFullName(squeezed, range, isBlueprintPathName);\n            if (fullName != null)\n            {\n                return fullName;\n            }\n\n\n            return new LinkResponseUnresolved();\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/PluginInstaller/PluginPathsProvider.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Reflection;\nusing ICSharpCode.SharpZipLib.Zip;\nusing JetBrains.Application;\nusing JetBrains.Application.Environment;\nusing JetBrains.Application.Environment.Components;\nusing JetBrains.Application.Environment.DeployedPackages;\nusing JetBrains.Application.Parts;\nusing JetBrains.Extension;\nusing JetBrains.Util;\n\nnamespace RiderPlugin.UnrealLink.PluginInstaller\n{\n    [ShellComponent(Instantiation.DemandAnyThreadSafe)]\n    public class PluginPathsProvider\n    {\n        private readonly ApplicationPackages myApplicationPackages;\n        private readonly IDeployedPackagesExpandLocationResolver myResolver;\n        private readonly ILogger myLogger;\n\n        private static readonly string EditorPluginFile = \"RiderLink.zip\";\n        public readonly FileSystemPath PathToPackedPlugin;\n        public readonly byte[] CurrentPluginChecksum;\n        public static readonly byte[] NullChecksum = { 0 };\n\n        public PluginPathsProvider(ApplicationPackages applicationPackages,\n            IDeployedPackagesExpandLocationResolver resolver, ProductSettingsLocation productSettingsLocation,\n            ILogger logger)\n        {\n            myApplicationPackages = applicationPackages;\n            myResolver = resolver;\n            myLogger = logger;\n            PathToPackedPlugin = GetEditorPluginPathFile(productSettingsLocation);\n            CurrentPluginChecksum = GetCurrentPluginChecksum();\n        }\n\n        private FileSystemPath GetEditorPluginPathFile(ProductSettingsLocation productSettingsLocation)\n        {\n            var assembly = Assembly.GetExecutingAssembly();\n            var package = myApplicationPackages.FindPackageWithAssembly(assembly, OnError.LogException);\n            var installDirectory = myResolver.GetDeployedPackageDirectory(package);\n            var editorPluginPathDirectory = installDirectory != productSettingsLocation.InstallDir\n              ? installDirectory.Parent.Combine(\"EditorPlugin\")\n              : installDirectory;\n            return editorPluginPathDirectory.Combine(EditorPluginFile);\n        }\n\n        private byte[] GetCurrentPluginChecksum()\n        {\n          return PathToPackedPlugin.ReadStream(stream =>\n          {\n            using(var zip = new ZipFile(stream))\n            {\n              if(zip.GetEntry(UnrealPluginDetector.CHEKCSUM_ENTRY_PATH) is not { } zentry)\n                return null;\n              using(var streamEntry = zip.GetInputStream(zentry))\n                return streamEntry.ReadAllBytes();\n            }\n          });\n        }\n\n        public byte[] GetPluginChecksum(VirtualFileSystemPath checksumPath)\n        {\n            if (!checksumPath.ExistsFile)\n            {\n                return NullChecksum;\n            }\n            try\n            {\n                return File.ReadAllBytes(checksumPath.FullPath);\n            }\n            catch (Exception exception)\n            {\n                myLogger.Error(exception, \"[UnrealLink]: Couldn't read RiderLink plugin version\");\n                return null;\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/PluginInstaller/UnrealPluginDetector.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\nusing JetBrains.Annotations;\nusing JetBrains.Application.I18n;\nusing JetBrains.Application.Parts;\nusing JetBrains.Application.Threading;\nusing JetBrains.DataFlow;\nusing JetBrains.Lifetimes;\nusing JetBrains.ProjectModel;\nusing JetBrains.ProjectModel.Tasks;\nusing JetBrains.ReSharper.Feature.Services.Cpp.ProjectModel.UE4;\nusing JetBrains.ReSharper.Feature.Services.Protocol;\nusing JetBrains.ReSharper.Resources.Shell;\nusing JetBrains.ReSharper.Psi.Cpp.UE4;\nusing JetBrains.Rider.Model.Notifications;\nusing JetBrains.Util;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\nusing RiderPlugin.UnrealLink.Resources;\n\nnamespace RiderPlugin.UnrealLink.PluginInstaller\n{\n    [SolutionComponent(InstantiationEx.LegacyDefault)]\n    public class UnrealPluginDetector\n    {\n        private const string UPLUGIN_FILENAME = \"RiderLink.uplugin\";\n        public const string CHEKCSUM_ENTRY_PATH = \"Resources/checksum\";\n        private const string UPROJECT_FILE_FORMAT = \"uproject\";\n        private readonly RelativePath ourPathToProjectPlugin = $\"Plugins/Developer/RiderLink/{UPLUGIN_FILENAME}\";\n\n        private readonly RelativePath ourPathToEnginePlugin =\n            $\"Engine/Plugins/Marketplace/Developer/RiderLink/{UPLUGIN_FILENAME}\";\n\n        public static VirtualFileSystemPath GetPathToUpluginFile(VirtualFileSystemPath rootFolder) => rootFolder / UPLUGIN_FILENAME;\n\n        private readonly Lifetime myLifetime;\n        private readonly ILogger myLogger;\n        private readonly CppUE4ProjectsTracker myProjectsTracker;\n        private readonly ICppUE4SolutionDetector mySolutionDetector;\n        public readonly IProperty<UnrealPluginInstallInfo> InstallInfoProperty;\n\n        public CppUE4Version UnrealVersion { get; private set; }\n        private readonly CppUE4Version myMinimalSupportedVersion = new(4, 23, 0);\n\n        private readonly JetHashSet<string> EXCLUDED_PROJECTS = new() {\"UnrealLaunchDaemon\"};\n\n\n        public UnrealPluginDetector(Lifetime lifetime, ILogger logger, ISolution solution, \n          ICppUE4SolutionDetector solutionDetector, IShellLocks locks, ISolutionLoadTasksScheduler scheduler,\n          CppUE4ProjectsTracker projectsTracker)\n        {\n            myLifetime = lifetime;\n            InstallInfoProperty =\n                new Property<UnrealPluginInstallInfo>( \"UnrealPlugin.InstallInfoNotification\", null, true);\n            myLogger = logger;\n            myProjectsTracker = projectsTracker;\n            mySolutionDetector = solutionDetector;\n\n            mySolutionDetector.IsUnrealSolution.Change.Advise_When(myLifetime,\n                newValue => newValue, _ =>\n                {\n                    scheduler.EnqueueTask(new SolutionLoadTask(typeof(UnrealPluginDetector),\n                        SolutionLoadTaskKinds.Done,\n                        () =>\n                        {\n                            myLogger.Info(\"[UnrealLink]: Looking for RiderLink plugins\");\n                            UnrealVersion = mySolutionDetector.UnrealContext.Value.Version;\n\n                            if (UnrealVersion < myMinimalSupportedVersion)\n                            {\n                                locks.ExecuteOrQueue(myLifetime, \"UnrealLink.CheckSupportedVersion\",\n                                    () =>\n                                    {\n                                        var notification =\n                                                new NotificationModel(\n                                                    solution.GetRdProjectId(),\n                                                    Strings.UnrealEngine_Version_IsRequired_Title.Format(myMinimalSupportedVersion.ToString()), \n                                            Strings.UnrealEngine_Version_IsRequired_Message.Format(myMinimalSupportedVersion),\n                                            true,\n                                            RdNotificationEntryType.WARN,\n                                            new List<NotificationHyperlink>());\n                                        var notificationsModel = Shell.Instance.GetComponent<NotificationsModel>();\n                                        notificationsModel.Notification(notification);\n                                    });\n                                return;\n                            }\n                            \n                            var riderLinkFolders = myProjectsTracker.GetAllUPlugins().Where(pluginPath => pluginPath.NameWithoutExtension.Equals(\"RiderLink\")).ToList();\n                            var uprojectNames = myProjectsTracker.GetAllUprojectNames().Where(uprojectName => !EXCLUDED_PROJECTS.Contains(uprojectName));\n\n                            var foundEnginePlugin = false;\n                            var installInfo = new UnrealPluginInstallInfo\n                            {\n                                EngineRoot = solutionDetector.UnrealContext.Value.UnrealEngineRoot\n                            };\n                            var enginePluginsFolder = solutionDetector.UnrealContext.Value.UnrealEngineRoot.Combine(\"Engine\").Combine(\"Plugins\");\n                            foreach (var riderLinkFolder in riderLinkFolders)\n                            {\n                                if (riderLinkFolder.StartsWith(enginePluginsFolder))\n                                {\n                                    myLogger.Info($\"[UnrealLink]: found plugin {installInfo.EnginePlugin.UnrealPluginRootFolder}\");\n                                    foundEnginePlugin = true;\n                                    installInfo.EnginePlugin = \n                                        GetPluginInfo(riderLinkFolder.Combine(UPLUGIN_FILENAME),\n                                            VirtualFileSystemPath.GetEmptyPathFor(InteractionContext.SolutionContext));\n                                }\n                            }\n\n                            if (!foundEnginePlugin)\n                            {\n                                installInfo.EnginePlugin.IsPluginAvailable = false;\n                                installInfo.EnginePlugin.PluginChecksum = PluginPathsProvider.NullChecksum;\n                                installInfo.EnginePlugin.ProjectName = \"<ENGINE>\";\n                                installInfo.EnginePlugin.UnrealPluginRootFolder =\n                                    installInfo.EngineRoot.Combine(ourPathToEnginePlugin).Directory;\n                            }\n\n                            // Gather data about Project plugins\n                            foreach (var uprojectName in uprojectNames)\n                            {\n                                var uprojectPath = myProjectsTracker.GetUProjectByName(uprojectName);\n                                var gameRoot = uprojectPath.Parent;\n                                myLogger.Info($\"[UnrealLink]: Looking for plugin in {gameRoot}\");\n                                var upluginFolder = riderLinkFolders.Find(path => path.StartsWith(gameRoot));\n                                var upluginPath = upluginFolder.IsNullOrEmpty()\n                                    ? gameRoot.Combine(ourPathToProjectPlugin)\n                                    : upluginFolder.CombineWithShortName(UPLUGIN_FILENAME);\n                                var projectPlugin = GetPluginInfo(upluginPath, uprojectPath );\n                                if (projectPlugin.IsPluginAvailable)\n                                {\n                                    myLogger.Info(\n                                        $\"[UnrealLink]: found plugin {projectPlugin.UnrealPluginRootFolder}\");\n                                }\n\n                                installInfo.ProjectPlugins.Add(projectPlugin);\n                            }\n\n                            if (foundEnginePlugin)\n                                installInfo.Location = PluginInstallLocation.Engine;\n                            else if (installInfo.ProjectPlugins.Any(description => description.IsPluginAvailable))\n                                installInfo.Location = PluginInstallLocation.Game;\n                            else\n                                installInfo.Location = PluginInstallLocation.NotInstalled;\n\n                            InstallInfoProperty.SetValue(installInfo);\n                        }));\n                });\n        }\n\n        [NotNull]\n        private UnrealPluginInstallInfo.InstallDescription GetPluginInfo(\n            [NotNull] VirtualFileSystemPath upluginFilePath, VirtualFileSystemPath uprojectPath)\n        {\n            var projectName = uprojectPath.IsNullOrEmpty() ? \"<ENGINE>\" : uprojectPath.Name;\n            var installDescription = new UnrealPluginInstallInfo.InstallDescription()\n            {\n                UnrealPluginRootFolder = upluginFilePath.Directory,\n                ProjectName = projectName,\n                UprojectPath = uprojectPath\n            };\n            if (!upluginFilePath.ExistsFile) return installDescription;\n\n            var pluginPathsProvider = Shell.Instance.GetComponent<PluginPathsProvider>();\n            var pluginChecksumFilePath = upluginFilePath.Directory.Combine(\"Resources\").Combine(\"checksum\");\n            var pluginChecksum = pluginPathsProvider.GetPluginChecksum(pluginChecksumFilePath);\n            if (pluginChecksum == null) return installDescription;\n\n            installDescription.IsPluginAvailable = true;\n            installDescription.PluginChecksum = pluginChecksum;\n            return installDescription;\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/PluginInstaller/UnrealPluginInstallInfo.cs",
    "content": "﻿using System.Collections.Generic;\nusing JetBrains.Util;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\n\nnamespace RiderPlugin.UnrealLink.PluginInstaller\n{    \n    public class UnrealPluginInstallInfo\n    {\n        public class InstallDescription\n        {\n            public bool IsPluginAvailable = false;\n            public byte[] PluginChecksum = null;\n            public VirtualFileSystemPath UnrealPluginRootFolder = VirtualFileSystemPath.GetEmptyPathFor(InteractionContext.SolutionContext);\n            public string ProjectName = string.Empty;\n            public VirtualFileSystemPath UprojectPath = VirtualFileSystemPath.GetEmptyPathFor(InteractionContext.SolutionContext);\n        }\n\n        public VirtualFileSystemPath EngineRoot = null;\n\n        public InstallDescription EnginePlugin = new();\n        public readonly List<InstallDescription> ProjectPlugins = new();\n\n        public PluginInstallLocation Location;\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/PluginInstaller/UnrealPluginInstaller.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.IO.Compression;\nusing System.Linq;\nusing JetBrains.Application.I18n;\nusing JetBrains.Application.Parts;\nusing JetBrains.Application.Settings;\nusing JetBrains.Application.Threading;\nusing JetBrains.Collections.Viewable;\nusing JetBrains.DataFlow;\nusing JetBrains.Diagnostics;\nusing JetBrains.HabitatDetector;\nusing JetBrains.IDE;\nusing JetBrains.Lifetimes;\nusing JetBrains.ProjectModel;\nusing JetBrains.ProjectModel.DataContext;\nusing JetBrains.ProjectModel.ProjectsHost.SolutionHost.Progress;\nusing JetBrains.Rd.Base;\nusing JetBrains.ReSharper.Feature.Services.Protocol;\nusing JetBrains.ReSharper.Psi.Cpp.UE4;\nusing JetBrains.ReSharper.Resources.Shell;\nusing JetBrains.Rider.Model;\nusing JetBrains.Rider.Model.Notifications;\nusing JetBrains.Util;\nusing Newtonsoft.Json.Linq;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\nusing RiderPlugin.UnrealLink.Resources;\nusing RiderPlugin.UnrealLink.Settings;\nusing RiderPlugin.UnrealLink.Utils;\n\nnamespace RiderPlugin.UnrealLink.PluginInstaller\n{\n    [SolutionComponent(InstantiationEx.LegacyDefault)]\n    public class UnrealPluginInstaller\n    {\n        public Lifetime Lifetime { get; }\n        private readonly ILogger myLogger;\n        private readonly PluginPathsProvider myPathsProvider;\n        private readonly ISolution mySolution;\n        private readonly UnrealHost myUnrealHost;\n        private readonly NotificationsModel myNotificationsModel;\n        private readonly BackgroundProgressManager myBackgroundProgressManager;\n        private IContextBoundSettingsStoreLive myBoundSettingsStore;\n        private UnrealPluginDetector myPluginDetector;\n        private const string TMP_PREFIX = \"UnrealLink\";\n\n        public UnrealPluginInstaller(Lifetime lifetime, ILogger logger, UnrealPluginDetector pluginDetector,\n            PluginPathsProvider pathsProvider, ISolution solution, ISettingsStore settingsStore, UnrealHost unrealHost,\n            NotificationsModel notificationsModel, BackgroundProgressManager backgroundProgressManager)\n        {\n            Lifetime = lifetime;\n            myLogger = logger;\n            myPathsProvider = pathsProvider;\n            mySolution = solution;\n            myUnrealHost = unrealHost;\n            myNotificationsModel = notificationsModel;\n            myBackgroundProgressManager = backgroundProgressManager;\n            myBoundSettingsStore =\n                settingsStore.BindToContextLive(Lifetime, ContextRange.Smart(solution.ToDataContext()));\n            myPluginDetector = pluginDetector;\n\n            myPluginDetector.InstallInfoProperty.Change.Advise_NewNotNull(Lifetime, installInfo =>\n            {\n                myUnrealHost.myModel.IsInstallInfoAvailable.Set(true);\n                myUnrealHost.myModel.GamePluginInstallInfos(\n                    installInfo.New.ProjectPlugins\n                        .Select(projectPlugin =>\n                        {\n                            var isPluginInstalled =\n                                UnrealPluginDetector.GetPathToUpluginFile(projectPlugin.UnrealPluginRootFolder).ExistsFile;\n                            var isPluginSynced = projectPlugin.IsPluginAvailable &&\n                                                 projectPlugin.PluginChecksum != null &&\n                                                 projectPlugin.PluginChecksum.SequenceEqual(myPathsProvider.CurrentPluginChecksum);\n                            return new GamePluginInstallInfo(\n                                projectPlugin.ProjectName,\n                                projectPlugin.UprojectPath.FullPath,\n                                isPluginInstalled,\n                                isPluginSynced\n                            );\n                        })\n                        .ToList());\n                mySolution.Locks.ExecuteOrQueueReadLockEx(Lifetime,\n                    \"UnrealPluginInstaller.CheckAllProjectsIfAutoInstallEnabled\",\n                    () => { HandleAutoUpdatePlugin(installInfo.New); });\n            });\n            BindToInstallationSettingChange();\n            BindToNotificationFixAction();\n        }\n\n        private void HandleAutoUpdatePlugin(UnrealPluginInstallInfo unrealPluginInstallInfo)\n        {\n            var status = PluginInstallStatus.NoPlugin;\n            var outOfSync = true;\n            if (unrealPluginInstallInfo.Location == PluginInstallLocation.Engine)\n            {\n                status = PluginInstallStatus.InEngine;\n                outOfSync = !unrealPluginInstallInfo.EnginePlugin.PluginChecksum.SequenceEqual(myPathsProvider.CurrentPluginChecksum);\n            }\n\n            if (unrealPluginInstallInfo.Location == PluginInstallLocation.Game)\n            {\n                status = PluginInstallStatus.InGame;\n                var hasSyncedProjectPlugin = unrealPluginInstallInfo.ProjectPlugins.Any(description =>\n                    description.IsPluginAvailable &&\n                    description.PluginChecksum.SequenceEqual(myPathsProvider.CurrentPluginChecksum));\n                outOfSync = !hasSyncedProjectPlugin;\n            }\n\n            if (!outOfSync) return;\n\n            if(myBoundSettingsStore.GetValue((UnrealLinkSettings s) => s.AutoUpdateRiderLinkPlugin))\n            {\n                var installLocation = unrealPluginInstallInfo.Location;\n                if (installLocation == PluginInstallLocation.NotInstalled)\n                {\n                    installLocation = GetInstallLocationFromSettings();\n                }\n                QueueAutoUpdate(installLocation);\n                return;\n            }\n\n            myLogger.Warn(\"[UnrealLink]: Plugin is out of sync\");\n            myUnrealHost.PerformModelAction(model =>\n            {\n                var isGameAvailable = !unrealPluginInstallInfo.ProjectPlugins.IsEmpty();\n                model.OnEditorPluginOutOfSync(new EditorPluginOutOfSync(status, isGameAvailable));\n            });\n        }\n\n        private void QueueAutoUpdate(PluginInstallLocation installLocation)\n        {\n            var entry = myBoundSettingsStore.GetValue((UnrealLinkSettings s) => s.DefaultUpdateRiderLinkBehavior);\n            var shouldBeBuilt = (entry == InstallOrExtract.Install) ||\n                                (!mySolution.GetComponent<ICppUE4SolutionDetector>().UnrealContext.Value.IsBuiltFromSource && installLocation == PluginInstallLocation.Engine);\n            mySolution.Locks.ExecuteOrQueueReadLockEx(Lifetime,\n                \"UnrealPluginInstaller.InstallPluginIfRequired\",\n                () => HandleManualInstallPlugin(\n                    ModelUtils.CreateInstallPluginDescription(installLocation, ForceInstall.No, shouldBeBuilt)\n                ));\n        }\n\n        private VirtualFileSystemPath CreateTempDirectory()\n        {\n            var entry = myBoundSettingsStore.GetValue((UnrealLinkSettings s) => s.IntermediateBuildFolderRoot);\n            if (entry.IsNullOrEmpty())\n            {\n                var defaultBuildPath = VirtualFileSystemDefinition.GetTempPath(InteractionContext.SolutionContext);\n                return VirtualFileSystemDefinition.CreateTemporaryDirectory(InteractionContext.SolutionContext, defaultBuildPath,\n                    TMP_PREFIX);\n            }\n            return VirtualFileSystemDefinition.CreateTemporaryDirectory(InteractionContext.SolutionContext, entry.ToVirtualFileSystemPath(),\n                TMP_PREFIX);\n        }\n\n        private void InstallPluginInGame(\n            Lifetime lifetime,\n            UnrealPluginInstallInfo unrealPluginInstallInfo,\n            Property<double> progress,\n            bool buildRequired,\n            IReadOnlyList<UnrealPluginInstallInfo.InstallDescription> projectPluginsToInstall,\n            IReadOnlyList<UnrealPluginInstallInfo.InstallDescription> projectPluginsToDelete)\n        {\n            myLogger.Verbose(\"[UnrealLink]: Installing plugin in Game\");\n            var backupDir = CreateTempDirectory();\n            if(backupDir.IsNullOrEmpty()) return;\n            \n            using var deleteTempFolders = new DeleteTempFolders(backupDir.Directory);\n\n            var backupAllPlugins = BackupAllPlugins(unrealPluginInstallInfo);\n            var success = true;\n            var cppUe4SolutionDetector = mySolution.GetComponent<ICppUE4SolutionDetector>();\n            var isSln = cppUe4SolutionDetector.SupportRiderProjectModel != CppUE4ProjectModelSupportMode.UprojectOpened;\n            foreach (var installDescription in projectPluginsToDelete)\n            {\n                success &= DeletePluginUsingDescription(installDescription, isSln);\n                if (!success) break;\n            }\n\n            var size = Math.Max(projectPluginsToInstall.Count, 1);\n            var range = 1.0 / size;\n            for (int i = 0; success && i < projectPluginsToInstall.Count; i++)\n            {\n                progress.Value = range * i;\n                var installDescription = projectPluginsToInstall[i];\n                myLogger.Verbose($\"[UnrealLink]: Installing plugin for {installDescription.ProjectName}\");\n                try\n                {\n                    if (buildRequired && InstallPlugin(lifetime, installDescription, unrealPluginInstallInfo.EngineRoot, progress,\n                        range)) continue;\n                    if (!buildRequired && ExtractPlugin(lifetime, installDescription, unrealPluginInstallInfo.EngineRoot, progress,\n                           range)) continue;\n                }\n                catch (OperationCanceledException)\n                {\n                    // Operation was cancelled, don't need to do anything, fallback to break case\n                }\n\n                success = false;\n            }\n\n            if (success)\n            {\n                unrealPluginInstallInfo.EnginePlugin.IsPluginAvailable = false;\n            }\n            else\n            {\n                foreach (var backupAllPlugin in backupAllPlugins)\n                {\n                    backupAllPlugin.Restore();\n                }\n            }\n\n            myUnrealHost.myModel.InstallPluginFinished(success);\n        }\n\n        private static Dictionary<string, UnrealPluginInstallInfo.InstallDescription> BuildProjectPluginsByUprojectPath(\n            UnrealPluginInstallInfo unrealPluginInstallInfo)\n        {\n            return unrealPluginInstallInfo.ProjectPlugins\n                .Where(it => !it.UprojectPath.IsNullOrEmpty())\n                .GroupBy(it => it.UprojectPath.FullPath, StringComparer.OrdinalIgnoreCase)\n                .ToDictionary(it => it.Key, it => it.First(), StringComparer.OrdinalIgnoreCase);\n        }\n\n        private List<BackupDir> BackupAllPlugins(UnrealPluginInstallInfo unrealPluginInstallInfo)\n        {\n            var result = new List<BackupDir>();\n            if (unrealPluginInstallInfo.EnginePlugin.IsPluginAvailable)\n            {\n                try\n                {\n                    result.Add(new BackupDir(unrealPluginInstallInfo.EnginePlugin.UnrealPluginRootFolder, TMP_PREFIX));\n                }\n                catch\n                {\n                    var text = \"Close all running instances of Unreal Editor and try again\\n\" +\n                               $\"Path to old plugin: {unrealPluginInstallInfo.EnginePlugin.UnrealPluginRootFolder}\";\n\n                    myUnrealHost.myModel.RiderLinkInstallMessage(\n                        new InstallMessage(\"Failed to backup old RiderLink plugin\", ContentType.Error));\n                    myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(text, ContentType.Error));\n                    throw;\n                }\n            }\n\n            foreach (var installDescription in unrealPluginInstallInfo.ProjectPlugins)\n            {\n                try\n                {\n                    if (installDescription.IsPluginAvailable)\n                        result.Add(new BackupDir(installDescription.UnrealPluginRootFolder, TMP_PREFIX));\n                }\n                catch\n                {\n                    var text = \"Close all running instances of Unreal Editor and try again\\n\" +\n                               $\"Path to old plugin: {installDescription.UnrealPluginRootFolder}\";\n\n                    myUnrealHost.myModel.RiderLinkInstallMessage(\n                        new InstallMessage(\"Failed to backup old RiderLink plugin\", ContentType.Error));\n                    myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(text, ContentType.Error));\n                    throw;\n                }\n            }\n\n            return result;\n        }\n\n        private void InstallPluginInEngine(Lifetime lifetime, UnrealPluginInstallInfo unrealPluginInstallInfo,\n            IProperty<double> progress, bool buildRequired)\n        {\n            var backupDir = CreateTempDirectory();\n            if (backupDir.IsNullOrEmpty()) return;\n            \n            using var deleteTempFolders = new DeleteTempFolders(backupDir.Directory);\n\n            var backupAllPlugins = BackupAllPlugins(unrealPluginInstallInfo);\n            progress.Value = 0.0;\n            bool success;\n            try\n            {\n                if (buildRequired)\n                {\n                    success = InstallPlugin(lifetime, unrealPluginInstallInfo.EnginePlugin,\n                        unrealPluginInstallInfo.EngineRoot, progress, 1.0);   \n                }\n                else\n                {\n                    success = ExtractPlugin(lifetime, unrealPluginInstallInfo.EnginePlugin,\n                        unrealPluginInstallInfo.EngineRoot, progress, 1.0);\n                }\n            }\n            catch (OperationCanceledException)\n            {\n                success = false;\n            }\n\n            if (!success)\n            {\n                foreach (var backupAllPlugin in backupAllPlugins)\n                {\n                    backupAllPlugin.Restore();\n                }\n            }\n            else\n            {\n                foreach (var installDescription in unrealPluginInstallInfo.ProjectPlugins)\n                {\n                    installDescription.IsPluginAvailable = false;\n                }\n            }\n\n            myUnrealHost.myModel.InstallPluginFinished(success);\n        }\n\n        private bool ExtractPlugin(Lifetime lifetime,\n            UnrealPluginInstallInfo.InstallDescription installDescription,\n            VirtualFileSystemPath engineRoot, IProperty<double> progressProperty, double range)\n        {\n            using var def = new LifetimeDefinition();\n            var ZIP_STEP = 0.5 * range;\n            var PATCH_STEP = 0.5 * range;\n\n            var pluginRootFolder = installDescription.UnrealPluginRootFolder;\n            pluginRootFolder.CreateDirectory().DeleteChildren();\n\n            var editorPluginPathFile = myPathsProvider.PathToPackedPlugin;\n            try\n            {\n                ZipFile.ExtractToDirectory(editorPluginPathFile.FullPath, pluginRootFolder.FullPath);\n                progressProperty.Value += ZIP_STEP;\n            }\n            catch (Exception exception)\n            {\n                myLogger.Warn(exception, $\"[UnrealLink]: Couldn't extract {editorPluginPathFile} to {pluginRootFolder}\");\n\n                const string unzipFailTitle = \"Failed to unzip new RiderLink plugin\";\n                var unzipFailText =\n                    $\"Failed to unzip new version of RiderLink ({editorPluginPathFile.FullPath}) to user folder ({pluginRootFolder.FullPath})\\n\" +\n                    \"Try restarting Rider in administrative mode\";\n\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(unzipFailTitle, ContentType.Error));\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(unzipFailText, ContentType.Error));\n                return false;\n            }\n\n            if (!PatchUpluginFileAfterInstallation(pluginRootFolder))\n            {\n                const string failedToPatch = \"Failed to patch RiderLink.uplugin\";\n                var failedPatchText = \"Failed to set `EnableByDefault` to true in RiderLink.uplugin\\n\" +\n                                      \"You need to manually enable RiderLink in UnrealEditor\";\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(failedToPatch, ContentType.Normal));\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(failedPatchText, ContentType.Normal));\n            }\n\n            progressProperty.Value += PATCH_STEP;\n\n            lifetime.ToCancellationToken().ThrowIfCancellationRequested();\n\n            installDescription.IsPluginAvailable = true;\n            installDescription.PluginChecksum = myPathsProvider.CurrentPluginChecksum;\n\n            var title = Strings.RiderLinkPluginExtracted_Title;\n            var text = Strings.RiderLinkPluginExtracted_Message.Format(pluginRootFolder);\n\n            myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(title, ContentType.Normal));\n            myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(text, ContentType.Normal));\n\n            var notification = new NotificationModel(mySolution.GetRdProjectId(), title, text, true,\n              RdNotificationEntryType.INFO, new List<NotificationHyperlink>());\n\n            mySolution.Locks.ExecuteOrQueue(Lifetime, \"UnrealLink.InstallPlugin\",\n                () => { myNotificationsModel.Notification(notification); });\n\n            var cppUe4SolutionDetector = mySolution.GetComponent<ICppUE4SolutionDetector>();\n            var isSln = cppUe4SolutionDetector.SupportRiderProjectModel != CppUE4ProjectModelSupportMode.UprojectOpened;\n\n            if (isSln)\n            {\n                RefreshSlnProjectFiles(installDescription, engineRoot);\n            } else\n            {\n                RefreshUprojectProjectFiles(lifetime, pluginRootFolder);\n            }\n            return true;\n        }\n\n        private void RefreshUprojectProjectFiles(Lifetime lifetime, VirtualFileSystemPath pluginRootFolder)\n        {\n            var actionTitle = \"Update VirtualFileSystem after RiderLink installation\";\n            mySolution.Locks.Queue(Lifetime, actionTitle, () =>\n            {\n                myLogger.Verbose(actionTitle);\n                var fileSystemModel = mySolution.GetProtocolSolution().GetFileSystemModel();\n                fileSystemModel.RefreshPaths.Start(lifetime,\n                    new RdFsRefreshRequest(new List<RdPath>{pluginRootFolder.ToRd()}, true));\n            });\n        }\n\n        private void RefreshSlnProjectFiles(UnrealPluginInstallInfo.InstallDescription installDescription, VirtualFileSystemPath engineRoot)\n        {\n            const string refreshText = \"Refreshing project files\";\n            myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(refreshText, ContentType.Normal));\n            mySolution.Locks.ExecuteOrQueue(Lifetime, \"Refresh projects after RiderLink installation\", () => \n                UnrealProjectsRefresher.RefreshProjects(Lifetime, mySolution, installDescription, engineRoot));\n        }\n\n        private bool InstallPlugin(Lifetime lifetime,\n            UnrealPluginInstallInfo.InstallDescription installDescription,\n            VirtualFileSystemPath engineRoot, IProperty<double> progressProperty, double range)\n        {\n            using var def = new LifetimeDefinition();\n            var ZIP_STEP = 0.1 * range;\n            var PATCH_STEP = 0.1 * range;\n            var BUILD_STEP = 0.7 * range;\n\n            var pluginRootFolder = installDescription.UnrealPluginRootFolder;\n\n            var editorPluginPathFile = myPathsProvider.PathToPackedPlugin;\n            var pluginTmpDir = CreateTempDirectory();\n            if (pluginTmpDir.IsNullOrEmpty()) return false;\n            if (PlatformUtil.RuntimePlatform == JetPlatform.Windows && pluginTmpDir.FullPath.Any(c => c >= 128))\n            {\n                string nonAsciiCharactersText = Strings.NonASCIICharactersInTheBuildDirectory_Text;\n\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(nonAsciiCharactersText, ContentType.Error));\n            }\n            \n            def.Lifetime.OnTermination(() => { pluginTmpDir.Delete(); });\n            try\n            {\n                ZipFile.ExtractToDirectory(editorPluginPathFile.FullPath, pluginTmpDir.FullPath);\n                progressProperty.Value += ZIP_STEP;\n            }\n            catch (Exception exception)\n            {\n                myLogger.Warn(exception, $\"[UnrealLink]: Couldn't extract {editorPluginPathFile} to {pluginTmpDir}\");\n\n                const string unzipFailTitle = \"Failed to unzip new RiderLink plugin\";\n                var unzipFailText =\n                    $\"Failed to unzip new version of RiderLink ({editorPluginPathFile.FullPath}) to user folder ({pluginTmpDir.FullPath})\\n\" +\n                    \"Try restarting Rider in administrative mode\";\n\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(unzipFailTitle, ContentType.Error));\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(unzipFailText, ContentType.Error));\n                return false;\n            }\n\n            lifetime.ToCancellationToken().ThrowIfCancellationRequested();\n\n            var upluginFile = UnrealPluginDetector.GetPathToUpluginFile(pluginTmpDir);\n            var pluginBuildOutput = CreateTempDirectory();\n            if (pluginBuildOutput.IsNullOrEmpty()) return false;\n            \n            def.Lifetime.OnTermination(() => { pluginBuildOutput.Delete(); });\n            var buildProgress = progressProperty.Value;\n            var isPluginBuilt = BuildPlugin(lifetime, upluginFile, pluginBuildOutput,\n                engineRoot, value => progressProperty.SetValue(buildProgress + value * BUILD_STEP));\n            if (!isPluginBuilt)\n            {\n                myLogger.Error($\"Failed to build RiderLink for any available project\");\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(Strings.FailedToBuildRiderLinkPlugin_Text, ContentType.Error));\n                return false;\n            }\n\n            progressProperty.Value = buildProgress + BUILD_STEP;\n\n            lifetime.ToCancellationToken().ThrowIfCancellationRequested();\n\n            if (!PatchUpluginFileAfterInstallation(pluginBuildOutput))\n            {\n                var failedToPatch = Strings.FailedToPatchRiderLinkUplugin_Text;\n                var failedPatchText = Strings.FailedToPatchRiderLinkUplugin_Message;\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(failedToPatch, ContentType.Normal));\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(failedPatchText, ContentType.Normal));\n            }\n\n            progressProperty.Value += PATCH_STEP;\n\n            lifetime.ToCancellationToken().ThrowIfCancellationRequested();\n\n            pluginRootFolder.CreateDirectory().DeleteChildren();\n            pluginBuildOutput.Copy(pluginRootFolder);\n\n            installDescription.IsPluginAvailable = true;\n            installDescription.PluginChecksum = myPathsProvider.CurrentPluginChecksum;\n\n            var title = Strings.RiderLinkPluginInstalled_Title;\n            var text = Strings.RiderLinkPluginInstalled_Message.Format(pluginRootFolder);\n\n            myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(title, ContentType.Normal));\n            myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(text, ContentType.Normal));\n\n            var notification = new NotificationModel(mySolution.GetRdProjectId(), title, text, true,\n              RdNotificationEntryType.INFO, new List<NotificationHyperlink>());\n\n            mySolution.Locks.ExecuteOrQueue(Lifetime, \"UnrealLink.InstallPlugin\",\n                () => { myNotificationsModel.Notification(notification); });\n\n            var cppUe4SolutionDetector = mySolution.GetComponent<ICppUE4SolutionDetector>();\n            var isSln  = cppUe4SolutionDetector.SupportRiderProjectModel != CppUE4ProjectModelSupportMode.UprojectOpened;\n            if (isSln)\n            {\n                var refreshText = Strings.RefreshingProjectFiles_Text;\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(refreshText, ContentType.Normal));\n                mySolution.Locks.ExecuteOrQueue(Lifetime, Strings.RefreshProjectsAfterRiderLinkInstallation_Text, () => \n                    UnrealProjectsRefresher.RefreshProjects(Lifetime, mySolution, installDescription, engineRoot));\n            } else {\n                var actionTitle = \"Update VirtualFileSystem after RiderLink installation\";\n                mySolution.Locks.Queue(Lifetime, actionTitle, () =>\n                {\n                    myLogger.Verbose(actionTitle);\n                    var fileSystemModel = mySolution.GetProtocolSolution().GetFileSystemModel();\n                    fileSystemModel.RefreshPaths.Start(lifetime,\n                        new RdFsRefreshRequest(new List<RdPath>() { pluginRootFolder.ToRd() }, true));\n                });\n            }\n            return true;\n        }\n\n        private bool PatchUpluginFileAfterInstallation(VirtualFileSystemPath pluginBuildOutput)\n        {\n            var upluginFile = pluginBuildOutput / \"RiderLink.uplugin\";\n            if (!upluginFile.ExistsFile) return false;\n\n            var jsonText = File.ReadAllText(upluginFile.FullPath);\n            try\n            {\n                var jsonObject = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonText) as JObject;\n                if (jsonObject == null)\n                {\n                    myLogger.Warn($\"[UnrealLink]: {upluginFile} is not a JSON file, couldn't patch it\");\n                    return false;\n                }\n\n                jsonObject[\"EnabledByDefault\"] = true;\n                jsonObject[\"Installed\"] = false;\n                File.WriteAllText(upluginFile.FullPath, jsonObject.ToString());\n            }\n            catch (Exception e)\n            {\n                myLogger.Warn($\"[UnrealLink]: Couldn't patch 'EnableByDefault' field of {upluginFile}\", e);\n                return false;\n            }\n\n            return true;\n        }\n\n        private void BindToInstallationSettingChange()\n        {\n            var entry = myBoundSettingsStore.Schema.GetScalarEntry((UnrealLinkSettings s) => s.AutoUpdateRiderLinkPlugin);\n            myBoundSettingsStore.GetValueProperty<bool>(Lifetime, entry, null).Change.Advise_When(Lifetime,\n                newValue => newValue, args => { InstallPluginIfInfoAvailable(); });\n        }\n\n        private void InstallPluginIfInfoAvailable()\n        {\n            var unrealPluginInstallInfo = myPluginDetector.InstallInfoProperty.Value;\n            if (unrealPluginInstallInfo != null)\n            {\n                HandleAutoUpdatePlugin(unrealPluginInstallInfo);\n            }\n        }\n\n        public void HandleManualInstallPlugin(InstallPluginDescription installPluginDescription)\n        {\n            var unrealPluginInstallInfo = myPluginDetector.InstallInfoProperty.Value;\n            if (unrealPluginInstallInfo == null) return;\n\n            Lifetime.UsingNestedAsync(async lt =>\n            {\n                var lifetimeDefinition = lt.CreateNested();\n                var lifetime = lifetimeDefinition.Lifetime;\n\n                lifetime.Bracket(\n                    () => myUnrealHost.myModel.RiderLinkInstallationInProgress.Value = true,\n                    () => myUnrealHost.myModel.RiderLinkInstallationInProgress.Value = false\n                );\n                var prefix = unrealPluginInstallInfo.EnginePlugin.IsPluginAvailable ? \"Updating\" : \"Installing\";\n                var header = $\"{prefix} RiderLink plugin\";\n                var progress = new Property<double>(\"UnrealLink.InstallPluginProgress\", 0.0);\n                var task = BackgroundProgressBuilder.Create()\n                    .AsCancelable(() =>\n                    {\n                        myUnrealHost.myModel.RiderLinkInstallMessage(\n                            new InstallMessage(Strings.RiderLinkInstallationHasBeenCancelled_Text, ContentType.Error));\n                        lifetimeDefinition.Terminate();\n                    })\n                    .WithHeader(header)\n                    .WithProgress(progress)\n                    .WithDescriptionFromProgress();\n                myBackgroundProgressManager.AddNewTask(lifetime, task);\n                myUnrealHost.myModel.CancelRiderLinkInstall.AdviseOnce(lifetime, _ =>\n                {\n                    myUnrealHost.myModel.RiderLinkInstallMessage(\n                        new InstallMessage(Strings.RiderLinkInstallationHasBeenCancelled_Text, ContentType.Error));\n                    lifetimeDefinition.Terminate();\n                });\n                myUnrealHost.myModel.RiderLinkInstallPanelInit();\n                await lifetime.StartBackground(() =>\n                {\n                    switch (installPluginDescription.Location)\n                    {\n                        case PluginInstallLocation.Engine:\n                            InstallPluginInEngine(lifetime, unrealPluginInstallInfo, progress, installPluginDescription.BuildRequired);\n                            break;\n                        case PluginInstallLocation.Game:\n                            var projectPluginsByUprojectPath = BuildProjectPluginsByUprojectPath(unrealPluginInstallInfo);\n                            var selectedProjectPlugins = installPluginDescription.SelectedUprojectPaths.Count == 0\n                                ? unrealPluginInstallInfo.ProjectPlugins\n                                : installPluginDescription.SelectedUprojectPaths\n                                    .Distinct(StringComparer.OrdinalIgnoreCase)\n                                    .Select(path => projectPluginsByUprojectPath.TryGetValue(path, out var description) ? description : null)\n                                    .Where(description => description != null)\n                                    .Select(description => description!)\n                                    .ToList();\n                            var selectedSet = selectedProjectPlugins\n                                .Select(it => it.UprojectPath.FullPath)\n                                .ToHashSet(StringComparer.OrdinalIgnoreCase);\n                            var unselectedProjectPlugins = installPluginDescription.UnselectedUprojectPaths\n                                .Distinct(StringComparer.OrdinalIgnoreCase)\n                                .Select(path => projectPluginsByUprojectPath.TryGetValue(path, out var description) ? description : null)\n                                .Where(description => description != null)\n                                .Select(description => description!)\n                                .Where(it => !selectedSet.Contains(it.UprojectPath.FullPath))\n                                .ToList();\n\n                            InstallPluginInGame(\n                                lifetime,\n                                unrealPluginInstallInfo,\n                                progress,\n                                installPluginDescription.BuildRequired,\n                                selectedProjectPlugins,\n                                unselectedProjectPlugins);\n                            break;\n                        case PluginInstallLocation.NotInstalled:\n                        default:\n                            myLogger.Error(\"UnrealLink: Invalid location set for installing RiderLink plugin\");\n                            break;\n                    }\n                });\n            });\n        }\n\n        private PluginInstallLocation GetInstallLocationFromSettings()\n        {\n            var entry = myBoundSettingsStore.Schema.GetScalarEntry((UnrealLinkSettings s) => s.DefaultLocationForRiderLink);\n            return (PluginInstallLocation)myBoundSettingsStore.GetValue(entry, null);\n        }\n\n        private void BindToNotificationFixAction()\n        {\n            myUnrealHost.PerformModelAction(model =>\n            {\n                model.InstallEditorPlugin.Advise(Lifetime,  HandleManualInstallPlugin);\n                model.DeletePlugin.Advise(Lifetime, DeletePlugin);\n                model.EnableAutoupdatePlugin.AdviseNotNull(Lifetime,\n                    unit =>\n                    {\n                        myBoundSettingsStore.SetValue<UnrealLinkSettings, bool>(s => s.AutoUpdateRiderLinkPlugin, true);\n                    });\n                model.RefreshProjects.Advise(Lifetime,\n                    _ => UnrealProjectsRefresher.RefreshProjects(Lifetime, mySolution, myPluginDetector.InstallInfoProperty.Value));\n            });\n        }\n\n        private void DeletePlugin()\n        {\n            var installInfo = myPluginDetector.InstallInfoProperty.Value;\n            myLogger.Info($\"[UnrealLink]: Deleting RiderLink plugins\");\n            \n            var cppUe4SolutionDetector = mySolution.GetComponent<ICppUE4SolutionDetector>();\n            var isSln = cppUe4SolutionDetector.SupportRiderProjectModel != CppUE4ProjectModelSupportMode.UprojectOpened;\n\n            UnrealPluginInstallInfo.InstallDescription description = installInfo.EnginePlugin;\n            bool result = true;\n            result &= DeletePluginUsingDescription(description, isSln);\n            foreach (var installInfoProjectPlugin in installInfo.ProjectPlugins)\n            {\n                description = installInfoProjectPlugin;\n                result &= DeletePluginUsingDescription(installInfoProjectPlugin, isSln);\n            }\n\n            if (result)\n            {\n                myLogger.Info($\"[UnrealLink]: RiderLink is deleted\");\n                \n                var title = Strings.DeletingRiderLinkPlugin_Text;\n                var text = Strings.RiderLinkIsDeleted_Text;\n\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(title, ContentType.Normal));\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(text, ContentType.Normal));\n\n                var notification = new NotificationModel(mySolution.GetRdProjectId(), title, text, true,\n                    RdNotificationEntryType.INFO, new List<NotificationHyperlink>());\n\n                mySolution.Locks.ExecuteOrQueue(Lifetime, \"UnrealLink.InstallPlugin\",\n                    () => { myNotificationsModel.Notification(notification); });\n            }\n            else\n            {\n                myLogger.Warn($\"[UnrealLink]: Failed to delete RiderLink\");\n                \n                var title = Strings.DeletingRiderLinkPlugin_Text;\n                var text = Strings.FailedToDeleteRiderLink_Text;\n\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(title, ContentType.Normal));\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(text, ContentType.Normal));\n\n                var notification = new NotificationModel(mySolution.GetRdProjectId(), title, text, true,\n                    RdNotificationEntryType.ERROR, new List<NotificationHyperlink>());\n\n                mySolution.Locks.ExecuteOrQueue(Lifetime, \"UnrealLink.InstallPlugin\",\n                    () => { myNotificationsModel.Notification(notification); });\n            }\n\n            if (isSln)\n            {\n                RefreshSlnProjectFiles(description, installInfo.EngineRoot);\n            }\n        }\n\n        private bool DeletePluginUsingDescription(UnrealPluginInstallInfo.InstallDescription description, bool isSln)\n        {\n            if (description.IsPluginAvailable)\n            {\n                try\n                {\n                    description.UnrealPluginRootFolder.Delete();\n                }\n                catch (Exception)\n                {\n                    myLogger.Warn($\"[UnrealLink]: Failed to delete RiderLink from {description.UnrealPluginRootFolder}\");\n                    return false;\n                }\n                description.IsPluginAvailable = false;\n                if (!isSln)\n                {\n                    RefreshUprojectProjectFiles(Lifetime, description.UnrealPluginRootFolder);\n                }\n            }\n\n            return true;\n        }\n\n        private bool BuildPlugin(Lifetime lifetime, VirtualFileSystemPath upluginPath,\n            VirtualFileSystemPath outputDir, VirtualFileSystemPath engineRoot,\n            Action<double> progressPump)\n        {\n            var runUatName = $\"RunUAT.{CmdUtils.GetPlatformCmdExtension()}\";\n            var pathToUat = engineRoot / \"Engine\" / \"Build\" / \"BatchFiles\" / runUatName;\n            if (!pathToUat.ExistsFile)\n            {\n                myLogger.Warn($\"[UnrealLink]: Failed build plugin: {runUatName} is not available\");\n                myUnrealHost.myModel.RiderLinkInstallMessage(\n                    new InstallMessage(Strings.FailedToBuildRiderLinkPluginFor__Text.Format(engineRoot), ContentType.Error));\n                myUnrealHost.myModel.RiderLinkInstallMessage(\n                    new InstallMessage(Strings.Reason_UatIsNotAvailable_Text.Format(runUatName, pathToUat), ContentType.Error));\n                return false;\n            }\n\n            try\n            {\n                var pipeStreams = CreatePipeStreams(\"[UAT]:\", progressPump);\n                var startInfo = CmdUtils.GetProcessStartInfo(pipeStreams, pathToUat, null, \"BuildPlugin\",\n                    \"-Unversioned\", $\"-Plugin=\\\"{upluginPath.FullPath}\\\"\",\n                    $\"-Package=\\\"{outputDir.FullPath}\\\"\");\n\n                myLogger.Info($\"[UnrealLink]: Building UnrealLink plugin with: {startInfo.Arguments}\");\n                myLogger.Verbose(\"[UnrealLink]: Start building UnrealLink\");\n\n                var result = CmdUtils.RunCommandWithLock(lifetime, startInfo, myLogger);\n                myLogger.Verbose(\"[UnrealLink]: Stop building UnrealLink\");\n                lifetime.ToCancellationToken().ThrowIfCancellationRequested();\n\n                if (result != 0)\n                {\n                    myLogger.Error($\"[UnrealLink]: Failed to build plugin for {engineRoot}\");\n                    myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(Strings.FailedToBuildRiderLinkPluginFor__Text.Format(engineRoot),\n                        ContentType.Error));\n                    return false;\n                }\n            }\n            catch (OperationCanceledException)\n            {\n                myLogger.Verbose(\"[UnrealLink]: Build cancelled\");\n                throw;\n            }\n            catch (Exception exception)\n            {\n                myLogger.Verbose(\"[UnrealLink]: Stop building UnrealLink\");\n                myLogger.Error(exception,\n                    $\"[UnrealLink]: Failed to build plugin for {engineRoot}\");\n\n                myUnrealHost.myModel.RiderLinkInstallMessage(\n                    new InstallMessage(Strings.FailedToBuildRiderLinkPluginFor__Text.Format(engineRoot), ContentType.Error));\n                return false;\n            }\n\n            return true;\n        }\n\n        private InvokeChildProcess.PipeStreams CreatePipeStreams(string prefix, Action<double> progressPump = null)\n        {\n            return InvokeChildProcess.PipeStreams.Custom((chunk, isErr, logger) =>\n            {\n                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(chunk,\n                    isErr ? ContentType.Error : ContentType.Normal));\n                    \n                logger.Info(prefix + chunk);\n\n                if (isErr) return;\n                if (progressPump == null) return;\n\n                var progressText = chunk.Trim();\n                if (!progressText.StartsWith(\"[\")) return;\n\n                var closingBracketIndex = progressText.IndexOf(']');\n                if (closingBracketIndex == -1) return;\n\n                var progressNumberWithDivision = progressText.Substring(1, closingBracketIndex - 1);\n                var numbers = progressNumberWithDivision.Split('/');\n                if (numbers.Length != 2) return;\n\n                if (!int.TryParse(numbers[0], out var leftInt)) return;\n                if (!int.TryParse(numbers[1], out var rightInt)) return;\n\n                progressPump((double) leftInt / rightInt);\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/PluginInstaller/UnrealProjectsRefresher.cs",
    "content": "using System;\nusing JetBrains.Annotations;\nusing JetBrains.HabitatDetector;\nusing JetBrains.Lifetimes;\nusing JetBrains.ProjectModel;\nusing JetBrains.ProjectModel.ProjectsHost.SolutionHost.Progress;\nusing JetBrains.ReSharper.Feature.Services.Cpp.ProjectModel.UE4;\nusing JetBrains.ReSharper.Psi.Cpp.UE4;\nusing JetBrains.ReSharper.Resources.Shell;\nusing JetBrains.Util;\nusing JetBrains.Util.Interop;\nusing JetBrains.Util.Logging;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\nusing RiderPlugin.UnrealLink.Resources;\nusing RiderPlugin.UnrealLink.Utils;\n\nnamespace RiderPlugin.UnrealLink.PluginInstaller\n{\n    public static class UnrealProjectsRefresher\n    {\n        private static readonly ILogger OurLogger = Logger.GetLogger(typeof(UnrealProjectsRefresher));\n\n        public static void RefreshProjects(Lifetime parentLifetime,\n            [NotNull] ISolution solution,\n            [NotNull] UnrealPluginInstallInfo installInfo)\n        {\n            RefreshProjects(parentLifetime, solution, installInfo.ProjectPlugins.FirstOrDefault(null), installInfo.EngineRoot);\n        }\n        \n        public static void RefreshProjects(Lifetime parentLifetime,\n            [NotNull] ISolution solution,\n            [CanBeNull] UnrealPluginInstallInfo.InstallDescription installDescription,\n            [CanBeNull] VirtualFileSystemPath engineRoot)\n        {\n            parentLifetime.UsingNestedAsync(async lt =>\n            {\n                var lifetimeDefinition = lt.CreateNested();\n                var lifetime = lifetimeDefinition.Lifetime;\n                \n                var unrealHost = solution.GetComponent<UnrealHost>();\n                \n                lifetime.Bracket(\n                    () => unrealHost.myModel.RefreshInProgress.Value = true,\n                    () => unrealHost.myModel.RefreshInProgress.Value = false\n                );\n\n                var task = BackgroundProgressBuilder.Create()\n                    .AsCancelable(() =>\n                    {\n                        unrealHost.myModel.RiderLinkInstallMessage(\n                            new InstallMessage(Strings.RefreshingProjectsFilesHasBeenCancelled_Text, ContentType.Error));\n                        lifetimeDefinition.Terminate();\n                    })\n                    .WithHeader(Strings.RefreshingProjectFiles_Text);\n                solution.GetComponent<BackgroundProgressManager>().AddNewTask(lifetime, task);\n                var uprojectFile = installDescription?.UprojectPath;\n                if (uprojectFile.IsNullOrEmpty())\n                {\n                    var cppUe4SolutionDetector = solution.GetComponent<ICppUE4SolutionDetector>();\n                    uprojectFile = cppUe4SolutionDetector.GetUProjectPath();\n                }\n\n                await lifetime.StartBackground(() => RegenerateProjectFiles(lifetime, solution, unrealHost, engineRoot, uprojectFile));\n            });\n        }\n        \n        private static void RegenerateProjectFiles(Lifetime lifetime, ISolution solution,\n            UnrealHost unrealHost,\n            VirtualFileSystemPath engineRoot, VirtualFileSystemPath uprojectFile)\n        {\n            void LogFailedRefreshProjectFiles()\n            {\n                unrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(Strings.FailedToRefreshProjectFiles_Text,\n                    ContentType.Normal));\n                unrealHost.myModel.RiderLinkInstallMessage(\n                    new InstallMessage(Strings.RiderLinkPluginWillNotBeVisibleInThe_Text, ContentType.Normal));\n                unrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(\n                    Strings.NeedToRefreshProjectFilesManually_Text,\n                    ContentType.Normal));\n            }\n            if (!engineRoot.IsValidAndExistDirectory())\n            {\n                OurLogger.Warn($\"[UnrealLink]: Couldn't find Unreal Engine root\");\n\n                LogFailedRefreshProjectFiles();\n                return;\n            }\n\n            if (PlatformUtil.RuntimePlatform != JetPlatform.Windows) return;\n\n            var ueVersion = solution.GetComponent<ICppUE4SolutionDetector>().UnrealContext.Value.Version;\n            var pathToUnrealBuildToolBin = CppUE4FolderFinder.GetAbsolutePathToUnrealBuildToolBin(engineRoot, ueVersion);\n\n            // 1. If project is under engine root, use GenerateProjectFiles.{extension} first\n            if (GenerateProjectFilesCmd(lifetime, solution, unrealHost, uprojectFile, engineRoot)) return;\n            // 2. If it's a standalone project, use UnrealVersionSelector\n            //    The same way \"Generate project files\" from context menu of .uproject works\n            if (RegenerateProjectUsingBundledUVS(lifetime, unrealHost, uprojectFile, engineRoot)) return;\n            if (RegenerateProjectUsingSystemUVS(lifetime, solution, unrealHost, uprojectFile)) return;\n            // 3. If UVS is missing or have failed, fallback to UnrealBuildTool\n            if (RegenerateProjectUsingUBT(lifetime, unrealHost, uprojectFile, pathToUnrealBuildToolBin, engineRoot)) return;\n\n            OurLogger.Warn(\"[UnrealLink]: Couldn't refresh project files\");\n            LogFailedRefreshProjectFiles();\n        }\n\n        private static bool GenerateProjectFilesCmd(Lifetime lifetime, ISolution solution, UnrealHost unrealHost,\n            VirtualFileSystemPath uprojectFile, VirtualFileSystemPath engineRoot)\n        {\n            // Invalid uproject file means we couldn't get uproject file from solution detector and the project might be\n            // under Engine source\n            var invalidUprojectFile = !uprojectFile.IsValidAndExistFile();\n            var isProjectUnderEngine = invalidUprojectFile || uprojectFile.StartsWith(engineRoot);\n            if (!isProjectUnderEngine)\n            {\n                OurLogger.Info($\"[UnrealLink]: {solution.SolutionFilePath} is not in {engineRoot} \");\n                return false;\n            }\n\n            var generateProjectFilesCmd = engineRoot / $\"GenerateProjectFiles.{CmdUtils.GetPlatformCmdExtension()}\";\n            if (!generateProjectFilesCmd.ExistsFile)\n            {\n                OurLogger.Info($\"[UnrealLink]: {generateProjectFilesCmd} is not available\");\n                return false;\n            }\n\n            var pipeStreams = CreatePipeStreams(unrealHost, \"[GenerateProjectFiles]:\");\n            var startInfo = CmdUtils.GetProcessStartInfo(pipeStreams, generateProjectFilesCmd, generateProjectFilesCmd.Directory);\n            \n            OurLogger.Info($\"[UnrealLink]: Regenerating project files: {startInfo.Arguments}\");\n            try\n            {\n                var result = CmdUtils.RunCommandWithLock(lifetime, startInfo, OurLogger) == 0;\n                if (!result)\n                {\n                    OurLogger.Warn($\"[UnrealLink]: Failed refresh project files, calling {generateProjectFilesCmd} went wrong\");\n                }\n\n                return result;\n            }\n            catch (ErrorLevelException errorLevelException)\n            {\n                OurLogger.Error(errorLevelException,\n                    $\"[UnrealLink]: Failed refresh project files, calling {generateProjectFilesCmd} went wrong\");\n                return false;\n            }\n        }\n\n        private static bool RegenerateProjectUsingSystemUVS(Lifetime lifetime, ISolution solution, UnrealHost unrealHost,\n            VirtualFileSystemPath uprojectFile)\n        {\n            var programFiles = Environment.GetEnvironmentVariable(\"ProgramFiles(x86)\");\n            if (programFiles.IsNullOrEmpty()) return false;\n            \n            var programFilesPath = VirtualFileSystemPath.Parse(programFiles, solution.GetInteractionContext());\n            if (!programFilesPath.ExistsDirectory) return false;\n            \n            var pathToUnrealVersionSelector =\n                programFilesPath / \"Epic Games\" / \"Launcher\" / \"Engine\"/ \"Binaries\" / \"Win64\" / \"UnrealVersionSelector.exe\";\n            return RegenerateProjectUsingUVS(lifetime, unrealHost, uprojectFile, pathToUnrealVersionSelector);\n        }\n        \n        private static bool RegenerateProjectUsingBundledUVS(Lifetime lifetime, UnrealHost unrealHost, VirtualFileSystemPath uprojectFile,\n            VirtualFileSystemPath engineRoot)\n        {\n            var pathToUnrealVersionSelector =\n                engineRoot / \"Engine\" / \"Binaries\" / \"Win64\" / \"UnrealVersionSelector.exe\";\n            return RegenerateProjectUsingUVS(lifetime, unrealHost, uprojectFile, pathToUnrealVersionSelector);\n        }\n\n        private static bool RegenerateProjectUsingUVS(Lifetime lifetime, UnrealHost unrealHost, VirtualFileSystemPath uprojectFile,\n            VirtualFileSystemPath pathToUnrealVersionSelector)\n        {\n            if (!uprojectFile.IsValidAndExistFile()) return false;\n            if (!pathToUnrealVersionSelector.ExistsFile)\n            {\n                OurLogger.Info($\"[UnrealLink]: {pathToUnrealVersionSelector} is not available\");\n                return false;\n            }\n            \n            var pipeStreams = CreatePipeStreams(unrealHost,\"[UVS]:\");\n            var startInfo = CmdUtils.GetProcessStartInfo(pipeStreams, pathToUnrealVersionSelector,\n                pathToUnrealVersionSelector.Directory,\n                \"-projectFiles\", $\"\\\"{uprojectFile}\\\"\");\n\n            try\n            {\n                var result = CmdUtils.RunCommandWithLock(lifetime, startInfo, OurLogger) == 0;\n                if (!result)\n                {\n                    OurLogger.Warn(\n                        $\"[UnrealLink]: Failed refresh project files: calling {pathToUnrealVersionSelector} {startInfo.Arguments}\");\n                }\n\n                return result;\n            }\n            catch (ErrorLevelException errorLevelException)\n            {\n                OurLogger.Error(errorLevelException,\n                    $\"[UnrealLink]: Failed refresh project files: calling {pathToUnrealVersionSelector} {startInfo.Arguments}\");\n                return false;\n            }\n        }\n\n        private static bool RegenerateProjectUsingUBT(Lifetime lifetime, UnrealHost unrealHost, VirtualFileSystemPath uprojectFile,\n            VirtualFileSystemPath pathToUnrealBuildToolBin, VirtualFileSystemPath engineRoot)\n        {\n            if (uprojectFile.IsNullOrEmpty()) return false;\n            \n            bool isInstalledBuild = IsInstalledBuild(engineRoot);\n\n            var pipeStreams = CreatePipeStreams(unrealHost, \"[UBT]:\");\n            var startInfo = CmdUtils.GetProcessStartInfo(pipeStreams, pathToUnrealBuildToolBin,\n                pathToUnrealBuildToolBin.Directory, \"-ProjectFiles\",\n                $\"-project=\\\"{uprojectFile.FullPath}\\\"\", \"-game\", \"-progress\", isInstalledBuild ? \"-rocket\" : \"-engine\");\n            try\n            {\n                var result = CmdUtils.RunCommandWithLock(lifetime, startInfo, OurLogger) == 0;\n                if (!result)\n                {\n                    OurLogger.Warn($\"[UnrealLink]: Failed refresh project files: calling {startInfo.Arguments}\");\n                }\n\n                return result;\n            }\n            catch (ErrorLevelException errorLevelException)\n            {\n                OurLogger.Error(errorLevelException,\n                    $\"[UnrealLink]: Failed refresh project files: calling {startInfo.Arguments}\");\n                return false;\n            }\n        }\n        \n        private static InvokeChildProcess.PipeStreams CreatePipeStreams(UnrealHost unrealHost, string prefix)\n        {\n            return InvokeChildProcess.PipeStreams.Custom((chunk, isErr, logger) =>\n            {\n                unrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(chunk,\n                    isErr ? ContentType.Error : ContentType.Normal));\n                    \n                logger.Info(prefix + chunk);\n            });\n        }\n\n        private static bool IsInstalledBuild(VirtualFileSystemPath engineRoot)\n        {\n            var installedBuildTxt = engineRoot / \"Engine\" / \"Build\" / \"InstalledBuild.txt\";\n            var isInstalledBuild = installedBuildTxt.ExistsFile;\n            return isInstalledBuild;\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/Resources/Strings.Designer.cs",
    "content": "// <auto-generated/>\nnamespace RiderPlugin.UnrealLink.Resources\n{\n  using System;\n  using JetBrains.Application.I18n;\n  using JetBrains.DataFlow;\n  using JetBrains.Diagnostics;\n  using JetBrains.Lifetimes;\n  using JetBrains.Util;\n  using JetBrains.Util.Logging;\n  using JetBrains.Application.I18n.Plurals;\n  \n  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n  public static class Strings\n  {\n    private static readonly ILogger ourLog = Logger.GetLogger(\"RiderPlugin.UnrealLink.Resources.Strings\");\n\n    static Strings()\n    {\n      CultureContextComponent.Instance.Change.Advise(Lifetime.Eternal, args =>\n      {\n          var instance = args.HasNew ? args.New : null;\n          if (instance != null)\n          {\n            ourResourceManager = new Lazy<JetResourceManager>(\n              () =>\n              {\n                return instance\n                  .CreateResourceManager(\"RiderPlugin.UnrealLink.Resources.Strings\", typeof(Strings).Assembly);\n              });\n          }\n          else\n          {\n            ourResourceManager = null;\n          };\n      });\n    }\n    \n    private static Lazy<JetResourceManager> ourResourceManager = null;\n    \n    [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n    public static JetResourceManager ResourceManager\n    {\n      get\n      {\n        var resourceManager = ourResourceManager;\n        if (resourceManager == null)\n        {\n          return ErrorJetResourceManager.Instance;\n        }\n        return resourceManager.Value;\n      }\n    }\n\n    public static string Choice(string format, params object[] args)\n    {\n        var formatter = ResourceManager.ChoiceFormatter;\n        if (formatter == null) return \"???\";\n        return string.Format(formatter, format, args);\n    }\n\n    public static string DeletingRiderLinkPlugin_Text => ResourceManager.GetString(\"DeletingRiderLinkPlugin_Text\");\n    public static string FailedToBuildRiderLinkPlugin_Text => ResourceManager.GetString(\"FailedToBuildRiderLinkPlugin_Text\");\n    public static string FailedToDeleteRiderLink_Text => ResourceManager.GetString(\"FailedToDeleteRiderLink_Text\");\n    public static string IfThisOptionIsEnabledTheRiderLinkEditor_Text => ResourceManager.GetString(\"IfThisOptionIsEnabledTheRiderLinkEditor_Text\");\n    public static string NonASCIICharactersInTheBuildDirectory_Text => ResourceManager.GetString(\"NonASCIICharactersInTheBuildDirectory_Text\");\n    public static string PathContainsNonASCIICharactersBuild_Text => ResourceManager.GetString(\"PathContainsNonASCIICharactersBuild_Text\");\n    public static string RiderLinkIsDeleted_Text => ResourceManager.GetString(\"RiderLinkIsDeleted_Text\");\n    public static string UnrealLinkPluginSettings_Text => ResourceManager.GetString(\"UnrealLinkPluginSettings_Text\");\n    public static string UnrealLinkPluginSettings_Title_Text => ResourceManager.GetString(\"UnrealLinkPluginSettings_Title_Text\");\n    public static string InstallRiderLinkInEngine_Text => ResourceManager.GetString(\"InstallRiderLinkInEngine_Text\");\n    public static string InstallRiderLinkPluginInEngineDescription_Text => ResourceManager.GetString(\"InstallRiderLinkPluginInEngineDescription_Text\");\n    public static string InstallRiderLinkInGame_Text => ResourceManager.GetString(\"InstallRiderLinkInGame_Text\");\n    public static string InstallRiderLinkPluginInGameDescription_Text => ResourceManager.GetString(\"InstallRiderLinkPluginInGameDescription_Text\");\n    public static string ExtractRiderLinkInEngine_Text => ResourceManager.GetString(\"ExtractRiderLinkInEngine_Text\");\n    public static string ExtractRiderLinkPluginInEngineDescription_Text => ResourceManager.GetString(\"ExtractRiderLinkPluginInEngineDescription_Text\");\n    public static string ExtractRiderLinkInGame_Text => ResourceManager.GetString(\"ExtractRiderLinkInGame_Text\");\n    public static string ExtractRiderLinkPluginInGameDescription_Text => ResourceManager.GetString(\"ExtractRiderLinkPluginInGameDescription_Text\");\n    public static string RiderLinkInstallationIsInProgress_Text => ResourceManager.GetString(\"RiderLinkInstallationIsInProgress_Text\");\n    public static string UnrealEngine_Version_IsRequired_Title => ResourceManager.GetString(\"UnrealEngine_Version_IsRequired_Title\");\n    public static string UnrealEngine_Version_IsRequired_Message => ResourceManager.GetString(\"UnrealEngine_Version_IsRequired_Message\");\n    public static string RiderLinkPluginExtracted_Title => ResourceManager.GetString(\"RiderLinkPluginExtracted_Title\");\n    public static string RiderLinkPluginExtracted_Message => ResourceManager.GetString(\"RiderLinkPluginExtracted_Message\");\n    public static string RiderLinkPluginInstalled_Title => ResourceManager.GetString(\"RiderLinkPluginInstalled_Title\");\n    public static string RiderLinkPluginInstalled_Message => ResourceManager.GetString(\"RiderLinkPluginInstalled_Message\");\n    public static string RefreshProjectsAfterRiderLinkInstallation_Text => ResourceManager.GetString(\"RefreshProjectsAfterRiderLinkInstallation_Text\");\n    public static string FailedToPatchRiderLinkUplugin_Text => ResourceManager.GetString(\"FailedToPatchRiderLinkUplugin_Text\");\n    public static string FailedToPatchRiderLinkUplugin_Message => ResourceManager.GetString(\"FailedToPatchRiderLinkUplugin_Message\");\n    public static string RefreshingProjectFiles_Text => ResourceManager.GetString(\"RefreshingProjectFiles_Text\");\n    public static string RiderLinkInstallationHasBeenCancelled_Text => ResourceManager.GetString(\"RiderLinkInstallationHasBeenCancelled_Text\");\n    public static string FailedToBuildRiderLinkPluginFor__Text => ResourceManager.GetString(\"FailedToBuildRiderLinkPluginFor__Text\");\n    public static string Reason_UatIsNotAvailable_Text => ResourceManager.GetString(\"Reason_UatIsNotAvailable_Text\");\n    public static string RefreshingProjectsFilesHasBeenCancelled_Text => ResourceManager.GetString(\"RefreshingProjectsFilesHasBeenCancelled_Text\");\n    public static string FailedToRefreshProjectFiles_Text => ResourceManager.GetString(\"FailedToRefreshProjectFiles_Text\");\n    public static string RiderLinkPluginWillNotBeVisibleInThe_Text => ResourceManager.GetString(\"RiderLinkPluginWillNotBeVisibleInThe_Text\");\n    public static string NeedToRefreshProjectFilesManually_Text => ResourceManager.GetString(\"NeedToRefreshProjectFilesManually_Text\");\n    public static string IntermediateBuildFolderRoot_Text => ResourceManager.GetString(\"IntermediateBuildFolderRoot_Text\");\n    public static string IntermediateBuildFolder_FileChooserOption_Tooltip => ResourceManager.GetString(\"IntermediateBuildFolder_FileChooserOption_Tooltip\");\n    public static string BuildingRiderLinkMightFailWithNonASCIISymbols_Text => ResourceManager.GetString(\"BuildingRiderLinkMightFailWithNonASCIISymbols_Text\");\n    public static string DefaultBehaviorForRiderLinkUpdate_Text => ResourceManager.GetString(\"DefaultBehaviorForRiderLinkUpdate_Text\");\n    public static string BuildAndInstall_RadioButton_Text => ResourceManager.GetString(\"BuildAndInstall_RadioButton_Text\");\n    public static string ExtractOnly_RadioButton_Text => ResourceManager.GetString(\"ExtractOnly_RadioButton_Text\");\n    public static string InstallOrExtractRadio_Comment_Text => ResourceManager.GetString(\"InstallOrExtractRadio_Comment_Text\");\n    public static string AutoupdateRiderLink_CheckBox_Text => ResourceManager.GetString(\"AutoupdateRiderLink_CheckBox_Text\");\n    public static string Settings_AutoUpdate_Header_Text => ResourceManager.GetString(\"Settings_AutoUpdate_Header_Text\");\n    public static string Settings_General_Header_Text => ResourceManager.GetString(\"Settings_General_Header_Text\");\n    public static string Settings_ManualInstallation_Header_Text => ResourceManager.GetString(\"Settings_ManualInstallation_Header_Text\");\n    public static string DefaultLocationForRiderLinkInstallation_Text => ResourceManager.GetString(\"DefaultLocationForRiderLinkInstallation_Text\");\n    public static string InstallInEngine_Text => ResourceManager.GetString(\"InstallInEngine_Text\");\n    public static string InstallInGame_Text => ResourceManager.GetString(\"InstallInGame_Text\");\n  }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/Resources/Strings.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<root>\n    <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n        <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n            \n        </xsd:element>\n    </xsd:schema>\n    <resheader name=\"resmimetype\">\n        <value>text/microsoft-resx</value>\n    </resheader>\n    <resheader name=\"version\">\n        <value>1.3</value>\n    </resheader>\n    <resheader name=\"reader\">\n        <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n    </resheader>\n    <resheader name=\"writer\">\n        <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n    </resheader>\n    <data name=\"DeletingRiderLinkPlugin_Text\" xml:space=\"preserve\">\n        <value>Deleting RiderLink plugin</value>\n    </data>\n    <data name=\"FailedToBuildRiderLinkPlugin_Text\" xml:space=\"preserve\">\n        <value>Failed to build RiderLink plugin</value>\n    </data>\n    <data name=\"FailedToDeleteRiderLink_Text\" xml:space=\"preserve\">\n        <value>Failed to delete RiderLink</value>\n    </data>\n    <data name=\"IfThisOptionIsEnabledTheRiderLinkEditor_Text\" xml:space=\"preserve\">\n        <value>If this option is enabled, the RiderLink editor plugin will be automatically updated</value>\n    </data>\n    <data name=\"NonASCIICharactersInTheBuildDirectory_Text\" xml:space=\"preserve\">\n        <value>Non-ASCII characters are found in the build directory for RiderLink. If the build fails, try changing the temporary path in 'File | Settings | Languages &amp; Frameworks | Unreal Engine'.</value>\n    </data>\n    <data name=\"PathContainsNonASCIICharactersBuild_Text\" xml:space=\"preserve\">\n        <value>The path contains non-ASCII characters, which could cause the build to fail. Change the temp directory or use the 'Extract RiderLink…' action.</value>\n    </data>\n    <data name=\"RiderLinkIsDeleted_Text\" xml:space=\"preserve\">\n        <value>RiderLink is deleted</value>\n    </data>\n    <data name=\"UnrealLinkPluginSettings_Text\" xml:space=\"preserve\">\n        <value>UnrealLink plugin settings</value>\n    </data>\n    <data name=\"UnrealLinkPluginSettings_Title_Text\" xml:space=\"preserve\">\n        <value>Unreal Engine</value>\n    </data>\n    <data name=\"InstallRiderLinkInEngine_Text\" xml:space=\"preserve\">\n        <value>Install RiderLink in Engine</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"InstallRiderLinkPluginInEngineDescription_Text\" xml:space=\"preserve\">\n        <value>Install RiderLink plugin into the Engine.</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"InstallRiderLinkInGame_Text\" xml:space=\"preserve\">\n        <value>Install RiderLink in Game</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"InstallRiderLinkPluginInGameDescription_Text\" xml:space=\"preserve\">\n        <value>Install RiderLink plugin into every Game available in the Solution. If Rider will fail to install RiderLink plugin to any of the Game projects, It'll revert the installation process.</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"ExtractRiderLinkInEngine_Text\" xml:space=\"preserve\">\n        <value>Extract RiderLink in Engine</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"ExtractRiderLinkPluginInEngineDescription_Text\" xml:space=\"preserve\">\n        <value>Extract RiderLink plugin into the Engine in the Solution.\nNote: Use it for Unreal Engine version built from source only. It will not work with UE4 and UE5 from Epic Games Launcher.\nUse this option if installation of RiderLink plugin fails for some reason.</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"ExtractRiderLinkInGame_Text\" xml:space=\"preserve\">\n        <value>Extract RiderLink in Game</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"ExtractRiderLinkPluginInGameDescription_Text\" xml:space=\"preserve\">\n        <value>Extract RiderLink plugin into every Game available in the Solution.\nNote: It will not try to build RiderLink for your current project.\nUse this option if installation of RiderLink plugin fails for some reason.</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"RiderLinkInstallationIsInProgress_Text\" xml:space=\"preserve\">\n        <value>Installation is in progress...</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"UnrealEngine_Version_IsRequired_Title\" xml:space=\"preserve\">\n        <value>Unreal Engine {0}+ is required</value>\n        <comment>{0} &lt;- 'myMinimalSupportedVersion'; \n        </comment>\n    </data>\n    <data name=\"UnrealEngine_Version_IsRequired_Message\" xml:space=\"preserve\">\n        <value>&lt;html&gt;UnrealLink supports Unreal Engine versions starting with {0}&lt;/html&gt;</value>\n        <comment>{0} &lt;- 'myMinimalSupportedVersion'; \n        </comment>\n    </data>\n    <data name=\"RiderLinkPluginExtracted_Title\" xml:space=\"preserve\">\n        <value>RiderLink plugin extracted</value>\n    </data>\n    <data name=\"RiderLinkPluginExtracted_Message\" xml:space=\"preserve\">\n        <value>RiderLink plugin was extracted to: {0}</value>\n        <comment>{0} &lt;- 'pluginRootFolder'; \n        </comment>\n    </data>\n    <data name=\"RiderLinkPluginInstalled_Title\" xml:space=\"preserve\">\n        <value>RiderLink plugin installed</value>\n    </data>\n    <data name=\"RiderLinkPluginInstalled_Message\" xml:space=\"preserve\">\n        <value>RiderLink plugin was installed to: {0}</value>\n        <comment>{0} &lt;- 'pluginRootFolder'; \n        </comment>\n    </data>\n    <data name=\"RefreshProjectsAfterRiderLinkInstallation_Text\" xml:space=\"preserve\">\n        <value>Refresh projects after RiderLink installation</value>\n    </data>\n    <data name=\"FailedToPatchRiderLinkUplugin_Text\" xml:space=\"preserve\">\n        <value>Failed to patch RiderLink.uplugin</value>\n    </data>\n    <data name=\"FailedToPatchRiderLinkUplugin_Message\" xml:space=\"preserve\">\n        <value>Failed to set `EnableByDefault` to true in RiderLink.uplugin\nYou need to manually enable RiderLink in UnrealEditor</value>\n    </data>\n    <data name=\"RefreshingProjectFiles_Text\" xml:space=\"preserve\">\n        <value>Refreshing project files</value>\n    </data>\n    <data name=\"RiderLinkInstallationHasBeenCancelled_Text\" xml:space=\"preserve\">\n        <value>RiderLink installation has been cancelled</value>\n    </data>\n    <data name=\"FailedToBuildRiderLinkPluginFor__Text\" xml:space=\"preserve\">\n        <value>Failed to build RiderLink plugin for {0}</value>\n        <comment>{0} &lt;- 'engineRoot'; \n        </comment>\n    </data>\n    <data name=\"Reason_UatIsNotAvailable_Text\" xml:space=\"preserve\">\n        <value>Reason: {0} is not available at expected destination: {1}</value>\n        <comment>{0} &lt;- 'runUatName'; \n            {1} &lt;- 'pathToUat'; \n        </comment>\n    </data>\n    <data name=\"RefreshingProjectsFilesHasBeenCancelled_Text\" xml:space=\"preserve\">\n        <value>Refreshing projects files has been cancelled</value>\n    </data>\n    <data name=\"FailedToRefreshProjectFiles_Text\" xml:space=\"preserve\">\n        <value>Failed to refresh project files</value>\n    </data>\n    <data name=\"RiderLinkPluginWillNotBeVisibleInThe_Text\" xml:space=\"preserve\">\n        <value>RiderLink plugin will not be visible in the solution explorer</value>\n    </data>\n    <data name=\"NeedToRefreshProjectFilesManually_Text\" xml:space=\"preserve\">\n        <value>Need to refresh project files in the Unreal Editor or in the File Explorer with a context action for .uproject file 'Generate project files'</value>\n    </data>\n    <data name=\"IntermediateBuildFolderRoot_Text\" xml:space=\"preserve\">\n        <value>Intermediate folder to build RiderLink, before installing into the project</value>\n    </data>\n    <data name=\"IntermediateBuildFolder_FileChooserOption_Tooltip\" xml:space=\"preserve\">\n        <value>Path to intermediate folder to build RiderLink, before installing into the project</value>\n    </data>\n    <data name=\"BuildingRiderLinkMightFailWithNonASCIISymbols_Text\" xml:space=\"preserve\">\n        <value>Building RiderLink might fail if the path contains non-ASCII symbols.\n        If you have issues with building RiderLink that shows '???' symbols in the build Output window, try setting this variable to a folder without special characters (e.g. C:\\temp_folder), but make sure that current user has write access to this folder</value>\n    </data>\n    <data name=\"DefaultBehaviorForRiderLinkUpdate_Text\" xml:space=\"preserve\">\n        <value>Default behavior for auto-updating RiderLink plugin</value>\n    </data>\n    <data name=\"BuildAndInstall_RadioButton_Text\" xml:space=\"preserve\">\n        <value>Build and install the RiderLink plugin</value>\n    </data>\n    <data name=\"ExtractOnly_RadioButton_Text\" xml:space=\"preserve\">\n        <value>Extract the source code, don't build the RiderLink plugin</value>\n    </data>\n    <data name=\"InstallOrExtractRadio_Comment_Text\" xml:space=\"preserve\">\n        <value>Note: if the plugin is placed in the Engine project and the Engine is pre-built (e.g. installed from the Epic Games Launcher), it will always Install RiderLink, instead of extracting</value>\n    </data>\n    <data name=\"AutoupdateRiderLink_CheckBox_Text\" xml:space=\"preserve\">\n        <value>Automatically update RiderLink plugin for Unreal Editor</value>\n    </data>\n    <data name=\"Settings_AutoUpdate_Header_Text\" xml:space=\"preserve\">\n        <value>Auto-update</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"Settings_General_Header_Text\" xml:space=\"preserve\">\n        <value>General</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"Settings_ManualInstallation_Header_Text\" xml:space=\"preserve\">\n        <value>Manual Installation</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"DefaultLocationForRiderLinkInstallation_Text\" xml:space=\"preserve\">\n        <value>Default location for RiderLink installation</value>\n    </data>\n    <data name=\"InstallInEngine_Text\" xml:space=\"preserve\">\n        <value>Install in Engine</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n    <data name=\"InstallInGame_Text\" xml:space=\"preserve\">\n        <value>Install in Game</value>\n        <comment>Option Page: Name\n        </comment>\n    </data>\n</root>"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/RiderBackendToUnrealEditor.cs",
    "content": "using System;\nusing System.IO;\nusing System.Linq;\nusing JetBrains.Application.Parts;\nusing JetBrains.Application.Threading;\nusing JetBrains.Collections.Viewable;\nusing JetBrains.DataFlow;\nusing JetBrains.HabitatDetector;\nusing JetBrains.Lifetimes;\nusing JetBrains.Platform.RdFramework.Impl;\nusing JetBrains.ProjectModel;\nusing JetBrains.Rd;\nusing JetBrains.Rd.Base;\nusing JetBrains.Rd.Impl;\nusing JetBrains.Rd.Tasks;\nusing JetBrains.Util;\nusing JetBrains.Util.Threading;\nusing RiderPlugin.UnrealLink.Model;\nusing RiderPlugin.UnrealLink.Model.BackendUnreal;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\nusing RiderPlugin.UnrealLink.PluginInstaller;\n\nnamespace RiderPlugin.UnrealLink\n{\n    [SolutionComponent(InstantiationEx.LegacyDefault)]\n    public class RiderBackendToUnrealEditor\n    {\n        public RdEditorModel EditorModel { get; private set; }\n\n        private readonly RdDispatcher myDispatcher;\n        private readonly ILogger myLogger;\n        private readonly UnrealHost myUnrealHost;\n        private readonly UnrealLinkResolver myLinkResolver;\n        private readonly EditorNavigator myEditorNavigator;\n        private Lifetime myComponentLifetime;\n        private readonly IShellLocks myLocks;\n        private SequentialLifetimes myConnectionLifetimeProducer;\n\n        private static string GetPathToPortsFolder()\n        {\n            return PlatformUtil.RuntimePlatform switch\n            {\n                JetPlatform.Windows => Path.Combine(\n                    Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), \"..\", \"Local\", \"Jetbrains\",\n                    \"Rider\", \"Unreal\", \"Ports\"),\n                JetPlatform.MacOsX => Path.Combine(Environment.GetEnvironmentVariable(\"HOME\"), \"Library\",\n                    \"Logs\", \"Unreal Engine\", \"Ports\"),\n                _ => Path.Combine(Environment.GetEnvironmentVariable(\"HOME\") ?? \"\", \".config\",\n                    \"unrealEngine\", \"Ports\")\n            };\n        }\n\n        public LifetimeDefinition NestedLifetime() => myComponentLifetime.CreateNested();\n\n        public RiderBackendToUnrealEditor(Lifetime lifetime, IShellLocks locks, RdDispatcher dispatcher, ILogger logger,\n            UnrealHost unrealHost, UnrealLinkResolver linkResolver, EditorNavigator editorNavigator,\n            UnrealPluginDetector pluginDetector, ISolution solution)\n        {\n            myComponentLifetime = lifetime;\n            myLocks = locks;\n            myConnectionLifetimeProducer = new SequentialLifetimes(lifetime);\n            myDispatcher = dispatcher;\n            myLogger = logger;\n            myUnrealHost = unrealHost;\n            myLinkResolver = linkResolver;\n            myEditorNavigator = editorNavigator;\n\n            myLogger.Info(\"RiderBackendToUnrealEditor building started\");\n\n            pluginDetector.InstallInfoProperty.ForEachValue_NotNull(myComponentLifetime, (lt, pluginInfo) =>\n            {\n                var portDirectoryFullPath = GetPathToPortsFolder();\n\n                Directory.CreateDirectory(portDirectoryFullPath);\n\n                var projects = pluginInfo.ProjectPlugins.Select(it => it.ProjectName)\n                    .ToList();\n\n                solution.Locks.Tasks.Queue(myComponentLifetime, () =>\n                {\n                    var watcher = new FileSystemWatcher(portDirectoryFullPath)\n                    {\n                        NotifyFilter = NotifyFilters.FileName,\n                        Filter = \"*.uproject\",\n                        IncludeSubdirectories = false\n                    };\n\n                    RenamedEventHandler handler = (obj, fileSystemEvent) =>\n                    {\n                        var path = VirtualFileSystemPath.Parse(fileSystemEvent.FullPath,\n                            solution.GetInteractionContext());\n                        // Skip changes to temp files\n                        if (path.Name.StartsWith(\"~\")) return;\n\n                        if (projects.Contains(path.Name) && myComponentLifetime.IsAlive)\n                        {\n                            myLogger.Info(\n                                $\"FileSystemWatcher event {fileSystemEvent.ChangeType} found \\\"{path.Name}\\\"\");\n                            myLocks.ExecuteOrQueue(myComponentLifetime, \"UnrealLink.CreateProtocol\",\n                                () => CreateProtocols(path));\n                        }\n                    };\n\n                    watcher.Renamed += handler;\n\n                    lt.Bracket(() => { }, () => { watcher.Dispose(); });\n\n                    StartWatcher(watcher);\n                }, callerInfo: CallerInfo.CreateByCurrentContext());\n\n                foreach (var projectName in projects)\n                {\n                    var portFileFullPath =\n                        VirtualFileSystemPath.Parse(portDirectoryFullPath, InteractionContext.SolutionContext) /\n                        projectName;\n                    myLocks.ExecuteOrQueue(myComponentLifetime, \"UnrealLink.CreateProtocol\",\n                        () => CreateProtocols(portFileFullPath));\n                }\n            });\n\n            myLogger.Info(\"RiderBackendToUnrealEditor building finished\");\n        }\n\n        private static void StartWatcher(FileSystemWatcher watcher)\n        {\n            watcher.EnableRaisingEvents = true;\n        }\n\n        private void CreateProtocols(VirtualFileSystemPath portFileFullPath)\n        {\n            myLogger.Info($\"Trying to read port file {portFileFullPath}\");\n            if (!portFileFullPath.ExistsFile) return;\n\n            if (!ReadPortFile(portFileFullPath, out var text))\n            {\n                return;\n            }\n\n            if (!int.TryParse(text, out var port))\n            {\n                myLogger.Error($\"[UnrealLink]: Couldn't parse port from file:{portFileFullPath}, text:{text}\");\n                return;\n            }\n\n            var modelLifetime = myConnectionLifetimeProducer.Next();\n            var projectName = portFileFullPath.Name;\n\n            myLogger.Info($\"Creating SocketWire with port = {port}\");\n            var wire = new SocketWire.Client(modelLifetime, myDispatcher, port, \"UnrealEditorClient\");\n            wire.Connected.Advise(modelLifetime,\n                isConnected => myUnrealHost.PerformModelAction(riderModel =>\n                    riderModel.IsConnectedToUnrealEditor.SetValue(isConnected)\n                )\n            );\n\n            var protocol = new Protocol(\"UnrealEditorPlugin\", new Serializers(null, null),\n                new Identities(IdKind.Client), myDispatcher, wire, modelLifetime);\n\n            wire.Connected.View(modelLifetime, (lf, isConnected) =>\n            {\n                RdEditorModel model;\n                if (isConnected)\n                {\n                    myLogger.Info(\"Wire connected\");\n                    model = ResetModel(lf, protocol);\n                }\n                else\n                {\n                    myLogger.Info(\"Wire disconnected\");\n                    model = null;\n                }\n\n                EditorModel = model;\n            });\n        }\n\n        private bool ReadPortFile(VirtualFileSystemPath portFileFullPath, out string text)\n        {\n            text = \"\";\n            try\n            {\n                text = VirtualFileSystemPath.Parse(portFileFullPath.FullPath, InteractionContext.SolutionContext)\n                    .ReadAllText2().Text;\n            }\n            catch (Exception exception)\n            {\n                myLogger.Warn(\n                    $\"[UnrealLink]: Failed to read connection port from {portFileFullPath}, reason: {exception.Message}\");\n                return false;\n            }\n\n            return true;\n        }\n\n        void OnMessageReceived(RdRiderModel riderModel, UnrealLogEvent message)\n        {\n            riderModel.UnrealLog.Fire(message);\n        }\n\n        private RdEditorModel ResetModel(Lifetime lf, IProtocol protocol)\n        {\n            myUnrealHost.PerformModelAction(riderModel =>\n            {\n                riderModel.EditorId.SetValue(riderModel.EditorId.Value + 1);\n            });\n\n            var unrealModel = new RdEditorModel(lf, protocol);\n            UE4Library.RegisterDeclaredTypesSerializers(protocol.Serializers);\n\n            unrealModel.ConnectionInfo.Advise(lf, info =>\n                myUnrealHost.myModel.ConnectionInfo.SetValue(info)\n            );\n            \n            unrealModel.AllowSetForegroundWindow.SetAsync((lt, pid) =>\n            {\n                return myUnrealHost.PerformModelAction(riderModel =>\n                    riderModel.AllowSetForegroundWindow.Start(lt, pid)) as RdTask<bool>;\n            });\n\n            unrealModel.PlayStateFromEditor.Advise(lf, myUnrealHost.myModel.PlayStateFromEditor);\n\n            unrealModel.PlayModeFromEditor.Advise(lf, myUnrealHost.myModel.PlayModeFromEditor);\n\n            unrealModel.NotificationReplyFromEditor.Advise(lf, myUnrealHost.myModel.NotificationReplyFromEditor);\n\n            unrealModel.IsGameControlModuleInitialized.Advise(lf,\n                myUnrealHost.myModel.IsGameControlModuleInitialized.Set);\n\n            unrealModel.UnrealLog.Advise(lf,\n                logEvent =>\n                {\n                    myUnrealHost.PerformModelAction(riderModel => { OnMessageReceived(riderModel, logEvent); });\n                });\n\n            unrealModel.OnBlueprintAdded.Advise(lf, blueprintClass =>\n            {\n                //TO-DO\n            });\n\n            myUnrealHost.PerformModelAction(riderModel =>\n            {\n                riderModel.FilterLinkCandidates.SetAsync((_, candidates) =>\n                    RdTask.Successful(candidates\n                        .Select(request => myLinkResolver.ResolveLink(request, unrealModel.IsBlueprintPathName))\n                        .AsArray()));\n                riderModel.IsMethodReference.SetAsync((_, methodReference) =>\n                {\n                    var b = myEditorNavigator.IsMethodReference(methodReference);\n                    return RdTask.Successful(b);\n                });\n                riderModel.OpenBlueprint.Advise(lf, blueprintReference =>\n                    OnOpenedBlueprint(unrealModel, blueprintReference));\n\n                riderModel.NavigateToClass.Advise(lf,\n                    uClass => myEditorNavigator.NavigateToClass(uClass));\n\n                riderModel.NavigateToMethod.Advise(lf,\n                    methodReference => myEditorNavigator.NavigateToMethod(methodReference));\n\n                riderModel.RequestPlayFromRider.Advise(lf, unrealModel.RequestPlayFromRider);\n                riderModel.RequestPauseFromRider.Advise(lf, unrealModel.RequestPauseFromRider);\n                riderModel.RequestResumeFromRider.Advise(lf, unrealModel.RequestResumeFromRider);\n                riderModel.RequestStopFromRider.Advise(lf, unrealModel.RequestStopFromRider);\n                riderModel.RequestFrameSkipFromRider.Advise(lf, unrealModel.RequestFrameSkipFromRider);\n                riderModel.PlayModeFromRider.Advise(lf, unrealModel.PlayModeFromRider);\n            });\n\n            unrealModel.IsHotReloadAvailable.Advise(lf, myUnrealHost.myModel.IsHotReloadAvailable.Set);\n            unrealModel.IsHotReloadCompiling.Advise(lf, myUnrealHost.myModel.IsHotReloadCompiling.Set);\n            myUnrealHost.PerformModelAction(riderModel =>\n            {\n                riderModel.TriggerHotReload.Advise(lf, _ => unrealModel.TriggerHotReload());\n                riderModel.IsConnectedToUnrealEditor.WhenFalse(lf, _ =>\n                {\n                    riderModel.IsHotReloadAvailable.Set(false);\n                    riderModel.IsHotReloadCompiling.Set(false);\n                });\n            });\n\n            return unrealModel;\n        }\n\n        private void OnOpenedBlueprint(RdEditorModel unrealModel, BlueprintReference blueprintReference)\n        {\n            unrealModel.OpenBlueprint.Fire(blueprintReference);\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/RiderPlugin.UnrealLink.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <RootNamespace>RiderPlugin.UnrealLink</RootNamespace>\n    <InternalBuild Condition=\"'$(SolutionFileName)' != 'UnrealLink.sln'\">True</InternalBuild>\n    <InternalBuild Condition=\"$(InternalBuild) == ''\">False</InternalBuild>\n  </PropertyGroup>\n  <Import Project=\"Sdk.props\" Sdk=\"JetBrains.Toolset.MainSolution.Sdk\" Version=\"20200625.1.1.2\" Condition=\"$(InternalBuild)\" />\n  <Import Project=\"Sdk.props\" Sdk=\"Microsoft.NET.Sdk\" Condition=\"!$(InternalBuild)\" />\n  <PropertyGroup>\n    <AssemblyName>RiderPlugin.UnrealLink</AssemblyName>\n    <DefineConstants>$(DefineConstants);RIDER</DefineConstants>\n    <IsPackable>false</IsPackable>\n    <LanguageTargets>$(MSBuildToolsPath)\\Microsoft.CSharp.targets</LanguageTargets>\n    <NoWarn>NU1603</NoWarn>\n    <TargetFramework>net472</TargetFramework>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\".\\obj\\model\\*\\*.cs\" />\n    <Compile Update=\"Resources\\Strings.Designer.cs\">\n      <DesignTime>True</DesignTime>\n      <AutoGen>True</AutoGen>\n      <DependentUpon>Strings.resx</DependentUpon>\n      <DesignTimeSharedInput>True</DesignTimeSharedInput>\n    </Compile>\n  </ItemGroup>\n  <ItemGroup>\n    <EmbeddedResource Remove=\"Resources\\Strings.resx\"/>\n    <EmbeddedResource Include=\"Resources\\Strings.resx\">\n      <Generator>JetResourceGenerator</Generator>\n      <LastGenOutput>Strings.Designer.cs</LastGenOutput>\n    </EmbeddedResource>\n  </ItemGroup>\n  <ItemGroup Label=\"PackageReference\">\n    <PackageReference Include=\"JetBrains.Annotations\" />\n    <PackageReference Include=\"JetBrains.HabitatDetector\" />\n    <PackageReference Include=\"JetBrains.Lifetimes\" />\n    <PackageReference Include=\"JetBrains.RdFramework\" />\n    <PackageReference Include=\"Newtonsoft.Json\" />\n    <PackageReference Include=\"System.Memory\" />\n  </ItemGroup>\n  <Import Project=\"ManagedProject.Generated.Targets\" Condition=\"$(InternalBuild)\" />\n  <Import Project=\"$(DotNetSdkPath)\\Build\\SubplatformReference.ReSharperCpp_RiderPlugin.Props\" Condition=\"Exists('$(DotNetSdkPath)\\Build\\SubplatformReference.ReSharperCpp_RiderPlugin.Props')\" />\n  <Import Project=\"Sdk.targets\" Sdk=\"JetBrains.Toolset.MainSolution.Sdk\" Version=\"20200625.1.1.2\" Condition=\"$(InternalBuild)\" />\n  <Import Project=\"Sdk.targets\" Sdk=\"Microsoft.NET.Sdk\" Condition=\"!$(InternalBuild)\" />\n</Project>"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/Settings/UnrealLinkOptionsPage.cs",
    "content": "﻿using System.Linq;\nusing JetBrains.Application.Help;\nusing JetBrains.Application.Settings;\nusing JetBrains.Application.UI.Controls.FileSystem;\nusing JetBrains.Application.UI.Options;\nusing JetBrains.Application.UI.Options.OptionsDialog;\nusing JetBrains.Application.UI.Options.OptionsDialog.SimpleOptions.ViewModel;\nusing JetBrains.DataFlow;\nusing JetBrains.HabitatDetector;\nusing JetBrains.IDE.UI;\nusing JetBrains.IDE.UI.Extensions;\nusing JetBrains.IDE.UI.Extensions.PathActions;\nusing JetBrains.IDE.UI.Options;\nusing JetBrains.Lifetimes;\nusing JetBrains.ProjectModel;\nusing JetBrains.ReSharper.Psi.Cpp.Resources;\nusing JetBrains.ReSharper.Feature.Services.OptionPages.CodeEditing;\nusing JetBrains.ReSharper.Resources.Settings;\nusing JetBrains.ReSharper.Resources.Shell;\nusing JetBrains.Rider.Model.UIAutomation;\nusing JetBrains.Util;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\nusing RiderPlugin.UnrealLink.PluginInstaller;\nusing RiderPlugin.UnrealLink.Resources;\nusing RiderPlugin.UnrealLink.Utils;\nusing Strings = RiderPlugin.UnrealLink.Resources.Strings;\n\nnamespace RiderPlugin.UnrealLink.Settings\n{\n    public enum InstallOrExtract\n    {\n        Install,\n        Extract\n    }\n    [SettingsKey(typeof(CodeEditingSettings),\n        typeof(Strings),\n        nameof(Strings.UnrealLinkPluginSettings_Text))]\n    public class UnrealLinkSettings\n    {\n        [SettingsEntry(false,\n            typeof(Strings),\n            nameof(Strings.IfThisOptionIsEnabledTheRiderLinkEditor_Text))]\n        public bool AutoUpdateRiderLinkPlugin;\n\n        [SettingsEntry(null,\n            typeof(Strings),\n            nameof(Strings.IntermediateBuildFolderRoot_Text))]\n        public FileSystemPath IntermediateBuildFolderRoot;\n\n        [SettingsEntry(InstallOrExtract.Install,\n            typeof(Strings),\n            nameof(Strings.DefaultBehaviorForRiderLinkUpdate_Text))]\n        public InstallOrExtract DefaultUpdateRiderLinkBehavior;\n\n        [SettingsEntry(PluginInstallLocation.Engine,\n            typeof(Strings),\n            nameof(Strings.DefaultLocationForRiderLinkInstallation_Text))]\n        public InstallOrExtract DefaultLocationForRiderLink;\n    }\n    \n\n    [OptionsPage(PID, Name, typeof(CppThemedIcons.Unreal), Sequence = 0.02,\n        ParentId = CodeEditingPage.PID, SearchTags = new []{\"Unreal Engine\", \"UnrealLink\", \"RiderLink\"},\n        NameResourceType = typeof(Strings),\n        HelpKeyword = HelpId.Settings_Languages_Unreal_Engine,\n        NameResourceName = nameof(Strings.UnrealLinkPluginSettings_Title_Text))]\n    public class UnrealLinkOptionsPage : BeSimpleOptionsPage\n    {\n      // Keep these in sync with the values in the front end!\n        public const string PID = \"UnrealLinkOptions\";\n        public const string Name = \"Unreal Engine\";\n\n        public UnrealLinkOptionsPage(\n            Lifetime lifetime,\n            OptionsPageContext optionsPageContext,\n            OptionsSettingsSmartContext optionsSettingsSmartContext,\n            IconHostBase iconHost,\n            ICommonFileDialogs commonFileDialogs)\n            : base(lifetime, optionsPageContext, optionsSettingsSmartContext)\n        {\n            AddTmpDirChooserOption(lifetime, iconHost, commonFileDialogs);\n            AddAutoUpdateOption(lifetime);\n            SetupInstallButtons();\n        }\n\n        private void AddAutoUpdateOption(Lifetime lifetime)\n        {\n            AddHeader(Strings.Settings_AutoUpdate_Header_Text);\n            var autoUpdateCheckbox = AddBoolOption((UnrealLinkSettings k) => k.AutoUpdateRiderLinkPlugin,\n                Strings.AutoupdateRiderLink_CheckBox_Text);\n            using (Indent())\n            {\n                AddRadioOption(\n                    (UnrealLinkSettings s) => s.DefaultUpdateRiderLinkBehavior,\n                    /*Localized*/ string.Empty,\n                    new RadioOptionPoint(InstallOrExtract.Install, Strings.BuildAndInstall_RadioButton_Text),\n                    new RadioOptionPoint(InstallOrExtract.Extract, Strings.ExtractOnly_RadioButton_Text));\n                AddCommentText(Strings.InstallOrExtractRadio_Comment_Text);\n                AddRadioOption(\n                    (UnrealLinkSettings s) => s.DefaultLocationForRiderLink,\n                    /*Localized*/ string.Empty,\n                    new RadioOptionPoint(PluginInstallLocation.Engine, Strings.InstallInEngine_Text),\n                    new RadioOptionPoint(PluginInstallLocation.Game, Strings.InstallInGame_Text));\n\n            }\n        }\n\n        private void AddTmpDirChooserOption(Lifetime lifetime, IconHostBase iconHost, ICommonFileDialogs commonFileDialogs)\n        {\n            AddHeader(Strings.Settings_General_Header_Text);\n            var intermediateBuildFolderProperty = new Property<string>( \"IntermediateBuildFolderProperty\");\n      \n            var intermediateBuildFolder = \n                OptionsSettingsSmartContext.GetValue((UnrealLinkSettings s) => s.IntermediateBuildFolderRoot);\n\n            var defaultBuildPath = VirtualFileSystemDefinition.GetTempPath(InteractionContext.SolutionContext);\n            intermediateBuildFolderProperty.Value = intermediateBuildFolder.IsNullOrEmpty() ? defaultBuildPath.FullPath : intermediateBuildFolder.FullPath;\n      \n            intermediateBuildFolderProperty.Change.Advise_NoAcknowledgement(lifetime, args =>\n            {\n                var newValue = FileSystemPath.Parse(args.New);\n                \n                OptionsSettingsSmartContext.SetValue((UnrealLinkSettings s) => s.IntermediateBuildFolderRoot, (newValue.IsValidOnCurrentOS && newValue.IsAbsolute)? newValue : defaultBuildPath.ToNativeFileSystemPath());\n            });\n\n            AddControl(Strings.IntermediateBuildFolderRoot_Text.GetBeLabel());\n            AddFolderChooserOption(\n                intermediateBuildFolderProperty,\n                defaultBuildPath.ToNativeFileSystemPath(),\n                defaultBuildPath.ToNativeFileSystemPath(),\n                iconHost,\n                commonFileDialogs,\n                null,\n                null,\n                new[] { (BeSimplePathValidationRules.SHOULD_BE_ABSOLUTE, ValidationStates.validationWarning) },\n                path => CheckForNonAsciiSymbols(path));\n      \n            AddCommentText(Strings.BuildingRiderLinkMightFailWithNonASCIISymbols_Text);\n        }\n\n        private (string, ValidationStates) CheckForNonAsciiSymbols(FileSystemPath path)\n        {\n            if (PlatformUtil.RuntimePlatform == JetPlatform.Windows && path.FullPath.Any(c => c >= 128))\n            {\n                return (Strings.PathContainsNonASCIICharactersBuild_Text, ValidationStates.validationWarning);\n            }\n            \n            return (\"\", ValidationStates.validationPassed);\n        }\n\n        private void SetupInstallButtons()\n        {\n            AddHeader(Strings.Settings_ManualInstallation_Header_Text);\n            var owner = Shell.Instance.GetComponents<RealSolutionManagerBase>()\n                .FirstOrDefault(it => it.CurrentSolution != null);\n            var solution = owner?.CurrentSolution;\n            var unrealPluginInstaller = solution?.GetComponent<UnrealPluginInstaller>();\n\n            var installInEngineButton = AddButton(Strings.InstallRiderLinkInEngine_Text, () =>\n            {\n                unrealPluginInstaller?.HandleManualInstallPlugin(\n                    ModelUtils.CreateInstallPluginDescription(PluginInstallLocation.Engine, ForceInstall.Yes)\n                    );\n            });\n            AddCommentText(Strings.InstallRiderLinkPluginInEngineDescription_Text);\n\n            var installInGameButton = AddButton(Strings.InstallRiderLinkInGame_Text, () =>\n            {\n                unrealPluginInstaller?.HandleManualInstallPlugin(\n                    ModelUtils.CreateInstallPluginDescription(PluginInstallLocation.Game, ForceInstall.Yes)\n                    );\n            });\n            AddCommentText(Strings.InstallRiderLinkPluginInGameDescription_Text);\n\n            var extractInEngineButton = AddButton(Strings.ExtractRiderLinkInEngine_Text, () =>\n            {\n                unrealPluginInstaller?.HandleManualInstallPlugin(\n                    ModelUtils.CreateInstallPluginDescription(PluginInstallLocation.Engine, ForceInstall.Yes, false)\n                );\n            });\n            AddCommentText(Strings.ExtractRiderLinkPluginInEngineDescription_Text);\n\n            var extractInGameButton = AddButton(Strings.ExtractRiderLinkInGame_Text, () =>\n            {\n                unrealPluginInstaller?.HandleManualInstallPlugin(\n                    ModelUtils.CreateInstallPluginDescription(PluginInstallLocation.Game, ForceInstall.Yes, false)\n                );\n            });\n            AddCommentText(Strings.ExtractRiderLinkPluginInGameDescription_Text);\n\n            var installationInProgressText = AddText(Strings.RiderLinkInstallationIsInProgress_Text);\n            installationInProgressText.Visible.Value = ControlVisibility.Hidden;\n\n            var unrealHost = solution?.GetComponent<UnrealHost>();\n            unrealHost?.myModel.RiderLinkInstallationInProgress.Advise(unrealPluginInstaller.Lifetime,\n                installationInProgress =>\n                {\n                    installInEngineButton.Enabled.Value = !installationInProgress;\n                    foreach (var beControl in installInEngineButton.Descendants<BeControl>())\n                    {\n                        beControl.Enabled.Value = !installationInProgress;\n                    }\n                    installInGameButton.Enabled.Value = !installationInProgress;\n                    foreach (var beControl in installInGameButton.Descendants<BeControl>())\n                    {\n                        beControl.Enabled.Value = !installationInProgress;\n                    }\n                    extractInEngineButton.Enabled.Value = !installationInProgress;\n                    foreach (var beControl in extractInEngineButton.Descendants<BeControl>())\n                    {\n                        beControl.Enabled.Value = !installationInProgress;\n                    }\n                    extractInGameButton.Enabled.Value = !installationInProgress;\n                    foreach (var beControl in extractInGameButton.Descendants<BeControl>())\n                    {\n                        beControl.Enabled.Value = !installationInProgress;\n                    }\n                    installationInProgressText.Visible.Value = installationInProgress ?\n                        ControlVisibility.Visible :\n                        ControlVisibility.Hidden;\n                }\n            );\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/UnrealEngineAssetsNavigationProvider.cs",
    "content": "using JetBrains.Application.Parts;\nusing JetBrains.ProjectModel;\nusing JetBrains.ReSharper.Feature.Services.Cpp.UE4.UEAsset.Search;\nusing JetBrains.Util;\nusing RiderPlugin.UnrealLink.Model;\n\nnamespace RiderPlugin.UnrealLink\n{\n\t[SolutionComponent(Instantiation.DemandAnyThreadUnsafe)]\n\tpublic class UnrealEngineAssetsNavigationProvider : IUnrealEngineNavigationProvider\n\t{\n\t\tprivate readonly RiderBackendToUnrealEditor myBackendToUnrealEditor;\n\n\t\tpublic UnrealEngineAssetsNavigationProvider(RiderBackendToUnrealEditor backendToUnrealEditor)\n\t\t{\n\t\t\tmyBackendToUnrealEditor = backendToUnrealEditor;\n\t\t}\n\t\t\n\t\tpublic bool Navigate(VirtualFileSystemPath assetPath, string guid)\n\t\t{\n\t\t\tvar model = myBackendToUnrealEditor.EditorModel;\n\t\t\tif (model == null)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t\n\t\t\tmodel.OpenBlueprint.Fire(new BlueprintReference(new FString(assetPath.NormalizeSeparators(FileSystemPathEx.SeparatorStyle.Unix)), new FString(guid ?? \"\")));\n\t\t\treturn true;\n\t\t}\n\t}\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/UnrealHost.cs",
    "content": "using System;\nusing JetBrains.Application.Parts;\nusing JetBrains.Application.Threading;\nusing JetBrains.DataFlow;\nusing JetBrains.Lifetimes;\nusing JetBrains.ProjectModel;\nusing JetBrains.Rd.Base;\nusing JetBrains.ReSharper.Feature.Services.Protocol;\nusing JetBrains.ReSharper.Psi.Cpp.UE4;\nusing RiderPlugin.UnrealLink.Model;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\n\nnamespace RiderPlugin.UnrealLink\n{\n    [SolutionComponent(InstantiationEx.LegacyDefault)]\n    public class UnrealHost\n    {\n        private readonly Lifetime myLifetime;\n\n        // TO-DO: frontend isn't up in backend tests\n        private readonly bool myIsInTests;\n\n        public readonly RdRiderModel myModel;\n\n        public UnrealHost(Lifetime lifetime, ISolution solution, IShellLocks locks, ICppUE4SolutionDetector solutionDetector)\n        {\n            myIsInTests = locks.Dispatcher.IsAsyncBehaviorProhibited;\n            if (myIsInTests)\n                return;\n\n            myLifetime = lifetime;   \n            myModel = solution.GetProtocolSolution().GetRdRiderModel();\n            solutionDetector.IsUnrealSolution.Change.Advise_HasNew(myLifetime, args =>\n            {\n                myModel.IsUnrealEngineSolution.Set(args.New);\n                myModel.IsUproject.Set(args.New && solutionDetector.SupportRiderProjectModel == CppUE4ProjectModelSupportMode.UprojectOpened);\n                myModel.IsPreBuiltEngine.Set(args.New && !solutionDetector.UnrealContext.Value.IsBuiltFromSource);\n            });\n            \n            if (myModel.TryGetProto() is {} protocol)\n            {\n                UE4Library.RegisterDeclaredTypesSerializers(protocol.Serializers);\n            }\n        }\n\n        public void PerformModelAction(Action<RdRiderModel> action)\n        {\n            if (myIsInTests)\n                return;\n\n            action(myModel);\n        }\n        \n        public T PerformModelAction<T>(Func<RdRiderModel, T> action)\n        {\n            \n            if (myIsInTests)\n                return default;\n\n            return action(myModel);\n        }\n\n        public T GetValue<T>(Func<RdRiderModel, T> getter)\n        {\n            return getter(myModel);\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/UnrealLiveCodingBuildRunner.cs",
    "content": "using System.Collections.Generic;\nusing System.Threading.Tasks;\nusing JetBrains.Application.Parts;\nusing JetBrains.Collections.Viewable;\nusing JetBrains.DataFlow;\nusing JetBrains.Lifetimes;\nusing JetBrains.Platform.BuildEvents;\nusing JetBrains.Platform.MsBuildHost.Models;\nusing JetBrains.ProjectModel;\nusing JetBrains.ProjectModel.Features.SolutionBuilders;\nusing JetBrains.ProjectModel.Tasks.Listeners;\nusing JetBrains.ReSharper.Feature.Services.Cpp.UE4;\nusing JetBrains.ReSharper.Resources.Shell;\nusing JetBrains.ReSharperCpp.RiderPlugin.Build;\nusing RiderPlugin.UnrealLink.Model;\n\nnamespace RiderPlugin.UnrealLink;\n\n[SolutionComponent(Instantiation.DemandAnyThreadSafe)]\npublic class UnrealLiveCodingBuildRunner(\n    Lifetime lifetime,\n    ISolution solution,\n    CppUE4SolutionDetector solutionDetector,\n    CppUE4UbtBuildRunner buildRunner)\n    : ISolutionBuilderRunner, ISolutionLoadTasksSolutionStructureReadyListener2\n{\n    public IProperty<bool> IsAvailable { get; } = new Property<bool>(\"IsAvailable\", false);\n\n    public bool IsDefault()\n    {\n        return true;\n    }\n\n    public double Priority => 120;\n    public bool IsIncremental => false;\n    public IProperty<bool> IsReady { get; } = new Property<bool>(\"IsReady\", true);\n\n    public void ExecuteBuildRequest(SolutionBuilderRequest request)\n    {\n        var backendToUnrealEditor = solution.GetComponent<RiderBackendToUnrealEditor>();\n        var editorModel = backendToUnrealEditor.EditorModel;\n        if (!request.BuildWholeSolution || request.BuildSessionTarget != BuildTarget.Instance ||\n            editorModel == null || !editorModel.IsHotReloadAvailable.HasTrueValue())\n        {\n            buildRunner.ExecuteBuildRequest(request);\n            return;\n        }\n        \n        var def = Lifetime.Define(request.Lifetime);\n        request.State.Value = BuildRunState.Running;\n        var parser = new CppUE4UbtBuildOutputParser();\n        var saver = new InFileBuildSessionSaver(def.Lifetime, request.EventsStoragePath.FullPath,\n            InFileBuildSessionSaver.EnabledFeatures.Events | InFileBuildSessionSaver.EnabledFeatures.Projects);\n\n        editorModel.IsHotReloadCompiling.Change.AdviseUntil(def.Lifetime, val =>\n        {\n            if (!val)\n            {\n                // Wait for last live coding messages\n                def.Lifetime.StartBackgroundAsync(async () =>\n                {\n                    await Task.Delay(100, def.Lifetime);\n                    await def.Lifetime.StartMainRead(() =>\n                    {\n                        request.State.Value = BuildRunState.Completed;\n                    });\n                });\n                return true;\n            }\n\n            return false;\n        });\n        editorModel.UnrealLog.Advise(def.Lifetime, logEvent =>\n        {\n            var category = logEvent.Info.Category.Data;\n            if (category == \"LogLiveCoding\")\n            {\n                \n                var outputKind = logEvent.Info.Type switch\n                {\n                    VerbosityType.Error => OutputKind.Error,\n                    VerbosityType.Warning => OutputKind.Warning,\n                    _ => OutputKind.Message\n                };\n                var message = logEvent.Text.Data;\n                switch (outputKind)\n                {\n                    case OutputKind.Error:\n                        request.AddError(message);\n                        break;\n                    case OutputKind.Warning:\n                        request.AddWarning(message);\n                        break;\n                }\n                \n                request.AddOutputBuildMessage(outputKind, message);\n                return;\n            }\n            \n            parser.ConsumeUnrealBuildToolMessage(request, null, new RdProjectId(-1), logEvent.Text.Data, saver);\n        });\n        editorModel.TriggerHotReload();\n\n        request.ContinueWith(def.Lifetime, _ =>\n        {\n            def.Terminate();\n        });\n    }\n\n    public void Abort(SolutionBuilderRequest request)\n    {\n    }\n\n    public bool CanExecuteCustomTarget => false;\n    public int GetSkippedProjectsCount(SolutionBuilderRequest request)\n    {\n        return 0;\n    }\n\n    IEnumerable<SolutionLoadTasksListenerExecutionStep> ISolutionLoadTasksSolutionStructureReadyListener2.OnSolutionLoadSolutionStructureReady(OuterLifetime loadLifetime)\n    {\n        yield return SolutionLoadTasksListenerExecutionStep.YieldToMainThreadGuarded;\n        solutionDetector.IsUnrealSolution.FlowInto(lifetime, IsAvailable);\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/Utils/CmdUtils.cs",
    "content": "﻿using System.Reflection;\nusing JetBrains.Annotations;\nusing JetBrains.HabitatDetector;\nusing JetBrains.Lifetimes;\nusing JetBrains.ReSharper.Feature.Services.Cpp.ProjectModel.UE4;\nusing JetBrains.Util;\n\nnamespace RiderPlugin.UnrealLink.Utils\n{\n    public static class CmdUtils\n    {\n        public static uint RunCommandWithLock(Lifetime lifetime, [NotNull] InvokeChildProcess.StartInfo startinfo, [CanBeNull] ILogger logger)\n        {\n            lock (HACK_getMutexForUBT())\n            {\n                return InvokeChildProcess.InvokeCore(lifetime, startinfo,\n                    InvokeChildProcess.SyncAsync.Sync, logger).Result;\n            }\n        }\n        \n        public static string GetPlatformCmdExtension()\n        {\n            switch (PlatformUtil.RuntimePlatform)\n            {\n                case JetPlatform.Windows:\n                    return \"bat\";\n                case JetPlatform.MacOsX:\n                    return \"command\";\n                default:\n                    return \"sh\";\n            }\n        }\n        \n        public static InvokeChildProcess.StartInfo GetProcessStartInfo([NotNull] InvokeChildProcess.PipeStreams pipeStreams,\n            [NotNull] VirtualFileSystemPath cmd, [CanBeNull] VirtualFileSystemPath workingDir, params string[] args)\n        {\n            var command = GetPlatformCommand(cmd);\n            var commandLine = GetPlatformCommandLine(cmd, args);\n\n            var startInfo = new InvokeChildProcess.StartInfo(command.ToNativeFileSystemPath())\n            {\n                Arguments = commandLine,\n                Pipe = pipeStreams,\n                CurrentDirectory = workingDir?.ToNativeFileSystemPath()\n            };\n            \n            return startInfo;\n        }\n\n        private static VirtualFileSystemPath GetPlatformCommand([NotNull] VirtualFileSystemPath command)\n        {\n            return PlatformUtil.RuntimePlatform == JetPlatform.Windows ? GetPathToCmd() : command;\n        }\n        \n        private static CommandLineBuilderJet GetPlatformCommandLine([NotNull] VirtualFileSystemPath command, params string[] args)\n        {\n            var commandLine = new CommandLineBuilderJet();\n            if (PlatformUtil.RuntimePlatform == JetPlatform.Windows)\n            {\n                commandLine.AppendFileName(command.ToNativeFileSystemPath());\n            }\n\n            foreach (var arg in args)\n            {\n                commandLine.AppendSwitch(arg);\n            }\n\n            if (PlatformUtil.RuntimePlatform == JetPlatform.Windows)\n            {\n                return new CommandLineBuilderJet().AppendSwitch(\"/C\")\n                    .AppendSwitch($\"\\\"{commandLine}\\\"\");\n            }\n\n            return commandLine;\n        }\n\n        private static VirtualFileSystemPath GetPathToCmd()\n        {\n            var comspec = InteractionContext.SolutionContext.EnvironmentInteraction.GetEnvironmentVariable(\"COMSPEC\");\n            var pathToCmd = VirtualFileSystemPath.Parse(comspec, InteractionContext.SolutionContext);\n            return pathToCmd;\n        }\n        \n        private static object HACK_getMutexForUBT()\n        {\n            var field =\n                typeof(CppUE4UbtRunner).GetField(\"ourLocker\", BindingFlags.Static | BindingFlags.NonPublic);\n            return field.GetValue(null);\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/Utils/FsUtils.cs",
    "content": "﻿using System;\nusing JetBrains.Util;\n\nnamespace RiderPlugin.UnrealLink.Utils\n{\n    public class DeleteTempFolders : IDisposable\n    {\n        private readonly VirtualFileSystemPath myTempFolder;\n\n        public DeleteTempFolders(VirtualFileSystemPath tempFolder)\n        {\n            myTempFolder = tempFolder;\n        }\n\n        public void Dispose()\n        {\n            myTempFolder.Delete();\n        }\n    }\n    \n    public class BackupDir\n    {\n        private readonly VirtualFileSystemPath myOldDir;\n        private readonly VirtualFileSystemPath myBackupDir;\n\n        public BackupDir(VirtualFileSystemPath oldDir, string backupFolderPrefix)\n        {\n            myOldDir = oldDir;\n            myBackupDir = VirtualFileSystemDefinition.CreateTemporaryDirectory(InteractionContext.SolutionContext, null, backupFolderPrefix);\n            myOldDir.CopyDirectory(myBackupDir);\n            myOldDir.Delete();\n        }\n\n        public void Restore()\n        {\n            myOldDir.Delete();\n            myBackupDir.CopyDirectory(myOldDir);\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/Utils/ModelUtils.cs",
    "content": "using System.Collections.Generic;\nusing RiderPlugin.UnrealLink.Model.FrontendBackend;\n\nnamespace RiderPlugin.UnrealLink.Utils;\n\npublic static class ModelUtils\n{\n    public static InstallPluginDescription CreateInstallPluginDescription(PluginInstallLocation installLocation, ForceInstall forceInstall, bool shouldBeBuilt = true)\n    {\n        return new InstallPluginDescription(installLocation, forceInstall, shouldBeBuilt, [], []);\n    }\n        \n    public static InstallPluginDescription CreateInstallPluginDescription(PluginInstallLocation installLocation, ForceInstall forceInstall, bool shouldBeBuilt, List<string> selectedUprojectPaths, List<string> unselectedUprojectPaths)\n    {\n        return new InstallPluginDescription(installLocation, forceInstall, shouldBeBuilt, selectedUprojectPaths, unselectedUprojectPaths);\n    }\n}"
  },
  {
    "path": "src/dotnet/RiderPlugin.UnrealLink/ZoneMarker.cs",
    "content": "﻿using JetBrains.Application.BuildScript.Application.Zones;\nusing JetBrains.ReSharper.Feature.Services.Daemon;\nusing JetBrains.ReSharper.Psi;\nusing JetBrains.Rider.Backend.Env;\nusing JetBrains.Rider.Backend.Product;\n\nnamespace RiderPlugin.UnrealLink\n{\n    [ZoneMarker]\n    public class ZoneMarker :\n        IRequire<ILanguageCppZone>,\n        IRequire<IUnrealEngineZone>,\n        IRequire<DaemonZone>,\n        IRequire<IRiderFeatureZone>,\n        IRequire<IRiderProductEnvironmentZone>\n    {\n    }\n}"
  },
  {
    "path": "src/dotnet/Subplatform.Root",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<SubplatformInfo xmlns=\"urn:schemas-jetbrains-com:build-subplatform-info\" CompanyNameHuman=\"JetBrains\" IsGitSubplatform=\"true\">\n    <SubplatformInfo.SubplatformReferences>\n        <SubplatformReference Name=\"ReSharperCpp\\RiderPlugin\" />\n        <SubplatformReference Name=\"Plugins\\_UnrealLink.Pregenerated\\BackendModel\" />\n    </SubplatformInfo.SubplatformReferences>\n</SubplatformInfo>"
  },
  {
    "path": "src/dotnet/Versions.props",
    "content": "<Project>\n  <PropertyGroup>\n    <WaveVersionBase>$(SdkVersion.Substring(2,2))$(SdkVersion.Substring(5,1))</WaveVersionBase>\n    <WaveVersion>$(WaveVersionBase).0.0$(SdkVersion.Substring(8))</WaveVersion>\n  </PropertyGroup>\n</Project>"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/UnrealLinkBundle.kt",
    "content": "package com.jetbrains.rider\n\nimport com.intellij.DynamicBundle\nimport org.jetbrains.annotations.Nls\nimport org.jetbrains.annotations.NonNls\nimport org.jetbrains.annotations.PropertyKey\nimport java.util.function.Supplier\n\n@NonNls\nconst val BUNDLE = \"messages.UnrealLinkBundle\"\n\nobject UnrealLinkBundle : DynamicBundle(BUNDLE) {\n    @JvmStatic\n    @Nls\n    fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String {\n        return getMessage(key, *params)\n    }\n\n    @JvmStatic\n    fun messagePointer(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): Supplier<String> {\n        return getLazyMessage(key, *params)\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/RiderLinkInstallService.kt",
    "content": "package com.jetbrains.rider.plugins.unreal\n\nimport com.intellij.execution.filters.TextConsoleBuilderFactory\nimport com.intellij.execution.impl.ConsoleViewImpl\nimport com.intellij.execution.ui.ConsoleViewContentType\nimport com.intellij.icons.AllIcons\nimport com.intellij.openapi.actionSystem.ActionManager\nimport com.intellij.openapi.actionSystem.DefaultActionGroup\nimport com.intellij.openapi.components.Service\nimport com.intellij.openapi.components.service\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.ui.SimpleToolWindowPanel\nimport com.intellij.openapi.util.Disposer\nimport com.intellij.openapi.wm.ToolWindow\nimport com.intellij.openapi.wm.impl.status.StatusBarUtil\nimport com.intellij.ui.content.Content\nimport com.jetbrains.rd.platform.util.idea.LifetimedService\nimport com.jetbrains.rd.util.getLogger\nimport com.jetbrains.rd.util.info\nimport com.jetbrains.rd.util.lifetime.Lifetime\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.build.BuildToolWindowService\nimport com.jetbrains.rider.plugins.unreal.actions.CancelRiderLinkInstallAction\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.ContentType\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.InstallMessage\nimport java.awt.BorderLayout\nimport java.awt.CardLayout\nimport javax.swing.JPanel\n\n@Service(Service.Level.PROJECT)\nclass RiderLinkInstallService(\n    val project: Project\n) : LifetimedService() {\n    companion object {\n        fun getInstance(project: Project): RiderLinkInstallService = project.service()\n        val logger = getLogger<RiderLinkInstallService>()\n    }\n\n    private var context: RiderLinkInstallContext? = null\n    private val buildToolWindowFactory = project.getService(BuildToolWindowService::class.java)\n\n\n    fun getOrCreateRiderLinkInstallContext(): RiderLinkInstallContext {\n        logger.info { \"[UnrealLink]: ${::getOrCreateRiderLinkInstallContext.name}\" }\n        val currentContext = context\n        if (currentContext != null)\n            return currentContext\n        val toolWindow = buildToolWindowFactory.getOrRegisterToolWindow(project)\n        val contentManager = toolWindow.contentManager\n\n        val panel = RiderLinkInstallPanel(project, this, serviceLifetime)\n        val toolWindowContent = contentManager.factory.createContent(null, UnrealLinkBundle.message(\"RiderLink.InstallProgress.text.title\"), true).apply {\n            StatusBarUtil.setStatusBarInfo(project, \"Install\")\n            component = panel\n            panel.toolbar = createToolbarPanel(panel)\n            isCloseable = false\n            icon = AllIcons.Actions.Install\n        }\n        contentManager.addContent(toolWindowContent)\n        val ctx = RiderLinkInstallContext(toolWindow, toolWindowContent, panel)\n        context = ctx\n        return ctx\n    }\n\n    private fun createToolbarPanel(mainPanel: RiderLinkInstallPanel): JPanel {\n        logger.info { \"[UnrealLink]: ${::createToolbarPanel.name}\" }\n        val buildActionGroup = DefaultActionGroup().apply {\n            add(CancelRiderLinkInstallAction())\n        }\n        val panel = JPanel(BorderLayout())\n        val toolbar = ActionManager.getInstance().createActionToolbar(\"UnrealLink.BuildRiderLinkToolbar\", buildActionGroup, false)\n        toolbar.targetComponent = mainPanel\n        panel.add(toolbar.component, BorderLayout.WEST)\n\n        return panel\n    }\n}\n\nfun ConsoleViewImpl.println(text: String, type: ConsoleViewContentType) {\n    print(text, type)\n    print(\"\\n\", type)\n}\n\n\nclass RiderLinkInstallPanel(\n    project: Project,\n    riderLinkInstallService: RiderLinkInstallService,\n    lifetime: Lifetime\n) : SimpleToolWindowPanel(false) {\n    companion object {\n        val logger = getLogger<RiderLinkInstallPanel>()\n    }\n    private val console = TextConsoleBuilderFactory.getInstance().createBuilder(project).console as ConsoleViewImpl\n    private val container: JPanel\n\n    init {\n        logger.info { \"[UnrealLink]: init\" }\n\n        Disposer.register(riderLinkInstallService, console)\n        setProvideQuickActions(true)\n        container = JPanel(CardLayout()).apply {\n            add(console.component, \"console\")\n        }\n        setContent(container)\n        lifetime.onTermination {\n            console.dispose()\n        }\n    }\n\n    fun writeMessage(message: InstallMessage) {\n        logger.info { \"[UnrealLink]: ${::writeMessage.name} $message\" }\n        when (message.type) {\n            ContentType.Normal -> console.println(message.text, ConsoleViewContentType.NORMAL_OUTPUT)\n            ContentType.Error -> console.println(message.text, ConsoleViewContentType.ERROR_OUTPUT)\n        }\n    }\n\n    fun clear() {\n        logger.info { \"[UnrealLink]: ${::clear.name}\" }\n        console.clear()\n    }\n}\n\nclass RiderLinkInstallContext(\n    private val toolWindow: ToolWindow,\n    private val content: Content,\n    private val panel: RiderLinkInstallPanel\n) {\n    companion object {\n        val logger = getLogger<RiderLinkInstallContext>()\n    }\n    private fun makeActive() {\n        logger.info { \"[UnrealLink]: ${::makeActive.name}\" }\n        toolWindow.contentManager.setSelectedContent(content)\n    }\n\n    fun showToolWindowIfHidden() {\n        logger.info { \"[UnrealLink]: ${::showToolWindowIfHidden.name} toolWindow.isActive ${toolWindow.isActive}\" }\n        if (!toolWindow.isActive)\n            toolWindow.activate {}\n        makeActive()\n    }\n\n    fun writeMessage(message: InstallMessage) {\n        logger.info { \"[UnrealLink]: ${::writeMessage.name} $message\" }\n        panel.writeMessage(message)\n    }\n\n    fun clear() {\n        logger.info { \"[UnrealLink]: ${::clear.name}\" }\n        panel.clear()\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/UE4LibraryStartUpSerializerRegistrar.kt",
    "content": "package com.jetbrains.rider.plugins.unreal\n\nimport com.jetbrains.rd.framework.ISerializers\nimport com.jetbrains.rdclient.protocol.RdStartUpSerializerRegistrar\nimport com.jetbrains.rider.plugins.unreal.model.UE4Library\n\nclass UE4LibraryStartUpSerializerRegistrar : RdStartUpSerializerRegistrar {\n    override fun register(serializers: ISerializers) {\n        UE4Library.register(serializers)\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/UnrealHost.kt",
    "content": "package com.jetbrains.rider.plugins.unreal\n\nimport com.intellij.openapi.client.ClientProjectSession\nimport com.intellij.openapi.components.Service\nimport com.intellij.openapi.components.service\nimport com.intellij.openapi.diagnostic.Logger\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.util.SystemInfo\nimport com.jetbrains.rd.framework.impl.RdTask\nimport com.jetbrains.rd.framework.protocolOrThrow\nimport com.jetbrains.rd.protocol.SolutionExtListener\nimport com.jetbrains.rd.util.lifetime.Lifetime\nimport com.jetbrains.rd.util.reactive.IProperty\nimport com.jetbrains.rd.util.reactive.Property\nimport com.jetbrains.rd.util.reactive.adviseNotNull\nimport com.jetbrains.rd.util.reactive.whenTrue\nimport com.jetbrains.rider.plugins.unreal.actions.forceTriggerUIUpdate\nimport com.jetbrains.rider.plugins.unreal.model.ConnectionInfo\nimport com.jetbrains.rider.plugins.unreal.model.PlayState\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.GamePluginInstallInfo\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.RdRiderModel\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.plugins.unreal.toolWindow.UnrealToolWindowFactory\nimport com.jetbrains.rider.projectView.solution\nimport com.sun.jna.LastErrorException\nimport com.sun.jna.Native\nimport com.sun.jna.platform.win32.WinDef\nimport com.sun.jna.win32.StdCallLibrary\n\n@Service(Service.Level.PROJECT)\nclass UnrealHost(val project: Project) {\n    companion object {\n        fun getInstance(project:Project) = project.service<UnrealHost>()\n    }\n    val logger = Logger.getInstance(UnrealHost::class.java)\n\n    internal val playStateModel: IProperty<PlayState> = Property(PlayState.Idle)\n    val playState: PlayState\n        get() = playStateModel.value\n    var playMode: Int = 0\n\n    internal val model = project.solution.rdRiderModel\n    val isConnectedToUnrealEditor:Boolean\n        get() = model.isConnectedToUnrealEditor.value\n    val connectionInfo:ConnectionInfo?\n        get() = model.connectionInfo.valueOrNull\n    val isRiderLinkInstallationInProgress:Boolean\n        get() = model.riderLinkInstallationInProgress.value\n    val isRefreshProjectsInProgress:Boolean\n        get() = model.refreshInProgress.value\n    val isUproject:Boolean\n        get() = model.isUproject.value\n    val isInstallInfoAvailable:Boolean\n        get() = model.isInstallInfoAvailable.value\n    var gamePluginInstallInfos: List<GamePluginInstallInfo> = emptyList()\n    val isHotReloadAvailable: Boolean\n        get() = model.isHotReloadAvailable.value\n    val isHotReloadCompiling: Boolean\n        get() = model.isHotReloadCompiling.value\n\n\n    var isUnrealEngineSolution = false\n    var isPreBuiltEngine = false\n\n    class ProtocolListener : SolutionExtListener<RdRiderModel> {\n        override fun extensionCreated(lifetime: Lifetime, session: ClientProjectSession, model: RdRiderModel) {\n            model.allowSetForegroundWindow.set { _, id ->\n                if (SystemInfo.isWindows) {\n                    return@set if (!user32!!.AllowSetForegroundWindow(id)) {\n                        val lastError = kernel32!!.GetLastError()\n                        RdTask.faulted(LastErrorException(lastError))\n                    } else {\n                        RdTask.fromResult(true)\n                    }\n                }\n                RdTask.fromResult(true)\n            }\n\n            val project = session.project\n            model.isUnrealEngineSolution.change.advise(lifetime) { isUnrealEngineSolution ->\n                val host = project.service<UnrealHost>()\n                host.isUnrealEngineSolution = isUnrealEngineSolution\n            }\n            model.isPreBuiltEngine.change.advise(lifetime) { isPreBuiltEngine ->\n                val host = project.service<UnrealHost>()\n                host.isPreBuiltEngine = isPreBuiltEngine\n            }\n\n            model.isConnectedToUnrealEditor.change.advise(lifetime) { connected ->\n                if (!connected) {\n                    project.service<UnrealHost>().playStateModel.set(PlayState.Idle)\n                }\n                forceTriggerUIUpdate()\n            }\n\n            model.riderLinkInstallPanelInit.advise(lifetime) {\n                val riderLinkInstallContext =\n                    RiderLinkInstallService.getInstance(project).getOrCreateRiderLinkInstallContext()\n                riderLinkInstallContext.clear()\n                riderLinkInstallContext.showToolWindowIfHidden()\n            }\n\n            model.riderLinkInstallMessage.advise(lifetime) { message ->\n                RiderLinkInstallService.getInstance(project).getOrCreateRiderLinkInstallContext().writeMessage(message)\n            }\n            model.gamePluginInstallInfos.advise(lifetime) { gamePluginInstallInfos ->\n                project.service<UnrealHost>().gamePluginInstallInfos = gamePluginInstallInfos\n            }\n\n//  Update state of Unreal actions on toolbar\n            model.playStateFromEditor.adviseNotNull(lifetime) { newState ->\n                project.service<UnrealHost>().playStateModel.set(newState)\n            }\n\n            model.playModeFromEditor.adviseNotNull(lifetime) { mode ->\n                project.service<UnrealHost>().playMode = mode\n                forceTriggerUIUpdate()\n            }\n\n            model.isGameControlModuleInitialized.adviseNotNull(lifetime) {\n                forceTriggerUIUpdate()\n            }\n\n            model.isConnectedToUnrealEditor.whenTrue(lifetime) {\n                val toolWindowsFactory = UnrealToolWindowFactory.getInstance(project)\n                toolWindowsFactory.showTabForNewSession()\n            }\n        }\n\n        private val user32 = if (SystemInfo.isWindows) Native.load(\"user32\", User32::class.java) else null\n        private val kernel32 = if (SystemInfo.isWindows) Native.load(\"kernel32\", Kernel32::class.java) else null\n\n        @Suppress(\"FunctionName\")\n        private interface User32 : StdCallLibrary {\n            fun AllowSetForegroundWindow(id: Int): Boolean\n\n            @Suppress(\"unused\")\n            fun SetForegroundWindow(hwnd: WinDef.HWND): Boolean\n\n            @Suppress(\"unused\")\n            fun EnumWindows(callback: EnumWindowsProc, intPtr: WinDef.INT_PTR): Boolean\n\n            @Suppress(\"unused\")\n            fun GetWindowThreadProcessId(hwnd: WinDef.HWND, processId: WinDef.UINTByReference): Boolean\n\n            @Suppress(\"unused\")\n            fun ShowWindow(hwnd: WinDef.HWND, nCmdShow: Int): Boolean\n        }\n\n        @Suppress(\"FunctionName\")\n        private interface Kernel32 : StdCallLibrary {\n            fun GetLastError(): Int\n        }\n\n        private interface EnumWindowsProc : StdCallLibrary.StdCallCallback {\n            @Suppress(\"unused\")\n            fun callback(hwnd: WinDef.HWND, intPtr: WinDef.INT_PTR): Boolean\n        }\n    }\n\n    fun <R> performModelAction(action:(RdRiderModel)->R) {\n        model.protocolOrThrow.scheduler.invokeOrQueue {\n            action(model)\n        }\n    }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/UnrealLinkSettings.kt",
    "content": "package com.jetbrains.rider.plugins.unreal\n\nimport com.intellij.openapi.components.BaseState\nimport com.intellij.openapi.components.Service\nimport com.intellij.openapi.components.SimplePersistentStateComponent\nimport com.intellij.openapi.components.State\nimport com.intellij.openapi.components.Storage\nimport com.intellij.openapi.components.StoragePathMacros\nimport com.intellij.openapi.components.service\nimport com.intellij.openapi.project.Project\n\n@Service(Service.Level.PROJECT)\n@State(name = \"UnrealLinkSettings\", storages = [Storage(StoragePathMacros.WORKSPACE_FILE)])\nclass UnrealLinkSettings : SimplePersistentStateComponent<UnrealLinkSettings.State>(State()) {\n    companion object {\n        fun getInstance(project: Project): UnrealLinkSettings = project.service()\n    }\n\n    var replaceWithHotReload: Boolean\n        get() = state.replaceWithHotReload\n        set(value) {\n            state.replaceWithHotReload = value\n        }\n\n    class State : BaseState() {\n        var replaceWithHotReload by property(defaultValue = true)\n    }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/UnrealPluginUsagesCollector.kt",
    "content": "package com.jetbrains.rider.plugins.unreal\n\nimport com.intellij.internal.statistic.StructuredIdeActivity\nimport com.intellij.internal.statistic.eventLog.EventLogGroup\nimport com.intellij.internal.statistic.eventLog.events.EventFields\nimport com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector\n\nimport com.intellij.openapi.project.Project\n\n\nobject UnrealPluginUsagesCollector : CounterUsagesCollector() {\n  override fun getGroup(): EventLogGroup = GROUP\n\n  private val GROUP = EventLogGroup(\"rider.unreal.debugger\", 1)\n\n  private val IS_PLATFORM_SUPPORTED_ARG = EventFields.Boolean(\"platform_supported\")\n  private val IS_RIDER_DEBUGGING_SUPPORT_MODULE_AVAILABLE_ARG = EventFields.Boolean(\"rider_debugging_support_module_available\")\n  private val IS_SHOW_BLUEPRINT_FRAMES_ENABLED_ARG = EventFields.Enum<OptionalBoolean>(\"show_blueprint_frames_enabled\")\n  private val IS_SHOW_UNREAL_FRAMES_ENABLED_ARG = EventFields.Enum<OptionalBoolean>(\"show_unreal_frames_enabled\")\n\n  private val BLUEPRINT_STACK_TRANSFORM_ACTIVITY = GROUP.registerIdeActivity(\"blueprint_stack_transform\",\n                                                                             startEventAdditionalFields = arrayOf(\n                                                                               IS_PLATFORM_SUPPORTED_ARG,\n                                                                               IS_RIDER_DEBUGGING_SUPPORT_MODULE_AVAILABLE_ARG,\n                                                                               IS_SHOW_BLUEPRINT_FRAMES_ENABLED_ARG,\n                                                                               IS_SHOW_UNREAL_FRAMES_ENABLED_ARG,\n                                                                             ))\n\n  private val BATCH_NUMBER_ARG = EventFields.Int(\"batch_number\")\n  private val BATCH_SIZE_ARG = EventFields.Int(\"batch_size\")\n\n  private val BLUEPRINT_STACK_TRANSFORM_BATCH_ACTIVITY = GROUP.registerIdeActivity(\"blueprint_stack_transform_batch\",\n                                                                                   startEventAdditionalFields = arrayOf(BATCH_NUMBER_ARG,\n                                                                                                                        BATCH_SIZE_ARG),\n                                                                                   parentActivity = BLUEPRINT_STACK_TRANSFORM_ACTIVITY)\n  private val BLUEPRINT_STACK_GETTING_DATA_FROM_DBG_DRIVER_ACTIVITY = GROUP.registerIdeActivity(\n    \"blueprint_stack_getting_data_from_dbg_driver\", parentActivity = BLUEPRINT_STACK_TRANSFORM_BATCH_ACTIVITY)\n\n  enum class OptionalBoolean {\n    True, False, Undefined\n  }\n\n  private fun Boolean?.toEnum() = when (this) {\n    true -> OptionalBoolean.True\n    false -> OptionalBoolean.False\n    null -> OptionalBoolean.Undefined\n  }\n\n  @JvmStatic\n  fun startBlueprintStackTransformActivity(project: Project?,\n                                           isPlatformSupported: Boolean,\n                                           isRiderDebuggingSupportModuleAvailable: Boolean,\n                                           isShowBlueprintFramesEnabled: Boolean?,\n                                           isShowUnrealFramesEnabled: Boolean?): StructuredIdeActivity? {\n    if (project?.isDisposed == true) return null\n\n    return BLUEPRINT_STACK_TRANSFORM_ACTIVITY.started(project) {\n      listOf(IS_PLATFORM_SUPPORTED_ARG.with(isPlatformSupported),\n             IS_RIDER_DEBUGGING_SUPPORT_MODULE_AVAILABLE_ARG.with(isRiderDebuggingSupportModuleAvailable),\n             IS_SHOW_BLUEPRINT_FRAMES_ENABLED_ARG.with(isShowBlueprintFramesEnabled.toEnum()),\n             IS_SHOW_UNREAL_FRAMES_ENABLED_ARG.with(isShowUnrealFramesEnabled.toEnum()))\n    }\n  }\n\n  @JvmStatic\n  fun startBlueprintStackTransformBatchActivity(project: Project?,\n                                                activity: StructuredIdeActivity?,\n                                                batchNumber: Int,\n                                                batchSize: Int): StructuredIdeActivity? {\n    if (project?.isDisposed == true) return null\n\n    if (activity == null) return null\n\n    return BLUEPRINT_STACK_TRANSFORM_BATCH_ACTIVITY.startedWithParent(project, activity) {\n      listOf(BATCH_NUMBER_ARG.with(batchNumber), BATCH_SIZE_ARG.with(batchSize))\n    }\n  }\n\n  @JvmStatic\n  fun startBlueprintStackGettingDataActivity(project: Project?, activity: StructuredIdeActivity?): StructuredIdeActivity? {\n    if (project?.isDisposed == true) return null\n\n    if (activity == null) return null\n\n    return BLUEPRINT_STACK_GETTING_DATA_FROM_DBG_DRIVER_ACTIVITY.startedWithParent(project, activity)\n  }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/ActionsUtils.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.ide.ActivityTracker\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.jetbrains.rider.plugins.unreal.UnrealHost\n\nfun AnActionEvent.getUnrealHost(): UnrealHost? {\n    val project = project ?: return null\n    return UnrealHost.getInstance(project)\n}\n\nfun forceTriggerUIUpdate() {\n    // Action button presentations won't be updated if no events occur\n    // (e.g. mouse isn't moving, keys aren't being pressed).\n    // In that case emulating activity will help:\n    ActivityTracker.getInstance().inc()\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/CancelRiderLinkInstallAction.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.openapi.actionSystem.ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.AnAction\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.actionSystem.Presentation\nimport com.intellij.openapi.actionSystem.ex.CustomComponentAction\nimport com.intellij.openapi.actionSystem.impl.ActionButton\nimport com.intellij.openapi.project.DumbAware\nimport com.jetbrains.rider.plugins.unreal.UnrealHost\nimport icons.RiderIcons\nimport javax.swing.JComponent\n\nclass CancelRiderLinkInstallAction : AnAction(), CustomComponentAction, DumbAware {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun createCustomComponent(presentation: Presentation, place: String): JComponent {\n        return ActionButton(this, presentation, place, DEFAULT_MINIMUM_BUTTON_SIZE)\n    }\n\n    override fun update(e: AnActionEvent) {\n        val project = e.project\n        if (project == null) {\n            e.presentation.isEnabled = false\n            return\n        }\n        e.presentation.icon = RiderIcons.Actions.CancelCompile\n        e.presentation.isEnabled = UnrealHost.getInstance(project).isRiderLinkInstallationInProgress\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val host = e.getUnrealHost() ?:  error(\"UnrealHost not found\")\n        host.model.cancelRiderLinkInstall.fire(Unit)\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/EnableAutoUpdatePlugin.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.notification.Notification\nimport com.intellij.notification.NotificationAction\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.projectView.solution\n\nclass EnableAutoUpdatePlugin : NotificationAction(UnrealLinkBundle.message(\"action.UnrealLink.EnableAutoUpdatePlugin.text\")) {\n    override fun actionPerformed(e: AnActionEvent, notifcation:Notification) {\n        notifcation.expire()\n        val project = e.project ?: return\n        project.solution.rdRiderModel.enableAutoupdatePlugin.fire(Unit)\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/FilterCheckboxAction.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.actionSystem.KeepPopupOnPerform\nimport com.intellij.openapi.project.DumbAwareAction\nimport com.jetbrains.rdclient.usages.SelfUpdatingCheckIcon\nimport kotlin.reflect.KMutableProperty0\n\nclass FilterCheckboxAction(\n  text: String,\n  private val isSelected: () -> Boolean,\n  private val setSelected: (Boolean) -> Unit\n) : DumbAwareAction(text) {\n  constructor(text: String, property: KMutableProperty0<Boolean>) : this(text, property::get, property::set)\n\n  private val checkboxIcon = SelfUpdatingCheckIcon(12) { isSelected() }\n\n  init {\n    templatePresentation.icon = checkboxIcon\n    templatePresentation.selectedIcon = checkboxIcon\n    templatePresentation.keepPopupOnPerform = KeepPopupOnPerform.IfPreferred\n  }\n\n  override fun actionPerformed(e: AnActionEvent) {\n    val curState = isSelected()\n    setSelected(!curState)\n  }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/HotReloadBuildAction.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.project.DumbAwareAction\nimport com.intellij.util.application\nimport com.jetbrains.rd.util.reactive.fire\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.projectView.solution\nimport icons.RiderIcons\n\nclass HotReloadBuildAction : DumbAwareAction(RiderIcons.Actions.CompileLive) {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n        val host = e.getUnrealHost()\n        if (host == null) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n\n        if (!host.isUnrealEngineSolution || !host.isHotReloadAvailable) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n\n        e.presentation.isVisible = true\n        e.presentation.isEnabled = !host.isHotReloadCompiling\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val project = e.project ?: return\n        application.assertIsDispatchThread()\n        application.saveAll()\n        project.solution.rdRiderModel.triggerHotReload.fire()\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/HotReloadBuildModeProvider.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.openapi.project.Project\nimport com.jetbrains.rider.build.actions.BuildButtonModeProvider\nimport com.jetbrains.rider.plugins.unreal.UnrealHost\nimport com.jetbrains.rider.plugins.unreal.UnrealLinkSettings\n\nclass HotReloadBuildModeProvider : BuildButtonModeProvider {\n    override fun getPriority(): Int {\n        return 10000\n    }\n\n    override fun isApplicable(project: Project): Boolean {\n        val host = UnrealHost.getInstance(project)\n        val settings: UnrealLinkSettings = UnrealLinkSettings.getInstance(project)\n        return host.isUnrealEngineSolution && host.isHotReloadAvailable && settings.replaceWithHotReload\n    }\n\n    override fun getButtonActionId(): String {\n        return \"UnrealLink.HotReloadBuild\"\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/InstallActions.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.components.service\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.ui.DialogWrapper\nimport com.intellij.openapi.project.DumbAwareAction\nimport com.intellij.ui.components.JBScrollPane\nimport com.intellij.ui.components.JBTextField\nimport com.intellij.util.ui.JBUI\nimport com.jetbrains.rd.util.reactive.fire\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.UnrealHost\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.ForceInstall\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.InstallPluginDescription\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.PluginInstallLocation\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.projectView.solution\nimport java.awt.BorderLayout\nimport java.awt.GridBagConstraints\nimport java.awt.GridBagLayout\nimport javax.swing.JCheckBox\nimport javax.swing.JComponent\nimport javax.swing.JLabel\nimport javax.swing.JPanel\n\nclass InstallEditorPluginToEngineAction : DumbAwareAction() {\n    override fun getActionUpdateThread() = ActionUpdateThread.BGT\n\n    override fun actionPerformed(actionEvent: AnActionEvent) {\n        val project = actionEvent.project ?: return\n        project.solution.rdRiderModel.installEditorPlugin.fire(\n                InstallPluginDescription(PluginInstallLocation.Engine, ForceInstall.Yes, true, emptyList(), emptyList())\n        )\n    }\n\n    override fun update(e: AnActionEvent) {\n        val project = e.project\n        if (project == null) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n        val unrealHost = project.service<UnrealHost>()\n        e.presentation.isEnabledAndVisible = unrealHost.isUnrealEngineSolution\n    }\n}\n\nclass InstallEditorPluginToGameAction : DumbAwareAction() {\n    override fun getActionUpdateThread() = ActionUpdateThread.BGT\n\n    override fun actionPerformed(actionEvent: AnActionEvent) {\n        val project = actionEvent.project ?: return\n        installOrExtractPluginInGame(project, ForceInstall.Yes, buildRequired = true)\n    }\n\n    override fun update(e: AnActionEvent) {\n        val project = e.project\n        if (project == null) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n        val unrealHost = project.service<UnrealHost>()\n        e.presentation.isEnabledAndVisible = unrealHost.isUnrealEngineSolution\n    }\n}\n\nclass ExtractEditorPluginToEngineAction : DumbAwareAction() {\n    override fun getActionUpdateThread() = ActionUpdateThread.BGT\n\n    override fun actionPerformed(actionEvent: AnActionEvent) {\n        val project = actionEvent.project ?: return\n        project.solution.rdRiderModel.installEditorPlugin.fire(\n                InstallPluginDescription(PluginInstallLocation.Engine, ForceInstall.Yes, false, emptyList(), emptyList())\n        )\n    }\n\n    override fun update(e: AnActionEvent) {\n        val project = e.project\n        if (project == null) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n        val unrealHost = project.service<UnrealHost>()\n        e.presentation.isEnabledAndVisible = unrealHost.isUnrealEngineSolution && unrealHost.isPreBuiltEngine.not()\n    }\n}\n\nclass ExtractEditorPluginToGameAction : DumbAwareAction() {\n    override fun getActionUpdateThread() = ActionUpdateThread.BGT\n\n    override fun actionPerformed(actionEvent: AnActionEvent) {\n        val project = actionEvent.project ?: return\n        installOrExtractPluginInGame(project, ForceInstall.Yes, buildRequired = false)\n    }\n\n    override fun update(e: AnActionEvent) {\n        val project = e.project\n        if (project == null) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n        val unrealHost = project.service<UnrealHost>()\n        e.presentation.isEnabledAndVisible = unrealHost.isUnrealEngineSolution\n    }\n}\n\nclass DeleteRiderLinkPluginAction : DumbAwareAction() {\n    override fun getActionUpdateThread() = ActionUpdateThread.BGT\n\n    override fun actionPerformed(actionEvent: AnActionEvent) {\n        val project = actionEvent.project ?: return\n        project.solution.rdRiderModel.deletePlugin.fire()\n    }\n\n    override fun update(e: AnActionEvent) {\n        val project = e.project\n        if (project == null) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n        val unrealHost = UnrealHost.getInstance(project)\n        e.presentation.isEnabledAndVisible = unrealHost.isInstallInfoAvailable\n    }\n}\n\ninternal fun installOrExtractPluginInGame(project: Project, forceInstall: ForceInstall, buildRequired: Boolean) {\n    val model = project.solution.rdRiderModel\n    val unrealHost = project.service<UnrealHost>()\n    val discoveredProjects = unrealHost.gamePluginInstallInfos\n        .map { pluginInstallInfo ->\n            UprojectItem(\n                name = pluginInstallInfo.projectName,\n                path = pluginInstallInfo.uprojectPath,\n                installed = pluginInstallInfo.isPluginAvailable\n            )\n        }\n        .sortedBy { it.name.lowercase() }\n\n    if (discoveredProjects.size <= 1) {\n        model.installEditorPlugin.fire(\n            InstallPluginDescription(PluginInstallLocation.Game, forceInstall, buildRequired, discoveredProjects.map {it.path}, emptyList())\n        )\n        return\n    }\n\n    val confirmText = if (buildRequired) {\n        UnrealLinkBundle.message(\"dialog.UnrealLink.InstallEditorPluginInGame.confirm.install\")\n    } else {\n        UnrealLinkBundle.message(\"dialog.UnrealLink.InstallEditorPluginInGame.confirm.extract\")\n    }\n    val dialog = InstallPluginInGameDialog(project, discoveredProjects, confirmText)\n    if (!dialog.showAndGet()) return\n\n    val selectedUprojectPaths = dialog.getSelectedPaths()\n    val selected = selectedUprojectPaths.toHashSet()\n    val unselectedUprojectPaths = discoveredProjects\n        .asSequence()\n        .map { it.path }\n        .filterNot { selected.contains(it) }\n        .toList()\n\n    model.installEditorPlugin.fire(\n        InstallPluginDescription(\n            PluginInstallLocation.Game,\n            forceInstall,\n            buildRequired,\n            selectedUprojectPaths,\n            unselectedUprojectPaths\n        )\n    )\n}\n\nprivate data class UprojectItem(\n    val name: String,\n    val path: String,\n    val installed: Boolean,\n)\n\nprivate class InstallPluginInGameDialog(\n    project: Project,\n    private val items: List<UprojectItem>,\n    okText: String,\n) : DialogWrapper(project, true) {\n    private val checkboxes = mutableMapOf<String, JCheckBox>()\n\n    init {\n        title = UnrealLinkBundle.message(\"dialog.UnrealLink.InstallEditorPluginInGame.title\")\n        setOKButtonText(okText)\n        init()\n    }\n\n    override fun createCenterPanel(): JComponent {\n        val content = JPanel(BorderLayout())\n        val rowsPanel = JPanel(GridBagLayout())\n        var row = 0\n\n        rowsPanel.add(JLabel(\"\"), gbc(0, row, 0.0))\n        rowsPanel.add(JLabel(UnrealLinkBundle.message(\"dialog.UnrealLink.InstallEditorPluginInGame.column.project\")), gbc(1, row, 0.0))\n        rowsPanel.add(JLabel(UnrealLinkBundle.message(\"dialog.UnrealLink.InstallEditorPluginInGame.column.path\")), gbc(2, row, 1.0))\n        row++\n\n        for (item in items) {\n            val checkbox = JCheckBox().apply { isSelected = item.installed }\n            checkboxes[item.path] = checkbox\n            rowsPanel.add(checkbox, gbc(0, row, 0.0))\n            rowsPanel.add(JLabel(item.name), gbc(1, row, 0.0))\n\n            val pathField = JBTextField(item.path).apply {\n                isEditable = false\n                border = null\n                isOpaque = false\n            }\n            rowsPanel.add(pathField, gbc(2, row, 1.0))\n            row++\n        }\n\n        content.add(JBScrollPane(rowsPanel), BorderLayout.CENTER)\n        return content\n    }\n\n    fun getSelectedPaths(): List<String> =\n        items.asSequence()\n            .filter { item -> checkboxes[item.path]?.isSelected == true }\n            .map { it.path }\n            .toList()\n\n    private fun gbc(column: Int, row: Int, weightX: Double): GridBagConstraints = GridBagConstraints().apply {\n        gridx = column\n        gridy = row\n        fill = GridBagConstraints.HORIZONTAL\n        anchor = GridBagConstraints.WEST\n        insets = JBUI.insets(2, 4)\n        this.weightx = weightX\n    }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/PlayActions.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.icons.AllIcons\nimport com.intellij.notification.NotificationGroupManager\nimport com.intellij.notification.NotificationType\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.components.Service\nimport com.intellij.openapi.components.service\nimport com.intellij.openapi.project.DumbAwareAction\nimport com.intellij.openapi.project.Project\nimport com.intellij.ui.icons.CachedImageIcon\nimport com.intellij.ui.icons.loadIconCustomVersionOrScale\nimport com.intellij.util.ui.JBUI\nimport com.jetbrains.rd.platform.util.idea.LifetimedService\nimport com.jetbrains.rd.util.reactive.fire\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.UnrealHost\nimport com.jetbrains.rider.plugins.unreal.model.PlayState\nimport com.jetbrains.rider.plugins.unreal.model.RequestFailed\nimport com.jetbrains.rider.plugins.unreal.model.RequestSucceed\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanelSettings\nimport com.jetbrains.rider.projectView.solution\nimport icons.UnrealIcons\nimport javax.swing.Icon\nimport com.jetbrains.rider.plugins.unreal.model.NotificationType as ReplyNotificationType\n\n@Service(Service.Level.PROJECT)\nclass PlayStateActionStateService(val project: Project) : LifetimedService() {\n    companion object {\n        fun getInstance(project: Project): PlayStateActionStateService = project.service()\n        private const val RIDER_LINK_ACTIONS_NOTIFICATION_GROUP_ID = \"RiderLinkActions\"\n    }\n\n    private var disabledUntilModelChange: Boolean = false\n    private var currentRequestID: Int = 0\n\n    init {\n        val host = UnrealHost.getInstance(project)\n        host.performModelAction { model ->\n            model.isConnectedToUnrealEditor.change.advise(serviceLifetime) {\n                invalidate()\n            }\n            model.notificationReplyFromEditor.advise(serviceLifetime) {\n                if (it.requestID != currentRequestID) return@advise\n                when (it) {\n                    is RequestSucceed -> invalidate()\n                    is RequestFailed -> {\n                        invalidate()\n\n                        val title = UnrealLinkBundle.message(\"notification.RiderLink.ReplyFromEditor.title\")\n                        val message = it.message.data\n                        val type = when (it.type){\n                            ReplyNotificationType.Message -> NotificationType.INFORMATION\n                            ReplyNotificationType.Error -> NotificationType.ERROR\n                        }\n                        NotificationGroupManager.getInstance()\n                                .getNotificationGroup(RIDER_LINK_ACTIONS_NOTIFICATION_GROUP_ID)\n                                .createNotification(title, message, type)\n                                .notify(project)\n                    }\n                }\n            }\n        }\n        host.playStateModel.change.advise(serviceLifetime) {\n            invalidate()\n        }\n    }\n\n    fun invalidate() {\n        disabledUntilModelChange = false\n        forceTriggerUIUpdate()\n    }\n\n    fun disableUntilStateChange() {\n        disabledUntilModelChange = true\n    }\n\n    fun isDisabledUntilStateChange(): Boolean = disabledUntilModelChange\n\n    fun nextRequestID() : Int {\n        currentRequestID++\n        return currentRequestID\n    }\n}\n\nabstract class PlayStateAction() : DumbAwareAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun update(e: AnActionEvent) {\n        val project = e.project\n        if (project == null) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n        val host = UnrealHost.getInstance(project)\n        val settings = UnrealLogPanelSettings.getInstance(project)\n\n        e.presentation.isVisible = host.isUnrealEngineSolution && settings.showPlayButtons\n        e.presentation.isEnabled = host.isConnectedToUnrealEditor &&\n                host.model.isGameControlModuleInitialized.value\n\n        if (e.presentation.isEnabled) {\n            val state = PlayStateActionStateService.getInstance(project)\n            e.presentation.isEnabled = !state.isDisabledUntilStateChange()\n        }\n    }\n}\n\nclass PlayInUnrealAction : PlayStateAction() {\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n        val host = e.getUnrealHost() ?: return\n        e.presentation.icon = getToolbarIconHack(UnrealIcons.PIEControl.Play)\n        e.presentation.isEnabled = e.presentation.isEnabled && host.playState == PlayState.Idle\n        e.presentation.isVisible = e.presentation.isVisible && host.playState == PlayState.Idle\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val host = e.getUnrealHost() ?: return\n        val state = PlayStateActionStateService.getInstance(host.project)\n        state.disableUntilStateChange()\n        host.model.requestPlayFromRider.fire(state.nextRequestID())\n    }\n}\n\nclass ResumeInUnrealAction : PlayStateAction() {\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n        val host = e.getUnrealHost() ?: return\n        e.presentation.icon = getToolbarIconHack(UnrealIcons.PIEControl.Play)\n        e.presentation.isEnabled = e.presentation.isEnabled && host.playState == PlayState.Pause\n        e.presentation.isVisible = e.presentation.isVisible && host.playState != PlayState.Idle\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val host = e.getUnrealHost() ?: return\n        val state = PlayStateActionStateService.getInstance(host.project)\n        state.disableUntilStateChange()\n        host.model.requestResumeFromRider.fire(state.nextRequestID())\n    }\n}\n\nclass StopInUnrealAction : PlayStateAction() {\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n        val host = e.getUnrealHost() ?: return\n        e.presentation.icon = getToolbarIconHack(UnrealIcons.PIEControl.Stop)\n        e.presentation.isEnabled = e.presentation.isEnabled && host.playState != PlayState.Idle\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val host = e.getUnrealHost() ?: return\n        val state = PlayStateActionStateService.getInstance(host.project)\n        state.disableUntilStateChange()\n        host.model.requestStopFromRider.fire(state.nextRequestID())\n    }\n}\n\nclass PauseInUnrealAction : PlayStateAction() {\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n        val host = e.getUnrealHost() ?: return\n        e.presentation.icon = getToolbarIconHack(UnrealIcons.PIEControl.Pause)\n        e.presentation.isEnabled = e.presentation.isEnabled && host.playState == PlayState.Play\n        e.presentation.isVisible = e.presentation.isVisible && host.playState != PlayState.Pause\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val host = e.getUnrealHost() ?: return\n        val state = PlayStateActionStateService.getInstance(host.project)\n        state.disableUntilStateChange()\n        host.model.requestPauseFromRider.fire(state.nextRequestID())\n    }\n}\n\nclass SingleStepInUnrealAction : PlayStateAction() {\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n        val host = e.getUnrealHost() ?: return\n        e.presentation.icon = getToolbarIconHack(UnrealIcons.PIEControl.FrameSkip)\n        e.presentation.isEnabled = e.presentation.isEnabled && host.playState == PlayState.Pause\n        e.presentation.isVisible = e.presentation.isVisible && host.playState == PlayState.Pause\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val host = e.getUnrealHost() ?: return\n        val state = PlayStateActionStateService.getInstance(host.project)\n        state.disableUntilStateChange()\n        host.model.requestFrameSkipFromRider.fire(state.nextRequestID())\n    }\n}\n\nclass RefreshProjects : DumbAwareAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n        val host = e.getUnrealHost()\n        if (host == null) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n\n        e.presentation.icon = AllIcons.Actions.Refresh\n        e.presentation.isVisible = host.isUnrealEngineSolution && !host.isUproject\n        e.presentation.isEnabled = !host.isRefreshProjectsInProgress &&\n                !host.isRiderLinkInstallationInProgress &&\n                host.isInstallInfoAvailable\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val project = e.project ?: return\n        project.solution.rdRiderModel.refreshProjects.fire()\n    }\n}\n\n// RIDER-129158 Unreal buttons are rendered by default in the toolbar\n//\n// HeaderToolbarButtonLook#scaleAndAdjustIcon fails to preserve disabled filter on icon when loading icon of different size for dark toolbar\n// (it uses customIconUtil.kt#loadIconCustomVersionOrScale that calls loadIconCustomVersion() that, in turn,\n// doesn't preserve icon modifications if isDark != null)\n// So, we try to load icon of the correct toolbar size here, so HeaderToolbarButtonLook wouldn't have to load icon again and reset modifications\n// Remove this hack after fixing HeaderToolbarButtonLook\nprivate fun getToolbarIconHack(icon: Icon): Icon {\n  if (icon is CachedImageIcon) {\n    return loadIconCustomVersionOrScale(icon, size = JBUI.CurrentTheme.Toolbar.experimentalToolbarButtonIconSize())\n  }\n  return icon\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/PlaySettingsActions.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.execution.process.ProcessInfo\nimport com.intellij.ide.actions.ShowSettingsUtilImpl\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.actionSystem.DefaultActionGroup\nimport com.intellij.openapi.project.DumbAware\nimport com.intellij.openapi.project.DumbAwareAction\nimport com.intellij.openapi.project.DumbAwareToggleAction\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.util.NlsActions\nimport com.intellij.xdebugger.attach.LocalAttachHost\nimport com.jetbrains.rd.ide.model.unrealModel\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.cpp.debugger.RiderCppLLDBDriverConfiguration\nimport com.jetbrains.rider.cpp.debugger.RiderCppLocalAttachDebugger\nimport com.jetbrains.rider.plugins.unreal.UnrealHost\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanelSettings\nimport com.jetbrains.rider.projectView.solution\nimport com.jetbrains.rider.settings.UnrealLogSettingsConfigurable\nimport icons.UnrealIcons\n\nclass PlaySettings : DefaultActionGroup(), DumbAware {\n    private val connectedIcon = UnrealIcons.ConnectionStatus.UnrealEngineConnected\n    private val disconnectedIcon = UnrealIcons.ConnectionStatus.UnrealEngineDisconnected\n\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n        UnrealHostOperations.updatePresentationBasedOnUnrealAvailability(e, connectedIcon, disconnectedIcon)\n    }\n}\n\nclass ProtocolStatus : DumbAwareAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun actionPerformed(e: AnActionEvent) = Unit\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n\n        e.presentation.isEnabled = false\n\n        val host = e.getUnrealHost() ?: return\n        e.presentation.isVisible = true\n        e.presentation.text = getActionText(host)\n    }\n\n    @NlsActions.ActionText\n    fun getActionText(host: UnrealHost): String {\n        return if (host.isConnectedToUnrealEditor) {\n            val info = host.connectionInfo\n            if (info != null) {\n                UnrealLinkBundle.message(\"action.RiderLink.ProtocolStatus.connected.ex.text\", info.projectName, info.executableName,\n                                         info.processId.toString())\n            } else {\n                UnrealLinkBundle.message(\"action.RiderLink.ProtocolStatus.connected.text\")\n            }\n        } else {\n            UnrealLinkBundle.message(\"action.RiderLink.ProtocolStatus.disconnected.text\")\n        }\n    }\n}\n\nclass AttachToConnectedEditor : DumbAwareAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n\n        val host = e.getUnrealHost()\n        if (host == null) {\n            e.presentation.isEnabledAndVisible = false\n            return\n        }\n\n        e.presentation.isVisible = true\n\n        if (!host.isConnectedToUnrealEditor) {\n            e.presentation.isEnabled = false\n            return\n        }\n\n        val connectionInfo = host.connectionInfo\n        if (connectionInfo == null) {\n            e.presentation.isEnabled = false\n            return\n        }\n\n        // try to enumerate current debug sessions and find if we have already a debugger attached\n        /*\n        val debuggerManager = XDebuggerManager.getInstance(host.project)\n        for (session in debuggerManager.debugSessions) {\n            val debugProcess = session.debugProcess\n            if (debugProcess is CidrDebugProcess) {\n                // TODO: need to retrieve target pid from process\n                val pid = 0 // debugProcess.processHandler\n                if (pid == connectionInfo.processId) {\n                    e.presentation.isEnabled = false\n                    return\n                }\n            }\n        }\n        */\n\n        e.presentation.isEnabled = true\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val host = e.getUnrealHost() ?: return\n        val connectionInfo = host.connectionInfo ?: return\n\n        val processInfo = ProcessInfo(connectionInfo.processId, \"\", connectionInfo.executableName, \"\")\n        attachToUnrealProcess(host.project, processInfo)\n    }\n\n    private fun attachToUnrealProcess(project: Project, processInfo: ProcessInfo) {\n        val attachDebugger = RiderCppLocalAttachDebugger(RiderCppLLDBDriverConfiguration())\n        attachDebugger.attachDebugSession(project, LocalAttachHost.INSTANCE, processInfo)\n    }\n\n}\n\nclass OpenUnrealLinkSettings : DumbAwareAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun update(e: AnActionEvent) {\n        val host = e.getUnrealHost()\n        e.presentation.isEnabledAndVisible = host != null\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val project = e.project ?: return\n        ShowSettingsUtilImpl.showSettingsDialog(project, UnrealLogSettingsConfigurable.ID, null)\n    }\n}\n\nclass OpenRiderLinkSettings : DumbAwareAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun update(e: AnActionEvent) {\n        val host = e.getUnrealHost()\n        e.presentation.isEnabledAndVisible = host != null\n    }\n\n    override fun actionPerformed(e: AnActionEvent) {\n        val project = e.project ?: return\n        ShowSettingsUtilImpl.showSettingsDialog(project, \"UnrealLinkOptionsId\", null)\n    }\n}\n\nprivate fun updatePlayActionPresentation(e: AnActionEvent) {\n    val host = e.getUnrealHost()\n    if (host == null) {\n        e.presentation.isEnabledAndVisible = false\n        return\n    }\n    val settings = UnrealLogPanelSettings.getInstance(host.project)\n    e.presentation.isEnabled = host.isConnectedToUnrealEditor\n    e.presentation.isVisible = settings.showPlayButtons\n}\n\nclass PlaySubsettings : DefaultActionGroup(), DumbAware {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n\n        updatePlayActionPresentation(e)\n    }\n}\n\nclass NumberOfPlayers : DumbAwareToggleAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    private fun setNumPlayers(mode: Int, num: Int): Int {\n        return mode and 3.inv() or (num - 1)\n    }\n\n    override fun isSelected(e: AnActionEvent): Boolean {\n        val host: UnrealHost = e.getUnrealHost() ?: return false\n        return ((host.playMode and 3) + 1).toString() == e.presentation.text\n    }\n\n    override fun setSelected(e: AnActionEvent, isSelected: Boolean) {\n        val host: UnrealHost = e.getUnrealHost() ?: return\n\n        if (isSelected) {\n            host.playMode = setNumPlayers(host.playMode, e.presentation.text.toInt(10))\n            host.model.playModeFromRider.fire(host.playMode)\n        }\n    }\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n\n        updatePlayActionPresentation(e)\n    }\n}\n\nclass SpawnPlayer : DumbAwareToggleAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    private fun getSpawnPlayerMode(text: String?) = when (text) {\n        UnrealLinkBundle.message(\"action.RiderLink.CurrentCamLoc.text\") -> 0\n        UnrealLinkBundle.message(\"action.RiderLink.DefaultPlayerStart.text\") -> 1\n        else -> -1\n    }\n\n    override fun isSelected(e: AnActionEvent): Boolean {\n        val host: UnrealHost = e.getUnrealHost() ?: return false\n\n        val actionID = getSpawnPlayerMode(e.presentation.text)\n        if (actionID == -1) return false\n\n        return (host.playMode and 4).shr(2) == actionID\n    }\n\n    override fun setSelected(e: AnActionEvent, isSelected: Boolean) {\n        val host: UnrealHost = e.getUnrealHost() ?: return\n\n        if (isSelected) {\n            val actionID = getSpawnPlayerMode(e.presentation.text)\n            if (actionID != -1) return\n\n            host.playMode = (host.playMode and 4.inv()) or actionID.shl(2)\n            host.model.playModeFromRider.fire(host.playMode)\n        }\n    }\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n\n        updatePlayActionPresentation(e)\n    }\n}\n\nclass DedicatedServer : DumbAwareToggleAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    private fun setDedicatedServer(mode: Int, enabled: Boolean): Int {\n        return mode and 8.inv() or (if (enabled) 8 else 0)\n    }\n\n    override fun isSelected(e: AnActionEvent): Boolean {\n        val host: UnrealHost = e.getUnrealHost() ?: return false\n\n        return (host.playMode and 8) != 0\n    }\n\n    override fun setSelected(e: AnActionEvent, isSelected: Boolean) {\n        val host: UnrealHost = e.getUnrealHost() ?: return\n\n        host.playMode = setDedicatedServer(host.playMode, isSelected)\n        host.model.playModeFromRider.fire(host.playMode)\n    }\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n\n        updatePlayActionPresentation(e)\n    }\n}\n\nclass CompileBeforeRun : DumbAwareToggleAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    private fun setCompileBeforeRun(mode: Int, enabled: Boolean): Int {\n        return mode and 128.inv() or (if (enabled) 128 else 0)\n    }\n\n    override fun isSelected(e: AnActionEvent): Boolean {\n        val host: UnrealHost = e.getUnrealHost() ?: return false\n\n        return (host.playMode and 128) != 0\n    }\n\n    override fun setSelected(e: AnActionEvent, isSelected: Boolean) {\n        val host: UnrealHost = e.getUnrealHost() ?: return\n\n        host.playMode = setCompileBeforeRun(host.playMode, isSelected)\n        host.model.playModeFromRider.fire(host.playMode)\n    }\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n\n        updatePlayActionPresentation(e)\n    }\n}\n\nconst val PLAY_MODE_MASK_OFS = 4\nconst val PLAY_MODE_MASK_SIZE = 3\nconst val PLAY_MODE_MASK = (1.shl(PLAY_MODE_MASK_SIZE) - 1).shl(PLAY_MODE_MASK_OFS)\nconst val PLAY_MODE_MASK_INV = PLAY_MODE_MASK.inv()\n\nopen class PlayMode : DumbAwareToggleAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    private fun getModeIndex(playModeName: String?) = when (playModeName) {\n        UnrealLinkBundle.message(\"action.RiderLink.SelectedViewport.text\") -> 0\n        UnrealLinkBundle.message(\"action.RiderLink.MobilePreview.text\") -> 1\n        UnrealLinkBundle.message(\"action.RiderLink.NewEditorWindow.text\") -> 2\n        UnrealLinkBundle.message(\"action.RiderLink.VRPreview.text\") -> 3\n        UnrealLinkBundle.message(\"action.RiderLink.StandaloneGame.text\") -> 4\n        UnrealLinkBundle.message(\"action.RiderLink.Simulate.text\") -> 5\n        UnrealLinkBundle.message(\"action.RiderLink.VulkanPreview.text\") -> 6\n        else -> -1\n    }\n\n    private fun getPlayModeIndex(mode: Int) = (mode and PLAY_MODE_MASK).ushr(PLAY_MODE_MASK_OFS)\n\n    private fun setPlayMode(mode: Int, playModeIndex: Int): Int {\n        return (mode and PLAY_MODE_MASK_INV) or playModeIndex.shl(PLAY_MODE_MASK_OFS)\n    }\n\n    protected open fun isPlayModeSupported(project: Project?): Boolean = project != null\n\n    override fun isSelected(e: AnActionEvent): Boolean {\n        val host: UnrealHost = e.getUnrealHost() ?: return false\n\n        val ind = getModeIndex(e.presentation.text)\n        if (ind == -1 || !isPlayModeSupported(e.project)) return false\n        return getPlayModeIndex(host.playMode) == ind\n    }\n\n    override fun setSelected(e: AnActionEvent, isSelected: Boolean) {\n        val host: UnrealHost = e.getUnrealHost() ?: return\n\n        if (isSelected) {\n            val playModeIndex = getModeIndex(e.presentation.text)\n            if (playModeIndex == -1 || !isPlayModeSupported(e.project)) return\n\n            host.playMode = setPlayMode(host.playMode, playModeIndex)\n            host.model.playModeFromRider.fire(host.playMode)\n        }\n    }\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n\n        updatePlayActionPresentation(e)\n        e.presentation.isEnabledAndVisible = e.presentation.isEnabledAndVisible && isPlayModeSupported(e.project)\n    }\n}\n\nclass VulkanPlayMode : PlayMode() {\n  override fun isPlayModeSupported(project: Project?): Boolean {\n    if (project == null)\n      return false\n    // Vulkan Preview is deprecated since UE 5.7\n    val version = project.solution.unrealModel.unrealVersion.valueOrNull ?: return false\n    return version.major < 5 || version.major == 5 && version.minor < 7\n  }\n}\n\nclass HidePlayButtonsAction : DumbAwareToggleAction() {\n    override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n    override fun update(e: AnActionEvent) {\n        super.update(e)\n\n        val host = e.getUnrealHost()\n        e.presentation.isEnabledAndVisible = host != null\n    }\n\n    override fun isSelected(e: AnActionEvent): Boolean {\n        val project = e.project ?: return false\n        val settings = UnrealLogPanelSettings.getInstance(project)\n        return settings.showPlayButtons\n    }\n\n    override fun setSelected(e: AnActionEvent, selected: Boolean) {\n        val project = e.project ?: return\n        val settings = UnrealLogPanelSettings.getInstance(project)\n        settings.showPlayButtons = selected\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/actions/UnrealHostOperations.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.actions\n\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport javax.swing.Icon\n\nclass UnrealHostOperations {\n    companion object {\n        fun updatePresentationBasedOnUnrealAvailability(e: AnActionEvent, connectedIcon: Icon, disconnectedIcon: Icon) {\n            val host = e.getUnrealHost()\n            if (host == null || !host.isUnrealEngineSolution) {\n                e.presentation.isEnabledAndVisible = false\n                return\n            }\n\n            e.presentation.isEnabledAndVisible = true\n            e.presentation.icon = if (host.isConnectedToUnrealEditor) connectedIcon else disconnectedIcon\n        }\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/BlueprintCallstackFrameCompatibilityMatcher.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger\n\nimport com.intellij.xdebugger.frame.XStackFrame\nimport com.jetbrains.cidr.execution.debugger.CidrStackFrame\n\n\nclass BlueprintCallstackFrameCompatibilityMatcher {\n  companion object {\n    private const val UE_CORE_MODULE_NAME = \"UnrealEditor-CoreUObject.dll\"\n    private const val UE4_CORE_MODULE_NAME = \"UE4Editor-CoreUObject.dll\"\n\n    @Suppress(\"SpellCheckingInspection\")\n    private const val UE_UFUNCTION_INVOKE_NAME = \"UFunction::Invoke(UObject*,FFrame&,void*const)\"\n\n    @Suppress(\"SpellCheckingInspection\")\n    private const val UE_UOBJECT_PROCESSEVENT_NAME = \"UObject::ProcessEvent(UFunction*,void*)\"\n\n    @Suppress(\"SpellCheckingInspection\")\n    private const val UE_PROCESSLOCALSCRIPTFUNCTION_NAME = \"ProcessLocalScriptFunction(UObject*,FFrame&,void*const)\"\n\n    fun matchFrames(current: XStackFrame?, previous: XStackFrame?): BlueprintCallstackFrameMatchResult {\n      val currentFrame = current as? CidrStackFrame ?: return BlueprintCallstackFrameMatchResult.NotMatched\n      val previousFrame = previous as? CidrStackFrame\n\n      val modulePrefix = when (currentFrame.frame.module) {\n        UE_CORE_MODULE_NAME -> \"UnrealEditor\"\n        UE4_CORE_MODULE_NAME -> \"UE4Editor\"\n        else -> return BlueprintCallstackFrameMatchResult.NotMatched\n      }\n\n      val currentFrameFunction = currentFrame.frame.function.replace(\" \", \"\")\n      val previousFrameFunction = previousFrame?.frame?.function?.replace(\" \", \"\")\n\n      return when {\n        currentFrameFunction == UE_PROCESSLOCALSCRIPTFUNCTION_NAME -> BlueprintCallstackFrameMatchResult(true, modulePrefix)\n        currentFrameFunction == UE_UOBJECT_PROCESSEVENT_NAME && previousFrameFunction == UE_UFUNCTION_INVOKE_NAME -> BlueprintCallstackFrameMatchResult(\n          true, modulePrefix)\n        else -> BlueprintCallstackFrameMatchResult.NotMatched\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/BlueprintCallstackFrameMatchResult.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger\n\ndata class BlueprintCallstackFrameMatchResult(val isMatched: Boolean, val modulePrefix: String) {\n  companion object {\n    val NotMatched = BlueprintCallstackFrameMatchResult(false, \"\")\n  }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/BlueprintExecutionStack.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger\n\nimport com.jetbrains.cidr.execution.debugger.CidrDebugProcess\nimport com.jetbrains.cidr.execution.debugger.CidrExecutionStack\nimport com.jetbrains.cidr.execution.debugger.CidrSuspensionCause\nimport com.jetbrains.cidr.execution.debugger.backend.LLFrame\nimport com.jetbrains.cidr.execution.debugger.backend.LLThread\nimport com.jetbrains.cidr.execution.debugger.backend.LLValue\n\nclass BlueprintExecutionStack(process: CidrDebugProcess,\n                              thread: LLThread,\n                              frame: LLFrame?,\n                              current: Boolean,\n                              cause: CidrSuspensionCause?,\n                              returnValue: LLValue?,\n                              private val isSupportModuleAvailable: Boolean) : CidrExecutionStack(process, thread, frame,\n                                                                                                  current, cause,\n                                                                                                  returnValue) {\n\n  override fun computeStackFrames(firstFrameIndex: Int, container: XStackFrameContainer) {\n    val myContainer = BlueprintStackFrameContainer(container, BlueprintStackTransformer(), isSupportModuleAvailable, myProcess.project,\n                                                   myProcess)\n\n    super.computeStackFrames(firstFrameIndex, myContainer)\n  }\n}\n\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/BlueprintStackFrameContainer.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger\n\nimport com.intellij.openapi.project.Project\nimport com.intellij.xdebugger.frame.XExecutionStack\nimport com.intellij.xdebugger.frame.XStackFrame\nimport com.intellij.xdebugger.impl.frame.XStackFrameContainerEx\nimport com.jetbrains.cidr.execution.debugger.CidrDebugProcess\n\nclass BlueprintStackFrameContainer(private val myOriginalContainer: XExecutionStack.XStackFrameContainer,\n                                   private val bluePrintStackTransformer: BlueprintStackTransformer,\n                                   private val isSupportModuleAvailable: Boolean,\n                                   private val project: Project,\n                                   private val myProcess: CidrDebugProcess) : XStackFrameContainerEx {\n  private var myIsStarted = false\n\n  override fun hashCode(): Int = myOriginalContainer.hashCode()\n  override fun isObsolete(): Boolean = myOriginalContainer.isObsolete\n  override fun toString(): String = myOriginalContainer.toString()\n  override fun equals(other: Any?): Boolean = myOriginalContainer == other\n  override fun errorOccurred(errorMessage: String) = myOriginalContainer.errorOccurred(errorMessage)\n\n  override fun addStackFrames(stackFrames: MutableList<out XStackFrame>, toSelect: XStackFrame?, last: Boolean) {\n    if (!myIsStarted) {\n      myIsStarted = true\n      bluePrintStackTransformer.beginTransformation(myOriginalContainer, project, myProcess, isSupportModuleAvailable)\n    }\n\n    bluePrintStackTransformer.transform(stackFrames).thenApply {\n      if (last) {\n        bluePrintStackTransformer.endTransformation()\n      }\n      when (myOriginalContainer) {\n        is XStackFrameContainerEx -> myOriginalContainer.addStackFrames(it, toSelect, last)\n        else -> myOriginalContainer.addStackFrames(it, last)\n      }\n    }\n  }\n\n  override fun addStackFrames(stackFrames: MutableList<out XStackFrame>, last: Boolean) {\n    addStackFrames(stackFrames, null, last)\n  }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/BlueprintStackTransformer.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger\n\nimport com.intellij.internal.statistic.StructuredIdeActivity\nimport com.intellij.openapi.diagnostic.debug\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.util.NlsSafe\nimport com.intellij.openapi.util.SystemInfo\nimport com.intellij.xdebugger.Obsolescent\nimport com.intellij.xdebugger.frame.XStackFrame\nimport com.jetbrains.cidr.execution.debugger.CidrDebugProcess\nimport com.jetbrains.cidr.execution.debugger.CidrStackFrame\nimport com.jetbrains.rd.ide.model.unrealModel\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.UnrealPluginUsagesCollector\nimport com.jetbrains.rider.plugins.unreal.debugger.frames.BlueprintFrame\nimport com.jetbrains.rider.plugins.unreal.debugger.frames.StubBlueprintFrame\nimport com.jetbrains.rider.plugins.unreal.debugger.frames.UnrealExternalCodeFrame\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanelSettings\nimport com.jetbrains.rider.projectView.solution\nimport java.util.concurrent.CompletableFuture\nimport java.util.concurrent.atomic.AtomicInteger\n\nclass BlueprintStackTransformer {\n  companion object {\n    private val myInstanceCounter: AtomicInteger = AtomicInteger(0)\n  }\n\n  private var myOverallTransformActivity: StructuredIdeActivity? = null\n  private var myBatchNumber: Int = 0\n  private var myRiderModuleIsAvailable: Boolean? = null\n  private var myProcess: CidrDebugProcess? = null\n  private var myPreviousFrame: XStackFrame? = null\n  private var myObsolescent: Obsolescent? = null\n  private var myProject: Project? = null\n  private var myCachedBlueprintCallstack: MutableList<BlueprintCallFrame>? = null\n\n  @NlsSafe\n  private var myCachedErrorForBlueprintCallstack: String? = null\n  private var myTopFrame: XStackFrame? = null\n  private var myUnrealEngineLocation: String? = null\n\n  private var myLastCollapsedFrame: UnrealExternalCodeFrame? = null\n\n  private val myInstanceNumber: Int = myInstanceCounter.incrementAndGet()\n\n  fun beginTransformation(obsolescent: Obsolescent, project: Project, process: CidrDebugProcess, isSupportModuleAvailable: Boolean) {\n    UnrealDebuggerLogger.logger.debug {\n      \"Begin transformation of blueprint stack frames. Project: ${project.name}\" +\n      \" process: ${process.runParameters}\" +\n      \" isSupportModuleAvailable: ${isSupportModuleAvailable}\" +\n      \" myInstanceNumber: ${myInstanceNumber}\"\n    }\n    myPreviousFrame = null\n    myCachedBlueprintCallstack = null\n    myCachedErrorForBlueprintCallstack = null\n    myTopFrame = null\n\n    myRiderModuleIsAvailable = isSupportModuleAvailable\n\n    myLastCollapsedFrame = null\n\n    myObsolescent = obsolescent\n    myProject = project\n    myProcess = process\n\n    myUnrealEngineLocation = project.solution.unrealModel.unrealEngineLocation.valueOrNull\n    if (myUnrealEngineLocation == null) {\n      UnrealDebuggerLogger.logger.warn(\"Unreal Engine location is not set, project: ${project.name}\")\n    }\n\n    propertyInitializedInvariant()\n\n    myBatchNumber = 0\n    myOverallTransformActivity = UnrealPluginUsagesCollector.startBlueprintStackTransformActivity(project, isSupportedPlatform(),\n                                                                                                  isSupportModuleAvailable,\n                                                                                                  isBlueprintCallstackEnabled(),\n                                                                                                  isShowUnrealFramesEnabled())\n  }\n\n  fun endTransformation() {\n    UnrealDebuggerLogger.logger.debug { \"End transformation of blueprint stack frames. myInstanceNumber: ${myInstanceNumber}\" }\n    myOverallTransformActivity?.finished()\n  }\n\n  private fun propertyInitializedInvariant() {\n    assert(myProject != null)\n    assert(myProcess != null)\n    assert(myObsolescent != null)\n  }\n\n  fun transform(stackFrames: List<XStackFrame?>): CompletableFuture<List<XStackFrame?>> {\n    UnrealDebuggerLogger.logger.debug {\n      \"Transforming blueprint stack frames. myInstanceNumber: ${myInstanceNumber}\" +\n      \" stackFrames: ${stackFrames.size}\"\n    }\n\n    myBatchNumber++\n    val transformActivity = UnrealPluginUsagesCollector.startBlueprintStackTransformBatchActivity(myProject, myOverallTransformActivity,\n                                                                                                  myBatchNumber, stackFrames.size)\n\n    return transformInternalAsync(stackFrames, transformActivity).handle { okResult, exception ->\n      transformActivity?.finished()\n\n      if (exception != null) {\n        throw exception\n      }\n\n      okResult\n    }\n  }\n\n  private fun transformInternalAsync(stackFrames: List<XStackFrame?>,\n                                     transformActivity: StructuredIdeActivity?): CompletableFuture<List<XStackFrame?>> {\n    if (!isSupportedPlatform()) return CompletableFuture.completedFuture(stackFrames)\n\n    if (myProject == null || (!isBlueprintCallstackEnabled() && isShowUnrealFramesEnabled())) {\n      return CompletableFuture.completedFuture(stackFrames)\n    }\n\n    propertyInitializedInvariant()\n\n    if (myTopFrame == null) {\n      myTopFrame = stackFrames.firstOrNull()\n    }\n\n    val stackWithInjectedBlueprint = injectBlueprintFunctions(stackFrames, transformActivity)\n    return stackWithInjectedBlueprint.thenApply(::collapseExternalCodeFrames)\n  }\n\n  private fun collapseExternalCodeFrames(stackFrames: List<XStackFrame?>): List<XStackFrame?> {\n    if (isShowUnrealFramesEnabled() || myUnrealEngineLocation == null) {\n      return stackFrames\n    }\n    val frames = mutableListOf<XStackFrame?>()\n    var exCodeFramesCount = 0\n\n    var index = 0\n    var equalityObject: Any? = null\n    for (frame in stackFrames) {\n      index++\n\n      if (shouldFrameBeCollapsed(frame)) {\n        exCodeFramesCount++\n        equalityObject = frame?.equalityObject\n        continue\n      }\n\n      if (exCodeFramesCount > 0) {\n\n        updateOrAddCollapsedFrame(frames, exCodeFramesCount, equalityObject ?: index)\n        exCodeFramesCount = 0\n        equalityObject = null\n      }\n\n      frames.add(frame)\n      myLastCollapsedFrame = null\n    }\n    index++\n\n    if (exCodeFramesCount > 0) {\n      updateOrAddCollapsedFrame(frames, exCodeFramesCount, equalityObject ?: index)\n    }\n\n    return frames\n  }\n\n  private fun updateOrAddCollapsedFrame(frames: MutableList<XStackFrame?>, newCollapsedCount: Int, equalityObject: Any) {\n    if (myLastCollapsedFrame != null) {\n      myLastCollapsedFrame!!.collapsedFramesCount += newCollapsedCount\n    }\n    else {\n      val newCollapsedFrame = UnrealExternalCodeFrame(equalityObject, newCollapsedCount)\n      frames.add(newCollapsedFrame)\n      myLastCollapsedFrame = newCollapsedFrame\n    }\n  }\n\n  private fun shouldFrameBeCollapsed(frame: XStackFrame?): Boolean {\n\n    if (frame == myTopFrame) {\n      return false\n    }\n\n    if (frame !is CidrStackFrame) {\n      return false\n    }\n\n    if (frame.sourcePosition?.file?.path?.startsWith(myUnrealEngineLocation!!, ignoreCase = true) == true) {\n      return true\n    }\n\n    return false\n  }\n\n  private fun initializeBlueprintDataForStack(frame: CidrStackFrame, parentActivity: StructuredIdeActivity?): CompletableFuture<Void> {\n\n    var featureResult: CompletableFuture<Void> = CompletableFuture.completedFuture(null)\n\n    if (myRiderModuleIsAvailable == false) {\n      myCachedErrorForBlueprintCallstack = UnrealLinkBundle.message(\n        \"RiderLink.Unreal.Debugger.BlueprintCallstack.Blueprint.StubFrame.InstallRiderLink\")\n      return featureResult\n    }\n\n    if (myCachedBlueprintCallstack != null) {\n      return featureResult\n    }\n\n    if (myCachedErrorForBlueprintCallstack != null) {\n      return featureResult\n    }\n\n    featureResult = myProcess!!.postCommand { driver ->\n      if (myObsolescent?.isObsolete == true) return@postCommand\n\n      val activity = UnrealPluginUsagesCollector.startBlueprintStackGettingDataActivity(myProject, parentActivity)\n\n      val bpStackData: String\n      try {\n        bpStackData = driver.executeInterpreterCommand(frame.threadId, frame.frameIndex,\n                                                       \"jb_unreal_blueprint_get_stack ${frame.thread.tid}\").trim()\n      }\n      finally {\n        activity?.finished()\n      }\n\n      when {\n        bpStackData.startsWith(\"NONE_BP_FRAMES\") || bpStackData.startsWith(\"ERROR_BP_FRAMES\") || bpStackData.isEmpty() -> {\n          myCachedErrorForBlueprintCallstack = UnrealLinkBundle.message(\n            \"RiderLink.Unreal.Debugger.BlueprintCallstack.Blueprint.StubFrame.UnspecifiedError\")\n        }\n        bpStackData.startsWith(\"ERROR_AV_EXCEPTION\") -> {\n          myCachedErrorForBlueprintCallstack = UnrealLinkBundle.message(\n            \"RiderLink.Unreal.Debugger.BlueprintCallstack.Blueprint.StubFrame.EvaluationFailed\")\n        }\n        else -> {\n          myCachedBlueprintCallstack = decodeBlueprintCallFrames(bpStackData)\n        }\n      }\n    }\n\n    return featureResult\n\n  }\n\n  private fun processStackFramesSynchronously(stackFrames: List<XStackFrame?>): List<XStackFrame?> {\n    if (myCachedBlueprintCallstack != null) {\n      return addBlueprintFramesToStack(stackFrames)\n    }\n\n    return addBlueprintStubFramesToStack(stackFrames)\n  }\n\n  private fun addBlueprintFramesToStack(stackFrames: List<XStackFrame?>): MutableList<XStackFrame?> {\n    val result = mutableListOf<XStackFrame?>()\n\n    var bpIndex = 0\n    for (current in stackFrames) {\n      if (current !is CidrStackFrame) {\n        result.add(current)\n        continue\n      }\n\n      bpIndex = createBlueprintFrame(current.equalityObject!!, bpIndex, myCachedBlueprintCallstack!!, current.frameIndex, result)\n\n      result.add(current)\n    }\n    return result\n  }\n\n  private fun injectBlueprintFunctions(stackFrames: List<XStackFrame?>,\n                                       parentActivity: StructuredIdeActivity?): CompletableFuture<List<XStackFrame?>> {\n    if (myProject == null || !isBlueprintCallstackEnabled()) {\n      return CompletableFuture.completedFuture(stackFrames)\n    }\n\n    if (myObsolescent?.isObsolete == true) {\n      return CompletableFuture.completedFuture(stackFrames)\n    }\n\n    if (!isProcessingNeeds(stackFrames)) {\n      myPreviousFrame = stackFrames.lastOrNull()\n      return CompletableFuture.completedFuture(stackFrames)\n    }\n\n    assert(stackFrames.isNotEmpty())\n\n    val firstFrame = stackFrames.firstOrNull { it is CidrStackFrame } as? CidrStackFrame ?: return CompletableFuture.completedFuture(\n      stackFrames)\n\n    return initializeBlueprintDataForStack(firstFrame, parentActivity).thenApply { processStackFramesSynchronously(stackFrames) }\n  }\n\n  private fun addBlueprintStubFramesToStack(stackFrames: List<XStackFrame?>): MutableList<XStackFrame?> {\n    assert(myCachedErrorForBlueprintCallstack != null)\n\n    val resultWithStubs = mutableListOf<XStackFrame?>()\n\n    stackFrames.forEachIndexed { index, currentFrame ->\n      var found = false\n      if (currentFrame is CidrStackFrame && index > 0) {\n        val previousCidrFrame = stackFrames[index - 1]\n        if (BlueprintCallstackFrameCompatibilityMatcher.matchFrames(currentFrame, previousCidrFrame).isMatched) {\n          found = true\n        }\n      }\n\n      resultWithStubs.add(currentFrame)\n      if (found) {\n        val stubFrame = StubBlueprintFrame(currentFrame!!.equalityObject!!, myCachedErrorForBlueprintCallstack!!)\n        resultWithStubs.add(stubFrame)\n      }\n    }\n    return resultWithStubs\n  }\n\n  private fun createBlueprintFrame(frameEqualityObject: Any,\n                                   bpIndex: Int,\n                                   decodeBlueprintCallFrames: List<BlueprintCallFrame>,\n                                   frameIndex: Int,\n                                   result: MutableList<XStackFrame?>): Int {\n    var bpIndexLocal = bpIndex\n    if (bpIndexLocal >= decodeBlueprintCallFrames.size) return bpIndexLocal\n\n    val bpFrame = decodeBlueprintCallFrames[bpIndexLocal]\n\n    if (frameIndex != bpFrame.originalFrameIndex) return bpIndexLocal\n\n    var functionFullName = bpFrame.functionFullName\n\n    @Suppress(\"SpellCheckingInspection\") val ubergraphConst = \"ExecuteUbergraph\"\n\n    if (functionFullName.contains(\"${ubergraphConst}_${bpFrame.objectName}\")) {\n      functionFullName = \"Event Graph\"\n    }\n\n    result.add(BlueprintFrame(frameEqualityObject, bpFrame.objectName, bpFrame.functionDisplayName, functionFullName))\n\n    bpIndexLocal++\n\n    return bpIndexLocal\n  }\n\n  private fun decodeBlueprintCallFrames(input: String): MutableList<BlueprintCallFrame> {\n    if (input.isEmpty()) return mutableListOf()\n    val result = mutableListOf<BlueprintCallFrame>()\n    input.splitToSequence(\"<<<!!!\").forEach {\n      val parts = it.split(\"^^^\")\n      if (parts.size >= 4) {\n        result.add(BlueprintCallFrame(parts[0].toInt(), parts[1], parts[2], parts[3]))\n      }\n      else {\n        throw IllegalArgumentException(\"Invalid line format: $it\")\n      }\n    }\n    return result\n  }\n\n  private fun isProcessingNeeds(stackFrames: List<XStackFrame?>): Boolean {\n    if (stackFrames.isEmpty()) return false\n\n    if (BlueprintCallstackFrameCompatibilityMatcher.matchFrames(stackFrames.first(), myPreviousFrame).isMatched) {\n      return true\n    }\n\n    for (i in 1 until stackFrames.size) {\n      if (BlueprintCallstackFrameCompatibilityMatcher.matchFrames(stackFrames[i], stackFrames[i - 1]).isMatched) {\n        return true\n      }\n    }\n    return false\n  }\n\n  private fun isBlueprintCallstackEnabled(): Boolean {\n    assert(myProject != null)\n\n    return UnrealLogPanelSettings.getInstance(myProject!!).showBlueprintCallstack\n  }\n\n  private fun isShowUnrealFramesEnabled(): Boolean {\n    assert(myProject != null)\n\n    return UnrealLogPanelSettings.getInstance(myProject!!).showUnrealFrames\n  }\n\n  private fun isSupportedPlatform(): Boolean {\n    return SystemInfo.isWindows\n  }\n\n  data class BlueprintCallFrame(val originalFrameIndex: Int,\n                                val functionFullName: String,\n                                val objectName: String,\n                                val functionDisplayName: String)\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/UnrealDebugProcessExtension.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger\n\nimport com.jetbrains.cidr.execution.debugger.CidrDebugProcess\nimport com.jetbrains.cidr.execution.debugger.CidrExecutionStack\nimport com.jetbrains.cidr.execution.debugger.CidrSuspensionCause\nimport com.jetbrains.cidr.execution.debugger.backend.LLFrame\nimport com.jetbrains.cidr.execution.debugger.backend.LLModule\nimport com.jetbrains.cidr.execution.debugger.backend.LLThread\nimport com.jetbrains.cidr.execution.debugger.backend.LLValue\nimport com.jetbrains.rider.cpp.debugger.RiderCppDebugProcess\n\nclass UnrealDebugProcessExtension : com.jetbrains.rider.cpp.debugger.RiderCppDebugProcessExtension {\n  private val mySupportModuleIsAvailableKey = com.intellij.openapi.util.Key<Boolean>(\"riderDebuggingSupportModuleIsAvailable\")\n  private val myIsUnrealHostKey = com.intellij.openapi.util.Key<Boolean>(\"riderIsUnrealHost\")\n\n  override fun getExecutionStack(process: RiderCppDebugProcess,\n                                 thread: LLThread,\n                                 frame: LLFrame?,\n                                 current: Boolean,\n                                 cause: CidrSuspensionCause?,\n                                 returnValue: LLValue?): CidrExecutionStack? {\n    initIsUnrealHost(process)\n\n    if (!process.getUserData(myIsUnrealHostKey)!!) return null\n\n    val isSupportModuleAvailable = process.getUserData(mySupportModuleIsAvailableKey) ?: false\n\n    return BlueprintExecutionStack(process, thread, frame, current, cause, returnValue, isSupportModuleAvailable)\n  }\n\n  override fun handleModulesLoaded(debugProcess: RiderCppDebugProcess, changedModules: MutableList<LLModule>) {\n    debugProcess.getUserData(mySupportModuleIsAvailableKey).let {\n      if (it == true) return\n    }\n\n    if (!containsRiderDebuggerSupportModule(changedModules)) return\n\n    debugProcess.putUserData(mySupportModuleIsAvailableKey, true)\n  }\n\n  override fun handleModulesUnloaded(debugProcess: RiderCppDebugProcess, changedModules: MutableList<LLModule>) {\n    debugProcess.getUserData(mySupportModuleIsAvailableKey).let {\n      if (it != true) return\n    }\n\n    if (!containsRiderDebuggerSupportModule(changedModules)) return\n\n    debugProcess.putUserData(mySupportModuleIsAvailableKey, false)\n  }\n\n  private fun containsRiderDebuggerSupportModule(modules: MutableList<LLModule>): Boolean {\n    return modules.any { it.path.contains(\"RiderDebuggerSupport\", ignoreCase = true) }\n  }\n\n  private fun initIsUnrealHost(debugProcess: CidrDebugProcess) {\n    debugProcess.getUserData(myIsUnrealHostKey).let {\n      if (it != null) return\n    }\n\n    val project = debugProcess.project\n    val host = com.jetbrains.rider.plugins.unreal.UnrealHost.getInstance(project)\n    debugProcess.putUserData(myIsUnrealHostKey, host.isUnrealEngineSolution)\n\n  }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/UnrealDebuggerLogger.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger\n\nimport com.jetbrains.rd.platform.util.getLogger\n\ninternal class UnrealDebuggerLogger {\n    companion object {\n        val logger = getLogger<UnrealDebuggerLogger>()\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/actions/FramesPopupGroup.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.actions\n\nimport com.intellij.icons.AllIcons\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.actionSystem.DefaultActionGroup\nimport com.intellij.openapi.actionSystem.ToggleAction\nimport com.intellij.openapi.project.DumbAware\nimport com.intellij.ui.BadgeIconSupplier\nimport com.jetbrains.rider.plugins.unreal.actions.UnrealHostOperations\n\ninternal class FramesPopupGroup : DefaultActionGroup(), DumbAware {\n  private val FILTER_ICON = BadgeIconSupplier(AllIcons.General.Filter)\n  private val myFilterActiveIcon = FILTER_ICON.getLiveIndicatorIcon(true)\n  private val myFilterInactiveIcon = FILTER_ICON.getLiveIndicatorIcon(false)\n\n  override fun update(e: AnActionEvent) {\n    super.update(e)\n\n    val icon = if (isAllVisibleChildrenSelected(e)) myFilterInactiveIcon else myFilterActiveIcon\n\n    UnrealHostOperations.updatePresentationBasedOnUnrealAvailability(e, icon, icon)\n  }\n\n  private fun isAllVisibleChildrenSelected(e: AnActionEvent): Boolean {\n    getChildren(e).forEach {\n      when (it) {\n        is UnrealToggleBaseAction -> {\n          if (!(!it.isVisible || it.isSelected(e))) return false\n        }\n        is ToggleAction -> {\n          if (!it.isSelected(e)) return false\n        }\n        else -> {\n          assert(false) { \"Unexpected action type: $it\" }\n        }\n      }\n    }\n    return true\n  }\n\n  override fun getActionUpdateThread(): ActionUpdateThread {\n    return ActionUpdateThread.BGT\n  }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/actions/ShowBlueprintFunctionsAction.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.actions\n\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanelSettings\n\n\nclass ShowBlueprintFunctionsAction : UnrealToggleBaseAction() {\n\n  override fun getToggleActionText(settings: UnrealLogPanelSettings): String =\n    \"action.RiderLink.Unreal.Debugger.BlueprintCallstack.show.text\"\n\n  override fun getIsSelected(settings: UnrealLogPanelSettings): Boolean = settings.showBlueprintCallstack\n\n  override fun setSelectedAction(settings: UnrealLogPanelSettings, selected: Boolean) {\n    settings.showBlueprintCallstack = selected\n  }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/actions/ShowLibraryFramesAction.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.actions\n\nimport com.intellij.openapi.actionSystem.ActionManager\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.actionSystem.ToggleAction\nimport com.intellij.openapi.project.DumbAwareToggleAction\nimport com.jetbrains.rider.UnrealLinkBundle\n\ninternal class ShowLibraryFramesAction : DumbAwareToggleAction() {\n\n  override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n  override fun isSelected(e: AnActionEvent): Boolean {\n    return !getBaseAction().isSelected(e)\n  }\n\n  override fun update(e: AnActionEvent) {\n    super.update(e)\n    e.presentation.text = UnrealLinkBundle.message(\"action.RiderLink.Unreal.Debugger.OtherLibrariesFrames.show.text\")\n  }\n\n  override fun setSelected(e: AnActionEvent, state: Boolean) {\n    getBaseAction().setSelected(e, !state)\n  }\n\n  private fun getBaseAction(): ToggleAction = ActionManager.getInstance().getAction(\"Debugger.ShowLibraryFrames\") as ToggleAction\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/actions/ShowUnrealFramesAction.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.actions\n\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanelSettings\n\nclass ShowUnrealFramesAction : UnrealToggleBaseAction() {\n\n  override fun getToggleActionText(settings: UnrealLogPanelSettings): String =\n    \"action.RiderLink.Unreal.Debugger.UnrealFrames.show.text\"\n\n  override fun getIsSelected(settings: UnrealLogPanelSettings): Boolean = settings.showUnrealFrames\n\n  override fun setSelectedAction(settings: UnrealLogPanelSettings, selected: Boolean) {\n    settings.showUnrealFrames = selected\n  }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/actions/UnrealToggleBaseAction.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.actions\n\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.project.DumbAwareToggleAction\nimport com.intellij.openapi.util.NlsActions\nimport com.intellij.openapi.util.SystemInfo\nimport com.intellij.openapi.util.registry.Registry\nimport com.intellij.xdebugger.impl.XDebuggerUtilImpl\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.actions.getUnrealHost\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanelSettings\n\n\nabstract class UnrealToggleBaseAction : DumbAwareToggleAction() {\n  var isVisible: Boolean = true\n    private set\n\n  override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT\n\n  override fun update(e: AnActionEvent) {\n    super.update(e)\n\n    if (!Registry.`is`(\"rider.cpp.enable.debugger.unreal.blueprint-callstack\")\n        || !SystemInfo.isWindows) {\n      e.presentation.isEnabledAndVisible = false\n      isVisible = e.presentation.isVisible\n      return\n    }\n\n    val project = e.project ?: return\n    if (!isHostAvailable(e)) return\n\n    e.presentation.isEnabledAndVisible = true\n\n    val settings = UnrealLogPanelSettings.getInstance(project)\n    e.presentation.text = UnrealLinkBundle.message(getToggleActionText(settings))\n\n    isVisible = e.presentation.isVisible\n  }\n\n  private fun isHostAvailable(e: AnActionEvent): Boolean = e.getUnrealHost() != null\n\n  @NlsActions.ActionText\n  abstract fun getToggleActionText(settings: UnrealLogPanelSettings): String\n\n  override fun isSelected(e: AnActionEvent): Boolean {\n    val project = e.project ?: return false\n    val settings = UnrealLogPanelSettings.getInstance(project)\n    return getIsSelected(settings)\n  }\n\n  abstract fun getIsSelected(settings: UnrealLogPanelSettings): Boolean\n\n  override fun setSelected(e: AnActionEvent, selected: Boolean) {\n    val project = e.project ?: return\n    val settings = UnrealLogPanelSettings.getInstance(project)\n    setSelectedAction(settings, selected)\n\n    XDebuggerUtilImpl.rebuildAllSessionsViews(e.project)\n  }\n\n  abstract fun setSelectedAction(settings: UnrealLogPanelSettings, selected: Boolean)\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/frames/BlueprintFrame.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.frames\n\nimport com.intellij.openapi.util.NlsSafe\nimport com.intellij.openapi.util.Pair\nimport com.intellij.ui.ColoredTextContainer\nimport com.intellij.ui.SimpleTextAttributes\n\nclass BlueprintFrame(private val baseFrameEqualityObject: Any,\n                     @NlsSafe private val objectName: String,\n                     @NlsSafe private val functionDisplayName: String,\n                     @NlsSafe private val functionFullName: String) : UnrealFrameBase() {\n\n  override fun getEqualityObject(): Any {\n    return Pair.create(baseFrameEqualityObject, objectName + functionDisplayName + functionFullName)\n  }\n\n  override fun customizePresentation(component: ColoredTextContainer) {\n    component.append(blueprintTitlePrefix, SimpleTextAttributes.GRAYED_ATTRIBUTES)\n\n    component.append(\"$objectName: \", SimpleTextAttributes.REGULAR_ATTRIBUTES)\n    component.append(\"$functionDisplayName \", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES)\n    component.append(\" $functionFullName\", SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES)\n  }\n\n}\n\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/frames/BlueprintFrameMessages.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.frames\n\nimport com.jetbrains.rider.UnrealLinkBundle\n\nval blueprintTitlePrefix = \"[${UnrealLinkBundle.message(\"RiderLink.Unreal.Debugger.BlueprintCallstack.Blueprint.title\")}] \"\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/frames/StubBlueprintFrame.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.frames\n\nimport com.intellij.openapi.util.NlsSafe\nimport com.intellij.openapi.util.Pair\nimport com.intellij.ui.ColoredTextContainer\nimport com.intellij.ui.SimpleTextAttributes\n\nclass StubBlueprintFrame(private val baseFrameEqualityObject: Any, @NlsSafe private val titleResource: String) : UnrealFrameBase() {\n\n  override fun getEqualityObject(): Any {\n    return Pair.create(baseFrameEqualityObject, titleResource)\n  }\n\n  override fun customizePresentation(component: ColoredTextContainer) {\n\n    component.append(blueprintTitlePrefix, SimpleTextAttributes.GRAYED_ATTRIBUTES)\n\n    component.append(titleResource, SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES)\n  }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/frames/UnrealExternalCodeFrame.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.frames\n\nimport com.intellij.openapi.util.NlsSafe\nimport com.intellij.openapi.util.Pair\nimport com.intellij.ui.ColoredTextContainer\nimport com.intellij.ui.SimpleTextAttributes\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.debugger.DotNetStackFrame\nimport com.jetbrains.rider.debugger.RiderDebuggerBundle\n\nclass UnrealExternalCodeFrame(private val baseFrameEqualityObject: Any, var collapsedFramesCount: Int) : UnrealFrameBase() {\n\n  companion object {\n    @NlsSafe\n    private val myCodePrefix = \"${UnrealLinkBundle.message(\"RiderLink.Unreal.Debugger.BlueprintCallstack.UnrealEngineCode.title\")} \"\n\n    @NlsSafe\n    private val myCodeSuffix = UnrealLinkBundle.message(\"RiderLink.Unreal.Debugger.BlueprintCallstack.UnrealEngineCode.suffix\")\n  }\n\n  override fun getEqualityObject(): Any {\n    return Pair.create(baseFrameEqualityObject, collapsedFramesCount)\n  }\n\n  @Suppress(\"ConvertToStringTemplate\")\n  override fun customizePresentation(component: ColoredTextContainer) {\n    component.append(\"[\", SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, DotNetStackFrame.ExternalCodeSecondColor))\n    component.append(myCodePrefix, SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, DotNetStackFrame.ExternalCodeSecondColor))\n    component.append(collapsedFramesCount.toString() + \" \",\n                     SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, DotNetStackFrame.ExternalCodeSecondColor))\n    component.append((if (collapsedFramesCount == 1)\n                                RiderDebuggerBundle.message(\"ExternalCodeMetaFrame.single.frame.text\")\n                              else\n                                RiderDebuggerBundle.message(\"ExternalCodeMetaFrame.multiple.frames.text\")) + \" \",\n                     SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, DotNetStackFrame.ExternalCodeSecondColor))\n    component.append(myCodeSuffix + \"]\", SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, DotNetStackFrame.ExternalCodeSecondColor))\n  }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/debugger/frames/UnrealFrameBase.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.debugger.frames\n\nopen class UnrealFrameBase : com.intellij.xdebugger.frame.XStackFrame() {\n  override fun equals(other: Any?): Boolean {\n    if (this === other) return true\n    if (other == null || javaClass != other.javaClass) return false\n\n    val frame: UnrealFrameBase = other as UnrealFrameBase\n\n    return frame.equalityObject == equalityObject\n  }\n\n  override fun hashCode(): Int {\n    return equalityObject.hashCode()\n  }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/filters/linkInfo/BlueprintClassHyperLinkInfo.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.filters.linkInfo\n\nimport com.intellij.execution.filters.HyperlinkInfo\nimport com.intellij.openapi.project.Project\nimport com.jetbrains.rd.util.getLogger\nimport com.jetbrains.rd.util.info\nimport com.jetbrains.rd.util.reactive.ISignal\nimport com.jetbrains.rider.plugins.unreal.model.BlueprintReference\n\nclass BlueprintClassHyperLinkInfo(private val navigation: ISignal<BlueprintReference>, private val struct: BlueprintReference) : HyperlinkInfo {\n    companion object {\n        val logger = getLogger<BlueprintClassHyperLinkInfo>()\n    }\n\n    override fun navigate(project: Project) {\n        logger.info { \"[UnrealLink]: navigate by $struct\" }\n\n        navigation.fire(struct)\n    }\n\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/filters/linkInfo/BlueprintFunctionHyperLinkInfo.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.filters.linkInfo\n\nimport com.intellij.execution.filters.HyperlinkInfo\nimport com.intellij.openapi.project.Project\nimport com.jetbrains.rd.util.getLogger\nimport com.jetbrains.rd.util.info\nimport com.jetbrains.rd.util.reactive.ISignal\nimport com.jetbrains.rider.plugins.unreal.model.BlueprintFunction\n\nclass BlueprintFunctionHyperLinkInfo(private val navigation: ISignal<BlueprintFunction>, private val function: BlueprintFunction) : HyperlinkInfo {\n    companion object {\n        val logger = getLogger<BlueprintFunctionHyperLinkInfo>()\n    }\n\n    override fun navigate(project: Project) {\n        logger.info { \"navigate by $function\" }\n\n        navigation.fire(function)\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/filters/linkInfo/MethodReferenceHyperLinkInfo.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.filters.linkInfo\n\nimport com.intellij.execution.filters.HyperlinkInfo\nimport com.intellij.openapi.project.Project\nimport com.jetbrains.rd.framework.impl.startAndAdviseSuccess\nimport com.jetbrains.rd.util.getLogger\nimport com.jetbrains.rd.util.info\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.MethodReference\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.RdRiderModel\n\nclass MethodReferenceHyperLinkInfo(private val model: RdRiderModel,\n                                   private val methodReference: MethodReference) : HyperlinkInfo {\n    companion object {\n        val logger = getLogger<BlueprintFunctionHyperLinkInfo>()\n    }\n\n    override fun navigate(project: Project) {\n        UnrealClassHyperLinkInfo.logger.info { \"checking methodReference '$methodReference'\" }\n        model.isMethodReference.startAndAdviseSuccess(methodReference) {\n            if (!it) return@startAndAdviseSuccess\n\n            logger.info { \"navigate to '$methodReference'\" }\n            model.navigateToMethod.fire(methodReference)\n        }\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/filters/linkInfo/UnrealClassHyperLinkInfo.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.filters.linkInfo\n\nimport com.intellij.execution.filters.HyperlinkInfo\nimport com.intellij.openapi.project.Project\nimport com.jetbrains.rd.framework.impl.startAndAdviseSuccess\nimport com.jetbrains.rd.util.getLogger\nimport com.jetbrains.rd.util.info\nimport com.jetbrains.rider.plugins.unreal.model.UClass\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.MethodReference\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.RdRiderModel\n\nclass UnrealClassHyperLinkInfo(private val model: RdRiderModel,\n                               private val methodReference: MethodReference,\n                               private val uClass: UClass) : HyperlinkInfo {\n    companion object {\n        val logger = getLogger<UnrealClassHyperLinkInfo>()\n    }\n\n    override fun navigate(project: Project) {\n        logger.info { \"checking methodReference '$methodReference'\" }\n        model.isMethodReference.startAndAdviseSuccess(methodReference) {\n            if (!it) return@startAndAdviseSuccess\n\n            logger.info { \"navigate to '$uClass'\" }\n            model.navigateToClass.fire(uClass)\n        }\n    }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/notifications/OutOfSyncPluginProtocolListener.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.notifications\n\nimport com.intellij.notification.NotificationAction\nimport com.intellij.notification.NotificationGroupManager\nimport com.intellij.notification.NotificationType\nimport com.intellij.notification.Notifications\nimport com.intellij.openapi.client.ClientProjectSession\nimport com.jetbrains.rd.protocol.SolutionExtListener\nimport com.jetbrains.rd.util.lifetime.Lifetime\nimport com.jetbrains.rd.util.reactive.adviseNotNull\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.actions.installOrExtractPluginInGame\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.ForceInstall\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.InstallPluginDescription\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.PluginInstallLocation\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.PluginInstallStatus\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.RdRiderModel\n\nclass OutOfSyncPluginProtocolListener : SolutionExtListener<RdRiderModel> {\n    companion object {\n        private const val OUT_OF_SYNC_NOTIFICATION_GROUP_ID = \"OutOfSyncConnection\"\n    }\n\n    override fun extensionCreated(lifetime: Lifetime, session: ClientProjectSession, model: RdRiderModel) {\n        model.onEditorPluginOutOfSync.adviseNotNull(lifetime) {\n            if (it.status == PluginInstallStatus.UpToDate) return@adviseNotNull\n\n            val message = if (it.status == PluginInstallStatus.NoPlugin)\n                UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.description.notInstalled\")\n            else\n                UnrealLinkBundle.message(\n                    \"notificationAction.UnrealEditorOutOfSync.description.wrongVersion\"\n                )\n\n            val title = if (it.status == PluginInstallStatus.NoPlugin)\n                UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.title.notInstalled\")\n            else\n                UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.title.wrongVersion\")\n\n            val notification = NotificationGroupManager.getInstance()\n                .getNotificationGroup(OUT_OF_SYNC_NOTIFICATION_GROUP_ID)\n                .createNotification(title, message, NotificationType.WARNING)\n\n            when (it.status) {\n                PluginInstallStatus.NoPlugin -> {\n                    notification.apply {\n                        addAction(NotificationAction.createSimple(UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.installPluginInEngine.text\")) {\n                            expire()\n                            model.installEditorPlugin.fire(\n                                InstallPluginDescription(PluginInstallLocation.Engine, ForceInstall.No, true, emptyList(), emptyList())\n                            )\n                        })\n                        if (it.isGameAvailable) addAction(NotificationAction.createSimple(UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.installPluginInGame.text\")) {\n                            expire()\n                            installOrExtractPluginInGame(session.project, ForceInstall.No, buildRequired = true)\n                        })\n                    }\n                }\n                PluginInstallStatus.InEngine -> {\n                    notification.apply {\n                        addAction(NotificationAction.createSimple(UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.installPluginInEngine.text.update\")) {\n                            expire()\n                            model.installEditorPlugin.fire(\n                                InstallPluginDescription(PluginInstallLocation.Engine, ForceInstall.No, true, emptyList(), emptyList())\n                            )\n                        })\n                        if (it.isGameAvailable) addAction(NotificationAction.createSimple(UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.installPluginInGame.text.move\")) {\n                            expire()\n                            installOrExtractPluginInGame(session.project, ForceInstall.No, buildRequired = true)\n                        })\n                    }\n                }\n                PluginInstallStatus.InGame -> {\n                    notification.apply {\n                        addAction(NotificationAction.createSimple(UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.installPluginInEngine.text.move\")) {\n                            expire()\n                            model.installEditorPlugin.fire(\n                                InstallPluginDescription(PluginInstallLocation.Engine, ForceInstall.No, true, emptyList(), emptyList())\n                            )\n                        })\n                        if (it.isGameAvailable) addAction(NotificationAction.createSimple(UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.installPluginInGame.text.update\")) {\n                            expire()\n                            installOrExtractPluginInGame(session.project, ForceInstall.No, buildRequired = true)\n                        })\n                    }\n                }\n                else -> return@adviseNotNull\n            }\n\n            Notifications.Bus.notify(notification, session.project)\n        }\n    }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/spellchecker/UnrealBundledDictionaryProvider.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.spellchecker\n\nimport com.intellij.spellchecker.BundledDictionaryProvider\n\nclass UnrealBundledDictionaryProvider : BundledDictionaryProvider {\n    override fun getBundledDictionaries(): Array<String> = arrayOf(\"unreal.dic\")\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/toolWindow/UnrealToolWindowFactory.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.toolWindow\n\nimport com.intellij.ide.impl.ContentManagerWatcher\nimport com.intellij.openapi.components.Service\nimport com.intellij.openapi.components.service\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.rd.util.lifetime\nimport com.intellij.openapi.util.Disposer\nimport com.intellij.openapi.wm.RegisterToolWindowTask\nimport com.intellij.openapi.wm.ToolWindow\nimport com.intellij.openapi.wm.ToolWindowAnchor\nimport com.intellij.openapi.wm.ToolWindowManager\nimport com.intellij.ui.content.ContentManagerEvent\nimport com.intellij.ui.content.ContentManagerListener\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanel\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanelSettings\nimport com.jetbrains.rider.ui.toolWindow.RiderOnDemandToolWindowFactory\nimport icons.UnrealIcons\n\n@Suppress(\"UnstableApiUsage\")\n@Service(Service.Level.PROJECT)\nclass UnrealToolWindowFactory(val project: Project)\n    : RiderOnDemandToolWindowFactory<String>(project, TOOLWINDOW_ID, { it }, ::UnrealLogPanel, { it }) {\n\n    companion object {\n        const val TOOLWINDOW_ID = \"UnrealLink\"\n        val TITLE_ID =  UnrealLinkBundle.message(\"RiderLink.UnrealEditorLog.text.title\")\n\n        fun getInstance(project: Project): UnrealToolWindowFactory = project.service()\n    }\n\n    override fun registerToolWindow(toolWindowManager: ToolWindowManager, project: Project): ToolWindow {\n        val toolWindow = toolWindowManager.registerToolWindow(\n                RegisterToolWindowTask(\n                    id = TOOLWINDOW_ID, anchor = ToolWindowAnchor.BOTTOM,\n                    icon = UnrealIcons.ToolWindow.UnrealToolWindow,\n                    canCloseContent = false, canWorkInDumbMode = true, sideTool = false\n                )\n        )\n        toolWindow.title = UnrealLinkBundle.message(\"toolWindow.UnrealLog.title\")\n\n        val contentManager = toolWindow.contentManager\n        contentManager.addContentManagerListener(object : ContentManagerListener {\n            override fun contentAdded(event: ContentManagerEvent) {\n                // hacky way to fix memory leaks on exit\n                val content = event.content.component as UnrealLogPanel\n                Disposer.register(toolWindow.disposable, content.console)\n            }\n        })\n\n        ContentManagerWatcher.watchContentManager(toolWindow, contentManager)\n\n        return toolWindow\n    }\n\n    fun showTabForNewSession() {\n        val settings = project.service<UnrealLogPanelSettings>()\n        if (settings.focusOnStart) {\n            showTab(TITLE_ID, project.lifetime)\n        } else {\n            getOrCreateTab(TITLE_ID, project.lifetime)\n        }\n    }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/toolWindow/log/UnrealLogCategoryFilterComboBox.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.toolWindow.log\n\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.DefaultActionGroup\nimport com.intellij.openapi.actionSystem.ex.ComboBoxAction\nimport com.intellij.openapi.project.DumbAware\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.actions.FilterCheckboxAction\nimport javax.swing.JComponent\n\nclass UnrealLogCategoryFilterComboBox(private val settings: UnrealLogPanelSettings,\n                                      private val logFilter: UnrealLogFilter) : ComboBoxAction(), DumbAware {\n    override fun getActionUpdateThread() = ActionUpdateThread.BGT\n\n    init {\n        val presentation = this.templatePresentation\n        presentation.text = UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.categoriesSelection.label\")\n\n        logFilter.addOnCategoryAddedListener(this::onCategoryAdded)\n    }\n\n    private var showAllCategories: Boolean\n        get() = settings.showAllCategories\n        set(value) {\n            if (settings.showAllCategories != value) {\n                logFilter.toggleAllCategories(value)\n                settings.showAllCategories = value\n            }\n        }\n\n\n    private val allSelectedCheckbox: FilterCheckboxAction =\n            FilterCheckboxAction(UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.categories.ShowAll.text\"), ::showAllCategories)\n\n    // sorted list of categories\n    private val categoriesCheckboxes: ArrayList<FilterCheckboxAction> = arrayListOf()\n\n    override fun createPopupActionGroup(parent: JComponent?): DefaultActionGroup {\n        val group = DefaultActionGroup()\n        group.add(allSelectedCheckbox)\n        group.addSeparator()\n        group.addAll(categoriesCheckboxes)\n        return group\n    }\n\n    private fun isCategorySelected(category: String): Boolean = logFilter.isCategorySelected(category)\n\n    private fun selectCategory(category: String, state: Boolean) = logFilter.toggleCategory(category, state)\n\n    private fun onCategoryAdded(category: String) {\n        var idx = categoriesCheckboxes.binarySearchBy(category) { it.templatePresentation.text }\n        if (idx >= 0) return\n\n        val checkbox = FilterCheckboxAction(category,\n                { isCategorySelected(category) },\n                { selectCategory(category, it) }\n        )\n\n        // index to insert\n        idx = -idx - 1\n        categoriesCheckboxes.add(idx, checkbox)\n    }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/toolWindow/log/UnrealLogConsoleActionsPostProcessor.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.toolWindow.log\n\nimport com.intellij.execution.ExecutionBundle\nimport com.intellij.execution.actions.ClearConsoleAction\nimport com.intellij.execution.actions.ConsoleActionsPostProcessor\nimport com.intellij.execution.impl.ConsoleViewImpl\nimport com.intellij.execution.ui.ConsoleView\nimport com.intellij.icons.AllIcons\nimport com.intellij.ide.actions.NextOccurenceToolbarAction\nimport com.intellij.ide.actions.PreviousOccurenceToolbarAction\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.AnAction\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.project.DumbAwareAction\n\nclass UnrealLogConsoleActionsPostProcessor : ConsoleActionsPostProcessor() {\n    override fun postProcess(console: ConsoleView, actions: Array<AnAction>): Array<AnAction> {\n        if (console !is ConsoleViewImpl) {\n            return super.postProcess(console, actions)\n        }\n\n        val consoleParent = console.parent\n        if (consoleParent !is UnrealLogPanel) {\n            return super.postProcess(console, actions)\n        }\n\n        return processActions(consoleParent, actions)\n\n    }\n\n    private fun processActions(panel: UnrealLogPanel, actions: Array<AnAction>): Array<AnAction> {\n        val filteredActions =  actions.filter {\n                    it !is PreviousOccurenceToolbarAction &&\n                            it !is NextOccurenceToolbarAction &&\n                            it !is ClearConsoleAction\n                }.toMutableList()\n        filteredActions.add(ClearUnrealConsoleAction(panel))\n        return filteredActions.toTypedArray()\n    }\n\n    override fun postProcessPopupActions(console: ConsoleView, actions: Array<AnAction>): Array<AnAction> {\n        if (console !is ConsoleViewImpl) {\n            return super.postProcess(console, actions)\n        }\n\n        val consoleParent = console.parent\n        if (consoleParent !is UnrealLogPanel) {\n            return super.postProcess(console, actions)\n        }\n\n        return processPopupActions(consoleParent, actions)\n    }\n\n    private fun processPopupActions(panel: UnrealLogPanel, actions: Array<AnAction>): Array<AnAction> {\n        val filteredActions = actions.filter {\n            it !is ClearConsoleAction\n        }.toMutableList()\n        filteredActions.add(ClearUnrealConsoleAction(panel))\n        return filteredActions.toTypedArray()\n    }\n\n    private class ClearUnrealConsoleAction(private val panel: UnrealLogPanel) :\n            DumbAwareAction(ExecutionBundle.messagePointer(\"clear.all.from.console.action.name\"),\n                    ExecutionBundle.messagePointer(\"clear.all.from.console.action.description\"),\n                    AllIcons.Actions.GC) {\n        override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT\n\n        override fun update(e: AnActionEvent) {\n            val console = panel.console\n            val enabled: Boolean = console.contentSize > 0\n            e.presentation.isEnabled = enabled\n        }\n\n        override fun actionPerformed(e: AnActionEvent) {\n            panel.clear()\n        }\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/toolWindow/log/UnrealLogConsoleViewContentType.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.toolWindow.log\n\nimport com.intellij.execution.ui.ConsoleViewContentType\nimport com.intellij.openapi.editor.colors.TextAttributesKey\nimport org.jetbrains.annotations.NonNls\n\nclass UnrealLogConsoleViewContentType(@NonNls name: String, textAttributesKey: TextAttributesKey)\n    : ConsoleViewContentType(name, textAttributesKey) {\n\n    companion object {\n        val UE_LOG_FATAL_KEY = TextAttributesKey.createTextAttributesKey(\"UE_LOG_FATAL\", LOG_ERROR_OUTPUT_KEY)\n        val UE_LOG_ERROR_KEY = TextAttributesKey.createTextAttributesKey(\"UE_LOG_ERROR\", LOG_ERROR_OUTPUT_KEY)\n        val UE_LOG_WARNING_KEY = TextAttributesKey.createTextAttributesKey(\"UE_LOG_WARNING\", LOG_WARNING_OUTPUT_KEY)\n        val UE_LOG_DISPLAY_KEY = TextAttributesKey.createTextAttributesKey(\"UE_LOG_DISPLAY\", LOG_INFO_OUTPUT_KEY)\n        val UE_LOG_LOG_KEY = TextAttributesKey.createTextAttributesKey(\"UE_LOG_LOG\", LOG_INFO_OUTPUT_KEY)\n        val UE_LOG_VERBOSE_KEY = TextAttributesKey.createTextAttributesKey(\"UE_LOG_VERBOSE\", LOG_DEBUG_OUTPUT_KEY)\n        val UE_LOG_VERY_VERBOSE_KEY = TextAttributesKey.createTextAttributesKey(\"UE_LOG_VERY_VERBOSE\", LOG_DEBUG_OUTPUT_KEY)\n\n        val UE_LOG_FATAL = UnrealLogConsoleViewContentType(\"UE_LOG_FATAL\", UE_LOG_FATAL_KEY)\n        val UE_LOG_ERROR = UnrealLogConsoleViewContentType(\"UE_LOG_ERROR\", UE_LOG_ERROR_KEY)\n        val UE_LOG_WARNING = UnrealLogConsoleViewContentType(\"UE_LOG_WARNING\", UE_LOG_WARNING_KEY)\n        val UE_LOG_DISPLAY = UnrealLogConsoleViewContentType(\"UE_LOG_DISPLAY\", UE_LOG_DISPLAY_KEY)\n        val UE_LOG_LOG = UnrealLogConsoleViewContentType(\"UE_LOG_LOG\", UE_LOG_LOG_KEY)\n        val UE_LOG_VERBOSE = UnrealLogConsoleViewContentType(\"UE_LOG_VERBOSE\", UE_LOG_VERBOSE_KEY)\n        val UE_LOG_VERY_VERBOSE = UnrealLogConsoleViewContentType(\"UE_LOG_VERY_VERBOSE\", UE_LOG_VERY_VERBOSE_KEY)\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/toolWindow/log/UnrealLogFilter.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.toolWindow.log\n\nimport com.intellij.openapi.rd.createNestedDisposable\nimport com.jetbrains.rd.util.lifetime.Lifetime\nimport com.jetbrains.rider.plugins.unreal.model.LogMessageInfo\nimport com.jetbrains.rider.plugins.unreal.model.VerbosityType\n\nclass UnrealLogFilter(lifetime: Lifetime, private val settings: UnrealLogPanelSettings) {\n    private val categories: HashSet<String> = hashSetOf()\n    private val selectedCategories: HashSet<String> = hashSetOf()\n\n    private val filterChangedListeners: ArrayList<() -> Unit> = arrayListOf()\n    private val onCategoryAddedListeners: ArrayList<(String) -> Unit> = arrayListOf()\n\n    init {\n        val disposable = lifetime.createNestedDisposable()\n        settings.addSettingsChangedListener({ onFilterChanged() }, disposable)\n    }\n\n    fun addFilterChangedListener(listener: () -> Unit) {\n        filterChangedListeners.add(listener)\n    }\n\n    private fun onFilterChanged() {\n        filterChangedListeners.forEach { it.invoke() }\n    }\n\n    fun isMessageAllowed(message: LogMessageInfo): Boolean {\n        // see FOutputLogFilter::IsMessageAllowed from SOutputLog.cpp\n\n        // Checking verbosity\n        val verbosity = message.type\n        if (verbosity == VerbosityType.Error && !settings.showErrors) {\n            return false\n        }\n\n        if (verbosity == VerbosityType.Warning && !settings.showWarnings) {\n            return false\n        }\n\n        if (verbosity != VerbosityType.Error && verbosity != VerbosityType.Warning && !settings.showMessages) {\n            return false\n        }\n\n        // Checking if category is selected\n        val category = message.category.data\n        if (category !in selectedCategories) {\n            return false\n        }\n\n        return true\n    }\n\n    fun addCategory(category: String) {\n        if (!categories.add(category)) {\n            return\n        }\n\n        // new categories selected state relies on showAllCategories state\n        val isSelected = settings.showAllCategories\n        if (isSelected) {\n            selectedCategories.add(category)\n        }\n\n        fireOnCategoryAdded(category)\n    }\n\n    fun addOnCategoryAddedListener(listener: (String) -> Unit) {\n        onCategoryAddedListeners.add(listener)\n    }\n\n    private fun fireOnCategoryAdded(category: String) {\n        onCategoryAddedListeners.forEach { it.invoke(category) }\n    }\n\n    fun isCategorySelected(category: String): Boolean {\n        return category in selectedCategories\n    }\n\n    fun toggleCategory(category: String, state: Boolean) {\n        if (state) {\n            selectedCategories.add(category)\n        } else {\n            selectedCategories.remove(category)\n        }\n\n        onFilterChanged()\n    }\n\n    fun toggleAllCategories(state: Boolean) {\n        selectedCategories.clear()\n        if (state) {\n            selectedCategories.addAll(categories)\n        }\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/toolWindow/log/UnrealLogPanel.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.toolWindow.log\n\nimport com.intellij.execution.filters.TextConsoleBuilderFactory\nimport com.intellij.execution.impl.ConsoleViewImpl\nimport com.intellij.execution.ui.ConsoleViewContentType\nimport com.intellij.openapi.actionSystem.ActionManager\nimport com.intellij.openapi.actionSystem.ActionPlaces\nimport com.intellij.openapi.actionSystem.DefaultActionGroup\nimport com.intellij.openapi.application.invokeLater\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.ui.SimpleToolWindowPanel\nimport com.intellij.ui.components.panels.HorizontalLayout\nimport com.jetbrains.rd.util.eol\nimport com.jetbrains.rd.util.lifetime.Lifetime\nimport com.jetbrains.rider.plugins.unreal.filters.linkInfo.BlueprintClassHyperLinkInfo\nimport com.jetbrains.rider.plugins.unreal.filters.linkInfo.MethodReferenceHyperLinkInfo\nimport com.jetbrains.rider.plugins.unreal.filters.linkInfo.UnrealClassHyperLinkInfo\nimport com.jetbrains.rider.plugins.unreal.model.BlueprintReference\nimport com.jetbrains.rider.plugins.unreal.model.FString\nimport com.jetbrains.rider.plugins.unreal.model.LogMessageInfo\nimport com.jetbrains.rider.plugins.unreal.model.StringRange\nimport com.jetbrains.rider.plugins.unreal.model.UClass\nimport com.jetbrains.rider.plugins.unreal.model.UnrealLogEvent\nimport com.jetbrains.rider.plugins.unreal.model.VerbosityType\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.MethodReference\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.projectView.solution\nimport java.awt.BorderLayout\nimport java.util.ArrayDeque\nimport javax.swing.JPanel\n\ninternal class UnrealLogPanel(val tabModel: String, lifetime: Lifetime, val project: Project) : SimpleToolWindowPanel(false) {\n    companion object {\n        private const val MAX_STORED_LOG_DATA_ITEMS = 32 * 1024\n        private const val TIME_WIDTH = 29\n        private const val VERBOSITY_WIDTH = 12\n\n        private fun createConsole(project: Project, lifetime: Lifetime): ConsoleViewImpl {\n            val consoleView = TextConsoleBuilderFactory.getInstance()\n                    .createBuilder(project)\n                    .console as ConsoleViewImpl\n\n            lifetime.bracketIfAlive({\n                // force create console ui\n                consoleView.component\n            }, {\n                consoleView.dispose()\n            })\n\n            return consoleView\n\n        }\n    }\n\n    private val settings: UnrealLogPanelSettings = UnrealLogPanelSettings.getInstance(project)\n\n    private val logData: ArrayDeque<UnrealLogEvent> = ArrayDeque()\n    private val consoleView: ConsoleViewImpl = createConsole(project, lifetime)\n\n    val console: ConsoleViewImpl get() = consoleView\n\n    private val logFilter: UnrealLogFilter = UnrealLogFilter(lifetime, settings)\n    private val verbosityFilterActionGroup: UnrealLogVerbosityFilterComboBox = UnrealLogVerbosityFilterComboBox(settings)\n    private val categoryFilterActionGroup: UnrealLogCategoryFilterComboBox = UnrealLogCategoryFilterComboBox(settings, logFilter)\n    private val settingsActionGroup = UnrealLogSettingsActionGroup(settings)\n\n    init {\n        setContent(consoleView)\n        val actionGroup = DefaultActionGroup().apply {\n            addAll(consoleView.createConsoleActions().toList())\n        }\n\n        val toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.TOOLBAR, actionGroup, myVertical)\n\n        val topGroup = DefaultActionGroup().apply {\n            add(verbosityFilterActionGroup)\n            add(categoryFilterActionGroup)\n            add(settingsActionGroup)\n        }\n        val topToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.TOOLBAR, topGroup, true)\n\n        val topPanel = JPanel(HorizontalLayout(0))\n        topToolbar.targetComponent = topPanel\n        topPanel.add(topToolbar.component)\n\n        consoleView.scrollTo(0)\n\n        consoleView.add(topPanel, BorderLayout.NORTH)\n        toolbar.targetComponent = this\n        setToolbar(toolbar.component)\n\n        logFilter.addFilterChangedListener { filter(); }\n\n        val model = project.solution.rdRiderModel\n        model.isConnectedToUnrealEditor.advise(lifetime) {\n            if (it) {\n                if (settings.clearOnStart) {\n                    clear()\n                }\n            }\n        }\n        model.unrealLog.advise(lifetime) { event ->\n            print(event)\n        }\n    }\n\n    fun clear() {\n        logData.clear()\n        consoleView.clear()\n    }\n\n    private fun print(unrealLogEvent: UnrealLogEvent) {\n        addLogDataItem(unrealLogEvent)\n        printImpl(unrealLogEvent)\n    }\n\n    private fun filter() {\n        val currentScroll = consoleView.editor!!.scrollingModel.verticalScrollOffset\n        consoleView.clear()\n        // clear is not instant; it just adds an internal request in console\n        // so schedule filtered content printing on next UI update after clear had been already performed\n        invokeLater {\n            for (logEvent in logData) {\n                printImpl(logEvent)\n            }\n            consoleView.editor!!.scrollingModel.scrollVertically(currentScroll)\n        }\n    }\n\n    private fun printSpaces(n: Int = 1, style: ConsoleViewContentType) {\n        if (n <= 0) return\n        consoleView.print(\" \".repeat(n), style)\n    }\n\n    private fun printInfo(s: LogMessageInfo, style: ConsoleViewContentType) {\n        if (settings.showTimestamps) {\n            val timeString = s.time?.toString()\n            if (timeString != null) {\n                consoleView.print(timeString, style)\n                printSpaces(TIME_WIDTH + 1 - timeString.length, style)\n            } else {\n                printSpaces(TIME_WIDTH + 1, style)\n            }\n        }\n\n        if (settings.alignMessages) {\n            if (settings.showVerbosity) {\n                val verbosityString = s.type.toString()\n                consoleView.print(verbosityString, style)\n                printSpaces(VERBOSITY_WIDTH - verbosityString.length + 1, style)\n            }\n\n            val category = s.category.data\n            consoleView.print(category, style)\n            printSpaces(settings.categoryWidth - category.length, style)\n            printSpaces(1, style)\n        } else {\n            if (settings.showVerbosity) {\n                val verbosityString = s.type.toString()\n                consoleView.print(verbosityString, style)\n                consoleView.print(\": \", style)\n            }\n\n            consoleView.print(s.category.data, style)\n            consoleView.print(\": \", style)\n        }\n    }\n\n    private fun getMessageStyle(type: VerbosityType): ConsoleViewContentType {\n        return when (type) {\n            VerbosityType.Fatal -> UnrealLogConsoleViewContentType.UE_LOG_FATAL\n            VerbosityType.Error -> UnrealLogConsoleViewContentType.UE_LOG_ERROR\n            VerbosityType.Warning -> UnrealLogConsoleViewContentType.UE_LOG_WARNING\n            VerbosityType.Display -> UnrealLogConsoleViewContentType.UE_LOG_DISPLAY\n            VerbosityType.Log -> UnrealLogConsoleViewContentType.UE_LOG_LOG\n            VerbosityType.Verbose -> UnrealLogConsoleViewContentType.UE_LOG_VERBOSE\n            VerbosityType.VeryVerbose -> UnrealLogConsoleViewContentType.UE_LOG_VERY_VERBOSE\n            else -> UnrealLogConsoleViewContentType.UE_LOG_LOG\n        }\n    }\n\n    private fun printImpl(unrealLogEvent: UnrealLogEvent): Boolean {\n        logFilter.addCategory(unrealLogEvent.info.category.data)\n        if (!logFilter.isMessageAllowed(unrealLogEvent.info)) {\n            return false\n        }\n\n        val style = getMessageStyle(unrealLogEvent.info.type)\n\n        printInfo(unrealLogEvent.info, style)\n\n        if (unrealLogEvent.bpPathRanges.isEmpty() && unrealLogEvent.methodRanges.isEmpty()) {\n            with(consoleView) {\n                print(unrealLogEvent.text.data, style)\n            }\n            consoleView.print(eol, style)\n            return true\n        }\n\n        val sortedRanges = (unrealLogEvent.bpPathRanges + unrealLogEvent.methodRanges).sortedBy { it.first }\n        assert(sortedRanges.isNotEmpty())\n\n        // collect sorted non-intersecting string ranges\n        val allRanges = arrayListOf<StringRange>()\n        var lastAddedRange = sortedRanges[0]\n        allRanges.add(lastAddedRange)\n        for (index in 1 until sortedRanges.size) {\n            val curRange = sortedRanges[index]\n            if (lastAddedRange.last <= curRange.first) {\n                allRanges.add(curRange)\n                lastAddedRange = curRange\n            }\n        }\n\n        val line = unrealLogEvent.text.data\n        if (allRanges.first().first > 0) {\n            consoleView.print(line.substring(0, allRanges[0].first), style)\n        }\n\n        val model = project.solution.rdRiderModel\n\n        for (rangeWithIndex in allRanges.withIndex()) {\n            val match = line.substring(rangeWithIndex.value.first, rangeWithIndex.value.last)\n            if (rangeWithIndex.value in unrealLogEvent.bpPathRanges) {\n                val hyperLinkInfo = BlueprintClassHyperLinkInfo(model.openBlueprint, BlueprintReference(FString(match), FString(\"\")))\n                consoleView.printHyperlink(match, hyperLinkInfo)\n            } else {\n                val (`class`, method) = match.split(MethodReference.separator)\n                val methodReference = MethodReference(UClass(FString(`class`)), FString(method))\n\n                val classHyperLinkInfo = UnrealClassHyperLinkInfo(model, methodReference, UClass(FString(`class`)))\n                consoleView.printHyperlink(`class`, classHyperLinkInfo)\n\n                consoleView.print(MethodReference.separator, style)\n\n                val methodHyperLinkInfo = MethodReferenceHyperLinkInfo(model, methodReference)\n                consoleView.printHyperlink(method, methodHyperLinkInfo)\n            }\n            if (rangeWithIndex.index < allRanges.size - 1 &&\n                    allRanges[rangeWithIndex.index + 1].first != rangeWithIndex.value.last) {\n                consoleView.print(line.substring(rangeWithIndex.value.last,\n                        allRanges[rangeWithIndex.index + 1].first), style)\n            }\n        }\n        if (allRanges.last().last < line.length) {\n            consoleView.print(line.substring(allRanges.last().last), style)\n        }\n        consoleView.print(eol, style)\n        return true\n    }\n\n    private fun addLogDataItem(item: UnrealLogEvent) {\n        while (logData.size >= MAX_STORED_LOG_DATA_ITEMS)\n            logData.removeFirst()\n        logData.add(item)\n    }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/toolWindow/log/UnrealLogPanelSettings.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.toolWindow.log\n\nimport com.intellij.openapi.Disposable\nimport com.intellij.openapi.components.BaseState\nimport com.intellij.openapi.components.Service\nimport com.intellij.openapi.components.SimplePersistentStateComponent\nimport com.intellij.openapi.components.State\nimport com.intellij.openapi.components.Storage\nimport com.intellij.openapi.components.StoragePathMacros\nimport com.intellij.openapi.components.service\nimport com.intellij.openapi.project.Project\nimport com.intellij.util.EventDispatcher\nimport java.util.EventListener\n\n\n@Service(Service.Level.PROJECT)\n@State(name = \"UnrealLogPanelSettings\", storages = [Storage(StoragePathMacros.WORKSPACE_FILE)])\nclass UnrealLogPanelSettings(private val project: Project) : SimplePersistentStateComponent<UnrealLogPanelSettings.State>(State()) {\n    companion object {\n        fun getInstance(project: Project): UnrealLogPanelSettings = project.service()\n    }\n\n    var clearOnStart: Boolean\n        get() = state.clearOnStart\n        set(value) {\n            state.clearOnStart = value\n        }\n    var focusOnStart: Boolean\n        get() = state.focusOnStart\n        set(value) {\n            state.focusOnStart = value\n        }\n\n    var showMessages: Boolean\n        get() = state.showMessages\n        set(value) {\n            if (state.showMessages != value) {\n                state.showMessages = value\n                fireSettingsChanged()\n            }\n        }\n    var showWarnings: Boolean\n        get() = state.showWarnings\n        set(value) {\n            if (state.showWarnings != value) {\n                state.showWarnings = value\n                fireSettingsChanged()\n            }\n        }\n    var showErrors: Boolean\n        get() = state.showErrors\n        set(value) {\n            if (state.showErrors != value) {\n                state.showErrors = value\n                fireSettingsChanged()\n            }\n        }\n    var showAllCategories: Boolean\n        get() = state.showAllCategories\n        set(value) {\n            if (state.showAllCategories != value) {\n                state.showAllCategories = value\n                fireSettingsChanged()\n            }\n        }\n\n    var showTimestamps: Boolean\n        get() = state.showTimestamps\n        set(value) {\n            if (state.showTimestamps != value) {\n                state.showTimestamps = value\n                fireSettingsChanged()\n            }\n        }\n    var showVerbosity: Boolean\n        get() = state.showVerbosity\n        set(value) {\n            if (state.showVerbosity != value) {\n                state.showVerbosity = value\n                fireSettingsChanged()\n            }\n        }\n    var alignMessages: Boolean\n        get() = state.alignMessages\n        set(value) {\n            if (state.alignMessages != value) {\n                state.alignMessages = value\n                fireSettingsChanged()\n            }\n        }\n    var categoryWidth: Int\n        get() = state.categoryWidth\n        set(value) {\n            if (state.categoryWidth != value) {\n                state.categoryWidth = value\n                fireSettingsChanged()\n            }\n        }\n\n    var showPlayButtons: Boolean\n        get() = state.showPlayButtons\n        set(value) {\n            state.showPlayButtons = value\n        }\n\n    var showUnrealFrames: Boolean\n      get() = state.showUnrealFrames\n      set(value) {\n        state.showUnrealFrames = value\n      }\n\n    var showBlueprintCallstack: Boolean\n      get() = state.showBlueprintCallstack\n      set(value) {\n        state.showBlueprintCallstack = value\n      }\n\n    fun interface SettingsChangedListener : EventListener {\n        fun settingsChanged()\n    }\n\n    private val settingsChangedDispatcher: EventDispatcher<SettingsChangedListener> =\n            EventDispatcher.create(SettingsChangedListener::class.java)\n\n    fun addSettingsChangedListener(listener: SettingsChangedListener, disposable: Disposable) {\n        settingsChangedDispatcher.addListener(listener, disposable)\n    }\n\n    private fun fireSettingsChanged() {\n        settingsChangedDispatcher.multicaster.settingsChanged()\n    }\n\n    class State : BaseState() {\n        var clearOnStart by property(defaultValue = false)\n        var focusOnStart by property(defaultValue = true)\n\n        var showMessages by property(defaultValue = true)\n        var showWarnings by property(defaultValue = true)\n        var showErrors by property(defaultValue = true)\n        var showAllCategories by property(defaultValue = true)\n\n        var showTimestamps by property(defaultValue = false)\n        var showVerbosity by property(defaultValue = true)\n        var alignMessages by property(defaultValue = true)\n        var categoryWidth by property(defaultValue = 25)\n\n        var showPlayButtons by property(defaultValue = true)\n\n        var showBlueprintCallstack by property(defaultValue = true)\n        var showUnrealFrames by property(defaultValue = true)\n    }\n}\n\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/toolWindow/log/UnrealLogSettings.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.toolWindow.log\n\nimport com.intellij.icons.AllIcons\nimport com.intellij.openapi.actionSystem.DefaultActionGroup\nimport com.intellij.openapi.project.DumbAware\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.actions.FilterCheckboxAction\n\n\nclass UnrealLogSettingsActionGroup(private val settings: UnrealLogPanelSettings) : DefaultActionGroup(), DumbAware {\n    init {\n        isPopup = true\n        templatePresentation.icon = AllIcons.General.GearPlain\n\n        add(FilterCheckboxAction(UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.clearLogOnStart.label\"), settings::clearOnStart))\n        add(FilterCheckboxAction(UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.focusLogOnStart.label\"), settings::focusOnStart))\n        addSeparator()\n        add(FilterCheckboxAction(UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.showTimestampsCheckbox.label\"), settings::showTimestamps))\n        add(FilterCheckboxAction(UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.showVerbosityCheckbox.label\"), settings::showVerbosity))\n        add(FilterCheckboxAction(UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.alignMessagesCheckbox.label\"), settings::alignMessages))\n    }\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/plugins/unreal/toolWindow/log/UnrealLogVerbosityFilterComboBox.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.toolWindow.log\n\nimport com.intellij.openapi.actionSystem.ActionUpdateThread\nimport com.intellij.openapi.actionSystem.DefaultActionGroup\nimport com.intellij.openapi.actionSystem.ex.ComboBoxAction\nimport com.intellij.openapi.project.DumbAware\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.actions.FilterCheckboxAction\nimport javax.swing.JComponent\n\nclass UnrealLogVerbosityFilterComboBox(settings: UnrealLogPanelSettings) : ComboBoxAction(), DumbAware {\n    override fun getActionUpdateThread() = ActionUpdateThread.BGT\n    init {\n        val presentation = this.templatePresentation\n        presentation.text = UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.verbositySelection.label\")\n    }\n\n    private val messagesCheckBox: FilterCheckboxAction =\n            FilterCheckboxAction(UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.verbosity.Messages.text\"), settings::showMessages)\n    private val warningsCheckBox: FilterCheckboxAction =\n            FilterCheckboxAction(UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.verbosity.Warnings.text\"), settings::showWarnings)\n    private val errorsCheckBox: FilterCheckboxAction =\n            FilterCheckboxAction(UnrealLinkBundle.message(\"toolWindow.UnrealLog.settings.verbosity.Errors.text\"), settings::showErrors)\n    private val popupGroup: DefaultActionGroup = VerbosityActionGroup()\n\n    override fun createPopupActionGroup(button: JComponent?): DefaultActionGroup {\n        return popupGroup\n    }\n\n    inner class VerbosityActionGroup : DefaultActionGroup() {\n        init {\n            add(messagesCheckBox)\n            add(warningsCheckBox)\n            add(errorsCheckBox)\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/settings/UnrealLinkSettingsConfigurable.kt",
    "content": "package com.jetbrains.rider.settings\n\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.settings.simple.SimpleOptionsPage\n\nclass UnrealLinkSettingsConfigurable : SimpleOptionsPage(UnrealLinkBundle.message(\"configurable.UnrealLink.settings.title\"), \"UnrealLinkOptions\") {\n    override fun getId() = pageId + \"Id\"\n}\n"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/settings/UnrealLogColorSettingsPage.kt",
    "content": "package com.jetbrains.rider.settings\n\nimport com.intellij.execution.impl.ConsoleViewUtil\nimport com.intellij.openapi.editor.colors.EditorColorsScheme\nimport com.intellij.openapi.editor.colors.TextAttributesKey\nimport com.intellij.openapi.fileTypes.PlainSyntaxHighlighter\nimport com.intellij.openapi.fileTypes.SyntaxHighlighter\nimport com.intellij.openapi.options.colors.AttributesDescriptor\nimport com.intellij.openapi.options.colors.ColorDescriptor\nimport com.intellij.openapi.options.colors.ColorSettingsPage\nimport com.intellij.openapi.util.NlsSafe\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogConsoleViewContentType\nimport icons.UnrealIcons\nimport javax.swing.Icon\n\n\n@Suppress(\"UnstableApiUsage\")\nclass UnrealLogColorSettingsPage : ColorSettingsPage {\n    companion object {\n        // These names are from UE enumeration and should not be localized\n        private const val FATAL: @NlsSafe String = \"Fatal\"\n        private const val ERROR: @NlsSafe String = \"Error\"\n        private const val WARNING: @NlsSafe String = \"Warning\"\n        private const val DISPLAY: @NlsSafe String = \"Display\"\n        private const val LOG: @NlsSafe String = \"Log\"\n        private const val VERBOSE: @NlsSafe String = \"Verbose\"\n        private const val VERY_VERBOSE: @NlsSafe String = \"VeryVerbose\"\n\n        private val ATTR_DESCRIPTORS: Array<AttributesDescriptor> = arrayOf(\n                AttributesDescriptor(FATAL, UnrealLogConsoleViewContentType.UE_LOG_FATAL_KEY),\n                AttributesDescriptor(ERROR, UnrealLogConsoleViewContentType.UE_LOG_ERROR_KEY),\n                AttributesDescriptor(WARNING, UnrealLogConsoleViewContentType.UE_LOG_WARNING_KEY),\n                AttributesDescriptor(DISPLAY, UnrealLogConsoleViewContentType.UE_LOG_DISPLAY_KEY),\n                AttributesDescriptor(LOG, UnrealLogConsoleViewContentType.UE_LOG_LOG_KEY),\n                AttributesDescriptor(VERBOSE, UnrealLogConsoleViewContentType.UE_LOG_VERBOSE_KEY),\n                AttributesDescriptor(VERY_VERBOSE, UnrealLogConsoleViewContentType.UE_LOG_VERY_VERBOSE_KEY),\n        )\n\n        private val ADDITIONAL_HIGHLIGHT_DESCRIPTORS: Map<String, TextAttributesKey> = mapOf(\n                \"fatal\" to UnrealLogConsoleViewContentType.UE_LOG_FATAL_KEY,\n                \"error\" to UnrealLogConsoleViewContentType.UE_LOG_ERROR_KEY,\n                \"warning\" to UnrealLogConsoleViewContentType.UE_LOG_WARNING_KEY,\n                \"display\" to UnrealLogConsoleViewContentType.UE_LOG_DISPLAY_KEY,\n                \"log\" to UnrealLogConsoleViewContentType.UE_LOG_LOG_KEY,\n                \"verbose\" to UnrealLogConsoleViewContentType.UE_LOG_VERBOSE_KEY,\n                \"very_verbose\" to UnrealLogConsoleViewContentType.UE_LOG_VERY_VERBOSE_KEY,\n        )\n    }\n\n    override fun getDisplayName(): String {\n        return UnrealLinkBundle.message(\"color.settings.unreal.console.name\")\n    }\n\n    override fun getAttributeDescriptors(): Array<AttributesDescriptor> {\n        return ATTR_DESCRIPTORS\n    }\n\n    override fun getColorDescriptors(): Array<ColorDescriptor> {\n        return emptyArray()\n    }\n\n    override fun getHighlighter(): SyntaxHighlighter {\n        return PlainSyntaxHighlighter()\n    }\n\n    override fun getAdditionalHighlightingTagToDescriptorMap(): Map<String, TextAttributesKey> {\n        return ADDITIONAL_HIGHLIGHT_DESCRIPTORS\n    }\n\n    override fun getDemoText(): String {\n        return \"\"\"\n            \n            <fatal>UE_LOG(LogCategory, Fatal, TEXT(\"Message\"));</fatal>\n            <error>UE_LOG(LogCategory, Error, TEXT(\"Message\"));</error>\n            <warning>UE_LOG(LogCategory, Warning, TEXT(\"Message\"));</warning>\n            <display>UE_LOG(LogCategory, Display, TEXT(\"Message\"));</display>\n            <log>UE_LOG(LogCategory, Log, TEXT(\"Message\"));</log>\n            <verbose>UE_LOG(LogCategory, Verbose, TEXT(\"Message\"));</verbose>\n            <very_verbose>UE_LOG(LogCategory, VeryVerbose, TEXT(\"Message\"));</very_verbose>\n        \"\"\".trimIndent()\n    }\n\n    override fun getIcon(): Icon = UnrealIcons.ConnectionStatus.UnrealEngineLogo\n\n    override fun customizeColorScheme(scheme: EditorColorsScheme): EditorColorsScheme {\n        return ConsoleViewUtil.updateConsoleColorScheme(scheme)\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/com/jetbrains/rider/settings/UnrealLogSettingsConfigurable.kt",
    "content": "package com.jetbrains.rider.settings\n\nimport com.intellij.openapi.components.service\nimport com.intellij.openapi.options.DslConfigurableBase\nimport com.intellij.openapi.options.SearchableConfigurable\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.ui.DialogPanel\nimport com.intellij.openapi.util.NlsSafe\nimport com.intellij.ui.dsl.builder.RightGap\nimport com.intellij.ui.dsl.builder.bindIntText\nimport com.intellij.ui.dsl.builder.bindSelected\nimport com.intellij.ui.dsl.builder.columns\nimport com.intellij.ui.dsl.builder.panel\nimport com.intellij.ui.dsl.builder.selected\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.UnrealLinkSettings\nimport com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanelSettings\n\ninternal class UnrealLogSettingsConfigurable(private val project: Project) : DslConfigurableBase(), SearchableConfigurable {\n    companion object {\n        @NlsSafe\n        const val UNREAL_LINK = \"UnrealLink\"\n        const val ID = \"UnrealLogSettings\"\n    }\n\n    override fun getId(): String = ID\n\n    override fun getDisplayName(): String = UNREAL_LINK\n\n    override fun createPanel(): DialogPanel = panel {\n        val commonSettings = project.service<UnrealLinkSettings>()\n        val logSettings = project.service<UnrealLogPanelSettings>()\n\n        group(UnrealLinkBundle.message(\"configurable.UnrealLink.toolbar.settings.label\")) {\n            row {\n                checkBox(UnrealLinkBundle.message(\"configurable.UnrealLink.replaceWithHotReload.label\"))\n                        .bindSelected(commonSettings::replaceWithHotReload)\n            }\n        }\n\n        group(UnrealLinkBundle.message(\"configurable.UnrealLink.log.settings.label\")) {\n            row {\n                checkBox(UnrealLinkBundle.message(\"configurable.UnrealLink.clearLogOnStart.label\"))\n                        .bindSelected(logSettings::clearOnStart)\n            }\n            row {\n                checkBox(UnrealLinkBundle.message(\"configurable.UnrealLink.focusLogOnStart.label\"))\n                        .bindSelected(logSettings::focusOnStart)\n            }\n            separator()\n            row {\n                checkBox(UnrealLinkBundle.message(\"configurable.UnrealLink.showTimestampsCheckbox.label\"))\n                        .bindSelected(logSettings::showTimestamps)\n            }\n            row {\n                checkBox(UnrealLinkBundle.message(\"configurable.UnrealLink.showVerbosityCheckbox.label\"))\n                        .bindSelected(logSettings::showVerbosity)\n            }\n            row {\n                val alignMessages =\n                        checkBox(UnrealLinkBundle.message(\"configurable.UnrealLink.alignMessagesCheckbox.label\"))\n                                .bindSelected(logSettings::alignMessages)\n                                .gap(RightGap.SMALL)\n                intTextField(1..100, 1)\n                        .columns(2)\n                        .bindIntText(logSettings::categoryWidth)\n                        .enabledIf(alignMessages.selected)\n                        .gap(RightGap.SMALL)\n                label(UnrealLinkBundle.message(\"configurable.UnrealLink.alignMessagesCheckbox.label.ending\"))\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/rider/main/kotlin/icons/UnrealIcons.kt",
    "content": "package icons\n\nimport com.intellij.openapi.util.IconLoader\n\nclass UnrealIcons {\n    class ConnectionStatus {\n        companion object {\n            // TODO: add proper icon for settings\n            val UnrealEngineLogo = IconLoader.getIcon(\"/icons/toolWindows/toolWindowUnrealLog.svg\", UnrealIcons::class.java)\n            val UnrealEngineConnected = IconLoader.getIcon(\"/icons/run/unrealEngineConnected.svg\", UnrealIcons::class.java)\n            val UnrealEngineDisconnected = IconLoader.getIcon(\"/icons/run/unrealEngineDisconnected.svg\", UnrealIcons::class.java)\n        }\n    }\n\n    class PIEControl {\n        companion object {\n            val Pause = IconLoader.getIcon(\"/icons/run/unrealStatusPause.svg\", UnrealIcons::class.java)\n            val Play = IconLoader.getIcon(\"/icons/run/unrealStatusPlay.svg\", UnrealIcons::class.java)\n            val Stop = IconLoader.getIcon(\"/icons/run/unrealStatusStop.svg\", UnrealIcons::class.java)\n            val FrameSkip = IconLoader.getIcon(\"/icons/run/unrealFrameSkip.svg\", UnrealIcons::class.java)\n\n        }\n    }\n\n    class ToolWindow {\n        companion object {\n            val UnrealToolWindow = IconLoader.getIcon(\"/icons/toolWindows/toolWindowUnrealLog.svg\", UnrealIcons::class.java)\n        }\n    }\n}"
  },
  {
    "path": "src/rider/main/resources/META-INF/plugin.xml",
    "content": "<idea-plugin allow-bundled-update=\"true\" require-restart=\"true\">\n    <id>unreal-link</id>\n    <name>UnrealLink</name>\n    <vendor url=\"https://www.jetbrains.com/\">JetBrains</vendor>\n\n    <description><![CDATA[\n  <br/>\n    The UnrealLink plugin enables advanced integration between JetBrains\n    <a href=\"https://www.jetbrains.com/lp/rider-unreal/\">Rider</a>\n    and Epic Games’ <a href=\"https://www.unrealengine.com/en-US/\">Unreal Editor</a>.\n    <br/>\n    <br/>\n    The plugin brings Blueprints information to the editor, adds settings to manage game launch, and provides\n    a more convenient version of the Unreal Editor log.\n    <br/>\n    <br/>\n\n    <b>Plugin structure</b>\n    <br/>\n    There are two plugins under the hood, the <strong>UnrealLink</strong> plugin for Rider and\n    the <strong>RiderLink</strong> plugin for Unreal Editor, packed together.\n    <br/>\n    <br/>\n\n    <b>Installation</b>\n    <br/>\n    <em>UnrealLink</em> is bundled with Rider. Starting with Rider for Unreal Engine 2020.2.1, it’s also\n    distributed via the JetBrains plugin <a href=\"https://plugins.jetbrains.com/plugin/14989-unreal-link\">\n    marketplace</a>.\n    <br/>\n    <br/>\n    <em>RiderLink</em> is installed by Rider itself, there is no need to install it manually. The first\n    time you open an Unreal Engine project in Rider, you'll see a notification that the RiderLink plugin is missing\n    and an invitation to install it. If you skip this popup message, you can install the plugin later by going to the\n    Rider settings on the <em>Languages and Frameworks | Unreal Engine</em> page.\n    <br/>\n    <br/>\n    Both the popup message and the settings page offer two installation options:\n    <ul>\n      <li>\n        <em>Engine</em>: Select this option to install the plugin in the engine and use it for all game projects based\n        on the current engine version. The plugin will appear in the <code>Engine/Plugins/Developer</code> folder.\n      </li>\n      <li>\n        <em>Game</em>: Select this option to install the plugin in the game project and use it for the current project\n        only. The plugin will appear in the <code>Game/Plugins/Developer</code> folder.\n      </li>\n    </ul>\n\n    <b>Features</b>\n    <ul>\n      <li><b>Interact with blueprints</b>\n        <br/>\n        Blueprint files are written in binary form and are usually edited visually. However, they contain a whole lot\n        of useful information for the developers of the C++ part of the game.\n        <br/>\n        Rider reads Blueprints and allows you to see the bigger picture behind your code:\n        <br/>\n        <ul>\n          <li>\n            There may be derived blueprint classes, which you can see by invoking <em>Find Usages</em> on a C++ class or\n            when you're browsing your C++ code in the editor.\n          </li>\n          <li>\n            You can see the values of overridden properties.\n          </li>\n        </ul>\n        UnrealLink extends this functionality and introduces the ability to navigate to the Blueprint inside the\n        Unreal Editor from your C++ code.\n      </li>\n      <li><b>Manage the game</b>\n        <br/>\n        The plugin allows you to manage your game right inside the IDE: select the running mode, run a server for your\n        multiplayer game, specify the number of players, and more.\n      </li>\n      <li><b>Browse the Unreal Editor log</b>\n        <br/>\n        UnrealLink offers you an enhanced version of the Unreal Editor log output panel with colored text for easy\n        reading, as well as verbosity and event category filters. You can also click on any highlighted link to navigate\n        to the related source code line.\n      </li>\n    </ul>\n    <a href=\"https://www.jetbrains.com/help/rider/Working_with_Unreal_Engine.html\">Learn more about\n      Rider for Unreal Engine &gt;&gt;\n    </a>\n    <br/>\n    <br/>\n\n    <b>What could possibly go wrong?</b>\n    <br/>\n    The plugin and Rider for Unreal Engine itself are in active development now, so there could be some issues.\n    Please share your feedback and report any bugs you encounter:\n    <ul>\n      <li>\n        Submit plugin-specific issues to the <a href=\"https://github.com/JetBrains/UnrealLink/issues\">GitHub Issues\n        page</a>.\n      </li>\n      <li>\n        Rider-specific issues should be directed to the <a href=\"https://youtrack.jetbrains.com/issues/RIDER\">Rider\n        tracker</a>.\n      </li>\n      <li>\n        Send a message with any questions and feature suggestions to our support engineers and the Rider for\n        Unreal Engine developers at <a href=\"mailto:rider-cpp-support@jetbrains.com\">rider-cpp-support@jetbrains.com</a>.\n        We really love hearing from you!\n      </li>\n    </ul>\n    A few typical issues, and what to do in such cases:\n    <br/>\n    <ul>\n      <li>\n        <b>Failed to build RiderLink plugin</b>\n        <br/>\n        <pre><code>Failed to build RiderLink plugin\nCheck build logs for more info\nHelp > Diagnostic Tools > Show Log in Explorer\nAnd contact dev team for help at GitHub Issues page</code></pre>\n        There are several reasons you might get this message:\n        <br/>\n        <ul>\n          <li>\n            There’s a problem with your current Game or Unreal Engine code. Please make sure that you can build them\n            correctly.\n          </li>\n          <li>\n            You have an instance of Unreal Editor with the RiderLink plugin running. Please close Unreal Editor and\n            try installing RiderLink again.\n          </li>\n          <li>\n            Finally, if Unreal Editor is closed and your project builds fine, and you have an old version of RiderLink\n            installed, please move the old version of RiderLink to a temp folder manually and try reinstalling\n            RiderLink.\n          </li>\n        </ul>\n      </li>\n      <li>\n        <b>Failed to backup old plugin</b>\n        <br/>\n        <pre><code>Failed to backup old plugin\nClose all running instances of Unreal Editor and try again\nPath to old plugin:</code></pre>\n        You tried to install a new version of RiderLink while you have a running instance of Unreal Editor with\n        the plugin installed. Please close Unreal Editor and try again to install the plugin.\n        <br/>\n      </li>\n      <li>\n        <b>Failed to refresh project files</b>\n        <br/>\n        This warning message means that installation was successful, but updating the project files in Rider failed.\n        Everything should work fine, except the plugin will not appear in the <code>/Plugins/Developer</code> folder\n        in the Explorer view.\n      </li>\n    </ul>\n\n    If you have any issues with the plugin that you can’t resolve, please contact the developers\n    via <a href=\"https://github.com/JetBrains/UnrealLink/issues\">GitHub Issues</a>.\n    ]]>\n    </description>\n\n    <!-- region Generated dependencies - run `Generate Product Layouts` to regenerate -->\n    <dependencies>\n      <plugin id=\"com.jetbrains.rider-cpp\"/>\n      <module name=\"intellij.cidr.debugger.backend\"/>\n      <module name=\"intellij.cidr.debugger.core\"/>\n      <module name=\"intellij.cidr.runner\"/>\n      <module name=\"intellij.rd.client\"/>\n      <module name=\"intellij.rd.client.base\"/>\n      <module name=\"intellij.rider\"/>\n      <module name=\"intellij.rider.rdclient.dotnet\"/>\n      <module name=\"intellij.spellchecker\"/>\n    </dependencies>\n    <!-- endregion -->\n    <extensions defaultExtensionNs=\"rider.cpp\">\n        <debugProcessExtension implementation=\"com.jetbrains.rider.plugins.unreal.debugger.UnrealDebugProcessExtension\"/>\n    </extensions>\n\n    <extensions defaultExtensionNs=\"com.intellij\">\n\n        <rd.solutionExtListener endpoint=\"IDE Frontend\"\n                                listener=\"com.jetbrains.rider.plugins.unreal.UnrealHost$ProtocolListener\"/>\n        <rd.solutionExtListener endpoint=\"IDE Frontend\"\n                                listener=\"com.jetbrains.rider.plugins.unreal.notifications.OutOfSyncPluginProtocolListener\"/>\n        <applicationConfigurable groupId=\"language\" id=\"UnrealLinkOptionsId\" bundle=\"messages.UnrealLinkBundle\"\n                                 instance=\"com.jetbrains.rider.settings.UnrealLinkSettingsConfigurable\"\n                                 key=\"configurable.UnrealLink.settings.title\"/>\n        <projectConfigurable groupId=\"tools\" id=\"UnrealLogSettings\" bundle=\"messages.UnrealLinkBundle\"\n                             instance=\"com.jetbrains.rider.settings.UnrealLogSettingsConfigurable\"\n                             key=\"configurable.UnrealLog.settings.title\"/>\n        <colorSettingsPage implementation=\"com.jetbrains.rider.settings.UnrealLogColorSettingsPage\" id=\"unreal_log\"/>\n\n        <consoleActionsPostProcessor\n                implementation=\"com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogConsoleActionsPostProcessor\"/>\n        <notificationGroup id=\"OutOfSyncConnection\" displayType=\"BALLOON\"\n                           bundle=\"messages.UnrealLinkBundle\" key=\"notificationAction.UnrealEditorOutOfSync.groupId\"/>\n        <notificationGroup id=\"RiderLinkActions\" displayType=\"BALLOON\"\n                           bundle=\"messages.UnrealLinkBundle\" key=\"notification.RiderLink.ReplyFromEditor.groupId\"/>\n        <spellchecker.bundledDictionaryProvider implementation=\"com.jetbrains.rider.plugins.unreal.spellchecker.UnrealBundledDictionaryProvider\"/>\n        <rider.buildButtonModeProvider implementation=\"com.jetbrains.rider.plugins.unreal.actions.HotReloadBuildModeProvider\"/>\n        <iconMapper mappingFile=\"UnrealIconMappings.json\"/>\n\n        <rdStartUpSerializerRegistrar implementation=\"com.jetbrains.rider.plugins.unreal.UE4LibraryStartUpSerializerRegistrar\"/>\n\n        <toolWindowAllowlist id=\"UnrealLink\" />\n        <statistics.counterUsagesCollector implementationClass=\"com.jetbrains.rider.plugins.unreal.UnrealPluginUsagesCollector\"/>\n        <projectSettings service=\"com.jetbrains.rider.plugins.unreal.UnrealLinkSettings\"/>\n        <projectSettings service=\"com.jetbrains.rider.plugins.unreal.toolWindow.log.UnrealLogPanelSettings\"/>\n    </extensions>\n\n    <actions resource-bundle=\"messages.UnrealLinkBundle\">\n        <group id=\"UnrealInteractionToolbar\">\n            <action id=\"RiderLink.RefreshProjects\" class=\"com.jetbrains.rider.plugins.unreal.actions.RefreshProjects\"/>\n            <separator/>\n            <action id=\"RiderLink.StartUnreal\" class=\"com.jetbrains.rider.plugins.unreal.actions.PlayInUnrealAction\"/>\n            <action id=\"RiderLink.ResumeUnreal\"\n                    class=\"com.jetbrains.rider.plugins.unreal.actions.ResumeInUnrealAction\"/>\n            <action id=\"RiderLink.PauseUnreal\" class=\"com.jetbrains.rider.plugins.unreal.actions.PauseInUnrealAction\"/>\n            <action id=\"RiderLink.SingleStepUnreal\"\n                    class=\"com.jetbrains.rider.plugins.unreal.actions.SingleStepInUnrealAction\"/>\n            <action id=\"RiderLink.StopUnreal\" class=\"com.jetbrains.rider.plugins.unreal.actions.StopInUnrealAction\"/>\n            <group id=\"RiderLink.UnrealPlaySettings\" popup=\"true\"\n                   class=\"com.jetbrains.rider.plugins.unreal.actions.PlaySettings\">\n                <action id=\"RiderLink.ProtocolStatus\" class=\"com.jetbrains.rider.plugins.unreal.actions.ProtocolStatus\" />\n                <separator/>\n                <action id=\"RiderLink.AttachToConnectedEditor\"\n                        class=\"com.jetbrains.rider.plugins.unreal.actions.AttachToConnectedEditor\"\n                        icon=\"AllIcons.Debugger.AttachToProcess\"/>\n                <action id=\"RiderLink.OpenRiderLinkSettings\" class=\"com.jetbrains.rider.plugins.unreal.actions.OpenRiderLinkSettings\"\n                        icon=\"AllIcons.General.Settings\"/>\n                <action id=\"RiderLink.OpenUnrealLinkSettings\" class=\"com.jetbrains.rider.plugins.unreal.actions.OpenUnrealLinkSettings\"\n                        icon=\"AllIcons.General.Settings\"/>\n                <separator/>\n                <action id=\"RiderLink.HidePlayActions\"\n                        class=\"com.jetbrains.rider.plugins.unreal.actions.HidePlayButtonsAction\" />\n                <separator/>\n                <group id=\"RiderLink.NumberOfPlayers\" popup=\"true\"\n                       class=\"com.jetbrains.rider.plugins.unreal.actions.PlaySubsettings\">\n                    <action id=\"RiderLink.OnePlayer\" class=\"com.jetbrains.rider.plugins.unreal.actions.NumberOfPlayers\"\n                            text=\"1\"/>\n                    <action id=\"RiderLink.TwoPlayers\" class=\"com.jetbrains.rider.plugins.unreal.actions.NumberOfPlayers\"\n                            text=\"2\"/>\n                    <action id=\"RiderLink.ThreePlayers\"\n                            class=\"com.jetbrains.rider.plugins.unreal.actions.NumberOfPlayers\"\n                            text=\"3\"/>\n                    <action id=\"RiderLink.FourPlayers\"\n                            class=\"com.jetbrains.rider.plugins.unreal.actions.NumberOfPlayers\"\n                            text=\"4\"/>\n                </group>\n                <group id=\"RiderLink.SpawnPlayerAt\" popup=\"true\"\n                       class=\"com.jetbrains.rider.plugins.unreal.actions.PlaySubsettings\">\n                    <action id=\"RiderLink.CurrentCamLoc\"\n                            class=\"com.jetbrains.rider.plugins.unreal.actions.SpawnPlayer\"/>\n                    <action id=\"RiderLink.DefaultPlayerStart\"\n                            class=\"com.jetbrains.rider.plugins.unreal.actions.SpawnPlayer\"/>\n                </group>\n                <group id=\"RiderLink.Modes\" popup=\"true\"\n                       class=\"com.jetbrains.rider.plugins.unreal.actions.PlaySubsettings\">\n                    <action id=\"RiderLink.SelectedViewport\"\n                            class=\"com.jetbrains.rider.plugins.unreal.actions.PlayMode\"/>\n                    <action id=\"RiderLink.MobilePreview\" class=\"com.jetbrains.rider.plugins.unreal.actions.PlayMode\"/>\n                    <action id=\"RiderLink.NewEditorWindow\" class=\"com.jetbrains.rider.plugins.unreal.actions.PlayMode\"/>\n                    <action id=\"RiderLink.VRPreview\" class=\"com.jetbrains.rider.plugins.unreal.actions.PlayMode\"/>\n                    <action id=\"RiderLink.StandaloneGame\" class=\"com.jetbrains.rider.plugins.unreal.actions.PlayMode\"/>\n                    <action id=\"RiderLink.Simulate\" class=\"com.jetbrains.rider.plugins.unreal.actions.PlayMode\"/>\n                    <action id=\"RiderLink.VulkanPreview\" class=\"com.jetbrains.rider.plugins.unreal.actions.VulkanPlayMode\"/>\n                </group>\n                <action id=\"RiderLink.DedicatedServer\"\n                        class=\"com.jetbrains.rider.plugins.unreal.actions.DedicatedServer\"/>\n                <action id=\"RiderLink.CompileBeforeRun\"\n                        class=\"com.jetbrains.rider.plugins.unreal.actions.CompileBeforeRun\"/>\n            </group>\n            <separator/>\n            <add-to-group group-id=\"NavBarToolBar\" relative-to-action=\"ToolbarRunGroup\" anchor=\"before\"/>\n            <add-to-group group-id=\"MainToolBar\" relative-to-action=\"ToolbarRunGroup\" anchor=\"before\"/>\n            <add-to-group group-id=\"MainToolbarRight\" anchor=\"first\"/>\n            <add-to-group group-id=\"RightToolbarSideGroup\" anchor=\"first\"/>\n            <add-to-group group-id=\"RightToolbarSideGroupXamarin\" anchor=\"first\"/>\n        </group>\n\n        <action id=\"UnrealLink.DeleteRiderLinkPluginAction\"\n                class=\"com.jetbrains.rider.plugins.unreal.actions.DeleteRiderLinkPluginAction\" text=\"Delete RiderLink Plugin\"\n                description=\"Delete RiderLink plugin from the project\"/>\n\n        <action id=\"UnrealLink.InstallEditorPluginToEngineAction\"\n                class=\"com.jetbrains.rider.plugins.unreal.actions.InstallEditorPluginToEngineAction\"/>\n        <action id=\"UnrealLink.InstallEditorPluginToGameAction\"\n                class=\"com.jetbrains.rider.plugins.unreal.actions.InstallEditorPluginToGameAction\"/>\n\n        <action id=\"UnrealLink.CopyEditorPluginToEngineAction\"\n                class=\"com.jetbrains.rider.plugins.unreal.actions.ExtractEditorPluginToEngineAction\"/>\n        <action id=\"UnrealLink.CopyEditorPluginToGameAction\"\n                class=\"com.jetbrains.rider.plugins.unreal.actions.ExtractEditorPluginToGameAction\"/>\n\n        <action id=\"UnrealLink.EnableAutoUpdatePlugin\"\n                class=\"com.jetbrains.rider.plugins.unreal.actions.EnableAutoUpdatePlugin\"/>\n        <action id=\"UnrealLink.CancelRiderLinkInstallAction\"\n                class=\"com.jetbrains.rider.plugins.unreal.actions.CancelRiderLinkInstallAction\"/>\n\n        <action id=\"UnrealLink.HotReloadBuild\"\n                class=\"com.jetbrains.rider.plugins.unreal.actions.HotReloadBuildAction\"/>\n\n        <group id=\"XDebugger.Frames.TopToolbar\" overrides=\"true\"/>\n\n        <group id=\"UnrealLink.Debugger.Rider.Unreal.Frames.Popup\" popup=\"true\" icon=\"ReSharperIcons.Cpp.Unreal\"\n               class=\"com.jetbrains.rider.plugins.unreal.debugger.actions.FramesPopupGroup\">\n            <add-to-group group-id=\"XDebugger.Frames.TopToolbar\" anchor=\"first\"/>\n            <action id=\"UnrealLink.Debugger.Rider.Unreal.Frames.ShowBlueprintFunctions\"\n                    class=\"com.jetbrains.rider.plugins.unreal.debugger.actions.ShowBlueprintFunctionsAction\"/>\n            <action id=\"UnrealLink.Debugger.Rider.Unreal.Frames.HideUnrealFrames\"\n                    class=\"com.jetbrains.rider.plugins.unreal.debugger.actions.ShowUnrealFramesAction\"/>\n            <action id=\"UnrealLink.Debugger.Rider.Unreal.Frames.ShowOtherLibraryFrames\"\n                    class=\"com.jetbrains.rider.plugins.unreal.debugger.actions.ShowLibraryFramesAction\"/>\n        </group>\n    </actions>\n</idea-plugin>\n"
  },
  {
    "path": "src/rider/main/resources/UnrealIconMappings.json",
    "content": "{\n    \"icons\": {\n        \"expui\": {\n            \"run\": {\n                \"unrealEngineConnected.svg\": \"icons/run/unrealEngineConnected.svg\",\n                \"unrealEngineDisconnected.svg\": \"icons/run/unrealEngineDisconnected.svg\",\n                \"unrealFrameSkip.svg\": \"icons/run/unrealFrameSkip.svg\",\n                \"unrealStatusOn.svg\": \"icons/run/unrealStatusOn.svg\",\n                \"unrealStatusPause.svg\": \"icons/run/unrealStatusPause.svg\",\n                \"unrealStatusPlay.svg\": \"icons/run/unrealStatusPlay.svg\",\n                \"unrealStatusStop.svg\": \"icons/run/unrealStatusStop.svg\"\n            },\n            \"toolWindows\": {\n                \"toolWindowUnrealLog.svg\": \"icons/toolWindows/toolWindowUnrealLog.svg\"\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/rider/main/resources/com/jetbrains/rider/plugins/unreal/spellchecker/unreal.dic",
    "content": "Blueprintable\nEDITORONLY\nFARCHIVE\nFSTRUCTUREDARCHIVE\nHISM\nHLOD\nIINTERFACE\nLOCTEXT\nMULTICAST\nUCLASS\nUDELEGATE\nUENUM\nUFUNCTION\nUINTERFACE\nUMG\nUOBJECT\nUPROPERTY\nUSTRUCT\nUnrealEngine\nDLAA\nDLSS\nbiome\nblackscreen\nbool\ncallspaces\ncinematic\ncrosshair\ncvar\ncvars\ndeinitialization\ndeinitialize\ndenoise\ndespawn\nemissives\nframerate\ngamepad\ngameplay\ninterp\niter\nlightmap\nmisprediction\nnativized\noutliner\nplaystation\nplaytest\npossessable\nprestream\nprestreamed\nquat\nragdoll\nrecurses\nredirector\nreinstancing\nrepro\nreregister\nretrigger\nspawnable\nsplitscreen\nsublevel\nsubmix\nsubstep\nthumbstick\ntickable\ntonemapper\ntracepoint\nubergraph\nuncrouch\nuncrouching\nundefines\nunhash\nunhovered\nuninitialize\nuninstanced\nunlockables\nunmute\nunpublish\nunregister\nunregistration\nunreserve\nunwalkable\nupsample\nupsampling\nupscaled\nupscaler\nupscaling\nxbox\n"
  },
  {
    "path": "src/rider/main/resources/icon-robots.txt",
    "content": "skip: *"
  },
  {
    "path": "src/rider/main/resources/icons/expui/ icon-robots.txt",
    "content": "skip: *"
  },
  {
    "path": "src/rider/main/resources/messages/UnrealLinkBundle.properties",
    "content": "notificationAction.UnrealEditorOutOfSync.groupId=Unreal Editor connection is out of sync\nnotificationAction.UnrealEditorOutOfSync.title.notInstalled=RiderLink plugin is recommended\nnotificationAction.UnrealEditorOutOfSync.title.wrongVersion=RiderLink plugin synchronization is required\nnotificationAction.UnrealEditorOutOfSync.description.notInstalled=The RiderLink Unreal Editor plugin is not installed. Consider installing it to use advanced Unreal integration features.\nnotificationAction.UnrealEditorOutOfSync.description.wrongVersion=<html>The RiderLink Unreal Editor plugin is not in sync with UnrealLink Rider plugin. Different versions of plugins are not guaranteed to work together.</html>\nnotificationAction.UnrealEditorOutOfSync.installPluginInEngine.text=Install plugin in Engine\nnotificationAction.UnrealEditorOutOfSync.installPluginInEngine.text.update=Update plugin in Engine\nnotificationAction.UnrealEditorOutOfSync.installPluginInEngine.text.move=Move plugin to Engine\nnotificationAction.UnrealEditorOutOfSync.installPluginInGame.text=Install plugin in Game\nnotificationAction.UnrealEditorOutOfSync.installPluginInGame.text.update=Update plugin in Game\nnotificationAction.UnrealEditorOutOfSync.installPluginInGame.text.move=Move plugin to Game\naction.UnrealLink.InstallEditorPluginToEngineAction.text=Install RiderLink in Engine\naction.UnrealLink.InstallEditorPluginToGameAction.text=Install RiderLink in Game\naction.UnrealLink.CopyEditorPluginToEngineAction.text=Extract RiderLink in Engine without building\naction.UnrealLink.CopyEditorPluginToGameAction.text=Extract RiderLink in Game without building\ndialog.UnrealLink.InstallEditorPluginInGame.title=Select Unreal projects for RiderLink\ndialog.UnrealLink.InstallEditorPluginInGame.column.project=Project\ndialog.UnrealLink.InstallEditorPluginInGame.column.path=Path to .uproject\ndialog.UnrealLink.InstallEditorPluginInGame.confirm.install=Install\ndialog.UnrealLink.InstallEditorPluginInGame.confirm.extract=Extract\naction.UnrealLink.EnableAutoUpdatePlugin.text=Enable Auto-Update\naction.UnrealLink.HotReloadBuild.text=Build and Reload\ntoolWindow.UnrealLog.title=Unreal Log\ntoolWindow.UnrealLog.settings.verbositySelection.label=Verbosity\ntoolWindow.UnrealLog.settings.verbosity.Messages.text=Messages\ntoolWindow.UnrealLog.settings.verbosity.Warnings.text=Warnings\ntoolWindow.UnrealLog.settings.verbosity.Errors.text=Errors\ntoolWindow.UnrealLog.settings.categoriesSelection.label=Categories\ntoolWindow.UnrealLog.settings.categories.ShowAll.text=Show All\ntoolWindow.UnrealLog.settings.clearLogOnStart.label=Clear Log On Start\ntoolWindow.UnrealLog.settings.focusLogOnStart.label=Show Log Panel On Start\ntoolWindow.UnrealLog.settings.showTimestampsCheckbox.label=Show Timestamps\ntoolWindow.UnrealLog.settings.showVerbosityCheckbox.label=Show Verbosity\ntoolWindow.UnrealLog.settings.alignMessagesCheckbox.label=Align Log Messages\ngroup.UnrealLink.Debugger.Rider.Unreal.Frames.Popup.text=Frames Filter\naction.RiderLink.Unreal.Debugger.BlueprintCallstack.show.text=Show Blueprint Frames\naction.RiderLink.Unreal.Debugger.UnrealFrames.show.text=Show C++ Frames from Unreal Engine\naction.RiderLink.Unreal.Debugger.OtherLibrariesFrames.show.text=Show Frames from Other Libraries\naction.RiderLink.ProtocolStatus.connected.text=Connected to Unreal Editor\naction.RiderLink.ProtocolStatus.connected.ex.text=Connected to {1} (PID: {2}): {0}\naction.RiderLink.ProtocolStatus.disconnected.text=Not Connected to Unreal Editor\naction.RiderLink.AttachToConnectedEditor.text=Attach to Unreal Editor\naction.RiderLink.AttachToConnectedEditor.description=Attach Debugger to Connected Unreal Editor Executable\naction.RiderLink.OpenRiderLinkSettings.text=RiderLink Installation Settings\\u2026\naction.RiderLink.OpenRiderLinkSettings.description=Edit RiderLink Installation Settings\naction.RiderLink.OpenUnrealLinkSettings.text=UnrealLink Settings\\u2026\naction.RiderLink.OpenUnrealLinkSettings.description=Edit UnrealLink Settings\naction.RiderLink.HidePlayActions.text=Show Editor Play Actions\naction.RiderLink.SelectedViewport.text=Selected Viewport\naction.RiderLink.MobilePreview.text=Mobile Preview\naction.RiderLink.NewEditorWindow.text=New Editor Window\naction.RiderLink.VRPreview.text=VR Preview\naction.RiderLink.StandaloneGame.text=Standalone Game\naction.RiderLink.Simulate.text=Simulate\naction.RiderLink.VulkanPreview.text=Vulkan Preview\naction.RiderLink.CurrentCamLoc.text=Current Camera Location\naction.RiderLink.DefaultPlayerStart.text=Default Player Start\naction.RiderLink.DedicatedServer.text=Run Dedicated Server\naction.RiderLink.CompileBeforeRun.text=Compile Before Play\ngroup.RiderLink.SpawnPlayerAt.text=Spawn Player at\\u2026\ngroup.RiderLink.NumberOfPlayers.text=Number of Players\ngroup.RiderLink.Modes.text=Mode\naction.RiderLink.PauseUnreal.text=Pause Play-in-Editor Session\naction.RiderLink.PauseUnreal.description=Pause Play-in-Editor Session\naction.RiderLink.SingleStepUnreal.text=Step Single Frame\naction.RiderLink.SingleStepUnreal.description=Step Single Frame\naction.RiderLink.StartUnreal.text=Start Play-in-Editor Session\naction.RiderLink.StartUnreal.description=Play Level in the Active Editor Viewport\naction.RiderLink.ResumeUnreal.text=Resume Play-in-Editor Session\naction.RiderLink.ResumeUnreal.description=Resume Play-in-Editor Session\naction.RiderLink.StopUnreal.text=Stop Play-in-Editor Session\naction.RiderLink.StopUnreal.description=Stop Play-in-Editor Session\naction.RiderLink.RefreshProjects.text=Refresh Solution\naction.RiderLink.RefreshProjects.description=Refresh Solution Files\nnotification.RiderLink.ReplyFromEditor.groupId=RiderLink\nnotification.RiderLink.ReplyFromEditor.title=RiderLink\naction.UnrealLink.CancelRiderLinkInstallAction.text=Cancel Installation\naction.UnrealLink.CancelRiderLinkInstallAction.description=Cancel installation of RiderLink plugin\nconfigurable.UnrealLink.focusLogOnStart.label=Show log on engine start\nconfigurable.UnrealLink.clearLogOnStart.label=Clear log on engine start\nconfigurable.UnrealLink.log.settings.label=Unreal Log Settings\nconfigurable.UnrealLink.toolbar.settings.label=Toolbar Settings\nconfigurable.UnrealLink.replaceWithHotReload.label=Replace 'Build Startup Project' button with 'Build and Reload'\nconfigurable.UnrealLink.showTimestampsCheckbox.label=Show message timestamps\nconfigurable.UnrealLink.showVerbosityCheckbox.label=Show message verbosity types\nconfigurable.UnrealLink.alignMessagesCheckbox.label=Align log messages by category of maximum of\nconfigurable.UnrealLink.alignMessagesCheckbox.label.ending=characters wide\n\n\nRiderLink.Unreal.Debugger.BlueprintCallstack.UnrealEngineCode.title=Unreal Engine code:\nRiderLink.Unreal.Debugger.BlueprintCallstack.UnrealEngineCode.suffix=filtered out\nRiderLink.Unreal.Debugger.BlueprintCallstack.Blueprint.title=Blueprint\nRiderLink.Unreal.Debugger.BlueprintCallstack.Blueprint.StubFrame.InstallRiderLink=Install RiderLink plugin to see BP function details\nRiderLink.Unreal.Debugger.BlueprintCallstack.Blueprint.StubFrame.EvaluationFailed=Evaluation unavailable, please make a step to see BP function details\nRiderLink.Unreal.Debugger.BlueprintCallstack.Blueprint.StubFrame.UnspecifiedError=Error obtaining BP function details. Please create an issue in our tracker with the details of this error: https://youtrack.jetbrains.com/issues/Rider\n\ncolor.settings.unreal.console.name=Unreal Log\nRiderLink.InstallProgress.text.title=RiderLink Install Progress\nconfigurable.UnrealLink.settings.title=Unreal Engine\nconfigurable.UnrealLog.settings.title=UnrealLink\nRiderLink.UnrealEditorLog.text.title=Unreal Editor Log\n"
  },
  {
    "path": "src/rider/test/kotlin/com/jetbrains/rider/plugins/unreal/test/cases/RiderTestDataMarker.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.test.cases\n\nimport com.jetbrains.rider.test.framework.testData.IRiderTestDataMarker\nimport java.nio.file.Path\n\n@Suppress(\"unused\")\nobject RiderTestDataMarker : IRiderTestDataMarker {\n  override val testDataFromRoot: Path\n    get() = Path.of(\"src/rider/test/testData\")\n\n  override val pluginDirectoryInUltimate: Path\n    get() = Path.of(\"dotnet/Plugins/UnrealLink\")\n}"
  },
  {
    "path": "src/rider/test/kotlin/com/jetbrains/rider/plugins/unreal/test/cases/integrationTests/Notification.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.test.cases.integrationTests\n\nimport com.intellij.notification.Notification\nimport com.intellij.notification.NotificationType\nimport com.intellij.notification.NotificationsManager\nimport com.jetbrains.rider.UnrealLinkBundle\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.PluginInstallLocation\nimport com.jetbrains.rider.test.annotations.Solution\nimport com.jetbrains.rider.test.annotations.Subsystem\nimport com.jetbrains.rider.test.annotations.TestSettings\nimport com.jetbrains.rider.test.annotations.report.ChecklistItems\nimport com.jetbrains.rider.test.annotations.report.Feature\nimport com.jetbrains.rider.test.asserts.shouldBe\nimport com.jetbrains.rider.test.asserts.shouldBeTrue\nimport com.jetbrains.rider.test.asserts.shouldNotBeNull\nimport com.jetbrains.rider.test.enums.BuildTool\nimport com.jetbrains.rider.test.enums.Mono\nimport com.jetbrains.rider.test.enums.sdk.SdkVersion\nimport com.jetbrains.rider.test.reporting.SubsystemConstants\nimport com.jetbrains.rider.test.scriptingApi.reopenSolution\nimport com.jetbrains.rider.test.suplementary.RiderTestSolution\nimport com.jetbrains.rider.test.unreal.UnrealEnvironment\nimport org.testng.annotations.Test\nimport java.time.Duration\n\n@Subsystem(SubsystemConstants.UNREAL_LINK)\n@Feature(\"Notification\")\n@TestSettings(buildTool = BuildTool.UNREAL, mono = Mono.UNIX_ONLY, sdkVersion = SdkVersion.DOT_NET_8, additionalSdkVersions = [SdkVersion.DOT_NET_6])\nclass RiderLinkNotification : UnrealLinkBase() {\n  @Solution(RiderTestSolution.Unreal.EmptyUProject)\n  @Test(dataProvider = \"unrealCombinations\")\n  @ChecklistItems([\"UnrealLink/Installation Notification\"])\n  fun installNotification(e: UnrealEnvironment) {\n    val notification = NotificationsManager.getNotificationsManager()\n      .getNotificationsOfType(Notification::class.java, project).single { it.groupId == \"OutOfSyncConnection\" }\n    notification.type.shouldBe(NotificationType.WARNING)\n    notification.title.shouldBe(UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.title.notInstalled\"))\n    notification.actions.size.shouldBe(2)\n    notification.actions.any { it.templateText.equals(UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.installPluginInEngine.text\")) }.shouldNotBeNull()\n    notification.actions.any { it.templateText.equals(UnrealLinkBundle.message(\"notificationAction.UnrealEditorOutOfSync.installPluginInGame.text\")) }.shouldNotBeNull()\n \n    installRiderLink(PluginInstallLocation.Game)\n\n    reopenSolution(project, Duration.ofMinutes(3))\n\n    NotificationsManager.getNotificationsManager().getNotificationsOfType(Notification::class.java,\n                                                                          project).none { it.groupId == \"OutOfSyncConnection\" }.shouldBeTrue()\n  }\n}"
  },
  {
    "path": "src/rider/test/kotlin/com/jetbrains/rider/plugins/unreal/test/cases/integrationTests/PlayButtons.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.test.cases.integrationTests\n\nimport com.intellij.openapi.actionSystem.ActionManager\nimport com.intellij.openapi.actionSystem.ActionUiKind\nimport com.intellij.openapi.actionSystem.AnAction\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport com.intellij.openapi.actionSystem.CommonDataKeys\nimport com.intellij.openapi.actionSystem.DataContext\nimport com.intellij.openapi.actionSystem.impl.SimpleDataContext\nimport com.jetbrains.rdclient.util.idea.pumpMessages\nimport com.jetbrains.rdclient.util.idea.waitAndPump\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.PluginInstallLocation\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.projectView.solution\nimport com.jetbrains.rider.test.annotations.RiderTestTimeout\nimport com.jetbrains.rider.test.annotations.Solution\nimport com.jetbrains.rider.test.annotations.Subsystem\nimport com.jetbrains.rider.test.reporting.SubsystemConstants\nimport com.jetbrains.rider.test.annotations.TestSettings\nimport com.jetbrains.rider.test.annotations.report.ChecklistItems\nimport com.jetbrains.rider.test.annotations.report.Feature\nimport com.jetbrains.rider.test.enums.BuildTool\nimport com.jetbrains.rider.test.enums.Mono\nimport com.jetbrains.rider.test.enums.sdk.SdkVersion\nimport com.jetbrains.rider.test.scriptingApi.setConfigurationAndPlatform\nimport com.jetbrains.rider.test.scriptingApi.withRunProgram\nimport com.jetbrains.rider.test.suplementary.RiderTestSolution\nimport com.jetbrains.rider.test.unreal.UnrealEnvironment\nimport org.testng.annotations.BeforeMethod\nimport org.testng.annotations.Test\nimport java.time.Duration\nimport java.util.concurrent.TimeUnit\n\n@Subsystem(SubsystemConstants.UNREAL_LINK)\n@Feature(\"PlayButtons\")\n@TestSettings(buildTool = BuildTool.UNREAL, mono = Mono.UNIX_ONLY, sdkVersion = SdkVersion.DOT_NET_8, additionalSdkVersions = [SdkVersion.DOT_NET_6])\n@RiderTestTimeout(10, TimeUnit.MINUTES)\nclass PlayButtons : UnrealLinkBase() {\n  @BeforeMethod\n  fun setOpenSolutionSettings() {\n    unrealApiFacade.disableEnginePlugins = false\n  }\n\n  private val runProgramTimeout: Duration = Duration.ofMinutes(10)\n\n  private val context: DataContext get() = SimpleDataContext.getSimpleContext(CommonDataKeys.PROJECT, project)\n  private val startAction: AnAction get() = ActionManager.getInstance().getAction(\"RiderLink.StartUnreal\")\n  private val stepAction: AnAction get() = ActionManager.getInstance().getAction(\"RiderLink.SingleStepUnreal\")\n  private val pauseAction: AnAction get() = ActionManager.getInstance().getAction(\"RiderLink.PauseUnreal\")\n  private val resumeAction: AnAction get() = ActionManager.getInstance().getAction(\"RiderLink.ResumeUnreal\")\n  private val stopAction: AnAction get() = ActionManager.getInstance().getAction(\"RiderLink.StopUnreal\")\n\n  @Solution(RiderTestSolution.Unreal.EmptyUProject)\n  @Test(dataProvider = \"unrealCombinations\")\n  @ChecklistItems([\"UnrealLink/Play Controls\"])\n  fun endToEndTest(e: UnrealEnvironment) {\n    setConfigurationAndPlatform(project, \"Development Editor\", \"Win64\")\n    installRiderLink(PluginInstallLocation.Game)\n\n    buildStartupProject()\n\n    checkActionsIsEnabled(mapOf(\n      startAction to false,\n      stepAction to false,\n      pauseAction to false,\n      resumeAction to false,\n      stopAction to false\n    ))\n\n    checkActionsIsVisible(mapOf(\n      startAction to true,\n      stepAction to false,\n      pauseAction to true,\n      resumeAction to false,\n      stopAction to true\n    ))\n\n    withRunProgram(project, configurationName = activeSolution) { // open Unreal Editor\n      waitAndPump(runProgramTimeout,\n                  { it.solution.rdRiderModel.isConnectedToUnrealEditor.value }, { \"Not connected to UnrealEditor\" })\n\n      checkActionsIsEnabled(mapOf(\n        startAction to true,\n        stepAction to false,\n        pauseAction to false,\n        resumeAction to false,\n        stopAction to false\n      ))\n\n      checkActionsIsVisible(mapOf(\n        startAction to true,\n        stepAction to false,\n        pauseAction to true,\n        resumeAction to false,\n        stopAction to true\n      ))\n\n      pushUnrealButton(startAction)\n\n      checkActionsIsEnabled(mapOf(\n        startAction to false,\n        stepAction to false,\n        pauseAction to true,\n        resumeAction to false,\n        stopAction to true\n      ))\n\n      checkActionsIsVisible(mapOf(\n        startAction to false,\n        stepAction to false,\n        pauseAction to true,\n        resumeAction to true,\n        stopAction to true\n      ))\n\n      pushUnrealButton(pauseAction)\n\n      checkActionsIsEnabled(mapOf(\n        startAction to false,\n        stepAction to true,\n        pauseAction to false,\n        resumeAction to true,\n        stopAction to true\n      ))\n\n      checkActionsIsVisible(mapOf(\n        startAction to false,\n        stepAction to true,\n        pauseAction to false,\n        resumeAction to true,\n        stopAction to true\n      ))\n\n      pushUnrealButton(resumeAction)\n\n      checkActionsIsEnabled(mapOf(\n        startAction to false,\n        stepAction to false,\n        pauseAction to true,\n        resumeAction to false,\n        stopAction to true\n      ))\n\n      checkActionsIsVisible(mapOf(\n        startAction to false,\n        stepAction to false,\n        pauseAction to true,\n        resumeAction to true,\n        stopAction to true\n      ))\n\n      pushUnrealButton(stopAction)\n\n      checkActionsIsEnabled(mapOf(\n        startAction to true,\n        stepAction to false,\n        pauseAction to false,\n        resumeAction to false,\n        stopAction to false\n      ))\n\n      checkActionsIsVisible(mapOf(\n        startAction to true,\n        stepAction to false,\n        pauseAction to true,\n        resumeAction to false,\n        stopAction to true\n      ))\n    } // close Unreal Editor\n\n    checkActionsIsEnabled(mapOf(\n      startAction to false,\n      stepAction to false,\n      pauseAction to false,\n      resumeAction to false,\n      stopAction to false\n    ))\n\n    checkActionsIsVisible(mapOf(\n      startAction to true,\n      stepAction to false,\n      pauseAction to true,\n      resumeAction to false,\n      stopAction to true\n    ))\n\n  }\n\n  fun createEvent(action: AnAction): AnActionEvent {\n    val event = AnActionEvent.createEvent(action, context, null, \"\", ActionUiKind.NONE, null)\n    action.update(event)\n    return event\n  }\n\n  fun checkActionsIsEnabled(actions: Map<AnAction, Boolean>) {\n    actions.forEach { (action, isEnabled) ->\n      val event = createEvent(action)\n      pumpMessages(timeout = Duration.ofSeconds(5)) {\n        action.update(event)\n        if (isEnabled) event.presentation.isEnabled else !event.presentation.isEnabled\n      }\n    }\n  }\n\n  fun checkActionsIsVisible(actions: Map<AnAction, Boolean>) {\n    actions.forEach { (action, isVisible) ->\n      val event = createEvent(action)\n      pumpMessages(timeout = Duration.ofSeconds(5)) {\n        action.update(event)\n        if (isVisible) event.presentation.isVisible else !event.presentation.isVisible\n      }\n    }\n  }\n\n  private fun pushUnrealButton(action: AnAction) = action.actionPerformed(createEvent(action))\n}"
  },
  {
    "path": "src/rider/test/kotlin/com/jetbrains/rider/plugins/unreal/test/cases/integrationTests/UnrealLinkBase.kt",
    "content": "@file:Suppress(\"JUnitTestCaseWithNoTests\")\n\npackage com.jetbrains.rider.plugins.unreal.test.cases.integrationTests\n\nimport com.jetbrains.rd.util.lifetime.Lifetime\nimport com.jetbrains.rd.util.reactive.fire\nimport com.jetbrains.rdclient.util.idea.waitAndPump\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.ForceInstall\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.InstallPluginDescription\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.PluginInstallLocation\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.projectView.solution\nimport com.jetbrains.rider.test.scriptingApi.waitPumping\nimport com.jetbrains.rider.test.unreal.UnrealTestLevelProject\nimport org.testng.annotations.AfterMethod\nimport java.time.Duration\n\nopen class UnrealLinkBase: UnrealTestLevelProject() {\n  @AfterMethod\n  override fun unrealCleanup() {\n    deleteRiderLink()\n    super.unrealCleanup()\n  }\n  \n  protected fun installRiderLink(place: PluginInstallLocation, timeout: Duration = Duration.ofSeconds(240)) {\n    logger.info(\"Installing RiderLink in ${place.name}\")\n    var riderLinkInstalled = false\n    project.solution.rdRiderModel.installPluginFinished.advise(Lifetime.Eternal) { riderLinkInstalled = true }\n    project.solution.rdRiderModel.installEditorPlugin.fire(\n      InstallPluginDescription(place, ForceInstall.Yes, true, emptyList(), emptyList())\n    )\n    waitAndPump(timeout, { riderLinkInstalled }, { \"RiderLink has not been installed\" })\n  }\n\n  protected fun deleteRiderLink() {\n    project.solution.rdRiderModel.deletePlugin.fire()\n    waitPumping(Duration.ofSeconds(5))\n  }\n}"
  },
  {
    "path": "src/rider/test/kotlin/com/jetbrains/rider/plugins/unreal/test/cases/integrationTests/UnrealLinkInstallation.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.test.cases.integrationTests\n\nimport com.jetbrains.rdclient.util.idea.waitAndPump\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.PluginInstallLocation\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.projectView.solution\nimport com.jetbrains.rider.test.annotations.RiderTestTimeout\nimport com.jetbrains.rider.test.annotations.Solution\nimport com.jetbrains.rider.test.annotations.Subsystem\nimport com.jetbrains.rider.test.annotations.TestSettings\nimport com.jetbrains.rider.test.annotations.report.ChecklistItems\nimport com.jetbrains.rider.test.annotations.report.Feature\nimport com.jetbrains.rider.test.enums.BuildTool\nimport com.jetbrains.rider.test.enums.Mono\nimport com.jetbrains.rider.test.enums.sdk.SdkVersion\nimport com.jetbrains.rider.test.framework.frameworkLogger\nimport com.jetbrains.rider.test.reporting.SubsystemConstants\nimport com.jetbrains.rider.test.scriptingApi.setUnrealConfigurationAndPlatform\nimport com.jetbrains.rider.test.scriptingApi.waitPumping\nimport com.jetbrains.rider.test.scriptingApi.withRunProgram\nimport com.jetbrains.rider.test.suplementary.RiderTestSolution\nimport com.jetbrains.rider.test.unreal.UnrealConstants\nimport com.jetbrains.rider.test.unreal.UnrealEnvironment\nimport com.jetbrains.rider.test.unreal.UnrealTestCombinations\nimport org.testng.annotations.BeforeMethod\nimport org.testng.annotations.DataProvider\nimport org.testng.annotations.Test\nimport java.lang.reflect.Method\nimport java.time.Duration\nimport java.util.concurrent.TimeUnit\n\n@Subsystem(SubsystemConstants.UNREAL_LINK)\n@Feature(\"Installation\")\n@TestSettings(buildTool = BuildTool.UNREAL, mono = Mono.UNIX_ONLY, sdkVersion = SdkVersion.DOT_NET_8, additionalSdkVersions = [SdkVersion.DOT_NET_6])\nclass UnrealLinkInstallation : UnrealLinkBase() {\n  private val runProgramTimeout: Duration = Duration.ofMinutes(10)\n\n  /**\n   * Extends standard [UnrealTestCombinations] with an additional [PluginInstallLocation] dimension.\n   * Produces (env, location) pairs — engine and openMode are applied automatically by\n   * [com.jetbrains.rider.test.unreal.UnrealBase.applyDataProviderCombination], only location is\n   * test-specific.\n   */\n  @DataProvider(name = \"unrealLinkCombinations\")\n  fun unrealLinkCombinations(method: Method): Array<Array<Any>> {\n    val combinations = UnrealTestCombinations.combinations(method)\n    val locations = listOf(PluginInstallLocation.Game, PluginInstallLocation.Engine)\n\n    val result = combinations.flatMap { (engine, openMode) ->\n      locations.map { location ->\n        arrayOf(UnrealEnvironment(engine, openMode) as Any, location as Any)\n      }\n    }.toTypedArray()\n\n    frameworkLogger.info(\"unrealLinkCombinations for ${method.name}:\" +\n            \"combinations=${combinations.size}, \" +\n            \"locations=${locations.size}, total=${result.size}\")\n\n    return result\n  }\n\n  @BeforeMethod\n  fun setOpenSolutionSettings() {\n    unrealApiFacade.disableEnginePlugins = false\n  }\n\n  @Solution(RiderTestSolution.Unreal.EmptyUProject)\n  @Test(dataProvider = \"unrealLinkCombinations\")\n  @RiderTestTimeout(10, TimeUnit.MINUTES)\n  @ChecklistItems([\"UnrealLink/Installation\"])\n  fun ul(env: UnrealEnvironment, location: PluginInstallLocation) {\n    setUnrealConfigurationAndPlatform(project, UnrealConstants.UnrealConfigurations.DevelopmentEditor)\n\n    installRiderLink(location)\n\n    buildStartupProject()\n\n    withRunProgram(project, configurationName = activeSolution) {\n      waitAndPump(runProgramTimeout, { it.solution.rdRiderModel.isConnectedToUnrealEditor.value }, { \"Not connected to UnrealEditor\" })\n      waitPumping(Duration.ofSeconds(15))\n    }\n  }\n}"
  },
  {
    "path": "src/rider/test/kotlin/com/jetbrains/rider/plugins/unreal/test/cases/integrationTests/projectModel/RefreshSolution.kt",
    "content": "package com.jetbrains.rider.plugins.unreal.test.cases.integrationTests.projectModel\n\nimport com.jetbrains.rd.util.reactive.fire\nimport com.jetbrains.rdclient.util.idea.waitAndPump\nimport com.jetbrains.rider.ideaInterop.vfs.VfsWriteOperationsHost\nimport com.jetbrains.rider.ijent.extensions.toRd\nimport com.jetbrains.rider.model.RdFsRefreshRequest\nimport com.jetbrains.rider.plugins.unreal.model.frontendBackend.rdRiderModel\nimport com.jetbrains.rider.projectView.solution\nimport com.jetbrains.rider.test.annotations.Solution\nimport com.jetbrains.rider.test.annotations.Subsystem\nimport com.jetbrains.rider.test.annotations.TestEnvironment\nimport com.jetbrains.rider.test.annotations.TestSettings\nimport com.jetbrains.rider.test.annotations.report.ChecklistItems\nimport com.jetbrains.rider.test.annotations.report.Feature\nimport com.jetbrains.rider.test.enums.BuildTool\nimport com.jetbrains.rider.test.enums.PlatformType\nimport com.jetbrains.rider.test.enums.sdk.SdkVersion\nimport com.jetbrains.rider.test.scriptingApi.combine\nimport com.jetbrains.rider.test.framework.waitBackendAndWorkspaceModel\nimport com.jetbrains.rider.test.reporting.SubsystemConstants\nimport com.jetbrains.rider.test.scriptingApi.copyAdditionalPluginToProject\nimport com.jetbrains.rider.test.scriptingApi.waitPumping\nimport com.jetbrains.rider.test.suplementary.RiderTestSolution\nimport com.jetbrains.rider.test.unreal.SlnOnly\nimport com.jetbrains.rider.test.unreal.UnrealEnvironment\nimport com.jetbrains.rider.test.unreal.UnrealTestLevelProject\nimport org.testng.annotations.Test\nimport java.time.Duration\n\n@Subsystem(SubsystemConstants.UNREAL_PROJECT_MODEL)\n@Feature(\"Refresh Solution\")\n@TestSettings(buildTool = BuildTool.UNREAL, sdkVersion = SdkVersion.DOT_NET_8, additionalSdkVersions = [SdkVersion.DOT_NET_6])\n@TestEnvironment(platform = [PlatformType.WINDOWS_X64])\nclass RefreshSolution : UnrealTestLevelProject() {\n\n  @SlnOnly\n  @Solution(RiderTestSolution.Unreal.EmptyUProject)\n  @Test(dataProvider = \"unrealCombinations\")\n  @ChecklistItems([\"Project Model/Refresh Solution\"])\n  fun refreshSolution(e: UnrealEnvironment) {\n    withDump {\n      dumpProfile.dumpDirList.clear()\n      dumpProfile.dumpDirList.add(activeSolutionDirectory.resolve(\"Intermediate/ProjectFiles\"))\n      dumpProfile.fileNames.add(\"$activeSolution.vcxproj.filters\")\n\n      dumpAfterAction(\"Init\") {}\n      dumpAfterAction(\"Copy TestPlugin to project\") {\n        copyAdditionalPluginToProject(\"EmptyTestPlugin\")\n      }\n\n      dumpAfterAction(\"Invoking refresh solution\") {\n        project.solution.rdRiderModel.refreshProjects.fire()\n        waitPumping(Duration.ofSeconds(1))\n        waitAndPump(Duration.ofSeconds(30), { !project.solution.rdRiderModel.refreshInProgress.value },\n                    { \"Response from UBT took longer than expected time\" })\n\n        VfsWriteOperationsHost.getInstance(project).refreshPaths(\n          RdFsRefreshRequest(listOf(activeSolutionDirectory.combine(\"Intermediate\", \"ProjectFiles\", \"$activeSolution.vcxproj\").toRd()),\n                             false))\n        waitPumping(Duration.ofSeconds(1))\n        waitBackendAndWorkspaceModel(project)\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/rider/test/resources/episodes/Plugins/UnrealIntegration.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE suite SYSTEM \"http://testng.org/testng-1.0.dtd\">\n\n<suite name=\"Rider Tests Unreal Integration\">\n  <test name=\"Main Tests Unreal Integration\">\n    <packages>\n      <package name=\"com.jetbrains.rider.plugins.unreal.test.cases.integrationTests.*\"/>\n    </packages>\n  </test>\n</suite>\n\n"
  },
  {
    "path": "src/rider/test/resources/episodes/Plugins/UnrealLinkSmoke.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE suite SYSTEM \"http://testng.org/testng-1.0.dtd\">\n\n<suite name=\"Rider Tests Unreal Integration Smoke\">\n    <test name=\"Smoke Tests Unreal Integration\">\n        <classes>\n            <class name=\"com.jetbrains.rider.plugins.unreal.test.cases.integrationTests.UnrealLinkInstallation\">\n                <methods>\n                    <include name=\"ul\"/>\n                </methods>\n            </class>\n            <class name=\"com.jetbrains.rider.plugins.unreal.test.cases.integrationTests.RiderLinkNotification\">\n                <methods>\n                    <include name=\"installNotification\"/>\n                </methods>\n            </class>\n        </classes>\n    </test>\n</suite>\n"
  },
  {
    "path": "src/rider/test/resources/intellij.rider.plugins.unreal.link.test.cases.xml",
    "content": "<idea-plugin>\n    <!-- region Generated dependencies - run `Generate Product Layouts` to regenerate -->\n    <dependencies>\n      <plugin id=\"unreal-link\"/>\n      <module name=\"intellij.rider.test.framework\"/>\n      <module name=\"intellij.rider.test.framework.integration.testng\"/>\n      <module name=\"intellij.rider.test.framework.integration.testng.tests\"/>\n      <module name=\"intellij.rider.test.framework.core\"/>\n      <module name=\"intellij.rider.test.framework.testng\"/>\n      <module name=\"intellij.libraries.gson\"/>\n      <module name=\"intellij.libraries.kotlin.reflect\"/>\n      <module name=\"intellij.libraries.kotlinx.coroutines.core\"/>\n      <module name=\"intellij.platform.analysis.impl\"/>\n      <module name=\"intellij.platform.core\"/>\n      <module name=\"intellij.platform.core.ui\"/>\n      <module name=\"intellij.platform.editor.ui\"/>\n      <module name=\"intellij.platform.ide.core\"/>\n      <module name=\"intellij.platform.ide.impl\"/>\n      <module name=\"intellij.platform.lang.impl\"/>\n      <module name=\"intellij.rd.client\"/>\n      <module name=\"intellij.rider.languages\"/>\n    </dependencies>\n    <!-- endregion -->\n</idea-plugin>\n"
  },
  {
    "path": "src/rider/test/testData/integrationTests/projectModel/RefreshSolution/refreshSolution/refreshSolution.gold",
    "content": "===================\nInit\n\n-EmptyUProject\n Dependencies\n -Source\n  -EmptyUProject\n   EmptyUProject.cpp\n   EmptyUProject.h\n   EmptyUProject.Build.cs\n  EmptyUProject.Target.cs\n  EmptyUProjectEditor.Target.cs\n EmptyUProject.uproject\n\n\n\nProject [Name:EmptyUProject, GUID:GUID]\n  Child items:\n    ProjectFileImpl(Path : EmptyUProject.uproject (relative_path/EmptyUProject.uproject))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.vcxproj)[]\n    Folder [Name:Source, Virtual:relative_path/Source]\n      Child items:\n        Folder [Name:EmptyUProject]\n          Child items:\n            ProjectFileImpl(Path : EmptyUProject.Build.cs)[NONE ]\n            ProjectFileImpl(Path : EmptyUProject.cpp)[CLCOMPILE ]\n            ProjectFileImpl(Path : EmptyUProject.h)[CLINCLUDE ]\n        ProjectFileImpl(Path : EmptyUProject.Target.cs)[NONE ]\n        ProjectFileImpl(Path : EmptyUProjectEditor.Target.cs)[NONE ]\n\n\n===================\nCopy TestPlugin to project\n\n-EmptyUProject\n Dependencies\n -Source\n  -EmptyUProject\n   EmptyUProject.cpp\n   EmptyUProject.h\n   EmptyUProject.Build.cs\n  EmptyUProject.Target.cs\n  EmptyUProjectEditor.Target.cs\n EmptyUProject.uproject\n\n\n\nProject [Name:EmptyUProject, GUID:GUID]\n  Child items:\n    ProjectFileImpl(Path : EmptyUProject.uproject (relative_path/EmptyUProject.uproject))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.vcxproj)[]\n    Folder [Name:Source, Virtual:relative_path/Source]\n      Child items:\n        Folder [Name:EmptyUProject]\n          Child items:\n            ProjectFileImpl(Path : EmptyUProject.Build.cs)[NONE ]\n            ProjectFileImpl(Path : EmptyUProject.cpp)[CLCOMPILE ]\n            ProjectFileImpl(Path : EmptyUProject.h)[CLINCLUDE ]\n        ProjectFileImpl(Path : EmptyUProject.Target.cs)[NONE ]\n        ProjectFileImpl(Path : EmptyUProjectEditor.Target.cs)[NONE ]\n\n\n===================\nInvoking refresh solution\n\n-EmptyUProject\n Dependencies\n -Plugins\n  -EmptyTestPlugin\n   -Resources\n    Icon128.png\n   -Source\n    -EmptyTestPlugin\n     -Private\n      EmptyTestPlugin.cpp\n     -Public\n      EmptyTestPlugin.h\n     EmptyTestPlugin.Build.cs\n   EmptyTestPlugin.uplugin\n -Source\n  -EmptyUProject\n   EmptyUProject.cpp\n   EmptyUProject.h\n   EmptyUProject.Build.cs\n  EmptyUProject.Target.cs\n  EmptyUProjectEditor.Target.cs\n .vsconfig\n EmptyUProject.uproject\n\n\n\nProject [Name:EmptyUProject, GUID:GUID]\n  Child items:\n    ProjectFileImpl(Path : .vsconfig (relative_path/.vsconfig))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.uproject (relative_path/EmptyUProject.uproject))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.vcxproj)[]\n    Folder [Name:Plugins, Virtual:relative_path/Plugins]\n      Child items:\n        Folder [Name:EmptyTestPlugin]\n          Child items:\n            ProjectFileImpl(Path : EmptyTestPlugin.uplugin)[NONE ]\n            Folder [Name:Resources]\n              Child items:\n                ProjectFileImpl(Path : Icon128.png)[NONE ]\n            Folder [Name:Source]\n              Child items:\n                Folder [Name:EmptyTestPlugin]\n                  Child items:\n                    ProjectFileImpl(Path : EmptyTestPlugin.Build.cs)[NONE ]\n                    Folder [Name:Private]\n                      Child items:\n                        ProjectFileImpl(Path : EmptyTestPlugin.cpp)[CLCOMPILE ]\n                    Folder [Name:Public]\n                      Child items:\n                        ProjectFileImpl(Path : EmptyTestPlugin.h)[CLINCLUDE ]\n    Folder [Name:Source, Virtual:relative_path/Source]\n      Child items:\n        Folder [Name:EmptyUProject]\n          Child items:\n            ProjectFileImpl(Path : EmptyUProject.Build.cs)[NONE ]\n            ProjectFileImpl(Path : EmptyUProject.cpp)[CLCOMPILE ]\n            ProjectFileImpl(Path : EmptyUProject.h)[CLINCLUDE ]\n        ProjectFileImpl(Path : EmptyUProject.Target.cs)[NONE ]\n        ProjectFileImpl(Path : EmptyUProjectEditor.Target.cs)[NONE ]\n\n\n"
  },
  {
    "path": "src/rider/test/testData/integrationTests/projectModel/RefreshSolution/refreshSolution/refreshSolution_4_27.gold",
    "content": "===================\nInit\n\n-EmptyUProject\n Dependencies\n -Source\n  -EmptyUProject\n   EmptyUProject.cpp\n   EmptyUProject.h\n   EmptyUProject.Build.cs\n  EmptyUProject.Target.cs\n  EmptyUProjectEditor.Target.cs\n EmptyUProject.uproject\n\nProject [Name:EmptyUProject, GUID:GUID]\n  Child items:\n    ProjectFileImpl(Path : EmptyUProject.uproject (relative_path/EmptyUProject.uproject))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.vcxproj)[]\n    Folder [Name:Source, Virtual:relative_path/Source]\n      Child items:\n        Folder [Name:EmptyUProject]\n          Child items:\n            ProjectFileImpl(Path : EmptyUProject.Build.cs)[NONE ]\n            ProjectFileImpl(Path : EmptyUProject.cpp)[CLCOMPILE ]\n            ProjectFileImpl(Path : EmptyUProject.h)[CLINCLUDE ]\n        ProjectFileImpl(Path : EmptyUProject.Target.cs)[NONE ]\n        ProjectFileImpl(Path : EmptyUProjectEditor.Target.cs)[NONE ]\n\n\n===================\nCopy TestPlugin to project\n\n-EmptyUProject\n Dependencies\n -Source\n  -EmptyUProject\n   EmptyUProject.cpp\n   EmptyUProject.h\n   EmptyUProject.Build.cs\n  EmptyUProject.Target.cs\n  EmptyUProjectEditor.Target.cs\n EmptyUProject.uproject\n\nProject [Name:EmptyUProject, GUID:GUID]\n  Child items:\n    ProjectFileImpl(Path : EmptyUProject.uproject (relative_path/EmptyUProject.uproject))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.vcxproj)[]\n    Folder [Name:Source, Virtual:relative_path/Source]\n      Child items:\n        Folder [Name:EmptyUProject]\n          Child items:\n            ProjectFileImpl(Path : EmptyUProject.Build.cs)[NONE ]\n            ProjectFileImpl(Path : EmptyUProject.cpp)[CLCOMPILE ]\n            ProjectFileImpl(Path : EmptyUProject.h)[CLINCLUDE ]\n        ProjectFileImpl(Path : EmptyUProject.Target.cs)[NONE ]\n        ProjectFileImpl(Path : EmptyUProjectEditor.Target.cs)[NONE ]\n\n\n===================\nInvoking refresh solution\n\n-EmptyUProject\n Dependencies\n -Plugins\n  -EmptyTestPlugin\n   -Resources\n    Icon128.png\n   -Source\n    -EmptyTestPlugin\n     -Private\n      EmptyTestPlugin.cpp\n     -Public\n      EmptyTestPlugin.h\n     EmptyTestPlugin.Build.cs\n   EmptyTestPlugin.uplugin\n -Source\n  -EmptyUProject\n   EmptyUProject.cpp\n   EmptyUProject.h\n   EmptyUProject.Build.cs\n  EmptyUProject.Target.cs\n  EmptyUProjectEditor.Target.cs\n EmptyUProject.uproject\n\nProject [Name:EmptyUProject, GUID:GUID]\n  Child items:\n    ProjectFileImpl(Path : EmptyUProject.uproject (relative_path/EmptyUProject.uproject))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.vcxproj)[]\n    Folder [Name:Plugins, Virtual:relative_path/Plugins]\n      Child items:\n        Folder [Name:EmptyTestPlugin]\n          Child items:\n            ProjectFileImpl(Path : EmptyTestPlugin.uplugin)[NONE ]\n            Folder [Name:Resources]\n              Child items:\n                ProjectFileImpl(Path : Icon128.png)[NONE ]\n            Folder [Name:Source]\n              Child items:\n                Folder [Name:EmptyTestPlugin]\n                  Child items:\n                    ProjectFileImpl(Path : EmptyTestPlugin.Build.cs)[NONE ]\n                    Folder [Name:Private]\n                      Child items:\n                        ProjectFileImpl(Path : EmptyTestPlugin.cpp)[CLCOMPILE ]\n                    Folder [Name:Public]\n                      Child items:\n                        ProjectFileImpl(Path : EmptyTestPlugin.h)[CLINCLUDE ]\n    Folder [Name:Source, Virtual:relative_path/Source]\n      Child items:\n        Folder [Name:EmptyUProject]\n          Child items:\n            ProjectFileImpl(Path : EmptyUProject.Build.cs)[NONE ]\n            ProjectFileImpl(Path : EmptyUProject.cpp)[CLCOMPILE ]\n            ProjectFileImpl(Path : EmptyUProject.h)[CLINCLUDE ]\n        ProjectFileImpl(Path : EmptyUProject.Target.cs)[NONE ]\n        ProjectFileImpl(Path : EmptyUProjectEditor.Target.cs)[NONE ]\n\n\n"
  },
  {
    "path": "src/rider/test/testData/integrationTests/projectModel/RefreshSolution/refreshSolution/refreshSolution_5_5.gold",
    "content": "===================\nInit\n\n-EmptyUProject\n Dependencies\n -Source\n  -EmptyUProject\n   EmptyUProject.cpp\n   EmptyUProject.h\n   EmptyUProject.Build.cs\n  EmptyUProject.Target.cs\n  EmptyUProjectEditor.Target.cs\n EmptyUProject.uproject\n\n\n\nProject [Name:EmptyUProject, GUID:GUID]\n  Child items:\n    ProjectFileImpl(Path : EmptyUProject.uproject (relative_path/EmptyUProject.uproject))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.vcxproj)[]\n    Folder [Name:Source, Virtual:relative_path/Source]\n      Child items:\n        Folder [Name:EmptyUProject]\n          Child items:\n            ProjectFileImpl(Path : EmptyUProject.Build.cs)[NONE ]\n            ProjectFileImpl(Path : EmptyUProject.cpp)[CLCOMPILE ]\n            ProjectFileImpl(Path : EmptyUProject.h)[CLCOMPILE ]\n        ProjectFileImpl(Path : EmptyUProject.Target.cs)[NONE ]\n        ProjectFileImpl(Path : EmptyUProjectEditor.Target.cs)[NONE ]\n\n\n===================\nCopy TestPlugin to project\n\n-EmptyUProject\n Dependencies\n -Source\n  -EmptyUProject\n   EmptyUProject.cpp\n   EmptyUProject.h\n   EmptyUProject.Build.cs\n  EmptyUProject.Target.cs\n  EmptyUProjectEditor.Target.cs\n EmptyUProject.uproject\n\n\n\nProject [Name:EmptyUProject, GUID:GUID]\n  Child items:\n    ProjectFileImpl(Path : EmptyUProject.uproject (relative_path/EmptyUProject.uproject))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.vcxproj)[]\n    Folder [Name:Source, Virtual:relative_path/Source]\n      Child items:\n        Folder [Name:EmptyUProject]\n          Child items:\n            ProjectFileImpl(Path : EmptyUProject.Build.cs)[NONE ]\n            ProjectFileImpl(Path : EmptyUProject.cpp)[CLCOMPILE ]\n            ProjectFileImpl(Path : EmptyUProject.h)[CLCOMPILE ]\n        ProjectFileImpl(Path : EmptyUProject.Target.cs)[NONE ]\n        ProjectFileImpl(Path : EmptyUProjectEditor.Target.cs)[NONE ]\n\n\n===================\nInvoking refresh solution\n\n-EmptyUProject\n Dependencies\n -Plugins\n  -EmptyTestPlugin\n   -Resources\n    Icon128.png\n   -Source\n    -EmptyTestPlugin\n     -Private\n      EmptyTestPlugin.cpp\n     -Public\n      EmptyTestPlugin.h\n     EmptyTestPlugin.Build.cs\n   EmptyTestPlugin.uplugin\n -Source\n  -EmptyUProject\n   EmptyUProject.cpp\n   EmptyUProject.h\n   EmptyUProject.Build.cs\n  EmptyUProject.Target.cs\n  EmptyUProjectEditor.Target.cs\n .vsconfig\n EmptyUProject.uproject\n\n\n\nProject [Name:EmptyUProject, GUID:GUID]\n  Child items:\n    ProjectFileImpl(Path : .vsconfig (relative_path/.vsconfig))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.uproject (relative_path/EmptyUProject.uproject))[NONE ]\n    ProjectFileImpl(Path : EmptyUProject.vcxproj)[]\n    Folder [Name:Plugins, Virtual:relative_path/Plugins]\n      Child items:\n        Folder [Name:EmptyTestPlugin]\n          Child items:\n            ProjectFileImpl(Path : EmptyTestPlugin.uplugin)[NONE ]\n            Folder [Name:Resources]\n              Child items:\n                ProjectFileImpl(Path : Icon128.png)[NONE ]\n            Folder [Name:Source]\n              Child items:\n                Folder [Name:EmptyTestPlugin]\n                  Child items:\n                    ProjectFileImpl(Path : EmptyTestPlugin.Build.cs)[NONE ]\n                    Folder [Name:Private]\n                      Child items:\n                        ProjectFileImpl(Path : EmptyTestPlugin.cpp)[CLCOMPILE ]\n                    Folder [Name:Public]\n                      Child items:\n                        ProjectFileImpl(Path : EmptyTestPlugin.h)[CLCOMPILE ]\n    Folder [Name:Source, Virtual:relative_path/Source]\n      Child items:\n        Folder [Name:EmptyUProject]\n          Child items:\n            ProjectFileImpl(Path : EmptyUProject.Build.cs)[NONE ]\n            ProjectFileImpl(Path : EmptyUProject.cpp)[CLCOMPILE ]\n            ProjectFileImpl(Path : EmptyUProject.h)[CLCOMPILE ]\n        ProjectFileImpl(Path : EmptyUProject.Target.cs)[NONE ]\n        ProjectFileImpl(Path : EmptyUProjectEditor.Target.cs)[NONE ]\n\n\n"
  },
  {
    "path": "src/rider/test/testData/integrationTests/projectModel/RefreshSolution/refreshSolution/refreshSolution_text.gold",
    "content": "===================\nInit\n\n[EmptyUProject.vcxproj.filters]\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClInclude Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>\n\n\n===================\nCopy TestPlugin to project\n\n[EmptyUProject.vcxproj.filters]\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClInclude Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>\n\n\n===================\nInvoking refresh solution\n\n[EmptyUProject.vcxproj.filters]\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/.vsconfig\" />\n    <Filter Include=\"Plugins\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\EmptyTestPlugin.Build.cs\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin</Filter>\n    </None>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <ClCompile Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private\\EmptyTestPlugin.cpp\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private</Filter>\n    </ClCompile>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <ClInclude Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public\\EmptyTestPlugin.h\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public</Filter>\n    </ClInclude>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\EmptyTestPlugin.uplugin\">\n      <Filter>Plugins\\EmptyTestPlugin</Filter>\n    </None>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Resources\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\Resources\\Icon128.png\">\n      <Filter>Plugins\\EmptyTestPlugin\\Resources</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClInclude Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>\n\n\n"
  },
  {
    "path": "src/rider/test/testData/integrationTests/projectModel/RefreshSolution/refreshSolution/refreshSolution_text_4_27.gold",
    "content": "===================\nInit\n\n[EmptyUProject.vcxproj.filters]\n﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClInclude Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>\n\n\n===================\nCopy TestPlugin to project\n\n[EmptyUProject.vcxproj.filters]\n﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClInclude Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>\n\n\n===================\nInvoking refresh solution\n\n[EmptyUProject.vcxproj.filters]\n﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Plugins\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\EmptyTestPlugin.Build.cs\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin</Filter>\n    </None>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <ClCompile Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private\\EmptyTestPlugin.cpp\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private</Filter>\n    </ClCompile>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <ClInclude Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public\\EmptyTestPlugin.h\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public</Filter>\n    </ClInclude>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\EmptyTestPlugin.uplugin\">\n      <Filter>Plugins\\EmptyTestPlugin</Filter>\n    </None>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Resources\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\Resources\\Icon128.png\">\n      <Filter>Plugins\\EmptyTestPlugin\\Resources</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClInclude Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>\n\n\n"
  },
  {
    "path": "src/rider/test/testData/integrationTests/projectModel/RefreshSolution/refreshSolution/refreshSolution_text_5_5.gold",
    "content": "===================\nInit\n\n[EmptyUProject.vcxproj.filters]\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n  </ItemGroup>\n</Project>\n\n\n===================\nCopy TestPlugin to project\n\n[EmptyUProject.vcxproj.filters]\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n  </ItemGroup>\n</Project>\n\n\n===================\nInvoking refresh solution\n\n[EmptyUProject.vcxproj.filters]\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/.vsconfig\" />\n    <Filter Include=\"Plugins\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\EmptyTestPlugin.Build.cs\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin</Filter>\n    </None>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <ClCompile Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private\\EmptyTestPlugin.cpp\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private</Filter>\n    </ClCompile>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <ClCompile Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public\\EmptyTestPlugin.h\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public</Filter>\n    </ClCompile>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\EmptyTestPlugin.uplugin\">\n      <Filter>Plugins\\EmptyTestPlugin</Filter>\n    </None>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Resources\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\Resources\\Icon128.png\">\n      <Filter>Plugins\\EmptyTestPlugin\\Resources</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n  </ItemGroup>\n</Project>\n\n\n"
  },
  {
    "path": "src/rider/test/testData/integrationTests/projectModel/RefreshSolution/refreshSolution/refreshSolution_text_5_7.gold",
    "content": "===================\nInit\n\n[EmptyUProject.vcxproj.filters]\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClInclude Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>\n\n\n===================\nCopy TestPlugin to project\n\n[EmptyUProject.vcxproj.filters]\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClInclude Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>\n\n\n===================\nInvoking refresh solution\n\n[EmptyUProject.vcxproj.filters]\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"17.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <None Include=\"relative_path/.vsconfig\" />\n    <None Include=\"relative_path/EmptyUProject.uproject\" />\n    <Filter Include=\"Plugins\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\EmptyTestPlugin.uplugin\">\n      <Filter>Plugins\\EmptyTestPlugin</Filter>\n    </None>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Resources\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\Resources\\Icon128.png\">\n      <Filter>Plugins\\EmptyTestPlugin\\Resources</Filter>\n    </None>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\EmptyTestPlugin.Build.cs\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin</Filter>\n    </None>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <ClCompile Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private\\EmptyTestPlugin.cpp\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Private</Filter>\n    </ClCompile>\n    <Filter Include=\"Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <ClInclude Include=\"relative_path/Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public\\EmptyTestPlugin.h\">\n      <Filter>Plugins\\EmptyTestPlugin\\Source\\EmptyTestPlugin\\Public</Filter>\n    </ClInclude>\n    <Filter Include=\"Source\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <None Include=\"relative_path/Source\\EmptyUProjectEditor.Target.cs\">\n      <Filter>Source</Filter>\n    </None>\n    <Filter Include=\"Source\\EmptyUProject\">\n      <UniqueIdentifier>{GUID}</UniqueIdentifier>\n    </Filter>\n    <None Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.Build.cs\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </None>\n    <ClCompile Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.cpp\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClCompile>\n    <ClInclude Include=\"relative_path/Source\\EmptyUProject\\EmptyUProject.h\">\n      <Filter>Source\\EmptyUProject</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>\n\n\n"
  },
  {
    "path": "src/rider/test/testData/solutions/TestSolutions/Unreal/EmptyUProject/EmptyUProject.uproject",
    "content": "{\n\t\"FileVersion\": 3,\n\t\"EngineAssociation\": \"\",\n\t\"Category\": \"\",\n\t\"Description\": \"\",\n\t\"DisableEnginePluginsByDefault\": true,\n\t\"Modules\": [\n\t\t{\n\t\t\t\"Name\": \"EmptyUProject\",\n\t\t\t\"Type\": \"Runtime\",\n\t\t\t\"LoadingPhase\": \"Default\"\n\t\t}\n\t]\n}"
  },
  {
    "path": "src/rider/test/testData/solutions/TestSolutions/Unreal/EmptyUProject/Source/EmptyUProject/EmptyUProject.Build.cs",
    "content": "// Fill out your copyright notice in the Description page of Project Settings.\n\nusing UnrealBuildTool;\n\npublic class EmptyUProject : ModuleRules\n{\n\tpublic EmptyUProject(ReadOnlyTargetRules Target) : base(Target)\n\t{\n\t\tPCHUsage = PCHUsageMode.NoPCHs;\n\t\n\t\tPublicDependencyModuleNames.AddRange(new string[] { \"Core\", \"CoreUObject\", \"Engine\", \"InputCore\" });\n\n\t\tPrivateDependencyModuleNames.AddRange(new string[] {  });\n\n\t\t// Uncomment if you are using Slate UI\n\t\t// PrivateDependencyModuleNames.AddRange(new string[] { \"Slate\", \"SlateCore\" });\n\t\t\n\t\t// Uncomment if you are using online features\n\t\t// PrivateDependencyModuleNames.Add(\"OnlineSubsystem\");\n\n\t\t// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true\n\t}\n}\n"
  },
  {
    "path": "src/rider/test/testData/solutions/TestSolutions/Unreal/EmptyUProject/Source/EmptyUProject/EmptyUProject.cpp",
    "content": "// Fill out your copyright notice in the Description page of Project Settings.\n\n#include \"EmptyUProject.h\"\n#include \"Modules/ModuleManager.h\"\n\n#include \"UObject/Object.h\"\n#include \"GameFramework/Actor.h\"\n#include \"Components/ActorComponent.h\"\n#include \"GameFramework/Character.h\"\n#include \"UObject/Interface.h\"\n#include \"GameFramework/Pawn.h\"\n#include \"Widgets/SCompoundWidget.h\"\n#include \"Styling/SlateWidgetStyle.h\"\n#include \"Styling/SlateWidgetStyleContainerBase.h\"\n#include \"Sound/SoundEffectSource.h\"\n#include \"Sound/SoundEffectSubmix.h\"\n#include \"Components/SynthComponent.h\"\n\nIMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, EmptyUProject, \"EmptyUProject\" );\n"
  },
  {
    "path": "src/rider/test/testData/solutions/TestSolutions/Unreal/EmptyUProject/Source/EmptyUProject/EmptyUProject.h",
    "content": "// Fill out your copyright notice in the Description page of Project Settings.\n\n#pragma once\n\n#include \"CoreMinimal.h\"\n\n"
  },
  {
    "path": "src/rider/test/testData/solutions/TestSolutions/Unreal/EmptyUProject/Source/EmptyUProject.Target.cs",
    "content": "// Fill out your copyright notice in the Description page of Project Settings.\n\nusing UnrealBuildTool;\nusing System.Collections.Generic;\n\npublic class EmptyUProjectTarget : TargetRules\n{\n\tpublic EmptyUProjectTarget(TargetInfo Target) : base(Target)\n\t{\n\t\tType = TargetType.Game;\n\t\tDefaultBuildSettings = BuildSettingsVersion.Latest;\n\n\t\tExtraModuleNames.AddRange( new string[] { \"EmptyUProject\" } );\n\t}\n}\n"
  },
  {
    "path": "src/rider/test/testData/solutions/TestSolutions/Unreal/EmptyUProject/Source/EmptyUProjectEditor.Target.cs",
    "content": "// Fill out your copyright notice in the Description page of Project Settings.\n\nusing UnrealBuildTool;\nusing System.Collections.Generic;\n\npublic class EmptyUProjectEditorTarget : TargetRules\n{\n\tpublic EmptyUProjectEditorTarget(TargetInfo Target) : base(Target)\n\t{\n\t\tType = TargetType.Editor;\n\t\tDefaultBuildSettings = BuildSettingsVersion.Latest;\n\n\t\tExtraModuleNames.AddRange( new string[] { \"EmptyUProject\" } );\n\t}\n}\n"
  },
  {
    "path": "src/rider/test/testData/unreal/additionalSource/plugins/EmptyTestPlugin/EmptyTestPlugin.uplugin",
    "content": "﻿{\n\t\"FileVersion\": 3,\n\t\"Version\": 1,\n\t\"VersionName\": \"1.0\",\n\t\"FriendlyName\": \"EmptyTestPlugin\",\n\t\"Description\": \"\",\n\t\"Category\": \"Other\",\n\t\"CreatedBy\": \"\",\n\t\"CreatedByURL\": \"\",\n\t\"DocsURL\": \"\",\n\t\"MarketplaceURL\": \"\",\n\t\"CanContainContent\": true,\n\t\"IsBetaVersion\": false,\n\t\"IsExperimentalVersion\": false,\n\t\"Installed\": false,\n\t\"Modules\": [\n\t\t{\n\t\t\t\"Name\": \"EmptyTestPlugin\",\n\t\t\t\"Type\": \"Runtime\",\n\t\t\t\"LoadingPhase\": \"Default\"\n\t\t}\n\t]\n}"
  },
  {
    "path": "src/rider/test/testData/unreal/additionalSource/plugins/EmptyTestPlugin/Source/EmptyTestPlugin/EmptyTestPlugin.Build.cs",
    "content": "﻿// Copyright Epic Games, Inc. All Rights Reserved.\n\nusing UnrealBuildTool;\n\npublic class EmptyTestPlugin : ModuleRules\n{\n\tpublic EmptyTestPlugin(ReadOnlyTargetRules Target) : base(Target)\n\t{\n\t\tPCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;\n\t\t\n\t\tPublicIncludePaths.AddRange(\n\t\t\tnew string[] {\n\t\t\t\t// ... add public include paths required here ...\n\t\t\t}\n\t\t\t);\n\t\t\t\t\n\t\t\n\t\tPrivateIncludePaths.AddRange(\n\t\t\tnew string[] {\n\t\t\t\t// ... add other private include paths required here ...\n\t\t\t}\n\t\t\t);\n\t\t\t\n\t\t\n\t\tPublicDependencyModuleNames.AddRange(\n\t\t\tnew string[]\n\t\t\t{\n\t\t\t\t\"Core\",\n\t\t\t\t// ... add other public dependencies that you statically link with here ...\n\t\t\t}\n\t\t\t);\n\t\t\t\n\t\t\n\t\tPrivateDependencyModuleNames.AddRange(\n\t\t\tnew string[]\n\t\t\t{\n\t\t\t\t\"CoreUObject\",\n\t\t\t\t\"Engine\",\n\t\t\t\t\"Slate\",\n\t\t\t\t\"SlateCore\",\n\t\t\t\t// ... add private dependencies that you statically link with here ...\t\n\t\t\t}\n\t\t\t);\n\t\t\n\t\t\n\t\tDynamicallyLoadedModuleNames.AddRange(\n\t\t\tnew string[]\n\t\t\t{\n\t\t\t\t// ... add any modules that your module loads dynamically here ...\n\t\t\t}\n\t\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/rider/test/testData/unreal/additionalSource/plugins/EmptyTestPlugin/Source/EmptyTestPlugin/Private/EmptyTestPlugin.cpp",
    "content": "﻿// Copyright Epic Games, Inc. All Rights Reserved.\n\n#include \"EmptyTestPlugin.h\"\n\n#define LOCTEXT_NAMESPACE \"FEmptyTestPluginModule\"\n\nvoid FEmptyTestPluginModule::StartupModule()\n{\n\t// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module\n}\n\nvoid FEmptyTestPluginModule::ShutdownModule()\n{\n\t// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,\n\t// we call this function before unloading the module.\n}\n\n#undef LOCTEXT_NAMESPACE\n\t\nIMPLEMENT_MODULE(FEmptyTestPluginModule, EmptyTestPlugin)"
  },
  {
    "path": "src/rider/test/testData/unreal/additionalSource/plugins/EmptyTestPlugin/Source/EmptyTestPlugin/Public/EmptyTestPlugin.h",
    "content": "﻿// Copyright Epic Games, Inc. All Rights Reserved.\n\n#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Modules/ModuleManager.h\"\n\nclass FEmptyTestPluginModule : public IModuleInterface\n{\npublic:\n\n\t/** IModuleInterface implementation */\n\tvirtual void StartupModule() override;\n\tvirtual void ShutdownModule() override;\n};\n"
  },
  {
    "path": "tools/dotnet.cmd",
    "content": ":<<\"::CMDLITERAL\"\n@ECHO OFF\nGOTO :CMDSCRIPT\n::CMDLITERAL\n\nset -eu\n\nDOTNET_VERSION=10.0.201\nDOTNET_SHORT_VERSION=\"${DOTNET_VERSION}\"\nCOMPANY_DIR=\"JetBrains\"\nTARGET_DIR=\"${TEMPDIR:-$HOME/.local/share}/$COMPANY_DIR/dotnet-cmd\"\nKEEP_ROSETTA2=false\nexport DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true\nexport DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true\nexport DOTNET_NOLOGO=true\nexport DOTNET_CLI_TELEMETRY_OPTOUT=true\nexport DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE=true\nexport DOTNET_MULTILEVEL_LOOKUP=false\nunset DOTNET_ROOT\nunset MSBUILD_TASK_PARENT_PROCESS_PID\nunset MSBuildSDKsPath\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\nretry_on_error () {\n  local n=\"$1\"\n  shift\n\n  for i in $(seq 2 \"$n\"); do\n    \"$@\" 2>&1 && return || echo \"WARNING: Command '$1' returned non-zero exit status $?, try again\"\n  done\n  \"$@\"\n}\n\nis_linux_musl () {\n  (ldd --version 2>&1 || true) | grep -q musl\n}\n\ncase $(uname) in\nDarwin)\n  DOTNET_OS=osx\n  UNAME_ARCH=$(uname -m)\n  if ! $KEEP_ROSETTA2 && [ \"$(sysctl -n sysctl.proc_translated 2>/dev/null || true)\" = \"1\" ]; then\n    DOTNET_ARCH=arm64\n  fi\n  case $UNAME_ARCH in\n  arm64)  DOTNET_ARCH=arm64;;\n  x86_64) DOTNET_ARCH=x64;;\n  *) echo \"Unknown architecture $UNAME_ARCH\" >&2; exit 1;;\n  esac;;\nLinux)\n  DOTNET_OS=linux\n  UNAME_ARCH=$(linux$(getconf LONG_BIT) uname -m)\n  case $UNAME_ARCH in\n  armv7l | armv8l) is_linux_musl && DOTNET_ARCH=musl-arm   || DOTNET_ARCH=arm;;\n  aarch64)         is_linux_musl && DOTNET_ARCH=musl-arm64 || DOTNET_ARCH=arm64;;\n  x86_64)          is_linux_musl && DOTNET_ARCH=musl-x64   || DOTNET_ARCH=x64;;\n  *) echo \"Unknown architecture $UNAME_ARCH\" >&2; exit 1;;\n  esac;;\n*) echo \"Unknown platform: $(uname)\" >&2; exit 1;;\nesac\n\nDOTNET_URL=https://cache-redirector.jetbrains.com/builds.dotnet.microsoft.com/dotnet/Sdk/$DOTNET_VERSION/dotnet-sdk-$DOTNET_VERSION-$DOTNET_OS-$DOTNET_ARCH.tar.gz\nDOTNET_TARGET_DIR=$TARGET_DIR/s$DOTNET_SHORT_VERSION-$DOTNET_ARCH\nDOTNET_TEMP_FILE=$TARGET_DIR/temp.tar.gz\n\nif grep -q -x \"$DOTNET_URL\" \"$DOTNET_TARGET_DIR/.flag\" 2>/dev/null; then\n  # Everything is up-to-date in $DOTNET_TARGET_DIR, do nothing\n  true\nelse\nwhile true; do  # Note(k15tfu): for goto\n  mkdir -p \"$TARGET_DIR\"\n\n  LOCK_FILE=\"$TARGET_DIR/.dotnet-cmd-lock.pid\"\n  TMP_LOCK_FILE=\"$TARGET_DIR/.tmp.$$.pid\"\n  echo $$ >\"$TMP_LOCK_FILE\"\n\n  while ! ln \"$TMP_LOCK_FILE\" \"$LOCK_FILE\" 2>/dev/null; do\n    LOCK_OWNER=$(cat \"$LOCK_FILE\" 2>/dev/null || true)\n    while [ -n \"$LOCK_OWNER\" ] && ps -p $LOCK_OWNER >/dev/null; do\n      warn \"Waiting for the process $LOCK_OWNER to finish bootstrap dotnet.cmd\"\n      sleep 1\n      LOCK_OWNER=$(cat \"$LOCK_FILE\" 2>/dev/null || true)\n\n      # Hurry up, bootstrap is ready..\n      if grep -q -x \"$DOTNET_URL\" \"$DOTNET_TARGET_DIR/.flag\" 2>/dev/null; then\n        break 3  # Note(k15tfu): goto out of the outer if-else block.\n      fi\n    done\n\n    if [ -n \"$LOCK_OWNER\" ] && grep -q -x $LOCK_OWNER \"$LOCK_FILE\" 2>/dev/null; then\n      die \"ERROR: The lock file $LOCK_FILE still exists on disk after the owner process $LOCK_OWNER exited\"\n    fi\n  done\n\n  trap \"rm -f \\\"$LOCK_FILE\\\"\" EXIT\n  rm \"$TMP_LOCK_FILE\"\n\n  if ! grep -q -x \"$DOTNET_URL\" \"$DOTNET_TARGET_DIR/.flag\" 2>/dev/null; then\n    warn \"Downloading $DOTNET_URL to $DOTNET_TEMP_FILE\"\n\n    rm -f \"$DOTNET_TEMP_FILE\"\n    if command -v curl >/dev/null 2>&1; then\n      if [ -t 1 ]; then CURL_PROGRESS=\"--progress-bar\"; else CURL_PROGRESS=\"--silent --show-error\"; fi\n      retry_on_error 5 curl -L $CURL_PROGRESS --output \"${DOTNET_TEMP_FILE}\" \"$DOTNET_URL\"\n    elif command -v wget >/dev/null 2>&1; then\n      if [ -t 1 ]; then WGET_PROGRESS=\"\"; else WGET_PROGRESS=\"-nv\"; fi\n      retry_on_error 5 wget $WGET_PROGRESS -O \"${DOTNET_TEMP_FILE}\" \"$DOTNET_URL\"\n    else\n      die \"ERROR: Please install wget or curl\"\n    fi\n\n    warn \"Extracting $DOTNET_TEMP_FILE to $DOTNET_TARGET_DIR\"\n    rm -rf \"$DOTNET_TARGET_DIR\"\n    mkdir -p \"$DOTNET_TARGET_DIR\"\n\n    tar -x -f \"$DOTNET_TEMP_FILE\" -C \"$DOTNET_TARGET_DIR\"\n    rm -f \"$DOTNET_TEMP_FILE\"\n\n    echo \"$DOTNET_URL\" >\"$DOTNET_TARGET_DIR/.flag\"\n  fi\n\n  rm \"$LOCK_FILE\"\n  break\ndone\nfi\n\nif [ ! -x \"$DOTNET_TARGET_DIR/dotnet\" ]; then\n  die \"Unable to find dotnet under $DOTNET_TARGET_DIR\"\nfi\n\n# Ensure usage of the same dotnet runtime for any child dotnet processes\nDOTNET_HOST_PATH=$DOTNET_TARGET_DIR/dotnet\n\nexec \"$DOTNET_HOST_PATH\" \"$@\"\n\n:CMDSCRIPT\n\nsetlocal\nset DOTNET_VERSION=10.0.201\nset DOTNET_SHORT_VERSION=%DOTNET_VERSION%\nset COMPANY_NAME=JetBrains\nset TARGET_DIR=%LOCALAPPDATA%\\%COMPANY_NAME%\\dotnet-cmd\\\n\nfor /f \"tokens=3 delims= \" %%a in ('reg query \"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\" /v \"PROCESSOR_ARCHITECTURE\"') do set ARCH=%%a\n\nif \"%ARCH%\"==\"ARM\"   (set DOTNET_ARCH=arm)   else (\nif \"%ARCH%\"==\"ARM64\" (set DOTNET_ARCH=arm64) else (\nif \"%ARCH%\"==\"AMD64\" (set DOTNET_ARCH=x64)   else (\nif \"%ARCH%\"==\"x86\"   (set DOTNET_ARCH=x86)   else (\n\necho Unknown Windows architecture\ngoto fail\n\n))))\n\nset DOTNET_URL=https://cache-redirector.jetbrains.com/builds.dotnet.microsoft.com/dotnet/Sdk/%DOTNET_VERSION%/dotnet-sdk-%DOTNET_VERSION%-win-%DOTNET_ARCH%.zip\nset DOTNET_TARGET_DIR=%TARGET_DIR%s%DOTNET_SHORT_VERSION%-%DOTNET_ARCH%\\\nset DOTNET_TEMP_FILE=%TARGET_DIR%temp.zip\nset DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true\nset DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true\nset DOTNET_NOLOGO=true\nset DOTNET_CLI_TELEMETRY_OPTOUT=true\nset DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE=true\nset DOTNET_MULTILEVEL_LOOKUP=false\nset DOTNET_ROOT=\nset MSBUILD_TASK_PARENT_PROCESS_PID=\nset MSBuildSDKsPath=\n\nset POWERSHELL=%SystemRoot%\\system32\\WindowsPowerShell\\v1.0\\powershell.exe\n\nif not exist \"%DOTNET_TARGET_DIR%.flag\" goto downloadAndExtractDotNet\n\nset /p CURRENT_FLAG=<\"%DOTNET_TARGET_DIR%.flag\"\nif \"%CURRENT_FLAG%\" == \"%DOTNET_URL%\" goto continueWithDotNet\n\n:downloadAndExtractDotNet\n\nset DOWNLOAD_AND_EXTRACT_DOTNET_PS1= ^\nSet-StrictMode -Version 3.0; ^\n$ErrorActionPreference = 'Stop'; ^\n ^\n$createdNew = $false; ^\n$lock = New-Object System.Threading.Mutex($true, 'Global\\dotnet-cmd-lock', [ref]$createdNew); ^\nif (-not $createdNew) { ^\n    Write-Host 'Waiting for the other process to finish bootstrap dotnet.cmd'; ^\n    [void]$lock.WaitOne(); ^\n} ^\n ^\ntry { ^\n    if ((Get-Content '%DOTNET_TARGET_DIR%.flag' -ErrorAction Ignore) -ne '%DOTNET_URL%') { ^\n        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; ^\n        Write-Host 'Downloading %DOTNET_URL% to %DOTNET_TEMP_FILE%'; ^\n        [void](New-Item '%TARGET_DIR%' -ItemType Directory -Force); ^\n        (New-Object Net.WebClient).DownloadFile('%DOTNET_URL%', '%DOTNET_TEMP_FILE%'); ^\n ^\n        Write-Host 'Extracting %DOTNET_TEMP_FILE% to %DOTNET_TARGET_DIR%'; ^\n        if (Test-Path '%DOTNET_TARGET_DIR%') { ^\n            Remove-Item '%DOTNET_TARGET_DIR%' -Recurse; ^\n        } ^\n        Add-Type -A 'System.IO.Compression.FileSystem'; ^\n        [IO.Compression.ZipFile]::ExtractToDirectory('%DOTNET_TEMP_FILE%', '%DOTNET_TARGET_DIR%'); ^\n        Remove-Item '%DOTNET_TEMP_FILE%'; ^\n ^\n        Set-Content '%DOTNET_TARGET_DIR%.flag' -Value '%DOTNET_URL%'; ^\n    } ^\n} ^\nfinally { ^\n    $lock.ReleaseMutex(); ^\n}\n\n\"%POWERSHELL%\" -nologo -noprofile -Command %DOWNLOAD_AND_EXTRACT_DOTNET_PS1%\nif errorlevel 1 goto fail\n\n:continueWithDotNet\n\nif not exist \"%DOTNET_TARGET_DIR%dotnet.exe\" (\n  echo Unable to find dotnet.exe under %DOTNET_TARGET_DIR%\n  goto fail\n)\n\nREM Prevent globally installed .NET Core from leaking into this runtime's lookup\nSET DOTNET_MULTILEVEL_LOOKUP=0\nREM Ensure usage of the same dotnet runtime for any child dotnet processes\nSET DOTNET_HOST_PATH=%DOTNET_TARGET_DIR%dotnet.exe\n\ncall \"%DOTNET_HOST_PATH%\" %*\nexit /B %ERRORLEVEL%\nendlocal\n\n:fail\necho \"FAIL\"\nexit /b 1"
  }
]