[
  {
    "path": ".appveyor.yml",
    "content": "# Notes:\n#   - Minimal appveyor.yml file is an empty file. All sections are optional.\n#   - Indent each level of configuration with 2 spaces. Do not use tabs!\n#   - All section names are case-sensitive.\n#   - Section names should be unique on each level.\n\n#---------------------------------#\n#      general configuration      #\n#---------------------------------#\n\n# branches to build\nbranches:\n  # blacklist\n  except:\n    - gh-pages\n\n#---------------------------------#\n#    environment configuration    #\n#---------------------------------#\n\n# Build worker image (VM template)\nimage: Visual Studio 2017\n\n# scripts that run after cloning repository\ninstall:\n  - pip install conan\n\n# stop all if one is failing\nmatrix:\n  fast_finish: true\n\nenvironment:\n  global:\n    OPENCL_INCLUDE_DIR: C:\\Intel\\OpenCL\\sdk\\include\n    OPENCL_LIB_DIR: C:\\Intel\\OpenCL\\sdk\\lib\\x64\\OpenCL.lib\n  matrix:\n    - GPU: OFF\n    - GPU: ON\n\ncache:\n  - C:\\Intel\\OpenCL\n  - C:\\Program Files (x86)\\Common Files\\Intel\\OpenCL\n\n#---------------------------------#\n#       build configuration       #\n#---------------------------------#\n\n# build platform, i.e. x86, x64, Any CPU. This setting is optional.\nplatform: x64\n\n# build Configuration, i.e. Debug, Release, etc.\nconfiguration: Release\n\nbuild:\n  parallel: true                  # enable MSBuild parallel builds\n  project: creepMiner.vcxproj     # path to Visual Studio solution or project\n\n  # MSBuild verbosity level\n  verbosity: normal\n\n# scripts to run before build\nbefore_build:\n  - IF \"%GPU%\" == \"ON\" ( IF NOT EXIST \"C:\\Intel\\OpenCL\\\" ( appveyor DownloadFile \"http://registrationcenter-download.intel.com/akdlm/irc_nas/vcp/12527/intel_sdk_for_opencl_2017_7.0.0.2567.exe\" ) )\n  - IF \"%GPU%\" == \"ON\" ( IF NOT EXIST \"C:\\Intel\\OpenCL\\\" ( start /wait .\\intel_sdk_for_opencl_2017_7.0.0.2567.exe install --output=output.log --eula=accept ) )\n  - IF \"%GPU%\" == \"ON\" ( IF NOT EXIST \"C:\\Program Files (x86)\\Common Files\\Intel\\OpenCL\\\" ( appveyor DownloadFile \"http://registrationcenter-download.intel.com/akdlm/irc_nas/12512/opencl_runtime_16.1.2_x64_setup.msi\" ) )\n  - IF \"%GPU%\" == \"ON\" ( IF NOT EXIST \"C:\\Program Files (x86)\\Common Files\\Intel\\OpenCL\\\" ( start /wait msiexec /i opencl_runtime_16.1.2_x64_setup.msi /qn  /l*v clruntime.log ) )\n  - pip install conan\n  - mkdir C:\\projects\\creepMiner\\bin\\Release\n  - cd C:\\projects\\creepminer\n  - conan install . -o Poco:shared=False -o OpenSSL:shared=False -o zlib:shared=False --build=missing\n  - cmake CMakeLists.txt -G \"Visual Studio 15 2017 Win64\" -DUSE_CUDA=OFF -DUSE_OPENCL=%GPU% -DCMAKE_BUILD_TYPE=RELWITHDEBINFO -DOpenCL_INCLUDE_DIR=%OPENCL_INCLUDE_DIR% -DOpenCL_LIBRARY=%OPENCL_LIB_DIR%\n\n# scripts to run after build\nafter_build:\n  - CPack -C Release\n\n#---------------------------------#\n#      artifacts configuration    #\n#---------------------------------#\n\nartifacts:\n  # pushing a single file\n  - path: '*.zip'\n\n#---------------------------------#\n#     deployment configuration    #\n#---------------------------------#\n\n# providers: Local, FTP, WebDeploy, AzureCS, AzureBlob, S3, NuGet, Environment\n# provider names are case-sensitive!\ndeploy:\n    # Deploy to GitHub Releases\n  - provider: GitHub\n    artifact: /.*\\.zip/\n    draft: false\n    prerelease: false\n    force_update: true\n    auth_token:\n      secure: cIGGvYiRLrapIH5uW9tl18cGB7qgBTTkrOo+yFo0Hcv7zl0KYu0qUaxFRvKLj1Yi\n    on:\n      branch: master\n      appveyor_repo_tag: true       # deploy on tag push only\n  - provider: BinTray\n    username: creepsky\n    repo: creepMiner\n    api_key:\n      secure: KkWiYEwxZuF+y1XOTWasSx0MT5GRP4f4o8k4TzavQl2lqzLEjhESqan+dt8jGLgX\n    subject: creepsky\n    package: creepMiner\n    version: stable\n    publish: true\n    artifact: /.*\\.zip/\n    override: true\n    on:\n      branch: master\n  - provider: BinTray\n    username: creepsky\n    repo: creepMiner\n    api_key:\n      secure: KkWiYEwxZuF+y1XOTWasSx0MT5GRP4f4o8k4TzavQl2lqzLEjhESqan+dt8jGLgX\n    subject: creepsky\n    package: creepMiner-dev\n    version: development\n    publish: true\n    artifact: /.*\\.zip/\n    override: true\n    on:\n      branch: development\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbld/\n[Oo]bj/\n[Ll]og/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\nProperties/launchSettings.json\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n# NuGet v3's project.json files produces more ignoreable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n\n# CodeRush\n.cr/\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/\n\n# Created by .ignore support plugin (hsz.mobi)\n### JetBrains template\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio\n\n*.iml\n\n## Directory-based project format:\n.idea/\n# if you remove the above rule, at least ignore the following:\n\n# User-specific stuff:\n# .idea/workspace.xml\n# .idea/tasks.xml\n# .idea/dictionaries\n\n# Sensitive or high-churn files:\n# .idea/dataSources.ids\n# .idea/dataSources.xml\n# .idea/sqlDataSources.xml\n# .idea/dynamic.xml\n# .idea/uiDesigner.xml\n\n# Gradle:\n# .idea/gradle.xml\n# .idea/libraries\n\n# Mongo Explorer plugin:\n# .idea/mongoSettings.xml\n\n## File-based project format:\n*.ipr\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\n/out/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\n### Java template\n*.class\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n### Eclipse template\n*.pydevproject\n.metadata\n.gradle\ntmp/\n*.tmp\n*.bak\n*.swp\n*~.nib\nlocal.properties\n.settings/\n.loadpath\n\n# Eclipse Core\n.project\n\n# External tool builders\n.externalToolBuilders/\n\n# Locally stored \"Eclipse launch configurations\"\n*.launch\n\n# CDT-specific\n.cproject\n\n# JDT-specific (Eclipse Java Development Tools)\n.classpath\n\n# Java annotation processor (APT)\n.factorypath\n\n# PDT-specific\n.buildpath\n\n# sbteclipse plugin\n.target\n\n# TeXlipse plugin\n.texlipse\n### NetBeans template\nnbproject/private/\nbuild/\nnbbuild/\ndist/\nnbdist/\nnbactions.xml\nnb-configuration.xml\n.nb-gradle/\n### Maven template\ntarget/\npom.xml.tag\npom.xml.releaseBackup\npom.xml.versionsBackup\npom.xml.next\nrelease.properties\ndependency-reduced-pom.xml\nbuildNumber.properties\n.mvn/timing.properties\n\n/cmake-build*\n\n# Custom files and dirs\nmakefile\nmining.conf\n*.graphml\nbuild/\n\n# Visual Code\n.vscode/*\n\n# CMake\nCMakeCache.txt\nCMakeFiles\nCMakeScripts\nTesting\nMakefile\ncmake_install.cmake\ninstall_manifest.txt\ncompile_commands.json\nCTestTestfile.cmake\nCMakeSettings.json\n\n# conan\nconanbuildinfo.cmake\nconanbuildinfo.txt\nconaninfo.txt\nconan_imports_manifest.txt\n\nCPackConfig.cmake\nCPackSourceConfig.cmake\n_CPack_Packages/\nlib/\n*.deb\n*.rpm\n*.tar*\nbin\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: cpp\nbefore_install:\n- eval \"${MATRIX_EVAL}\"\nmatrix:\n  fast_finish: true\n  include:\n  - os: osx\n    sudo: false\n    compiler: clang\n    script:\n    - conan install . --build=missing\n    - cmake . -DNO_GPU=ON\n    - make -j$(nproc)\n    - make package\n    file:\n    - \"*.tar.gz\"\n    env:\n    - NAME=\"osx clang\" MATRIX_EVAL=\"brew install conan\"\n    cache:\n      directories:\n      - \"$HOME/.conan\"\n    deploy:\n    - provider: releases\n      skip_cleanup: true\n      file_glob: true\n      file:\n      - \"*.tar.gz\"\n      on:\n        tags: true\n      api_key:\n        secure: xs3GCmymdo/fo46+ELma466ZdnYtYnQtV68EE3wbhXJD1Kc4Wq+rRiHXIpR+fhWhDFsbaiM0KIhjbMwwmphnXOhcVXvcufxqtvMxEySWx9uPOsIQ+LoeElmiU4AmmnEerVOEYDACj//KianI6Zm70PIwUBYGBaW41x97jhe4WLoQdKPj/ORsEGh/oZtJfI05qXzW1UdF6labSD/4jcx6CEsiFFCAh7EeAZjB0rhqfknp1IGn3N1G+rN43zYgMs9D3ww9PRDZdGlMqYk4cJglCQQAqQa0I71LtNcgkKNxfh4JBz8qyHRrTPr4tQXhtz9IPrQFLmSKtCvTJjjmUZ5RE2FqhVPXxswBKEv43tsDklqDt/qGjlcuMZwnn3c18R2gkBx2kXpyie6ujXIxrWaiao6Mp+OS2knzb5ebI4fqj6G8+mwQNheuR5qcmnZVfgv6CyCLxVgIOZEGaq6TBS9+6FiP6pqpKP3ySM/etmQB8GwDz53aUYirykL7sjunYMxiqf7T6XSwqHiZJWZUVZVPNxhEft2BVaxwhCf78KasZd0tzFfsEb0NM8vfKSAkj4zTdYTW3it6iSjH30PJbOjDuYSMC1Aje/T5q8JnPXJcIB2/i1BkAp37VXgC6ebOT/cSQsliVptzZx4ZXjuIN8zkuf6ka6NYNKVYOFRv5pChJoc=\n    - provider: bintray\n      file: bintray-dev.json\n      user: creepsky\n      skip_cleanup: true\n      key:\n        secure: Br+EQG0ypyBrzs/vvQozCmAdjE5yILyGY/IMcS2bUmlWurEBeQIk+nSSRFSCBdi0/GfXrs3a91XenIsvrYYIQQVNjJ277vw4fyJ2lFAbyIp7S3NeCFT04nmcDXqszIYDjdSHeQTFvuUnOD9vhLleDnke2Lff4+weVGgqD1Hr8mkPEUStqij3PYzk/5qVTUdQ69D0kIWr5+z+p0FSCerdAsdMW8LNX/6T+y4Cq7X4TdJudh4vW0mwnhkdj2IOl608cCNGU4OVLeHQdqQKC3yMxmJyyIryRa4ylwlqPw7s+9FBqGb2Gemip9a6gOowoPIbf2PPCquGDCKDtlTeT09fQbLcbOP4LtWZ/VentZAx6PbIrYxymPTI5p362a0z/SHCZ4X0I7ElUdCzGncHTkR9rKaRCEEnQiIsqK0OUa2sS18+rcnza0WgcXYR0ZUSWzjLbWhg1WeQzzQzITU3tM22CHG/Joy9z1Ob6xw+rdS9xw0/nTJoVHAfUobEfXx5tyFm5tnobIPrrdsoMZJ1sKH+geCP0m/tLyZCTQflmTwauUsB3+NTsomS2D4t3zX13XApGFgCRAbG+u3Hb9xv7PXSpxVpf70arDxVs8ZZsewJ4910VEoPk4Mg/dTYAh/M+2PQnd7TlNQ4pMkEOQTajti6bkHTA8dn2XjfomOCjOx5OxE=\n      on:\n        branch: development\n  - os: osx\n    sudo: false\n    compiler: clang\n    script:\n    - conan install . --build=missing\n    - cmake . -DUSE_CUDA=OFF -DUSE_OPENCL=ON\n    - make -j$(nproc)\n    - make package\n    file:\n    - \"*.tar.gz\"\n    env:\n    - NAME=\"osx clang opencl\" MATRIX_EVAL=\"brew install conan\"\n    cache:\n      directories:\n      - \"$HOME/.conan\"\n    deploy:\n    - provider: releases\n      skip_cleanup: true\n      file_glob: true\n      file:\n      - \"*.tar.gz\"\n      on:\n        tags: true\n      api_key:\n        secure: xs3GCmymdo/fo46+ELma466ZdnYtYnQtV68EE3wbhXJD1Kc4Wq+rRiHXIpR+fhWhDFsbaiM0KIhjbMwwmphnXOhcVXvcufxqtvMxEySWx9uPOsIQ+LoeElmiU4AmmnEerVOEYDACj//KianI6Zm70PIwUBYGBaW41x97jhe4WLoQdKPj/ORsEGh/oZtJfI05qXzW1UdF6labSD/4jcx6CEsiFFCAh7EeAZjB0rhqfknp1IGn3N1G+rN43zYgMs9D3ww9PRDZdGlMqYk4cJglCQQAqQa0I71LtNcgkKNxfh4JBz8qyHRrTPr4tQXhtz9IPrQFLmSKtCvTJjjmUZ5RE2FqhVPXxswBKEv43tsDklqDt/qGjlcuMZwnn3c18R2gkBx2kXpyie6ujXIxrWaiao6Mp+OS2knzb5ebI4fqj6G8+mwQNheuR5qcmnZVfgv6CyCLxVgIOZEGaq6TBS9+6FiP6pqpKP3ySM/etmQB8GwDz53aUYirykL7sjunYMxiqf7T6XSwqHiZJWZUVZVPNxhEft2BVaxwhCf78KasZd0tzFfsEb0NM8vfKSAkj4zTdYTW3it6iSjH30PJbOjDuYSMC1Aje/T5q8JnPXJcIB2/i1BkAp37VXgC6ebOT/cSQsliVptzZx4ZXjuIN8zkuf6ka6NYNKVYOFRv5pChJoc=\n    - provider: bintray\n      file: bintray-dev.json\n      user: creepsky\n      skip_cleanup: true\n      key:\n        secure: Br+EQG0ypyBrzs/vvQozCmAdjE5yILyGY/IMcS2bUmlWurEBeQIk+nSSRFSCBdi0/GfXrs3a91XenIsvrYYIQQVNjJ277vw4fyJ2lFAbyIp7S3NeCFT04nmcDXqszIYDjdSHeQTFvuUnOD9vhLleDnke2Lff4+weVGgqD1Hr8mkPEUStqij3PYzk/5qVTUdQ69D0kIWr5+z+p0FSCerdAsdMW8LNX/6T+y4Cq7X4TdJudh4vW0mwnhkdj2IOl608cCNGU4OVLeHQdqQKC3yMxmJyyIryRa4ylwlqPw7s+9FBqGb2Gemip9a6gOowoPIbf2PPCquGDCKDtlTeT09fQbLcbOP4LtWZ/VentZAx6PbIrYxymPTI5p362a0z/SHCZ4X0I7ElUdCzGncHTkR9rKaRCEEnQiIsqK0OUa2sS18+rcnza0WgcXYR0ZUSWzjLbWhg1WeQzzQzITU3tM22CHG/Joy9z1Ob6xw+rdS9xw0/nTJoVHAfUobEfXx5tyFm5tnobIPrrdsoMZJ1sKH+geCP0m/tLyZCTQflmTwauUsB3+NTsomS2D4t3zX13XApGFgCRAbG+u3Hb9xv7PXSpxVpf70arDxVs8ZZsewJ4910VEoPk4Mg/dTYAh/M+2PQnd7TlNQ4pMkEOQTajti6bkHTA8dn2XjfomOCjOx5OxE=\n      on:\n        branch: development\n  - os: linux\n    sudo: false\n    addons:\n      apt:\n        sources:\n        - ubuntu-toolchain-r-test\n        packages:\n        - g++-5\n    env:\n    - NAME=\"linux g++-5\" MATRIX_EVAL=\"CC=gcc-5 && CXX=g++-5\"\n    script:\n    - pip install conan --user\n    - conan install . --build=missing\n    - cmake . -DNO_GPU=ON\n    - make -j$(nproc)\n    - make package\n    cache:\n      directories:\n      - \"$HOME/.conan\"\n    deploy:\n    - provider: releases\n      skip_cleanup: true\n      file_glob: true\n      file:\n      - \"*.tar.gz\"\n      on:\n        tags: true\n      api_key:\n        secure: xs3GCmymdo/fo46+ELma466ZdnYtYnQtV68EE3wbhXJD1Kc4Wq+rRiHXIpR+fhWhDFsbaiM0KIhjbMwwmphnXOhcVXvcufxqtvMxEySWx9uPOsIQ+LoeElmiU4AmmnEerVOEYDACj//KianI6Zm70PIwUBYGBaW41x97jhe4WLoQdKPj/ORsEGh/oZtJfI05qXzW1UdF6labSD/4jcx6CEsiFFCAh7EeAZjB0rhqfknp1IGn3N1G+rN43zYgMs9D3ww9PRDZdGlMqYk4cJglCQQAqQa0I71LtNcgkKNxfh4JBz8qyHRrTPr4tQXhtz9IPrQFLmSKtCvTJjjmUZ5RE2FqhVPXxswBKEv43tsDklqDt/qGjlcuMZwnn3c18R2gkBx2kXpyie6ujXIxrWaiao6Mp+OS2knzb5ebI4fqj6G8+mwQNheuR5qcmnZVfgv6CyCLxVgIOZEGaq6TBS9+6FiP6pqpKP3ySM/etmQB8GwDz53aUYirykL7sjunYMxiqf7T6XSwqHiZJWZUVZVPNxhEft2BVaxwhCf78KasZd0tzFfsEb0NM8vfKSAkj4zTdYTW3it6iSjH30PJbOjDuYSMC1Aje/T5q8JnPXJcIB2/i1BkAp37VXgC6ebOT/cSQsliVptzZx4ZXjuIN8zkuf6ka6NYNKVYOFRv5pChJoc=\n    - provider: bintray\n      file: bintray-dev.json\n      user: creepsky\n      skip_cleanup: true\n      key:\n        secure: Br+EQG0ypyBrzs/vvQozCmAdjE5yILyGY/IMcS2bUmlWurEBeQIk+nSSRFSCBdi0/GfXrs3a91XenIsvrYYIQQVNjJ277vw4fyJ2lFAbyIp7S3NeCFT04nmcDXqszIYDjdSHeQTFvuUnOD9vhLleDnke2Lff4+weVGgqD1Hr8mkPEUStqij3PYzk/5qVTUdQ69D0kIWr5+z+p0FSCerdAsdMW8LNX/6T+y4Cq7X4TdJudh4vW0mwnhkdj2IOl608cCNGU4OVLeHQdqQKC3yMxmJyyIryRa4ylwlqPw7s+9FBqGb2Gemip9a6gOowoPIbf2PPCquGDCKDtlTeT09fQbLcbOP4LtWZ/VentZAx6PbIrYxymPTI5p362a0z/SHCZ4X0I7ElUdCzGncHTkR9rKaRCEEnQiIsqK0OUa2sS18+rcnza0WgcXYR0ZUSWzjLbWhg1WeQzzQzITU3tM22CHG/Joy9z1Ob6xw+rdS9xw0/nTJoVHAfUobEfXx5tyFm5tnobIPrrdsoMZJ1sKH+geCP0m/tLyZCTQflmTwauUsB3+NTsomS2D4t3zX13XApGFgCRAbG+u3Hb9xv7PXSpxVpf70arDxVs8ZZsewJ4910VEoPk4Mg/dTYAh/M+2PQnd7TlNQ4pMkEOQTajti6bkHTA8dn2XjfomOCjOx5OxE=\n      on:\n        branch: development\n  - os: linux\n    sudo: true\n    addons:\n      apt:\n        sources:\n        - ubuntu-toolchain-r-test\n        packages:\n        - g++-5\n    env:\n    - NAME=\"linux g++-5 opencl\" MATRIX_EVAL=\"CC=gcc-5 && CXX=g++-5\"\n    script:\n    - sudo apt-get install opencl-headers\n    - sudo apt install ocl-icd-opencl-dev\n    - pip install conan --user\n    - conan install . --build=missing\n    - cmake . -DUSE_CUDA=OFF -DUSE_OPENCL=ON\n    - make -j$(nproc)\n    - make package\n    cache:\n      directories:\n      - \"$HOME/.conan\"\n    deploy:\n    - provider: releases\n      skip_cleanup: true\n      file_glob: true\n      file:\n      - \"*.tar.gz\"\n      on:\n        tags: true\n      api_key:\n        secure: xs3GCmymdo/fo46+ELma466ZdnYtYnQtV68EE3wbhXJD1Kc4Wq+rRiHXIpR+fhWhDFsbaiM0KIhjbMwwmphnXOhcVXvcufxqtvMxEySWx9uPOsIQ+LoeElmiU4AmmnEerVOEYDACj//KianI6Zm70PIwUBYGBaW41x97jhe4WLoQdKPj/ORsEGh/oZtJfI05qXzW1UdF6labSD/4jcx6CEsiFFCAh7EeAZjB0rhqfknp1IGn3N1G+rN43zYgMs9D3ww9PRDZdGlMqYk4cJglCQQAqQa0I71LtNcgkKNxfh4JBz8qyHRrTPr4tQXhtz9IPrQFLmSKtCvTJjjmUZ5RE2FqhVPXxswBKEv43tsDklqDt/qGjlcuMZwnn3c18R2gkBx2kXpyie6ujXIxrWaiao6Mp+OS2knzb5ebI4fqj6G8+mwQNheuR5qcmnZVfgv6CyCLxVgIOZEGaq6TBS9+6FiP6pqpKP3ySM/etmQB8GwDz53aUYirykL7sjunYMxiqf7T6XSwqHiZJWZUVZVPNxhEft2BVaxwhCf78KasZd0tzFfsEb0NM8vfKSAkj4zTdYTW3it6iSjH30PJbOjDuYSMC1Aje/T5q8JnPXJcIB2/i1BkAp37VXgC6ebOT/cSQsliVptzZx4ZXjuIN8zkuf6ka6NYNKVYOFRv5pChJoc=\n    - provider: bintray\n      file: bintray-dev.json\n      user: creepsky\n      skip_cleanup: true\n      key:\n        secure: Br+EQG0ypyBrzs/vvQozCmAdjE5yILyGY/IMcS2bUmlWurEBeQIk+nSSRFSCBdi0/GfXrs3a91XenIsvrYYIQQVNjJ277vw4fyJ2lFAbyIp7S3NeCFT04nmcDXqszIYDjdSHeQTFvuUnOD9vhLleDnke2Lff4+weVGgqD1Hr8mkPEUStqij3PYzk/5qVTUdQ69D0kIWr5+z+p0FSCerdAsdMW8LNX/6T+y4Cq7X4TdJudh4vW0mwnhkdj2IOl608cCNGU4OVLeHQdqQKC3yMxmJyyIryRa4ylwlqPw7s+9FBqGb2Gemip9a6gOowoPIbf2PPCquGDCKDtlTeT09fQbLcbOP4LtWZ/VentZAx6PbIrYxymPTI5p362a0z/SHCZ4X0I7ElUdCzGncHTkR9rKaRCEEnQiIsqK0OUa2sS18+rcnza0WgcXYR0ZUSWzjLbWhg1WeQzzQzITU3tM22CHG/Joy9z1Ob6xw+rdS9xw0/nTJoVHAfUobEfXx5tyFm5tnobIPrrdsoMZJ1sKH+geCP0m/tLyZCTQflmTwauUsB3+NTsomS2D4t3zX13XApGFgCRAbG+u3Hb9xv7PXSpxVpf70arDxVs8ZZsewJ4910VEoPk4Mg/dTYAh/M+2PQnd7TlNQ4pMkEOQTajti6bkHTA8dn2XjfomOCjOx5OxE=\n      on:\n        branch: development\n  - os: linux\n    sudo: false\n    addons:\n      apt:\n        sources:\n        - ubuntu-toolchain-r-test\n        packages:\n        - g++-6\n    env:\n    - NAME=\"linux g++-6\" MATRIX_EVAL=\"CC=gcc-6 && CXX=g++-6\"\n    script:\n    - pip install conan --user\n    - conan install . --build=missing\n    - cmake . -DNO_GPU=ON\n    - make -j$(nproc)\n    cache:\n      directories:\n      - \"$HOME/.conan\"\n  - os: linux\n    addons:\n      apt:\n        sources:\n        - ubuntu-toolchain-r-test\n        packages:\n        - g++-7\n    env:\n    - NAME=\"linux g++-7\" - MATRIX_EVAL=\"CC=gcc-7 && CXX=g++-7\"\n    script:\n    - python -V\n    - pip install conan --user\n    - conan install . --build=missing\n    - cmake . -DNO_GPU=ON\n    - make -j$(nproc)\n    cache:\n      directories:\n      - \"$HOME/.conan\"\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "##################################################################\n# Project and CMake settings\n##################################################################\ncmake_minimum_required(VERSION 3.0.2)\nproject(creepMiner)\nset(CMAKE_CXX_STANDARD 14)\n\nif (NOT CMAKE_BUILD_TYPE)\n\tset(CMAKE_BUILD_TYPE RELWITHDEBINFO)\nendif ()\n\n##################################################################\n# Configuration types\n##################################################################\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG \"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}\")\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE \"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}\")\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO \"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}\")\n\noption(MINIMAL_BUILD \"If yes, the miner will be build without any extras like CUDA, CPU instructions...\" OFF)\noption(NO_GPU \"If yes, the miner will be build without CUDA and OpenCL.\" OFF)\n\n##################################################################\n# Environment variables\n##################################################################\n\n# get the version number from version.id\nfile(STRINGS version.id VERSION_RAW)\nstring(REPLACE \"version:\" \"\" VERSION ${VERSION_RAW})\n\n# make a list\nstring(REPLACE \".\" \";\" VERSION_LIST ${VERSION})\n\n# filter version numbers\nlist(GET VERSION_LIST 0 VERSION_MAJOR)\nlist(GET VERSION_LIST 1 VERSION_MINOR)\nlist(GET VERSION_LIST 2 VERSION_BUILD)\nlist(GET VERSION_LIST 3 VERSION_REVISION)\n\n# define it for the source files\nadd_definitions(-DVERSION_MAJOR=${VERSION_MAJOR}\n\t\t\t\t-DVERSION_MINOR=${VERSION_MINOR}\n\t\t\t\t-DVERSION_BUILD=${VERSION_BUILD}\n\t\t\t\t-DVERSION_REVISION=${VERSION_REVISION})\n\n##################################################################\n# using Conan for dependencies\n##################################################################\noption(USE_CONAN \"If ON, Conan will be used to satisfy OpenSSL,POCO,and zlib dependency\" ON)\n\nif (USE_CONAN)\n  # init conan\n  if (CONAN_DEBUG)\n    include(conan/debug/conanbuildinfo.cmake)\n  else ()\n    include(conanbuildinfo.cmake)\n  endif ()\n\n  conan_basic_setup()\nendif ()\n\n##################################################################\n# CPU architecture (only for Unix/Mac)\n##################################################################\nif (UNIX OR APPLE)\n\tset(CPU_ARCH \"X64\" CACHE STRING \"CPU architecture\")\n\tset_property(CACHE CPU_ARCH PROPERTY STRINGS X32 X64)\n\t\n\tif (CPU_ARCH STREQUAL \"X32\")\n\t\tadd_definitions(-m32)\n\tendif ()\nendif ()\n\n##################################################################\n# GPU acceleration\n##################################################################\noption(USE_CUDA \"If yes, CUDA will be enabled\" ON)\noption(USE_OPENCL \"If yes, OpenCL will be enabled\" ON)\n\nif (USE_CUDA AND NOT MINIMAL_BUILD AND NOT NO_GPU)\n\t find_package(CUDA REQUIRED)\n\t add_definitions(-DUSE_CUDA)\n\t set(GPU_CUDA_ARCH \"sm_52\" CACHE STRING \"The CUDA architecture\")\n\t set(CUDA_NVCC_FLAGS\n\t\t ${CUDA_NVCC_FLAGS}\n\t\t -arch=${GPU_CUDA_ARCH}\n\t\t -std=c++11\n\t\t -default-stream per-thread\n\t\t -gencode=arch=compute_30,code=sm_30\n\t\t -gencode=arch=compute_50,code=sm_50\n\t\t -gencode=arch=compute_52,code=sm_52\n\t\t -gencode=arch=compute_52,code=compute_52\n\t\t -gencode=arch=compute_60,code=sm_60\n\t\t -gencode=arch=compute_61,code=sm_61\n\t\t -gencode=arch=compute_62,code=sm_62)\nendif()\n\nif (USE_OPENCL AND NOT MINIMAL_BUILD AND NOT NO_GPU)\n\tfind_package(OpenCL REQUIRED)\n\tinclude_directories(${OpenCL_INCLUDE_DIR})\n\tadd_definitions(-DUSE_OPENCL)\nendif ()\n\n##################################################################\n# Additional options\n##################################################################\noption(CONAN_DEBUG \"Only for development\" OFF)\n\n##################################################################\n# UNIX / BSD specific\n##################################################################\nif (UNIX OR APPLE)\t \n\tadd_definitions(-D_REENTRANT -std=c++14)\n\tlink_directories(/usr/local/lib)\n\tinclude_directories(/usr/local/include ${CMAKE_CURRENT_SOURCE_DIR}/src)\n##################################################################\n# MSVC specific\n##################################################################\nelseif (MSVC)\n\tinclude_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)\n\tset_source_files_properties(bin/icon.ico src/resources.rc PROPERTIES LANGUAGE RC)\n\tadd_definitions(/MP)\nendif ()\n\n##################################################################\n# Source files\n##################################################################\nfile(GLOB SOURCE_FILES\n    src/*.*pp\n    src/gpu/impl/*.*pp\n    src/logging/channels/*.*pp\n    src/logging/*.*pp\n    src/mining/*.*pp\n    src/network/*.*pp\n    src/nxt/nxt_address.h\n    src/nxt/nxt_address.cpp\n    src/plots/*.*pp\n    src/shabal/*.*pp\n    src/shabal/sphlib/*.*pp\n    src/wallet/*.*pp\n    src/webserver/*.*pp\n    src/resources.rc)\n\n##################################################################\n# Special files and settings\n##################################################################\noption(USE_SSE4 \"If yes, SSE4 will be enabled\" ON)\noption(USE_AVX \"If yes, AVX will be enabled\" ON)\noption(USE_AVX2 \"If yes, AVX2 will be enabled\" ON)\n\nif (USE_SSE4 AND NOT MINIMAL_BUILD)\n\tadd_definitions(-DUSE_SSE4)\n\tset(SOURCE_FILES ${SOURCE_FILES} src/shabal/mshabal/mshabal_sse4.cpp)\n\tif (UNIX OR APPLE)\n\t\tset_source_files_properties(src/shabal/mshabal/mshabal_sse4.cpp PROPERTIES COMPILE_FLAGS -msse2)\n\tendif ()\nendif ()\n\nif (USE_AVX AND NOT MINIMAL_BUILD)\n\tadd_definitions(-DUSE_AVX)\n\tset(SOURCE_FILES ${SOURCE_FILES} src/shabal/mshabal/mshabal_avx1.cpp)\n\tif (UNIX OR APPLE)\n\t\tset_source_files_properties(src/shabal/mshabal/mshabal_avx1.cpp PROPERTIES COMPILE_FLAGS -mavx)\n\telseif (MSVC)\n\t\tset_source_files_properties(src/shabal/mshabal/mshabal_avx1.cpp PROPERTIES COMPILE_FLAGS /arch:AVX)\n\tendif ()\nendif ()\n\nif (USE_AVX2 AND NOT MINIMAL_BUILD)\n\tadd_definitions(-DUSE_AVX2)\n\tset(SOURCE_FILES ${SOURCE_FILES} src/shabal/mshabal/mshabal_avx2.cpp)\n\tif (UNIX OR APPLE)\n\t\tset_source_files_properties(src/shabal/mshabal/mshabal_avx2.cpp PROPERTIES COMPILE_FLAGS -mavx2)\n\telseif (MSVC)\n\t\tset_source_files_properties(src/shabal/mshabal/mshabal_avx2.cpp PROPERTIES COMPILE_FLAGS /arch:AVX2)\n\tendif ()\nendif ()\n\nif (USE_CUDA AND NOT MINIMAL_BUILD AND NOT NO_GPU)\n\tset(SOURCE_FILES ${SOURCE_FILES} src/shabal/cuda/Shabal.cu)\nendif ()\n\n##################################################################\n# Executable\n##################################################################\nif (USE_CUDA AND NOT MINIMAL_BUILD AND NOT NO_GPU)\n\t cuda_add_executable(creepMiner ${SOURCE_FILES})\nelse ()\n\t add_executable(creepMiner ${SOURCE_FILES})\nendif ()\n\n##################################################################\n# Libraries\n##################################################################\n\n# Optimised Shabal Library\nfind_library(SHABAL_LIB NAMES shabal.dll libshabal.dylib libshabal.so HINTS \"${CMAKE_SOURCE_DIR}/libShabal\")\nadd_library(shabalLib STATIC IMPORTED)\nset_property(TARGET shabalLib PROPERTY IMPORTED_LOCATION ${SHABAL_LIB})\ntarget_link_libraries(creepMiner shabalLib)\n\ntarget_link_libraries(creepMiner ${CONAN_LIBS})\n\nif (NOT USE_CONAN)\n  find_package(Poco REQUIRED Foundation Util Net Crypto NetSSL)\n  target_link_libraries(creepMiner ${Poco_LIBRARIES})\nendif()\n\nif (USE_OPENCL)\n\ttarget_link_libraries(creepMiner ${OpenCL_LIBRARY})\nendif ()\n\n##################################################################\n# Naming\n##################################################################\nset_target_properties(creepMiner PROPERTIES DEBUG_POSTFIX -d)\n\n##################################################################\n# Installing\n##################################################################\ninstall(FILES src/shabal/opencl/mining.cl DESTINATION .)\ninstall(DIRECTORY resources/public DESTINATION .)\n\nif (NOT MSVC)\n\tinstall(DIRECTORY bin/ DESTINATION . USE_SOURCE_PERMISSIONS)\n\tinstall(FILES resources/run.sh resources/screen.sh DESTINATION . PERMISSIONS\n\t\t\tOWNER_READ OWNER_WRITE OWNER_EXECUTE\n\t\t\tGROUP_READ GROUP_WRITE GROUP_EXECUTE\n\t\t\tWORLD_READ WORLD_WRITE WORLD_EXECUTE)\n\tif (UNIX)\n\t\tinstall(DIRECTORY lib/ DESTINATION lib)\n\t\tinstall(FILES libShabal/libshabal.so DESTINATION .)\n\telseif (APPLE)\n\t\tinstall(FILES libShabal/libshabal.dylib DESTINATION .)\n\tendif()\nelse ()\n\tinstall(TARGETS creepMiner RUNTIME DESTINATION .)\n\tinstall(FILES libShabal/shabal.dll DESTINATION .)\nendif ()\n\n##################################################################\n# Packaging\n##################################################################\nif (USE_CUDA AND NOT MINIMAL_BUILD AND NOT NO_GPU)\n\tset(PACKAGE_NAME ${CMAKE_PROJECT_NAME}-cuda)\nelseif (USE_OPENCL AND NOT MINIMAL_BUILD AND NOT NO_GPU)\n\tset(PACKAGE_NAME ${CMAKE_PROJECT_NAME}-opencl)\nelse ()\n\tset(PACKAGE_NAME ${CMAKE_PROJECT_NAME})\nendif ()\n\nset(CPACK_PACKAGE_NAME ${PACKAGE_NAME})\nset(CPACK_PACKAGE_DESCRIPTION_SUMMARY \"Burstcoin C++ CPU and GPU Miner\")\nset(CPACK_PACKAGE_VENDOR \"Creepsky\")\nset(CPACK_PACKAGE_VERSION ${VERSION})\nset(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})\nset(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})\nset(CPACK_PACKAGE_VERSION_PATCH ${VERSION_BUILD})\nset(CPACK_RESOURCE_FILE_LICENSE \"${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md\")\nSET(CPACK_RESOURCE_FILE_README \"${CMAKE_CURRENT_SOURCE_DIR}/README.md\")\nset(CPACK_SOURCE_PACKAGE_FILE ${PACKAGE_NAME})\n#set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)\n\nif (UNIX OR APPLE)\n    set(CPACK_SET_DESTDIR true)\n    set(CPACK_INSTALL_PREFIX \"/opt/${CMAKE_PROJECT_NAME}-${VERSION}\")\n    set(CPACK_SOURCE_GENERATOR \"TGZ;TBZ2\")\n    set(CPACK_GENERATOR \"TGZ\")\n    set(CPACK_PACKAGE_SECTION \"misc\")\n    set(CPACK_DEBIAN_PACKAGE_MAINTAINER \"Creepsky\")\n\tinclude(CPack)\nelseif (WIN32)\n\tset(CPACK_GENERATOR \"ZIP\")\n\t#set(CPACK_PACKAGE_ICON \"${CMAKE_SOURCE_DIR}\\\\resources\\\\icon.ico\")\n\t#set(CPACK_NSIS_MUI_ICON \"${CMAKE_SOURCE_DIR}\\\\resources\\\\icon.ico\")\n\t#set(CPACK_NSIS_MUI_UNIICON \"${CMAKE_SOURCE_DIR}\\\\resources\\\\icon.ico\")\n\tset(CPACK_NSIS_MENU_LINKS \"creepMiner.exe\" \"creepMiner\")\n\tinclude(CPack)\nendif ()\n"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "content": "Before submitting your issue, please review the following checklist:\n\n- [ ] **AVOID** using the issue tracker for questions or help. \nSubmitting issues to this repository are usually reserved for bugs, feature requests, or changes to the source code. We have a great discord to ask for help here: https://discord.gg/qnjyVQt\n- [ ] **DO** include log files.\n- [ ] **DO** include the miner config.\n- [ ] **DO** describe the operating system for the Server and Client (Windows / Linux). Also, the run-time platform and versions.\n\n\n### Subject of the issue\nDescribe your issue here.\n\n### Your environment\n* version of creepMiner.\n* version of OS.\n* which browser and its version.\n\n### Steps to reproduce\nTell us how to reproduce this issue.\n\n### Expected behavior\nTell us what should happen.\n\n### Actual behavior\nTell us what happens instead.\n\n\n### Other information\nList any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix etc.\n```\ninsert the output from ionic info here.\n```\n"
  },
  {
    "path": "LICENSE.md",
    "content": "GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {one line to give the program's name and a brief idea of what it does.}\n    Copyright (C) {year}  {name of author}\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    {project}  Copyright (C) {year}  {fullname}\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": " <img align=\"right\" src=\"https://i.imgur.com/KsPZaKu.png\">\n \ncreepMiner [![GPLv3](https://img.shields.io/badge/license-GPLv3-red.svg)](LICENSE.md)\n===========\nThe creepMiner is a client application for mining Burst on a pool or solo. For more detailed information on [Burst mining](https://www.burst-team.us/).\ncreepMiner is written in C++ and is multi-threaded to get the best performance, it can also be compiled on most operating systems.\n\n## Features\n- Mine with your **CPU** (__SSE2__/__SSE4__/__AVX__/__AVX2__) or your **GPU** (__OpenCL__, __CUDA__)\n- Mine **solo** or in a **pool**\n- Multi Mining (Build a network of several miners)\n- Filter bad deadlines with the auto target deadline feature\n- Responsive web interface for keeping a close eye on your mining \n- Support for **[BFS (Burst File System)](https://github.com/Creepsky/creepMiner/wiki/Burst-File-System)**\n\n## Getting Started\nPlease follow the [Quick start guide](https://github.com/Creepsky/creepMiner/wiki)\n\n## Instructions\n- [Quickstart Quide](https://github.com/Creepsky/creepMiner/wiki)\n- [Setting up the miner](https://github.com/Creepsky/creepMiner/wiki/Setting-up-the-miner)\n- [Multi miner setup](https://github.com/Creepsky/creepMiner/wiki/Multi-miner-setup)\n- [Solo mining](https://github.com/Creepsky/creepMiner/wiki/Solo-mining)\n- [Mining & Optimization](https://github.com/Creepsky/creepMiner/wiki/Mining-&-Optimization)\n\nIf you need help and support then please review the [**FAQ**](https://github.com/Creepsky/creepMiner/wiki/FAQ) and [Setting up the miner](https://github.com/Creepsky/creepMiner/wiki/Setting-up-the-miner) \n\n[![Join the chat at https://discord.gg/qnjyVQt](https://img.shields.io/badge/join-discord-blue.svg)](https://discord.gg/qnjyVQt) chat and ask in the **#help** channel.\n\n### Build Status\n| Platform | Master | Development |\n| -------- | ------ | ----------- |\n|   Linux   | [![Build Status](https://travis-ci.org/Creepsky/creepMiner.svg?branch=master)](https://travis-ci.org/Creepsky/creepMiner) | [![Build Status](https://travis-ci.org/Creepsky/creepMiner.svg?branch=development)](https://travis-ci.org/Creepsky/creepMiner) |\n|   Windows   | [![Build status](https://ci.appveyor.com/api/projects/status/8c4pu0t70riqydny/branch/master?svg=true)](https://ci.appveyor.com/project/Creepsky75522/creepminer/branch/master) | [![Build status](https://ci.appveyor.com/api/projects/status/8c4pu0t70riqydny/branch/master?svg=true)](https://ci.appveyor.com/project/Creepsky75522/creepminer/branch/development) |\n"
  },
  {
    "path": "_config.yml",
    "content": "theme: jekyll-theme-architect"
  },
  {
    "path": "bintray-dev.json",
    "content": "{\n    \"package\": {\n        \"name\": \"creepMiner-dev\",\n        \"repo\": \"creepMiner\",\n        \"subject\": \"creepsky\",\n        \"website_url\": \"https://github.com/Creepsky/creepMiner\",\n        \"issue_tracker_url\": \"https://github.com/Creepsky/creepMiner/issues\",\n        \"vcs_url\": \"https://github.com/Creepsky/creepMiner/tree/development\",\n        \"licenses\": [\"GPL-3.0\"]\n    },\n    \"version\": {\n        \"name\": \"development\",\n        \"desc\": \"latest development branch artifacts\"\n    },\n    \"files\": [\n        {\n            \"includePattern\": \"./(creepMiner-.*.tar.gz)\",\n            \"excludePattern\": \"./_CPack_Packages/.*\",\n            \"uploadPattern\": \"/$1\",\n            \"matrixParams\": {\n                \"override\": 1\n            }\n        }\n    ],\n    \"publish\": true\n}\n"
  },
  {
    "path": "conanfile.txt",
    "content": "[requires]\nPoco/1.9.0@pocoproject/stable\nzlib/1.2.8@conan/stable\n\n[options]\nPoco:shared=True\nOpenSSL:shared=True\nzlib:shared=True\n\n[generators]\ncmake\n\n[imports]\nbin, *.dll -> ./bin\nlib, *.dylib -> ./lib\nlib, *.so* -> ./lib\n\n"
  },
  {
    "path": "resources/cmSettings.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 15\r\nVisualStudioVersion = 15.0.27428.2005\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"ConfigEditor\", \"settingsui\\ConfigEditor.csproj\", \"{DB3992B4-2E37-4B25-8C42-2E52832788AC}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Any CPU = Debug|Any CPU\r\n\t\tRelease|Any CPU = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{DB3992B4-2E37-4B25-8C42-2E52832788AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{DB3992B4-2E37-4B25-8C42-2E52832788AC}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{DB3992B4-2E37-4B25-8C42-2E52832788AC}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{DB3992B4-2E37-4B25-8C42-2E52832788AC}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\n\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n\t\tSolutionGuid = {E87D0E0A-2137-48F1-974C-BFE7AE1DAA8D}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "resources/frontail.json",
    "content": "{\n    \"words\": {\n        \"ERROR\": \"color: #E88D67;\",\n        \"Error\": \"color: #E88D67;\",\n        \"WARN\": \"color: yellow;\",\n        \"INFO\": \"color: #99C5B5;\",\n        \"Node is DEAD\": \"color: #E88D67;\",\n        \"Nonce forward request\": \"color: yellow;\",\n        \"Got nonce forward request\": \"color: yellow;\",\n        \"nonce forward request from remote miner\": \"color: yellow;\",\n        \"success\": \"font-weight: bold;color: green;\",\n        \"deadlineText\": \"font-weight: bold;color: green;\",\n        \"ended in\": \"font-weight: bold;color:#70389c;\",\n        \"Sending wallet request\": \"color: yellow;\",\n        \"Processed block\": \"color: yellow;color: #99C5B5;\",\n        \"Ip\": \"color: yellow;color: #99C5B5;\",\n        \"in:    \": \"color: #2fa4e7;\",\n        \"Submit-loop 1\": \"color: #468847;\",\n        \"Submit-loop 2\": \"color: #468847;\",\n        \"Submit-loop \": \"color: yellow;\",\n        \"ItemStateChangedEvent\": \"font-weight: bold;\"\n    },\n    \"lines\": {\n        \"/Volumes/\": \"color: #ff3898;font-weight: bold;\",\n        \"miner-01\": \"color: #ff3898;font-weight: bold;\",\n        \"miner-02\": \"color: #ff54A7;font-weight: bold;\",\n        \"miner-03\": \"color: #E4239D;font-weight: bold;\",\n        \"ERROR\": \"font-weight: bold;\",\n        \"Error\": \"font-weight: bold;\",\n        \"block#\": \"color: #99C5B5;\",\n        \"scoop#\": \"color: #99C5B5;\",\n        \"baseTarget#\": \"color: #99C5B5;\",\n        \"nonce: \": \"color: #2fa4e7;\",\n        \"nonce found\": \"color: #73a839;\",\n        \"nonce submitted\": \"color: #468847;\",\n        \"JSON confirmation\": \"color: #468847;\",\n        \"nonce confirmed\": \"color: green;font-weight: bold;\",\n        \"requestType=getMiningInfo\": \"color: black;\"\n    }\n}\n"
  },
  {
    "path": "resources/gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\r\n## files generated by popular Visual Studio add-ons.\r\n##\r\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\r\n\r\n# User-specific files\r\n*.suo\r\n*.user\r\n*.userosscache\r\n*.sln.docstates\r\n\r\n# User-specific files (MonoDevelop/Xamarin Studio)\r\n*.userprefs\r\n\r\n# Build results\r\n[Dd]ebug/\r\n[Dd]ebugPublic/\r\n[Rr]elease/\r\n[Rr]eleases/\r\nx64/\r\nx86/\r\nbld/\r\n[Bb]in/\r\n[Oo]bj/\r\n[Ll]og/\r\n\r\n# Visual Studio 2015/2017 cache/options directory\r\n.vs/\r\n# Uncomment if you have tasks that create the project's static files in wwwroot\r\n#wwwroot/\r\n\r\n# Visual Studio 2017 auto generated files\r\nGenerated\\ Files/\r\n\r\n# MSTest test Results\r\n[Tt]est[Rr]esult*/\r\n[Bb]uild[Ll]og.*\r\n\r\n# NUNIT\r\n*.VisualState.xml\r\nTestResult.xml\r\n\r\n# Build Results of an ATL Project\r\n[Dd]ebugPS/\r\n[Rr]eleasePS/\r\ndlldata.c\r\n\r\n# Benchmark Results\r\nBenchmarkDotNet.Artifacts/\r\n\r\n# .NET Core\r\nproject.lock.json\r\nproject.fragment.lock.json\r\nartifacts/\r\n**/Properties/launchSettings.json\r\n\r\n# StyleCop\r\nStyleCopReport.xml\r\n\r\n# Files built by Visual Studio\r\n*_i.c\r\n*_p.c\r\n*_i.h\r\n*.ilk\r\n*.meta\r\n*.obj\r\n*.pch\r\n*.pdb\r\n*.pgc\r\n*.pgd\r\n*.rsp\r\n*.sbr\r\n*.tlb\r\n*.tli\r\n*.tlh\r\n*.tmp\r\n*.tmp_proj\r\n*.log\r\n*.vspscc\r\n*.vssscc\r\n.builds\r\n*.pidb\r\n*.svclog\r\n*.scc\r\n\r\n# Chutzpah Test files\r\n_Chutzpah*\r\n\r\n# Visual C++ cache files\r\nipch/\r\n*.aps\r\n*.ncb\r\n*.opendb\r\n*.opensdf\r\n*.sdf\r\n*.cachefile\r\n*.VC.db\r\n*.VC.VC.opendb\r\n\r\n# Visual Studio profiler\r\n*.psess\r\n*.vsp\r\n*.vspx\r\n*.sap\r\n\r\n# Visual Studio Trace Files\r\n*.e2e\r\n\r\n# TFS 2012 Local Workspace\r\n$tf/\r\n\r\n# Guidance Automation Toolkit\r\n*.gpState\r\n\r\n# ReSharper is a .NET coding add-in\r\n_ReSharper*/\r\n*.[Rr]e[Ss]harper\r\n*.DotSettings.user\r\n\r\n# JustCode is a .NET coding add-in\r\n.JustCode\r\n\r\n# TeamCity is a build add-in\r\n_TeamCity*\r\n\r\n# DotCover is a Code Coverage Tool\r\n*.dotCover\r\n\r\n# AxoCover is a Code Coverage Tool\r\n.axoCover/*\r\n!.axoCover/settings.json\r\n\r\n# Visual Studio code coverage results\r\n*.coverage\r\n*.coveragexml\r\n\r\n# NCrunch\r\n_NCrunch_*\r\n.*crunch*.local.xml\r\nnCrunchTemp_*\r\n\r\n# MightyMoose\r\n*.mm.*\r\nAutoTest.Net/\r\n\r\n# Web workbench (sass)\r\n.sass-cache/\r\n\r\n# Installshield output folder\r\n[Ee]xpress/\r\n\r\n# DocProject is a documentation generator add-in\r\nDocProject/buildhelp/\r\nDocProject/Help/*.HxT\r\nDocProject/Help/*.HxC\r\nDocProject/Help/*.hhc\r\nDocProject/Help/*.hhk\r\nDocProject/Help/*.hhp\r\nDocProject/Help/Html2\r\nDocProject/Help/html\r\n\r\n# Click-Once directory\r\npublish/\r\n\r\n# Publish Web Output\r\n*.[Pp]ublish.xml\r\n*.azurePubxml\r\n# Note: Comment the next line if you want to checkin your web deploy settings,\r\n# but database connection strings (with potential passwords) will be unencrypted\r\n*.pubxml\r\n*.publishproj\r\n\r\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\r\n# checkin your Azure Web App publish settings, but sensitive information contained\r\n# in these scripts will be unencrypted\r\nPublishScripts/\r\n\r\n# NuGet Packages\r\n*.nupkg\r\n# The packages folder can be ignored because of Package Restore\r\n**/[Pp]ackages/*\r\n# except build/, which is used as an MSBuild target.\r\n!**/[Pp]ackages/build/\r\n# Uncomment if necessary however generally it will be regenerated when needed\r\n#!**/[Pp]ackages/repositories.config\r\n# NuGet v3's project.json files produces more ignorable files\r\n*.nuget.props\r\n*.nuget.targets\r\n\r\n# Microsoft Azure Build Output\r\ncsx/\r\n*.build.csdef\r\n\r\n# Microsoft Azure Emulator\r\necf/\r\nrcf/\r\n\r\n# Windows Store app package directories and files\r\nAppPackages/\r\nBundleArtifacts/\r\nPackage.StoreAssociation.xml\r\n_pkginfo.txt\r\n*.appx\r\n\r\n# Visual Studio cache files\r\n# files ending in .cache can be ignored\r\n*.[Cc]ache\r\n# but keep track of directories ending in .cache\r\n!*.[Cc]ache/\r\n\r\n# Others\r\nClientBin/\r\n~$*\r\n*~\r\n*.dbmdl\r\n*.dbproj.schemaview\r\n*.jfm\r\n*.pfx\r\n*.publishsettings\r\norleans.codegen.cs\r\n\r\n# Including strong name files can present a security risk \r\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\r\n#*.snk\r\n\r\n# Since there are multiple workflows, uncomment next line to ignore bower_components\r\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\r\n#bower_components/\r\n\r\n# RIA/Silverlight projects\r\nGenerated_Code/\r\n\r\n# Backup & report files from converting an old project file\r\n# to a newer Visual Studio version. Backup files are not needed,\r\n# because we have git ;-)\r\n_UpgradeReport_Files/\r\nBackup*/\r\nUpgradeLog*.XML\r\nUpgradeLog*.htm\r\nServiceFabricBackup/\r\n\r\n# SQL Server files\r\n*.mdf\r\n*.ldf\r\n*.ndf\r\n\r\n# Business Intelligence projects\r\n*.rdl.data\r\n*.bim.layout\r\n*.bim_*.settings\r\n*.rptproj.rsuser\r\n\r\n# Microsoft Fakes\r\nFakesAssemblies/\r\n\r\n# GhostDoc plugin setting file\r\n*.GhostDoc.xml\r\n\r\n# Node.js Tools for Visual Studio\r\n.ntvs_analysis.dat\r\nnode_modules/\r\n\r\n# Visual Studio 6 build log\r\n*.plg\r\n\r\n# Visual Studio 6 workspace options file\r\n*.opt\r\n\r\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\r\n*.vbw\r\n\r\n# Visual Studio LightSwitch build output\r\n**/*.HTMLClient/GeneratedArtifacts\r\n**/*.DesktopClient/GeneratedArtifacts\r\n**/*.DesktopClient/ModelManifest.xml\r\n**/*.Server/GeneratedArtifacts\r\n**/*.Server/ModelManifest.xml\r\n_Pvt_Extensions\r\n\r\n# Paket dependency manager\r\n.paket/paket.exe\r\npaket-files/\r\n\r\n# FAKE - F# Make\r\n.fake/\r\n\r\n# JetBrains Rider\r\n.idea/\r\n*.sln.iml\r\n\r\n# CodeRush\r\n.cr/\r\n\r\n# Python Tools for Visual Studio (PTVS)\r\n__pycache__/\r\n*.pyc\r\n\r\n# Cake - Uncomment if you are using it\r\n# tools/**\r\n# !tools/packages.config\r\n\r\n# Tabs Studio\r\n*.tss\r\n\r\n# Telerik's JustMock configuration file\r\n*.jmconfig\r\n\r\n# BizTalk build output\r\n*.btp.cs\r\n*.btm.cs\r\n*.odx.cs\r\n*.xsd.cs\r\n\r\n# OpenCover UI analysis results\r\nOpenCover/\r\n\r\n# Azure Stream Analytics local run output \r\nASALocalRun/\r\n\r\n# MSBuild Binary and Structured Log\r\n*.binlog\r\n\r\n# NVidia Nsight GPU debugger configuration file\r\n*.nvuser"
  },
  {
    "path": "resources/install.sh",
    "content": "#!/bin/sh\n# script to compile and package the creepMiner and all of his dependencies on Linux systems\n\nusage()\n{\n    echo \"Usage:    install.sh [cpu] [gpu] [min] [cuda] [cl] [sse4] [avx] [avx2] [help]\"\n    echo \"cpu:      builds the cpu version (sse2 + sse4 + avx + avx2)\"\n    echo \"gpu:      builds the gpu version (opencl + cuda + cpu)\"\n    echo \"min:      builds the minimal version (only sse2)\"\n    echo \"cuda:     adds CUDA to the build\"\n    echo \"cl:       adds OpenCL to the build\"\n    echo \"sse2:     adds sse2 to the build\"\n    echo \"sse4:     adds sse4 to the build\"\n    echo \"avx:      adds avx to the build\"\n    echo \"avx2:     adds avx2 to the build\"\n    echo \"help:     shows this help\"\n}\n\nset_cpu()\n{\n    sse4=$1\n    avx=$1\n    avx2=$1\n}\n\nset_gpu()\n{\n    cuda=$1\n    opencl=$1\n}\n\n# default settings\nif [ $# = 0 ]; then\n    echo \"Using default settings\"\n    set_cpu true\n    set_gpu false\nfi\n\n# parse settings\nfor i in $*\ndo\n    if [ $i = \"help\" ]\n    then\n        usage\n        exit\n    elif [ $i = \"cpu\" ]\n    then\n        set_cpu true\n    elif [ $i = \"gpu\" ]\n    then\n        set_gpu true\n    elif [ $i = sse4 ]\n    then\n        sse4=true\n    elif [ $i = \"avx\" ]\n    then\n        avx=true\n    elif [ $i = \"avx2\" ]\n    then\n        avx2=true\n    elif [ $i = \"cl\" ]\n    then\n        opencl=true\n    elif [ $i = \"cuda\" ]\n    then\n        cuda=true\n    fi\ndone\n\nuse_flag()\n{\n    if [ \"$2\" = true ]; then\n        echo \"-D$1=ON\"\n    else\n        echo \"-D$1=OFF\"\n    fi\n}\n\nuse_sse4=$(use_flag \"USE_SSE4\" $sse4)\nuse_avx=$(use_flag \"USE_AVX\" $avx)\nuse_avx2=$(use_flag \"USE_AVX2\" $avx2)\nuse_opencl=$(use_flag \"USE_OPENCL\" $opencl)\nuse_cuda=$(use_flag \"USE_CUDA\" $cuda)\n\necho $use_sse4\necho $use_avx\necho $use_avx2\necho $use_opencl\necho $use_cuda\n\ncd ..\nconan install . --build=missing -s compiler.libcxx=libstdc++11\nrm CMakeCache.txt -f\ncmake . -DCMAKE_BUILD_TYPE=RELEASE $use_sse4 $use_avx $use_avx2 $use_opencl $use_cuda\nmake -j$(nproc)\ncp -Tr resources/public bin/public\ncp resources/run.sh bin\ncp resources/screen.sh bin\n"
  },
  {
    "path": "resources/install_deps_conan.bat",
    "content": "cd ..\nconan install . --build=missing -o Poco:shared=False -o OpenSSL:shared=False -o zlib:shared=False -if conan/debug -s build_type=Debug\nconan install . --build=missing -o Poco:shared=False -o OpenSSL:shared=False -o zlib:shared=False -s build_type=Release\npause\n"
  },
  {
    "path": "resources/install_deps_conan.sh",
    "content": "#!/bin/sh\ncd ..\nconan install . --build=missing -s compiler.libcxx=libstdc++11 -if conan/debug -s build_type=Debug\nconan install . --build=missing -s compiler.libcxx=libstdc++11 -s build_type=Release\npause\n"
  },
  {
    "path": "resources/install_deps_conan_mint.sh",
    "content": "#!/bin/sh\nsudo apt install python-pip\npip install --upgrade pip\nsudo apt install python-setuptools\npip install conan --user\nsh ./install_deps_conan.sh\n"
  },
  {
    "path": "resources/public/block.html",
    "content": "<div class=\"row bs-component\">\r\n    <!-- current block -->\r\n    <div class=\"col-lg-4\" style=\"margin:0;padding:0\">\r\n        <div class=\"col-lg-12\" id=\"container\">\r\n            <div class=\"btn-group d-flex\" role=\"group\">\r\n                <!-- refresh btn -->\r\n                <button type=\"button\" class=\"btn btn-primary w-100\" onclick=\"connectBlock();\" id=\"refreshButton\">\r\n                    <span class=\"fas fa-sync\"></span>\r\n                    Refresh\r\n                </button>\r\n                <!-- sound btn -->\r\n                <button type=\"button\" class=\"btn btn-primary w-100\" onclick=\"toggleConfirmationSound();\">\r\n                    <span class=\"fas fa-volume-up\" id=\"iconConfirmationSound\"></span>\r\n                    Sound\r\n                </button>\r\n            </div>\r\n            <!-- progress bar -->\r\n            <div class=\"progress\" style=\"margin-bottom:0\">\r\n                <label class=\"progress-label\" style=\"font-size:x-small;\"></label>\r\n                <div id=\"progressBarVerify\" class=\"progress-bar progress-bar-success progress-bar-striped bg-success\" role=\"progressbar\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"100\"></div>\r\n                <div id=\"progressBar\" class=\"progress-bar progress-bar-info progress-bar-striped bg-info\" role=\"progressbar\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"100\"></div>\r\n            </div>\r\n        </div>\r\n        <!-- Nonce Display Options -->\r\n        <div class=\"col-lg-12 mm-hide\">\r\n            <div class=\"row\">\r\n                <div class=\"col-3\" data-toggle=\"tooltip\" data-placement=\"bottom\" title=\"Show found nonce\">\r\n                    <div class=\"custom-control custom-checkbox\">\r\n                        <input type=\"checkbox\" class=\"custom-control-input\" id=\"cbNoncesFound\" checked><label class=\"custom-control-label\" for=\"cbNoncesFound\"><i class=\"far fa-compass\"></i>&nbsp;Found</label>\r\n                    </div>\r\n                </div>\r\n                <div class=\"col-3\" data-toggle=\"tooltip\" data-placement=\"bottom\" title=\"Show sent nonce\">\r\n                    <div class=\"custom-control custom-checkbox\">\r\n                        <input type=\"checkbox\" class=\"custom-control-input\" id=\"cbNoncesSent\" checked><label class=\"custom-control-label\" for=\"cbNoncesSent\"><i class=\"far fa-paper-plane\"></i>&nbsp;Sent</label>\r\n                    </div>\r\n                </div>\r\n                <div class=\"col-3\" data-toggle=\"tooltip\" data-placement=\"bottom\" title=\"Show confirmed nonce\">\r\n                    <div class=\"custom-control custom-checkbox\">\r\n                        <input type=\"checkbox\" class=\"custom-control-input\" id=\"cbNoncesConfirmed\" checked><label class=\"custom-control-label\" for=\"cbNoncesConfirmed\"><i class=\"far fa-check-circle\"></i>&nbsp;Conf</label>\r\n                    </div>\r\n                </div>\r\n                <div class=\"col-3\" data-toggle=\"tooltip\" data-placement=\"bottom\" title=\"Hide same nonce\">\r\n                    <div class=\"custom-control custom-checkbox\">\r\n                        <input type=\"checkbox\" class=\"custom-control-input\" id=\"cbHideSameNonces\" checked><label class=\"custom-control-label\" for=\"cbHideSameNonces\"><i class=\"far fa-eye-slash\"></i>&nbsp;Same</label>\r\n                    </div>\r\n                </div>\r\n                <br>\r\n            </div>\r\n        </div>\r\n        <!-- Last Winner -->\r\n        <div class=\"col-lg-12\" style=\"padding-top:1rem\">\r\n            <div id=\"lastWinnerContainer\" class=\"card mb-12\" style=\"display: none\">\r\n                <div class=\"card-header text-white bg-success\"><h4>Last Winner</h4></div>\r\n                <div id=\"lastWinner\" class=\"card-body\">\r\n                    <li class='list-group-item d-flex justify-content-between align-items-center' style='border:none; padding:0' id=\"lastWinnerNameRow\">\r\n                        Name <span id=\"lastWinnerName\"></span>\r\n                    </li>\r\n                    <li class='list-group-item d-flex justify-content-between align-items-center' style='border:none; padding:0'>\r\n                        Numeric <span id=\"lastWinnerNumeric\"></span>\r\n                    </li>\r\n                    <li class='list-group-item d-flex justify-content-between align-items-center' style='border:none; padding:0'>\r\n                        Address <span id=\"lastWinnerAddress\"></span>\r\n                    </li>\r\n                </div>\r\n            </div>\r\n        </div>\r\n    </div>\r\n    <!-- stats block -->\r\n    <div class=\"col-lg-8\">\r\n        <div class=\"card mb-12\">\r\n            <h4 class=\"card-header text-white bg-primary\">Statistics</h4>\r\n            <div class=\"card-body\">\r\n                <div class=\"row\">\r\n                    <div class=\"col-lg-3\">\r\n                        <h5 class=\"card-title\">Deadlines</h5>\r\n                        <div class=\"bs-component\">\r\n                            <ul class=\"list-group\">\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Best\r\n                                    <div id=\"bestOverall\">---</div>\r\n                                </li>\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Average\r\n                                    <span class=\"badge badge-primary badge-pill\"><div id=\"avgDeadline\">---</div></span>\r\n                                </li>\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"If this value is significantly lower than your real plot size over longer periods of time, you may want to check your plots for overlaps or corruption.\">\r\n                                    Performance\r\n                                    <div id=\"deadlinePerformance\">---</div>\r\n                                </li>\r\n                            </ul>\r\n                        </div>\r\n                    </div>\r\n                    <div class=\"col-lg-3\">\r\n                        <h5 class=\"card-title\">Blocks</h5>\r\n                        <div class=\"bs-component\">\r\n                            <ul class=\"list-group\">\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Mined\r\n                                    <div id=\"minedBlocks\">---</div>\r\n                                </li>\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Number of blocks in which at least one deadline has been found and confirmed\">\r\n                                    Confirmed\r\n                                    <div id=\"roundsSubmitted\">---</div>\r\n                                </li>\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Won\r\n                                    <div id=\"wonBlocks\">---</div>\r\n                                </li>\r\n                            </ul>\r\n                        </div>\r\n                    </div>\r\n                    <div class=\"col-lg-3\">\r\n                        <h5 class=\"card-title\">Difficulty</h5>\r\n                        <div class=\"bs-component\">\r\n                            <ul class=\"list-group\">\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Lowest\r\n                                    <div id=\"lowestDiff\">---</div>\r\n                                </li>\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Highest\r\n                                    <div id=\"highestDiff\">---</div>\r\n                                </li>\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Mean\r\n                                    <div id=\"meanDiff\">---</div>\r\n                                </li>\r\n\r\n                            </ul>\r\n                        </div>\r\n                    </div>\r\n                    <div class=\"col-lg-3\">\r\n                        <h5 class=\"card-title\">Times</h5>\r\n                        <div class=\"bs-component\">\r\n                            <ul class=\"list-group\">\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Maximum scan\r\n                                    <span class=\"badge badge-secondary\" id=\"maxRoundTime\">N/A</span>\r\n                                </li>\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Average scan\r\n                                    <span class=\"badge badge-secondary\" id=\"avgRoundTime\" data-toggle=\"tooltip\" data-placement=\"top\" title = \"\" >N/A</span>\r\n                                </li>\r\n                                <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                    Average block\r\n                                    <span class=\"badge badge-secondary\" id=\"avgBlockTime\">N/A</span>\r\n                                </li>\r\n                            </ul>\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n                <div class=\"row\">\r\n\r\n                    <div class=\"col-lg-6\">\r\n                        <div class=\"col-md-12\" style=\"text-align:center\"><h5 style=\"margin-bottom:0px; margin-top:10px\">Deadlines</h5></div>\r\n                        <div class=\"col-md-12\">\r\n                            <div id=\"deadlinesChart\" style=\"height: 150px; width: auto; margin: 0px; margin-bottom:10px\"></div>\r\n                            <div class=\"alert alert-info\">\r\n                                <span id=\"deadlinesInfo\">---</span>\r\n                                <span class=\"float-right\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Rescale\" id=\"deadlinePlotButton\" style=\"cursor: pointer\">\r\n                                    <i class=\"fas fa-expand-arrows-alt\"></i>\r\n                                </span>\r\n                            </div>\r\n                        </div>\r\n                    </div>\r\n                    <div class=\"col-lg-6\">\r\n                        <div class=\"col-md-12\" style=\"text-align:center\"><h5 style=\"margin-bottom:0px; margin-top:10px\">Distribution</h5></div>\r\n\r\n                        <div class=\"col-md-12\">\r\n                            <div id=\"deadlineDistributionChart\" style=\"height: 150px; width: auto; margin: 0px; margin-bottom:10px\"></div>\r\n                            <div id=\"deadlineDistributionInfo\" class=\"alert alert-info\">---</div>\r\n                        </div>\r\n                    </div>\r\n                    <div class=\"col-lg-6\">\r\n                        <div class=\"col-md-12\" style=\"text-align:center\"><h5 style=\"margin-bottom:0px; margin-top:10px\">Difficulty</h5></div>\r\n                        <div class=\"col-md-12\">\r\n                            <div id=\"difficultyChart\" style=\"height: 150px; width: auto; margin: 0px; margin-bottom:10px\"></div>\r\n                            <div id=\"difficultyInfo\" class=\"alert alert-info\">---</div>\r\n                        </div>\r\n                    </div>\r\n                    <div class=\"col-lg-6\">\r\n                        <div class=\"col-md-12\" style=\"text-align:center\"><h5 style=\"margin-bottom:0px; margin-top:10px\">Block and Scan Times</h5></div>\r\n                        <div class=\"col-md-12\">\r\n                            <div id=\"timeChart\" style=\"height: 150px; width: auto; margin: 0px; margin-bottom:10px\"></div>\r\n                            <div class=\"alert alert-info\">\r\n                                <span id=\"timeInfo\">---</span>\r\n                                <span class=\"float-right\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Rescale\" id=\"timePlotButton\" style=\"cursor: pointer\">\r\n                                    <i class=\"fas fa-expand-arrows-alt\"></i>\r\n                                </span>\r\n                            </div>\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        </div>\r\n        <!-- system block -->\r\n        <div class=\"card mb-12\">\r\n            <h4 class=\"card-header\">System</h4>\r\n                <div class=\"card-body\">\r\n                    <div class=\"row\">\r\n                        <!-- System -->\r\n                        <div class=\"row col-xs-12 col-md-12 col-lg-12\" id=\"system\">\r\n                            <div class=\"col-lg-6 col-md-6 mm-hide\">\r\n                                <h5 class=\"card-title\">URLs</h5>\r\n                                <div class=\"bs-component\">\r\n                                    <ul class=\"list-group\">\r\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                            Pool\r\n                                            <div id=\"poolURL\">---</div>\r\n                                        </li>\r\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                            Mining\r\n                                            <div id=\"miningURL\">---</div>\r\n                                        </li>\r\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                            Wallet\r\n                                            <div id=\"walletURL\">---</div>\r\n                                        </li>\r\n                                    </ul>\r\n                                </div>\r\n                            </div>\r\n                            <div class=\"col-lg-3 col-md-3\">\r\n                                <h5 class=\"card-title\">Mining</h5>\r\n                                <div class=\"bs-component\">\r\n                                    <ul class=\"list-group\">\r\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                            Plot size\r\n                                            <div id=\"plotSize\">---</div>\r\n                                        </li>\r\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\" id=\"submitProbDL\">\r\n                                            submitProb/targetDL\r\n                                            <div id=\"plotSize\">---</div>\r\n                                        </li>\r\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                            Pool DL limit\r\n                                            <span class=\"badge badge-primary badge-pill\"><div id=\"poolDL\">---</div></span>\r\n                                        </li>\r\n                                    </ul>\r\n                                </div>\r\n                            </div>\r\n                            <div class=\"col-lg-3 col-md-3\">\r\n                                <h5 class=\"card-title\">Processing</h5>\r\n                                <div class=\"bs-component\">\r\n                                    <ul class=\"list-group\">\r\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                            Readers\r\n                                            <div id=\"readers\">---</div>\r\n                                        </li>\r\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                            Intensity\r\n                                            <div id=\"intensity\">---</div>\r\n                                        </li>\r\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center\" style=\"padding:4px\">\r\n                                            Buffer size\r\n                                            <div id=\"bufferSize\">---</div>\r\n                                        </li>\r\n                                    </ul>\r\n                                </div>\r\n                            </div>\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n        </div>\r\n    </div>\r\n</div>"
  },
  {
    "path": "resources/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <title>%title%</title>\n    <link rel=\"stylesheet\" href=\"/css/custom.min.css\">\n\t<link rel=\"stylesheet\" href=\"/css/bootstrap/bootstrap.min.css\" media=\"screen\">\n    <!-- Themes -->\n\t<link rel=\"alternate stylesheet\" title=\"cerulean\" href=\"https://bootswatch.com/4/cerulean/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"cosmo\" href=\"https://bootswatch.com/4/cosmo/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"cyborg\" href=\"https://bootswatch.com/4/cyborg/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"darkly\" href=\"https://bootswatch.com/4/darkly/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"flatly\" href=\"https://bootswatch.com/4/flatly/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"journal\" href=\"https://bootswatch.com/4/journal/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"litera\" href=\"https://bootswatch.com/4/litera/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"lumen\" href=\"https://bootswatch.com/4/lumen/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"lux\" href=\"https://bootswatch.com/4/lux/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"materia\" href=\"https://bootswatch.com/4/materia/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"minty\" href=\"https://bootswatch.com/4/minty/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"pulse\" href=\"https://bootswatch.com/4/pulse/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"sandstone\" href=\"https://bootswatch.com/4/sandstone/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"simplex\" href=\"https://bootswatch.com/4/simplex/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"sketchy\" href=\"https://bootswatch.com/4/sketchy/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"slate\" href=\"https://bootswatch.com/4/slate/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"solar\" href=\"https://bootswatch.com/4/solar/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"spacelab\" href=\"https://bootswatch.com/4/spacelab/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"superhero\" href=\"https://bootswatch.com/4/superhero/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"united\" href=\"https://bootswatch.com/4/united/bootstrap.min.css\" type=\"text/css\">\n    <link rel=\"alternate stylesheet\" title=\"yeti\" href=\"https://bootswatch.com/4/yeti/bootstrap.min.css\" type=\"text/css\">\n    <!--[if lt IE 9]>\n      <script src=\"https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js\"></script>\n      <script src=\"https://oss.maxcdn.com/respond/1.4.2/respond.min.js\"></script>\n    <![endif]-->\n    <script> var nullDeadline = \"%nullDeadline%\";</script>\n  </head>\n  <body>\n    <div class=\"navbar navbar-expand-lg fixed-top navbar-dark bg-primary\" style=\"padding:0rem 1rem\">\n        <div class=\"container\">\n            <!-- logo & title -->\n            <img src=\"img/icon.png\" alt=\"%title%\" class=\"img-responsive img-logo\">&nbsp;<a href=\"../\" class=\"navbar-brand brand-cm\" id=\"server-name\"></a>\n            <!-- mobile navigation -->\n            <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarResponsive\" aria-controls=\"navbarResponsive\" aria-expanded=\"false\" aria-label=\"Toggle\">\n                <span class=\"navbar-toggler-icon\"></span>\n            </button>\n            <!-- main nav bar -->\n            <div class=\"collapse navbar-collapse\" id=\"navbarResponsive\">\n                <ul class=\"navbar-nav\">\n                    <li class=\"nav-item\" id=\"btnBlock\">\n                        <a class=\"nav-link\" href=\"/\"><i class=\"fas fa-th-large\"></i> Block</a>\n                    </li>\n                    <li class=\"nav-item\" id=\"btnPlots\">\n                        <a class=\"nav-link\" href=\"/plotfiles\"><i class=\"fas fa-hdd\"></i> Plots</a>\n                    </li>\n                    <li class=\"nav-item mm-hide\" id=\"btnSettings\">\n                        <a class=\"nav-link\" href=\"/settings\"><i class=\"fas fa-wrench\"></i> Settings</a>\n                    </li>\n                    <li class=\"nav-item\" id=\"btnAbout\" data-toggle='tooltip' data-placement='bottom' data-original-title=''>\n                        <a href=\"\" class=\"nav-link\" data-toggle=\"modal\" data-target=\"#aboutModal\"><i class=\"fas fa-info\"></i> About</a>\n                    </li>\n                </ul>\n                <!-- right nav bar-->\n                <ul class=\"nav navbar-nav ml-auto\">\n                    <!-- miner selector -->\n                    <li class=\"nav-item dropdown mm-show\">\n                        <a class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\" id=\"miners\"><i class=\"fas fa-server\"></i> Miners <span class=\"caret\"></span></a>\n                        <div id=\"dynamic-menu\" class=\"dropdown-menu\" aria-labelledby=\"dropdownMenuLink\"></div>\n                    </li>\n                    <!-- docker -->\n                    <li class=\"nav-item dropdown d-container\">\n                      <a class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\" id=\"download\"><i class=\"fab fa-docker\"></i> System <span class=\"caret\"></span></a>\n                      <div class=\"dropdown-menu\" aria-labelledby=\"download\">\n                        <a class=\"dropdown-item\" href=\"/\" onmouseover=\"javascript:event.target.port=9002\"><i class=\"fas fa-file-medical-alt\"></i> Logs</a>\n                        <a class=\"dropdown-item\" href=\"/\" onmouseover=\"javascript:event.target.port=9001\"><i class=\"fas fa-cubes\"></i> Supervisor</a>\n                        <div class=\"dropdown-divider\"></div>\n                        <a class=\"dropdown-item\" href=\"https://store.docker.com/community/images/whumphrey/creepminer\"><i class=\"fas fa-shopping-bag\"></i> docker store</a>\n                        <a class=\"dropdown-item\" href=\"https://github.com/nitr8/docker-creepminer\"><i class=\"fab fa-github\"></i> github</a>\n                      </div>\n                    </li>\n                    <!-- theme selector -->\n                    <li class=\"nav-item dropdown\">\n                        <a class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\" id=\"themes\"><i class=\"fas fa-paint-brush\"></i> Theme <span class=\"caret\"></span></a>\n                        <div class=\"dropdown-menu\" aria-labelledby=\"themes\" id=\"themeSelector\"></div>\n                    </li>\n                    <!-- sign out btn -->\n                    <li class=\"nav-item mm-hide\" id=\"btnSignOut\">\n                        <a class=\"nav-link\" href=\"/logout\"><i class=\"fas fa-sign-out-alt\"></i>Sign Out</a>\n                    </li>\n                </ul>\n            </div>\n        </div>\n    </div>\n    <!-- render page content -->\n    <div class=\"container-fluid\" id=\"content\">%content%</div>\n    <!-- js CDN plugins, or local js -->\n    <script src=\"https://code.jquery.com/jquery-3.3.1.min.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js\" integrity=\"sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js\" integrity=\"sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.min.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.time.min.js\"></script>\n    <script src=\"https://unpkg.com/sweetalert2@7.19.2/dist/sweetalert2.all.js\"></script>\n    <script defer src=\"https://use.fontawesome.com/releases/v5.0.9/js/all.js\" integrity=\"sha384-8iPTk2s/jMVj81dnzb/iFR2sdA7u06vHJyyLlAd4snFpCl/SnyUjRrbdJsw1pGIl\" crossorigin=\"anonymous\"></script>\n    <script src=\"js/biginteger.min.js\"></script>\n    <script src=\"js/general.js\"></script>\n\t<script>\n\t    if(getCookie(\"theme\")){\n\t\t\t$('link[rel*=jquery]').remove();\n\t\t\t$('head').append('<link rel=\"stylesheet jquery\" href=\"'+getCookie(\"theme\")+'\" type=\"text/css\" />');\n\t\t}\n\t</script>\n    <!-- About Modal -->\n    <div class=\"modal fade bd-about-modal-lg\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"aboutModalLabel\" aria-hidden=\"true\" aria-keyboard=\"false\" bd-about-modal-lg id=\"aboutModal\">\n        <div class=\"modal-dialog modal-lg\">\n            <div class=\"modal-content\">\n            <!-- head -->\n                <div class=\"modal-header\">\n                    <h5 class=\"modal-title\" id=\"aboutModalLabel\">About creepMiner</h5>\n                    <a class=\"btn btn-inf active close\" data-dismiss=\"modal\" role=\"button\" data-pressed=\"true\">&times;</a>\n                </div>\n            <!-- body -->\n                <div class=\"modal-body\">\n                    <div class=\"container-fluid\">\n                        <div class=\"row bs-component\">\n                            <div class=\"col-lg-12\">\n                                <div class=\"card mb-12\">\n                                    <!-- Version -->\n                                    <h4 class=\"card-header text-white bg-success\" id=\"versionCardHeader\">Version</h4>\n                                    <div class=\"card-body\" id=\"versionCard\">\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center list-cm\"><span class=\"badge badge-primary\">Running</span><span id=\"runningVer\"></span></li>\n                                        <li class=\"list-group-item d-flex justify-content-between align-items-center list-cm\"><span class=\"badge badge-success\">Latest</span><span id=\"latestVer\"></span></li>\n                                        <div class=\"alert\" id=\"versionAlert\" role=\"alert\"></div>\n                                    </div>\n                                    <!-- About creepMiner -->\n                                    <h4 class=\"card-header text-white bg-primary\" id=\"versionCardHeader\">Information</h4>\n                                    <div class=\"card-body\">\n                                        <p>creepMiner is an open source client application for burst mining. You can access the project on Github:</p>\n                                        <ul class=\"fa-ul\">\n                                          <li><span class=\"fa-li\"><i class=\"fas fa-file-archive\"></i></span><a href=\"https://github.com/Creepsky/creepMiner/releases\" target=\"blank_\">Releases</a></li>\n                                          <li><span class=\"fa-li\"><i class=\"fas fa-file-code\"></i></span><a href=\"https://github.com/Creepsky/creepMiner\" target=\"blank_\">Code</a></li>\n                                        </ul>\n                                        <p>If you would like to chat with us or are looking for help please join\n                                            <i class=\"fab fa-discord\"></i>&nbsp;<a href=\"https://discord.gg/YtwvuP\" target=\"blank_\" data-toggle=\"tooltip\" data-placement=\"bottom\" title=\"Discord server\">discord</a>. Should you encounter any problems please speak to us first in discord else open a <i class=\"fab fa-github-square\"></i>&nbsp;<a href=\"https://github.com/Creepsky/creepMiner/issues\" target=\"blank_\">issue</a> with the relevant information.\n                                        </p>\n                                    </div>\n                                    <!-- Donate -->\n                                    <h4 class=\"card-header text-white bg-info\" id=\"versionCardHeader\">Donate</h4>\n                                    <div class=\"card-body\">\n                                        <div class=\"row\">\n                                            <div class=\"col-lg-8\">\n                                                <b>Main author:</b>\n                                                <ul class=\"fa-ul\">\n                                                  <li><span class=\"fa-li\"><i class=\"fab fa-connectdevelop\"></i></span><a href=\"https://github.com/Creepsky\" target=\"blank_\"><span class=\"badge badge-info\">Creepsky</span></a><small>&nbsp;(core):<br><b>BURST-JBKL-ZUAV-UXMB-2G795</b></small></li>\n                                                </ul>\n                                                <b>Contributors:</b>\n                                                <ul class=\"fa-ul\">\n                                                  <li><span class=\"fa-li\"><i class=\"far fa-life-ring\"></i></span><a href=\"https://github.com/nitr8\" target=\"blank_\"><span class=\"badge badge-primary\">nitr8</span></a><small>&nbsp;(front-end)<br><b>BURST-2ZXJ-NC7Q-PM3W-GFU97</b></small></li>\n                                                  <li><span class=\"fa-li\"><i class=\"far fa-life-ring\"></i></span><a href=\"https://github.com/Herscht\" target=\"blank_\"><span class=\"badge badge-primary\">Herscht</span></a><small>&nbsp;(front-end / back-end)<br><b>BURST-HWKA-CTBB-J69E-79YHU</b></small></li>\n                                                </ul>\n                                            </div>\n                                            <div class=\"col-lg-4\">\n                                                <a href=\"https://github.com/Creepsky/creepMiner\" target=\"blank_\">\n                                                    <img class=\"img-responsive center-block\" alt=\"creepMiner\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAA9lBMVEUAAAAAcOoZc9EadtkZddYZc9IZc9MUbMYXcdAadtkZd9oZc88ZctEZdNMKbMwacM8ZdNQaeNoZc9EZdNMZc9QZddcZddcZddYZdNQWcc4Zcc4Tb8oXbcUZddcZddcaddcZctAZddYZdNUZdNUacMsZddcZc9QZdNMab70ZdNUYctEZdNUZc9IZddcZddYZc9IZdNQYdNUZdNUZc9MZc9QZcM4WbckZddYZdNUYdNMYcs8ZdNUZddYZdNQZdNYZdNQYdNQZdtgZddYZdNUZdNUaeNwZeNsZc9Ibe+Ead9oaed4ZctIaeNwZddcaet8ZdNUZdtkcgeym21DbAAAAR3RSTlMAAvyaof39GivcyT5n9QUwWN9Ecvr37LR4Ix4OCvzW2zrfwa0S5G5iB+hJ/fnwpqWWfspbTicWzo9TNJzFoLqDafPTXoqj5r+BCxMAAA3oSURBVHja7JqLUtpAFIZ31wboSFOqIigKIspFRAG1WivFSxWy2U3i+79M2SA9ZRJzX2s6PdPptKOyfPzn33OJCKN/ImYYD48rEuMxj+zIyz3lASH0+MymssKYPpfnIOXn2X9kBX1+RAitsGMiK475fRZhIXz2nks8hq0IkCmZyApCxwgLEIzGVJnICjKVDEJ45xrhuRevO/z3OekDoSO8AMEfaGpBFPPuSHDMSY7uzEVypQ2EsFIb6lS7xBYHpQwkM+k+AAdGD92JPrEjZSCEDQ/+BDkYLiRJGUhGawoOIGlqLyZJFwjRalvLIFs1bX5UykCMK4QBRPz7ykghiMI395CKEISK9ja5nVypAiH0FM8FAUnw6bwopglEMYvnC0FAkvOiXRTTBELY/s7C6mD3nX37Bk4RiK7zFnAASYtLqIkyQYh2n3UDyd6LGzhFIAodCA4nyUCMJekBIdZhDqwOoaLcoUXSBEL7CLspglGfpghEMXtrIMiyJGs9U0kNCKElFWH39ZNaoiQtIPqkWBAc7iSFYpJjiVQQwoaV10EqMJbIBdFJ7NCabhwwlpDYEQTE1GIGn9a3vUC261Me9wwzAEiv9jFe1J4GyAsEDZ5iH9HzBSG0cZGLGxXkGZXYB1w0GPEDMVZQCmLF8AWhH1SE4wbyjPgvr36g/op8wO/94Q/sXz0V+VdA/ivyevwHSQwERwwVeYaKI8Zf8AgO8yX5Zs+tN1v58NE88m5Rjpr58NFqrucip1Z28OlZC9/gsWJ/e4HixNjuF1n4RlR7/jTIxkitvZJmHW90M6Fiw6TVAnbfouBClZobmZAveMyt0l4ss6P2eocqRA8VE4Vou6MtEAXk2BrtakSZhHs5kqGHzTbCOAoInH09E4WEHU6JadRuVYSXOdTbmmGGHQ8zxNJK1wjhiGYHUXaahzQT8nghitX4jJAK+xP0uWEJOcKFLccOyBEBBETJlSwQJfQ7iPN56EKOHMgREQREua0bUd6EbVFs/9mL9mEY9VuQI3ZBxCItNC2KKJvlingflfJmFDk0TaQnTrDXUlE7Xw//ViaEa/trCK3tazz8z2ZoPd8Gl8UFAaec8Ahe1WlvMOhRPcJtwU/AHUmAAEq+bujh84NrGo+SlR/zgJGMR4Dk4kRjoUVRZhH2RwjjJxcIqZLmEYzarRqbkInkIBNWa7URljHqQpNxajcZEkM0OKfQ4CQNAigPdSpTFDKh9QfAkJBa4JSRPFHsfhPcIQkERKmBKEnLUQM55KUWOOX7LiNK8nKw3e/gDukgSGwXzqrhO3L/3r96JnYT6C1AYGQFUZKTA0Zk+R4BlEJ1apIk5SgAxluAQHe/tVJkipKIHAor9rfEa74pCDjlfMigj4ocOuFseA7uSNoj2N916Osg7KDhPrYMvvpfVlFBsFdZAtS9khatPEIJ1Ep7IIfHUThKamF0kT8IYD4xB9dodNMTk9ZgmvWSI7sdSRGMrp9uViG/vMtjkSokEsbM5FACPeVYG54hHEmRz1+mvZ9wsXue8u2S8hAkYHI6/IaCyLF9dWcUIoOYE3pZwEFN72i/kjI5RmqrSrkeDsT4A0SbKc8bMDj7mD7oSA9Dub0twr6X/HXDYse6GV0RTbGng3VvL8Ly6yOYPojJPwYz+UG5Y3RFsYqjyPx2/AEPPHwGlaJv+wWVXIwdAZL2aN+uubFB7FS+E6ZXA6CcD6k4NYDJRSUPeiEqYpcdFoQ6QMSajd6fqYFMnx33aEbxkSNDe+NsEJO3W7+HBT0eCGTCLmzLvJ25WrK44snBrdKqf2OFhcnh/ogLAjOocViuBBKl3ezwzOscGd5pthEKYvJNA270+B6B25KJNa4firDSCI5xBqEjX79h7Gisk1AE6tenqyCVHp16g5wi7PtZbPXvoOtJThG4+6u+psdBQLBPH5qHPjRZEDC9/UANY2kg2DY5rJiTTS0I0qU+psfIHwRhL5MPOi6zWiZhEPupnjC9ihMFAXcc3YDJ5aQWzBC0CKZPBgS6nP4Gg4IqEQRMPz/YHcTwAjEAxFnJ4UG8ZBBYpp2Ip+juICOmeBR2NlqAONr1kmM7Lsvsf1b6zjqYfhmkMT1+HeR42nCA2HIcOGYzOWZ3mp79mJnejaTMYW/nvMB5GWG3xvmGWSDHWymyaO+vXJtYFdoLt02c6tau92F/8UYegdDn7b3bTZwdw95ueUgfZ11NDpX8jUEgUYTpsbM6r4rBLrOU5YSzfVgwLVVyC0z+5qkFv56wXnFDqax3lrxLJhSuh6VvHHRo1/Mk+YpApXf9/ZWTrkaU31NA16kdVu2Z3AI//RVF4Kl472fWTRTcqlKTLEpoC7tk1faLyd8DyEwUk12e2SSuuwNdV6hzMSo41LN7anrKAQ6Tm1pQ6bujnFOUeQ/Y7bKbI4RUF5O/VPJ3osiLlQ9hkbe0TB3v7o6/OuUQizcKd+5fNzuIYmk/nMsRIUq57CbH2r5dyd8diLiJ3U1v/+XcrvcYmDwQSIzdr6VMQgXh9PKb6jQ9drvOuDuGhKbx+ulXe9ffnTQMRWkkoLJ16hji0AmTORmI000Y28T9YJa2Ke2+/5eRgOyeCSlL2lSqvj93ztrd3ZeX5r378gJp2RtlRZ7SFRg2GF+6GuxSS7XQk+8PJSoeWPTPD8KlPZXNPUfhwYHdU1ojHMnJloJejgzL4UAKNmspKAM/lisKjMzOCAoVtVywGQ7kgOakcXhsUs9UrbNnxqRcSpLi5tgSIC+KvhwQQsclOlSY5RhBuD/HrvUwIHZcQHAY6+PrXxYIoHQG66h4xAREgmPijkrlOET+xjRl9nBSYmIEh4R+FekaNSA4+ozLUJQk6VoIVo1yfCJ/kx9cEb6SAIJEDVpgIgHBpyqyCfpdC3TggzomvRYXBPSxUnQyAjrQcxEfEPSAaI9aON+8R00pHiBQafTRN6YVCDq0NHUrvAYpelwLOaYL9OvFBkTQzKcLiMvpgLxDjziTd1jujVyixbVQ0ed0aBMwo50Q/Wtxhl+I/LPIx2hiBB2FoyaJmRH0XOzHrvsVrTX0eMYGBB1JWdHqUO7VNcKgfFjDcTU6EKyOt9ci5aGh3qu7/cJEIF/UzBcQGmPUomSx4BTfexuKea3T2lleSLOZMdZqWCkRgaBSbAgX5mZpXzlBN5ykpsU18XfQYCsDQbAS08EPqn1mqyfoPBtF6EWkfNhH35jaGkGw2ukJ1BT8p51xXjIXJYndspwGmskXqZHab+wWVQaC1XEYsjqMXpd5LcuPkPuls9S0MJIY17Vhk6i5FoLVFadDqM/81mSERk5i81zMoBMSTL5mfawUqZ0ddOTF/ynzgrtvLPUR4rFub/zEkL4x/ipJ10Kw6h4LV8ekn5/7bjxlBUpZMzSkbGfRNyblWqBDrM/MkVjqI2jyWOPnNSEpvBYoDYT4I06HEAekWzG4Fo5s4rYbw+DVWU6KjGsRytYHIXRsc30mjU9UAw1gqVwP2R57vBQtAYR4DkqkcyTzTgvmEx2lN5ff3wC1v5CUh7kWpexyHAwNUXpgI+vxh8ULBP7lXOJ6o8V9PT55ECNclvICe8d8wgZ3qMQMBF9214Z4pXROiowES4HkyFjlDzedl9dD1aGrzk6p7fOTqOhv4KQ475cAWbft83lxOmoyg48MdOgAAmVARexfnYH9OWOGAmE8amQMoX+ONMtlka1h4s8vTsrxEkZ2C2I6vn7C3qoPCEgpDfIiUpZ2AdTrwmBlQhOfABC0Fpki91hihrhbNkG5LA7YyHdEN5Nr4vmHVeJaFGLxz6+4oExaWJnXcpOUOUEO5L08hX8pGlpYEXMTA4JrvPD5pW789yeawT+moIMwMyIdj7M+Ym7CawRt3FBjSxsup7P+vFyW+M4Vsl8KXlXoM5u4K6Cgo4T5yDzLelWHV4tXRS47rZQBigQdB18m9fsVAYKDsBwd03tV+DtWR5zJIzGUSOEGYePb0erJZV3icZWyxN0wG+1ZYm91XGsWicX3/C7qZRhZknJZdUY8QiWMtCx2dfQAJJOYG3hE7umuumv9cHxPynx/FLRPl0ExuMBw6Ms+2wuUXettcV3evNr7SvgJ0eyd+1vyD26tK8plM5VqQcGqBwf1cErMwnFV6dGdxK9bNzJ6TBGIoWjLF7ui/R8Ssar2jwH5a1zrPxBZ079GTCOy6Qm/MBNA9M6xMnRvl2ej5Yy0O/motkSR+CHyCzptESMwv3H+NKJdXYQDubiK+obzhm8tA+L6LKLZw518mNY1vzO0WUTz3UTmIXr7YUD2PRLZ3GQmVDq7rzNCe70b09BQ/UD4AG2xrpMP0k4JEIuwtrgw12apmeJqUa9RFQGpNrz0zNW1iDMQedZJmiYdW8R+8mpxL86rJ3aagFiUbS4GsslSNQ2czwiuAwlw1L+wdM1nd603zxYBefbGcq2YTScQTgnmaM9N0E4TED7ZfA7IbKZ5moDwCzLngZxNCUkXkGBvI2PeV2ls7AXpA2IVne+Z3+y7U7S4pQsIsXemQ8ExBnzn12aYLiAWDdbuA1mb3bOSMiCE7VbuDQHfnW2GKQNCra1exgAhvS0rnYzwWe+GYdzlst7dxd60AaFeqZAxZ7G3ULo7iKQNiFUcHeI2p8PRXexNHRAS1B7PgDyuYTNMHRCLOOUZkLKD16QQiN3tTJXAna6tHQhrEX3WPJoCOWoSfdZiHMjNLRtqM+e2Ox1+2r11htqM3d6MgVzfPNJo2ZNtDmT7JPtIo91g0J1GMxJ5yU+QCIojvptMXwAAAABJRU5ErkJggg==\"/>\n                                                </a>\n                                            </div>\n                                        </div>\n                                    </div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n\n            </div>\n        </div>\n    </div>\n     %includes%\n  </body>\n</html>\n"
  },
  {
    "path": "resources/public/js/block.js",
    "content": "var MasterMiner = 'false';\nclass Deadline {\n    constructor(deadline) {\n        this.accountName = deadline[\"account\"];\n        this.accountId = BigInteger(deadline[\"accountId\"]);\n        this.accountIdStr = deadline[\"accountId\"];\n        this.deadlineStr = deadline[\"deadline\"];\n        this.deadline = BigInteger(deadline[\"deadlineNum\"]);\n        this.nonce = BigInteger(deadline[\"nonce\"]);\n        this.time = deadline[\"time\"];\n        this.plotfile = deadline[\"plotfile\"];\n        this.miner = deadline[\"miner\"];\n        this.worker = deadline[\"worker\"];\n        this.ip = deadline[\"ip\"];\n    }\n}\n\nclass Block {\n    constructor() {\n        this.panel = $(\"<div class='card mb-12'></div>\");\n        this.head = $(\"<h4 class='card-header bg-success text-white'>\");\n        this.body = $(\"<div class='card-body'></div>\");\n        this.data = $(\"<ul id='blkdata' class='list-group'></ul>\");\n\n        this.panel.append(this.head);\n        this.panel.append(this.body);\n        this.panel.append(this.data);\n\n        this.bestDeadline = null;\n    }\n\n    newBlock(block) {\n        this.head.html(\"Current block: \" + block[\"block\"] + \"</h4><span class='badge badge-light float-sm-right' id='blockTimer'></span>\");\n        this.body.html(\"<li class='list-group-item d-flex justify-content-between align-items-center' style='border:none; padding:0'>Start time <span class='badge badge-secondary float-sm-right'>\" + block[\"time\"] + \"</span></li>\");\n        this.body.append($(\"<li class='list-group-item d-flex justify-content-between align-items-center' style='border:none; padding:0'>Scoop <span>\" + block[\"scoop\"] + \"</span></li>\"));\n        this.body.append($(\"<li class='list-group-item d-flex justify-content-between align-items-center' style='border:none; padding:0'>Base target<span>\" + block[\"baseTarget\"] + \"</span></li>\"));\n\n        blockStartTime=block[\"startTime\"];\n        var diffDifference = block['difficultyDifference'];\n        var diffDifferenceString = String(diffDifference);\n\n        if (diffDifference === 0)\n            diffDifferenceString = \"no change\";\n        else if (diffDifference > 0)\n            diffDifferenceString = \"+\" + String(diffDifference);\n\n        this.body.append($(\"<li class='list-group-item d-flex justify-content-between align-items-center' style='border:none; padding:0'>Difficulty <span>\" + block[\"difficulty\"] + \" (\" + diffDifferenceString + \")</span></li>\"));\n        this.body.append($(\"<li class='list-group-item d-flex justify-content-between align-items-center' style='border:none; padding:0'>Target <span class='badge badge-primary badge-pill'>\" + deadlineFormat(block[\"targetDeadline\"]) + \"</span></li>\"));\n\n        //this.body.append($(\"<li class='list-group-item d-flex justify-content-between align-items-center'>Generation signature</li>\"));\n        //this.body.append($(\"<li class='list-group-item d-flex justify-content-between align-items-center'><small>\" + block[\"gensigStr\"] + \"</small></li>\"));\n        this.data.empty();\n    }\n\n    addLine(line) {\n        this.data.prepend(line);\n    }\n\n    getLine(id) {\n        return this.data.find(\"#\" + id);\n    }\n\n    getData() {\n        return this.data;\n    }\n}\n\n$('#timePlotButton').on('click', function(event) {\n    if (timePlotMax == maxBlockTime*1.25)\n        timePlotMax = maxScanTime*1.25;\n    else\n        timePlotMax = maxBlockTime*1.25;\n    if (timePlotMax < 30) timePlotMax = 30;\n    timePlot.getAxes().yaxis.options.max = timePlotMax;\n    timePlot.setupGrid();\n    timePlot.draw();\n    $(\".flot-tick-label\").css(\"color\", flotFrameColor);\n});\n\n$('#deadlinePlotButton').on('click', function(event) {\n    if (deadlinePlotMax)\n        deadlinePlotMax = null;\n    else\n        deadlinePlotMax = deadlinePlotSmallMax;\n    deadlinePlot.getAxes().yaxis.options.max = deadlinePlotMax;\n    deadlinePlot.setupGrid();\n    deadlinePlot.draw();\n    $(\".flot-tick-label\").css(\"color\", flotFrameColor);\n});\n\nvar timerRefresh = setInterval(function(){ myTimer() }, 1000);\n\nfunction myTimer() {\n    var d = new Date() / 1000;\n    var t = Math.round(d - blockStartTime);\n    var timerElement=document.getElementById(\"blockTimer\");\n    if (timerElement)\n        timerElement.innerHTML = deadlineFormat(t);\n}\n\nvar system;\nvar bestDeadlineOverall;\nvar bestDeadlineOverallElement;\nvar bestHistorical;\nvar minedBlocks = -1;\nvar minedBlocksElement;\nvar name = document.title;\nvar hideSameNonces;\nvar noncesFound;\nvar noncesSent;\nvar noncesConfirmed;\nvar progressBar;\nvar progressBarVerify;\nvar lastWinnerContainer;\nvar lastWinner;\nvar confirmedSound = new Audio(\"sounds/alert.mp3\");\nvar playConfirmationSound = true;\nvar iconConfirmationSound;\nvar avgDeadline;\nvar wonBlocks;\nvar lowestDiff;\nvar highestDiff;\nvar deadlinePlotSmallMax=86400;\nvar deadlinePlotMax=null;\nvar bestDeadlinesChart;\nvar deadlinePlot;\nvar deadlinesInfo;\nvar maxScanTime=10;\nvar maxBlockTime=10;\nvar timePlotMax=10;\nvar timeChart;\nvar timePlot;\nvar timeInfo;\nvar deadlineDistributionChart;\nvar deadlineDistributionBarWidth = 1;\nvar deadlineDistributionPlot;\nvar deadlineDistributionInfo;\nvar difficultyChart;\nvar difficultyPlot;\nvar difficultyInfo;\nvar miningData = new Block();\nvar settingsDlComboboxes;\nvar maxHistoricalBlocks;\nvar blockStartTime = new Date() / 1000;\nvar flotFrameColor=\"#888888\";\n\n// ******************************************\nvar logSettings = {};\n// ******************************************\n\n// I change this [] to {} and also in settings.js and general.js\n\n// var logSettings = [];\n\nif (confirmedSound)\n    confirmedSound.volume = 0.5;\n\nvar NONCE_FOUND = 1 << 0;\nvar NONCE_SENT = 1 << 1;\nvar NONCE_CONFIRMED = 1 << 2;\n\n// ******************************************\n\n// Set on click event of elements\n$(\"#cbHideSameNonces\").on('click', function () {\n    localSet('hideSameNonces', this.checked);\n})\n\n$(\"#cbNoncesFound\").on('click', function () {\n    localSet('noncesFound', this.checked);\n})\n\n$(\"#cbNoncesSent\").on('click', function () {\n    localSet('noncesSent', this.checked);\n})\n\n$(\"#cbNoncesConfirmed\").on('click', function () {\n    localSet('noncesConfirmed', this.checked);\n})\n\n// Retrieve any possible local variable and set in js vars\nfunction localInitCheckBoxes() {\n    playConfirmationSound = localGet('playConfirmationSound');\n\n    // Check if values exist in local or set true(default)\n    var temp = localGet('hideSameNonces');\n\n    if (temp == null) temp = true;\n    hideSameNonces.prop('checked', temp);\n\n    temp = localGet('noncesFound');\n    if (temp == null) temp = true;\n    noncesFound.prop('checked', temp);\n\n    temp = localGet('noncesSent');\n    if (temp == null) temp = true;\n    noncesSent.prop('checked', temp);\n\n    temp = localGet('noncesConfirmed');\n    if (temp == null) temp = true;\n    noncesConfirmed.prop('checked', temp);\n}\n\n// I break in 2 functions because must initialized in different points of initBlock\nfunction localInitLogSettings() {\n    var temp = localGet('logSettings');\n\n    if (temp == null)\n        return;\n\n    if (temp['miner']) $(\"#cmb_miner\").val(temp['miner'])\n    if (temp['config']) $(\"#cmb_config\").val(temp['config'])\n    if (temp['server']) $(\"#cmb_server\").val(temp['server'])\n    if (temp['socket']) $(\"#cmb_socket\").val(temp['socket'])\n    if (temp['session']) $(\"#cmb_session\").val(temp['session'])\n    if (temp['nonceSubmitter']) $(\"#cmb_nonceSubmitter\").val(temp['nonceSubmitter'])\n    if (temp['plotReader']) $(\"#cmb_plotReader\").val(temp['plotReader'])\n    if (temp['plotVerifier']) $(\"#cmb_plotVerifier\").val(temp['plotVerifier'])\n    if (temp['wallet']) $(\"#cmb_wallet\").val(temp['wallet'])\n    if (temp['general']) $(\"#cmb_general\").val(temp['general'])\n}\n\n// Saves in local storage - no expiration\n// Item : name of local variable\n// Data : content of item variable\nfunction localSet(item, data) {\n    localStorage.setItem(item, JSON.stringify(data));\n}\n\n// Get from local storage\n// Item : name of local variable\nfunction localGet(item) {\n    return JSON.parse(localStorage.getItem(item));\n}\n\n// ******************************************\n\nfunction newBlock(json) {\n    miningData.newBlock(json);\n    setMinedBlocks(json[\"blocksMined\"]);\n    document.title = name + \" (\" + json[\"block\"] + \")\";\n    checkAddBestOverall(BigInteger(json[\"bestOverall\"][\"deadlineNum\"]),\n                                   json[\"bestOverall\"][\"deadline\"],\n                                   json[\"bestOverall\"][\"blockheight\"]);\n\n    var bestHistoricalJson = json[\"bestHistorical\"][\"deadline\"];\n    var bestHistoricalHeightJson = json[\"bestHistorical\"][\"blockheight\"];\n\n    if (bestHistoricalJson != null && bestHistoricalHeightJson != null)\n        bestHistorical.html(bestHistoricalJson + \" <small>@\" + bestHistoricalHeightJson + \"</small>\");\n\n    setOverallProgress(0);\n    setOverallProgressVerify(0);\n    avgDeadline.html(json[\"deadlinesAvg\"]);\n    deadlinePerformance.html(Math.round(json[\"deadlinePerformance\"]*1000)/1000 + \" TB\");\n    var roundsSub=json[\"nRoundsSubmitted\"];\n    var numHistor=json[\"numHistoricals\"];\n    var subPercent = 0;\n    if (numHistor!=0)\n        subPercent = Math.round(roundsSub/numHistor*1000)/10;\n    roundsSubmitted.html(\"<small>\" + subPercent +\"%</small>&nbsp;\" + roundsSub + \"/\" + numHistor);\n    wonBlocks.html(json[\"blocksWon\"]);\n    lowestDiff.html(\"<small>@\" + json[\"lowestDifficulty\"][\"blockheight\"] + \"</small>&nbsp;&nbsp;\" + json[\"lowestDifficulty\"][\"value\"]);\n    highestDiff.html(\"<small>@\" + json[\"highestDifficulty\"][\"blockheight\"] + \"</small>&nbsp;&nbsp;\" + json[\"highestDifficulty\"][\"value\"]);\n    meanDiff.html(Math.round(json[\"meanDifficulty\"]));\n    maxRoundTime.html(Math.round(json[\"maxRoundTime\"]*1000)/1000 + \" s\");\n    var meanScan = Math.round(json[\"meanRoundTime\"]*1000)/1000;\n    avgRoundTime.html(meanScan + \" s\");\n    avgRoundTime.attr({\"data-original-title\": \"You are ~\" + efficiency(meanScan) +\"% efficient at mining blocks with this average scan time.\"});\n    avgBlockTime.html(Math.round(json[\"meanBlockTime\"]*1000)/1000 + \" s\");\n    deadlinePlotSmallMax = -Math.log(0.95)*240*json[\"meanDifficulty\"]/json[\"deadlinePerformance\"];\n    deadlinePlot.setData([json[\"bestDeadlines\"]]);\n    deadlinePlot.setupGrid();\n    deadlinePlot.draw();\n    maxBlockTime=json[\"maxBlockTime\"];\n    maxScanTime=json[\"maxRoundTime\"];\n    timePlotMax=maxBlockTime*1.25;\n    initTimePlot();\n    timePlot.setData([  {data: json[\"roundTimeHistory\"], label:\"&nbsp;&nbsp;<b>Scan time</b>&nbsp;&nbsp;&nbsp;\"},\n                        {data: json[\"blockTimeHistory\"], label:\"&nbsp;&nbsp;<b>Block time</b>\",lines:{show:false},points:{show:true}}]);\n    timePlot.setupGrid();\n    timePlot.draw();\n    deadlineDistributionBarWidth = json[\"dlDistBarWidth\"]*0.99;\n    initDeadlineDistributionPlot();\n    deadlineDistributionPlot.setData([json[\"deadlineDistribution\"]]);\n    deadlineDistributionPlot.setupGrid();\n    deadlineDistributionPlot.draw();\n    difficultyPlot.setData([json[\"difficultyHistory\"]]);\n    difficultyPlot.setupGrid();\n    difficultyPlot.draw();\n    showDeadlinesInfo(null);\n    showDeadlineDistributionInfo(null);\n    showDifficultyInfo(null);\n    $(\".flot-tick-label\").css(\"color\", flotFrameColor);\n}\n\nfunction getNewLine(type, id) {\n    var line = $(\"<li class='list-group-item clearfix'></li>\");\n\n    if (id)\n        line.attr(\"id\", id);\n\n    if (type)\n        line.addClass(type);\n\n    return line;\n}\n\nfunction addMinedBlocks() {\n    minedBlocks += 1;\n    minedBlocksElement.html(minedBlocks);\n}\n\nfunction setMinedBlocks(blocks) {\n    minedBlocks = blocks;\n    minedBlocksElement.html(minedBlocks);\n}\n\nfunction createNonceLine(deadline, iconId, lineType, nonceType) {\n    var line = getNewLine(lineType, deadline.nonce);\n\n    var hiddenInfosDiv = $(\"<small></small>\");\n    var hiddenInfos = $(\"<dl class='dl'></dl>\");\n    hiddenInfos.append(\"<dt>Nonce</dt><dd>\" + deadline.nonce + \"</dd>\");\n    hiddenInfos.append(\"<dt>Plotfile</dt><dd>\" + deadline.plotfile + \"</dd>\");\n    hiddenInfos.append(\"<dt>Miner</dt><dd>\" + deadline.miner + \"</dd>\");\n    hiddenInfos.append(\"<dt>Worker</dt><dd>\" + deadline.worker + \"</dd>\");\n    hiddenInfos.append(\"<dt>Ip</dt><dd>\" + deadline.ip + \"</dd>\");\n    hiddenInfos.append(\"<span class='badge badge-secondary float-sm-right'>\" + deadline.time + \"</span>\");\n    hiddenInfos.hide();\n\n    hiddenInfosDiv.append(hiddenInfos);\n\n    var message = $(\"<div></div>\");\n\n    line.click(function () {\n        hiddenInfos.toggle();\n    });\n\n    var nonceTypeStr = \"\";\n\n    if (nonceType == NONCE_FOUND)\n        nonceTypeStr = \"found\";\n    else if (nonceType == NONCE_SENT)\n        nonceTypeStr = \"submitted\";\n    else if (nonceType == NONCE_CONFIRMED)\n        nonceTypeStr = \"confirmed\";\n\n    message.append(\"<span class='far \" + iconId + \"'></span> \");\n    if (MasterMiner == 'true') {\n        message.append(nonceTypeStr);\n        message.append(\"&nbsp;<span class='badge badge-primary badge-pill''>\" + deadline.deadlineStr + \"</span><small>&nbsp;(\" + deadline.nonce + \")</small>\");\n    } else {\n            message.append(\"<small><a href='https://explore.burst.cryptoguru.org/account/\" + deadline.accountId.toString() + \"' target='_blank'>\" +\n                deadline.accountName + \"</a>&nbsp;\" + nonceTypeStr + \"</small>\");\n            message.append(\"&nbsp;<span class='badge badge-primary badge-pill'>\" + deadline.deadlineStr + \"</span>\");\n    }\n\n    message.append(hiddenInfosDiv);\n\n    line.html(message);\n    line.attr(\"logger\", \"nonceSubmitter\");\n    line.attr(\"level\", 6);\n    line.attr(\"nonce\", deadline.nonce);\n    line.attr(\"nonceType\", nonceType);\n\n    return line;\n}\n\nfunction createMessageLine(lineType, logger, level, file, lineNumber, time, text, hidden) {\n    var line = getNewLine(lineType);\n\n    var hiddenInfosDiv = $(\"<small></small>\");\n    var hiddenInfos = $(\"<dl class='dl'></dl>\");\n    hiddenInfos.append(\"<dt>Logger</dt><dd>\" + logger + \"</dd>\");\n    hiddenInfos.append(\"<dt>File</dt><dd>\" + file + \"</dd>\");\n    hiddenInfos.append(\"<dt>Line</dt><dd>\" + lineNumber + \"</dd>\");\n    hiddenInfos.hide();\n\n    hiddenInfosDiv.append(hiddenInfos);\n\n    line.click(function () {\n        hiddenInfos.toggle();\n    });\n\n    var message = $(\"<div></div>\");\n    message.append(\"<span class='badge badge-secondary float-sm-right'>\" + time + \"</span>\");\n    message.append(text);\n    message.append(hiddenInfosDiv);\n\n    line.html(message);\n\n    if (hidden)\n        line.hide();\n\n    line.attr(\"logger\", logger);\n    line.attr(\"level\", level);\n\n    return line;\n}\n\nfunction checkAddBestOverall(deadlineNum, deadline, blockheight) {\n    if (deadline != null && (!bestDeadlineOverall || bestDeadlineOverall > deadlineNum)) {\n        bestDeadlineOverall = deadlineNum;\n        bestDeadlineOverallElement.html(\"<small>@\" + blockheight + \"</small>&nbsp;&nbsp;<span class='badge badge-primary badge-pill'>\" + deadline + \"</span>\");\n    }\n}\n\nfunction replaceOrAddNonceLine(json, glyphIcon, lineType, message) {\n    var deadline = new Deadline(json);\n    //var line = miningData.getLine(deadline.nonce);\n    var newLine = createNonceLine(deadline, glyphIcon, lineType, message);\n\n    //if (line.length)\n    //     line.replaceWith(newLine);\n    //else\n    miningData.addLine(newLine);\n\n    hideSameNonceLines(deadline.nonce);\n\n    return newLine;\n}\n\nfunction hideSameNonceLines(nonce) {\n    var doHideSameNonces = hideSameNonces.is(\":checked\");\n    var highest = -1;\n    var highestElement = null;\n\n    var nonceTypeChecked = [];\n\n    if (noncesFound.prop(\"checked\"))\n        nonceTypeChecked.push(NONCE_FOUND);\n\n    if (noncesSent.prop(\"checked\"))\n        nonceTypeChecked.push(NONCE_SENT);\n\n    if (noncesConfirmed.prop(\"checked\"))\n        nonceTypeChecked.push(NONCE_CONFIRMED);\n\n    var sameLines = miningData.getData().find(\"[nonce='\" + nonce + \"']\").each(function () {\n        var nonceTypeStr = $(this).attr(\"nonceType\");\n        var nonceType = null;\n\n        if (nonceTypeStr)\n            nonceType = parseInt(nonceTypeStr);\n\n        if (nonceType && nonceTypeChecked.indexOf(nonceType) != -1) {\n            if (doHideSameNonces) {\n                $(this).hide();\n\n                if (nonceType > highest) {\n                    highest = nonceType;\n                    highestElement = $(this);\n                }\n            }\n            else {\n                $(this).show();\n            }\n        }\n        else {\n            $(this).hide();\n        }\n    });\n\n    if (highestElement)\n        highestElement.show();\n}\n\nfunction nonceFound(json) {\n    if (noncesFound.prop(\"checked\"))\n        replaceOrAddNonceLine(json, \"fa-compass\", \"list-group-item-default\", NONCE_FOUND);\n}\n\nfunction addOrSubmit(json) {\n    if (noncesSent.prop(\"checked\"))\n        replaceOrAddNonceLine(json, \"fa-paper-plane\", \"list-group-item-success\", NONCE_SENT);\n}\n\nfunction addOrConfirm(json) {\n    if (noncesConfirmed.prop(\"checked\")) {\n        replaceOrAddNonceLine(json, \"fa-check-circle\", \"list-group-item-success\", NONCE_CONFIRMED);\n\n        if (confirmedSound && playConfirmationSound)\n            confirmedSound.play();\n    }\n}\n\nfunction addLinkWithLabel(label, link) {\n    return \"<a href='\" + link + \"' target='_blank'>\" + label + \"</a>\";\n}\n\nfunction config(cfg) {\n    maxHistoricalBlocks = cfg[\"maxHistoricalBlocks\"];\n    $(\"#poolURL\").html(addLinkWithLabel(cfg['poolUrl'] + ':' + cfg['poolUrlPort'], cfg[\"poolUrl\"]));\n    $(\"#miningURL\").html(addLinkWithLabel(cfg[\"miningInfoUrl\"] + ':' + cfg[\"miningInfoUrlPort\"], cfg[\"miningInfoUrl\"]));\n    $(\"#walletURL\").html(addLinkWithLabel(cfg[\"walletUrl\"] + ':' + cfg[\"walletUrlPort\"], cfg[\"walletUrl\"] + \":\" + cfg[\"walletUrlPort\"]));\n    $(\"#plotSize\").html(cfg[\"totalPlotSize\"]);\n    if (cfg[\"submitProbability\"] != 0)\n        $(\"#submitProbDL\").html(\"Submit probability<div>\"+cfg[\"submitProbability\"]+\"</div>\");\n    else\n        $(\"#submitProbDL\").html(\"Target DL<span class='badge badge-primary badge-pill'><div>\"+cfg[\"targetDeadlineCombined\"]+\"</div></span>\");\n    $(\"#poolDL\").html(cfg[\"targetDeadlinePool\"]);\n    $(\"#readers\").html(cfg[\"maxPlotReaders\"]);\n    $(\"#intensity\").html(cfg[\"miningIntensity\"]);\n    $(\"#bufferSize\").html(cfg[\"bufferSize\"]);\n}\n\n\nfunction setOverallProgress(value) {\n    setProgress(progressBar, value);\n}\n\nfunction setOverallProgressVerify(valueVerify) {\n    setProgressVerify(progressBarVerify, valueVerify);\n}\n\nfunction setLastWinner(winner) {\n    if (winner) {\n        var burstAddress = winner[\"address\"];\n        var numeric = lastWinner.find(\"#lastWinnerNumeric\");\n        var address = lastWinner.find(\"#lastWinnerAddress\");\n        var name = lastWinner.find(\"#lastWinnerName\");\n\n        var link = \"https://explore.burst.cryptoguru.org/account/\" + winner[\"numeric\"];\n\n        if (winner[\"name\"]) {\n            name.html(\"<a href = '\" + link + \"' target='blank_'>\" + winner[\"name\"] + \"</a>\");\n            lastWinner.find(\"#lastWinnerNameRow\").show();\n        }\n        else {\n            lastWinner.find(\"#lastWinnerNameRow\").hide();\n        }\n\n        numeric.html(\"<a href = '\" + link + \"' target='blank_'>\" + winner[\"numeric\"] + \"</a>\");\n        address.html(\"<a href = '\" + link + \"' target='blank_'>\" + winner[\"address\"] + \"</a>\");\n\n        lastWinnerContainer.show();\n    }\n    else {\n        lastWinnerContainer.hide();\n    }\n}\n\nfunction deActivateConfirmationSound(on) {\n    playConfirmationSound = on;\n\n    iconConfirmationSound.removeClass(\"fa-volume-up\");\n    iconConfirmationSound.removeClass(\"fa-volume-off\");\n\n    if (on)\n        iconConfirmationSound.addClass(\"fa-volume-up\");\n    else\n        iconConfirmationSound.addClass(\"fa-volume-off\");\n}\n\nfunction toggleConfirmationSound() {\n    // ******************************************\n    localSet('playConfirmationSound', !playConfirmationSound);\n    // ******************************************\n\n    deActivateConfirmationSound(!playConfirmationSound);\n    //sql\n    swal({\n        title: 'Nonce sound notifications',\n        type: 'info',\n        html:\n        'If you wish to use a custom notification please place ' +\n        '<pre>alert.mp3</pre> it into the <b>sounds </b> directory.',\n        showCloseButton: false,\n        showCancelButton: false,\n        confirmButtonText:\n        '<i class=\"fa fa-thumbs-up\"></i> Okay!'\n    });\n\n}\n\nfunction showMessage(json) {\n    var type = json[\"type\"];\n    var text = json[\"text\"];\n    var logger = json[\"source\"];\n\n    if (type && text && logger) {\n        /*\n        0 : all\n        1 : fatal\n        2 : critical\n        3 : error\n        4 : warning\n        5 : notice\n        6 : information\n        7 : debug\n        8 : trace\n        9 : off\n        */\n\n        var hidden = type > logSettings[logger].val();\n        var lineType;\n\n        switch (parseInt(type)) {\n            case 1:\n            case 2:\n            case 3:\n                lineType = \"list-group-item-danger\";\n                break;\n            case 4:\n                lineType = \"list-group-item-warning\";\n                break;\n            case 5:\n            case 6:\n            case 7:\n            case 8:\n                lineType = \"list-group-item-debug\";\n                break;\n            default:\n                lineType = \"list-group-item-default\";\n                break;\n        };\n\n        var newLine = createMessageLine(lineType, logger, parseInt(type), json[\"file\"], json[\"line\"],\n            json[\"time\"], json[\"text\"].replace(new RegExp('\\r?\\n', 'g'), '<br />'), hidden);\n\n        miningData.addLine(newLine);\n    }\n    else\n        console.log(\"unknown message type: \" + json);\n}\n\nfunction reparseMessages() {\n    var nonces = [];\n\n    miningData.getData().find(\"li\").each(function () {\n        var logger = $(this).attr(\"logger\");\n        var levelStr = $(this).attr(\"level\");\n        var nonce = $(this).attr(\"nonce\");\n\n        if (nonce) {\n            if (nonces.indexOf(nonce) == -1) {\n                nonces.push(nonce);\n                hideSameNonceLines(nonce);\n            }\n        }\n        else if (logger && levelStr) {\n            var loggerLevel = parseInt(logSettings[logger].val());\n            var level = parseInt(levelStr);\n\n            if (level <= loggerLevel)\n                $(this).show();\n            else\n                $(this).hide();\n        }\n    });\n\n    // ******************************************\n    var tempSettings = {\n        miner: logSettings['miner'].val(),\n        config: logSettings['config'].val(),\n        server: logSettings['server'].val(),\n        socket: logSettings['socket'].val(),\n        session: logSettings['session'].val(),\n        nonceSubmitter: logSettings['nonceSubmitter'].val(),\n        plotReader: logSettings['plotReader'].val(),\n        plotVerifier: logSettings['plotVerifier'].val(),\n        wallet: logSettings['wallet'].val(),\n        general: logSettings['general'].val(),\n    }\n\n    localSet('logSettings', tempSettings);\n    // ******************************************\n}\n\nfunction resetLogSettings() {\n    hideSameNonces.prop('checked', true);\n    noncesFound.prop('checked', true);\n    noncesSent.prop('checked', true);\n    noncesConfirmed.prop('checked', true);\n\n    loggers.forEach(function (element, index, array) {\n        logSettings[element[0]].val(element[2]);\n    });\n}\n\nfunction connectBlock() {\n    connect(function (msg) {\n        data = msg[\"data\"];\n\n        if (data) {\n            if (data == \"ping\")\n                return;\n\n            var response = JSON.parse(data);\n\n            switch (response[\"type\"]) {\n                case \"new block\":\n                    newBlock(response);\n                    checkVersion(response[\"runningVersion\"], response[\"onlineVersion\"], response[\"runningBuild\"]);\n                    break;\n                case \"nonce found\":\n                case \"nonce found (too high)\":\n                    nonceFound(response);\n                    break;\n                case \"nonce confirmed\":\n                    addOrConfirm(response);\n                    checkAddBestOverall(BigInteger(response[\"deadlineNum\"]), response[\"deadline\"], response[\"blockheight\"]);\n                    break;\n                case \"nonce submitted\":\n                    addOrSubmit(response);\n                    break;\n                case \"config\":\n                    config(response);\n                    break;\n                case \"progress\":\n                    setOverallProgress(response[\"value\"] - response[\"valueVerification\"]);\n                    setOverallProgressVerify(response[\"valueVerification\"]);\n                    break;\n                case \"lastWinner\":\n                    setLastWinner(response);\n                    break;\n                case \"blocksWonUpdate\":\n                    wonBlocks.html(reponse[\"blocksWon\"]);\n                    break;\n                case \"plotdir-progress\":\n                case \"plotdirs-rescan\":\n                    // do nothing\n                    break;\n                default:\n                    showMessage(response);\n                    break;\n            };\n        }\n    });\n}\n\nfunction deadlineFormat(val) {\n    var secs = Math.floor(val);\n    var mins = Math.floor(secs / 60);\n    var hours = Math.floor(mins / 60);\n    var day = Math.floor(hours / 24);\n    var months = Math.floor(day / 30);\n    var years = Math.floor(months / 12);\n    var msg = \"\";\n\n    if (years > 0)\n        msg += years.toFixed() + \"y \";\n    if (months > 0)\n        msg += (months % 12).toFixed() + \"m \";\n    if (day > 0)\n        msg += day % 30 + \"d \";\n    msg += (\"00\" + (hours % 24)).slice(-2) + ':';\n    msg += (\"00\" + (mins % 60)).slice(-2) + ':';\n    msg += (\"00\" + (secs % 60)).slice(-2);\n\n    return msg;\n}\n\nfunction deadlineFormatPlot(val) {\n    var secs = Math.floor(val);\n    var mins = Math.floor(secs / 60);\n    var hours = Math.floor(mins / 60);\n    var day = Math.floor(hours / 24);\n    var months = Math.floor(day / 30);\n    var years = Math.floor(months / 12);\n    var msg = \"\";\n\n    if (years > 0)\n    {\n        msg += years.toFixed() + \"y \";\n        msg += (months % 12).toFixed() + \"m \";\n        return msg;\n    }\n    if (months > 0)\n    {\n        msg += (months % 12).toFixed() + \"m \";\n        msg += day % 30 + \"d \";\n        return msg;\n    }\n    if (day > 0)\n    {\n        msg += day % 30 + \"d \";\n        msg += (hours % 24) + \"h \";\n        return msg;\n    }\n    msg += (\"00\" + (hours % 24)).slice(-2) + ':';\n    msg += (\"00\" + (mins % 60)).slice(-2) + ':';\n    msg += (\"00\" + (secs % 60)).slice(-2);\n\n    return msg;\n}\n\n\nfunction showDeadlinesInfo(deadlineObj) {\n    var infos = \"---\";\n\n    deadlinePlot.unhighlight();\n\n    if (deadlineObj) {\n        var infos = \"block <b>\" + deadlineObj.datapoint[0] + \"</b>: \" +\n            deadlineFormat(deadlineObj.datapoint[1]);\n\n        deadlinePlot.highlight(deadlineObj.series, deadlineObj.datapoint);\n    }\n\n    deadlinesInfo.html(infos);\n    lastDeadlineInfo = deadlineObj;\n}\n\nfunction showTimeInfo(timeObj) {\n    var infos = \"---\";\n\n    timePlot.unhighlight();\n\n    if (timeObj) {\n        var infos = \"block <b>\" + timeObj.datapoint[0] + \"</b>: \" + deadlineFormat(timeObj.datapoint[1]);\n\n        timePlot.highlight(timeObj.series, timeObj.datapoint);\n    }\n\n    timeInfo.html(infos);\n    lastTimeInfo = timeObj;\n}\n\nfunction showDeadlineDistributionInfo(deadlineDistObj) {\n    var infos = \"---\";\n\n    deadlineDistributionPlot.unhighlight();\n\n    if (deadlineDistObj) {\n        var barMax = deadlineFormat(Number(deadlineDistObj.datapoint[0]) +\n            Number(deadlineDistributionBarWidth)/0.99);\n        var infos = \"<b>\" + deadlineFormat(deadlineDistObj.datapoint[0]) + \" - \" +\n            barMax.toString() + \"</b>: \" + deadlineDistObj.datapoint[1] + \" Deadlines\";\n\n        deadlineDistributionPlot.highlight(deadlineDistObj.series, deadlineDistObj.datapoint);\n    }\n\n    deadlineDistributionInfo.html(infos);\n    lastDeadlineDistributionInfo = deadlineDistObj;\n}\n\nfunction showDifficultyInfo(difficultyObj) {\n    var infos = \"---\";\n\n    difficultyPlot.unhighlight();\n\n    if (difficultyObj) {\n        var infos = \"block <b>\" + difficultyObj.datapoint[0] + \"</b>: \" + Math.floor(difficultyObj.datapoint[1]);\n\n        difficultyPlot.highlight(difficultyObj.series, difficultyObj.datapoint);\n    }\n\n    difficultyInfo.html(infos);\n    lastDifficultyInfo = difficultyObj;\n}\n\nfunction initBlock() {\n    system = $(\"#system\");\n    bestDeadlineOverallElement = $(\"#bestOverall\");\n    bestHistorical = $(\"#bestHistorical\");\n    minedBlocksElement = $(\"#minedBlocks\");\n    roundsSubmitted = $(\"#roundsSubmitted\");\n    hideSameNonces = $(\"#cbHideSameNonces\");\n    noncesFound = $(\"#cbNoncesFound\");\n    noncesSent = $(\"#cbNoncesSent\");\n    noncesConfirmed = $(\"#cbNoncesConfirmed\");\n    progressBar = $(\"#progressBar\");\n    progressBarVerify = $(\"#progressBarVerify\");\n    lastWinnerContainer = $(\"#lastWinnerContainer\");\n    lastWinner = $(\"#lastWinner\");\n    iconConfirmationSound = $(\"#iconConfirmationSound\");\n    avgDeadline = $(\"#avgDeadline\");\n    deadlinePerformance = $(\"#deadlinePerformance\");\n    connectionStatus = $(\"#connectionStatus\");\n    wonBlocks = $(\"#wonBlocks\");\n    lowestDiff = $(\"#lowestDiff\");\n    highestDiff = $(\"#highestDiff\");\n    meanDiff = $(\"#meanDiff\");\n    maxRoundTime = $(\"#maxRoundTime\");\n    avgRoundTime = $(\"#avgRoundTime\");\n    avgBlockTime = $(\"#avgBlockTime\");\n    bestDeadlinesChart = $(\"#deadlinesChart\");\n    deadlinesInfo = $(\"#deadlinesInfo\");\n    timeChart = $(\"#timeChart\");\n    timeInfo = $(\"#timeInfo\");\n    deadlineDistributionChart = $(\"#deadlineDistributionChart\");\n    deadlineDistributionInfo = $(\"#deadlineDistributionInfo\");\n    difficultyChart = $(\"#difficultyChart\");\n    difficultyInfo = $(\"#difficultyInfo\");\n    settingsDlComboboxes = $(\"#settingsDlComboboxes\");\n\n    // ******************************************\n    localInitCheckBoxes();\n    // ******************************************\n\n    flotFrameColor = $(\"p\").css(\"color\");\n    flotColorOne = $(\"#progressBarVerify\").css(\"background-color\");\n    flotColorTwo = $(\"#progressBar\").css(\"background-color\");\n\n    initDeadlinePlot();\n    initTimePlot();\n    initDeadlineDistributionPlot();\n    initDifficultyPlot();\n    bestDeadlineOverallElement.html(nullDeadline);\n    bestHistorical.html(nullDeadline);\n    connectBlock();\n    // deActivateConfirmationSound(true);\n\n    // ******************************************\n    deActivateConfirmationSound(playConfirmationSound);\n    // ******************************************\n\n    showDeadlinesInfo(null);\n    showDeadlineDistributionInfo(null);\n    showDifficultyInfo(null);\n    $(\"#container\").append(miningData.panel);\n\n    hideSameNonces.change(reparseMessages);\n    noncesFound.change(reparseMessages);\n    noncesSent.change(reparseMessages);\n    noncesConfirmed.change(reparseMessages);\n\n    logSettings = initSettings(settingsDlComboboxes, reparseMessages);\n\n    // ******************************************\n    localInitLogSettings();\n    // ******************************************\n}\n\nfunction initDeadlinePlot() {\n    var options = {\n        series: {\n            points: { show: true, radius:2 }\n        },\n        grid: {\n            hoverable: true,\n            autoHighlight: true,\n            clickable: true,\n            color: flotFrameColor,\n        },\n        xaxis: {\n            show: false,\n        },\n        yaxis: {\n            mode: \"time\",\n            min: 0,\n            max: deadlinePlotMax,\n            tickFormatter: function (val, axis) {\n                return deadlineFormatPlot(val);\n            }\n        },\n        colors: [flotColorOne, flotColorTwo]\n    };\n\n    deadlinePlot = $.plot(bestDeadlinesChart, [], options);\n\n    bestDeadlinesChart.bind(\"plotclick\", function (event, pos, item) {\n        if (item)\n            showDeadlinesInfo(item);\n    });\n\n    bestDeadlinesChart.bind(\"plothover\", function (event, pos, item) {\n        if (item)\n            showDeadlinesInfo(item);\n    });\n}\n\nfunction initDeadlineDistributionPlot() {\n    var options = {\n        series: {\n            bars: { show: true }\n        },\n        bars: {\n            barWidth: deadlineDistributionBarWidth\n        },\n        grid: {\n            hoverable: true,\n            autoHighlight: true,\n            clickable: true,\n            color: flotFrameColor,\n        },\n        xaxis: {\n            show: false\n        },\n        yaxis: {\n            min: 0\n        },\n        colors: [flotColorOne, flotColorTwo]\n    };\n\n    deadlineDistributionPlot = $.plot(deadlineDistributionChart, [], options);\n\n    deadlineDistributionChart.bind(\"plotclick\", function (event, pos, item) {\n        if (item)\n            showDeadlineDistributionInfo(item);\n    });\n\n    deadlineDistributionChart.bind(\"plothover\", function (event, pos, item) {\n        if (item)\n            showDeadlineDistributionInfo(item);\n    });\n}\n\nfunction initTimePlot() {\n    var options = {\n        series: {\n            lines: {\n                show: true,\n                fill: true\n            },\n            points: {\n                show: false,\n                radius:2\n            }\n        },\n        grid: {\n            hoverable: true,\n            autoHighlight: true,\n            clickable: true,\n            color: flotFrameColor,\n        },\n        xaxis: {\n            show: false\n        },\n        yaxis: {\n            min: 0,\n            max: timePlotMax\n        },\n        legend: {\n            position:\"nw\",\n            backgroundOpacity: 0,\n            noColumns: 2\n        },\n        colors: [flotColorTwo, flotColorOne]\n    };\n\n    timePlot = $.plot(timeChart, [], options);\n\n    timeChart.bind(\"plotclick\", function (event, pos, item) {\n        if (item)\n            showTimeInfo(item);\n    });\n\n    timeChart.bind(\"plothover\", function (event, pos, item) {\n        if (item)\n            showTimeInfo(item);\n    });\n}\n\nfunction initDifficultyPlot() {\n    var options = {\n        series: {\n            lines: {\n                show: true,\n                fill: true\n            },\n            points: {\n                show: false,\n                radius:2\n            }\n        },\n        grid: {\n            hoverable: true,\n            autoHighlight: true,\n            clickable: true,\n            color: flotFrameColor,\n        },\n        xaxis: {\n            show: false\n        },\n        yaxis: {\n            min: 0,\n            tickFormatter: function (val, axis) {\n                if (val < 1000) return val;\n                if (val < 1000000) return val/1000 + \"K\";\n                if (val < 1000000000) return val/1000000 + \"M\";\n            }\n        },\n        colors: [flotColorOne, flotColorTwo]\n    };\n\n    difficultyPlot = $.plot(difficultyChart, [], options);\n\n    difficultyChart.bind(\"plotclick\", function (event, pos, item) {\n        if (item)\n            showDifficultyInfo(item);\n    });\n\n    difficultyChart.bind(\"plothover\", function (event, pos, item) {\n        if (item)\n            showDifficultyInfo(item);\n    });\n}\n\n// calculates an estimate for the miners efficiency based on the scan time (how many blocks is he going to win on the long run compared to a miner with 0s scan time)\nfunction efficiency(scantime) {\n    if ( scantime > 1 )\n        return Math.ceil(1000*(480.096+599760*Math.exp(-0.00416666666667*scantime)-600240.096384153*Math.exp(-0.004165*scantime))/scantime)/10;\n    else\n        return 100;\n}\n\nwindow.onresize = function (evt) {\n    if (deadlinePlot) {\n        deadlinePlot.resize(0, 0);\n        deadlinePlot.setupGrid();\n        deadlinePlot.draw();\n    }\n    if (timePlot) {\n        timePlot.resize(0, 0);\n        timePlot.setupGrid();\n        timePlot.draw();\n    }\n    if (deadlineDistributionPlot) {\n        deadlineDistributionPlot.resize(0, 0);\n        deadlineDistributionPlot.setupGrid();\n        deadlineDistributionPlot.draw();\n    }\n    if (difficultyPlot) {\n        difficultyPlot.resize(0, 0);\n        difficultyPlot.setupGrid();\n        difficultyPlot.draw();\n    }\n}\n\nwindow.onload = function (evt) {\n    $(\"#btnBlock\").addClass('active');\n    initBlock();\n}"
  },
  {
    "path": "resources/public/js/general.js",
    "content": "var websocket;\nvar servername = 'creepMiner';\nvar MasterMiner = 'false';\nvar container = 'false'\nvar loggers = [\n\t[\"miner\", \"Miner\", 6],\n\t[\"config\", \"Config\", 6],\n\t[\"server\", \"Server\", 1],\n\t[\"socket\", \"Socket\", 0],\n\t[\"session\", \"Session\", 3],\n\t[\"nonceSubmitter\", \"Nonce submitter\", 6],\n\t[\"plotReader\", \"Plot reader\", 6],\n\t[\"plotVerifier\", \"Plot verifier\", 6],\n\t[\"wallet\", \"Wallet\", 1],\n\t[\"general\", \"General\", 6]\n];\nvar levels = [\n\t\"off\", \"fatal\", \"critical\", \"error\", \"warning\",\n\t\"notice\", \"information\", \"debug\", \"trace\", \"all\"\n];\n\nfunction connect(onMessage) {\n\tif (\"WebSocket\" in window) {\n\t\tif (websocket)\n\t\t\twebsocket.close();\n\n\t\tif (location.protocol == \"https:\")\n\t\t\tprotocol =\"wss\"\n\t\telse\n\t\t\tprotocol = \"ws\"\n\n\t\twebsocket = new WebSocket(protocol + \"://\" + window.location.host);\n\t\twebsocket.onmessage = onMessage;\n\t}\n\telse {\n\t\twebsocket = null;\n\t}\n}\n\n// version checker and update about btn\nfunction checkVersion(runningVer, onlineVer, runningBuild) {\n\tvar onlineVersionSplit = onlineVer.split(\".\");\n    var runningVersionSplit = runningVer.split(\".\");\n\tvar current=true;\n\t//console.info(runningVer + '.' + runningBuild);\n    if (Number(runningVersionSplit[0]) > Number(runningVersionSplit[0]))\n        current=false;\n    else if (Number(onlineVersionSplit[1]) > Number(runningVersionSplit[1]))\n        current=false;\n    else if (Number(onlineVersionSplit[2]) > Number(runningVersionSplit[2]))\n        current=false;\n\tif(!current)\n\t{\n        $(\"#btnAbout\").find(\"a\").css({\"color\":\"#ffc107\"});\n        $(\"#btnAbout\").attr({\"data-original-title\": \"New version available\"});\n        $(\"#runningVer\").html(\"&nbsp;v&nbsp;\" + runningVer);\n        $(\"#latestVer\").html(\"&nbsp;v&nbsp;\" + onlineVer);\n        $(\"#versionCardHeader\").toggleClass(\"bg-success\",false);\n        $(\"#versionCardHeader\").toggleClass(\"bg-danger\",true);\n        $(\"#versionAlert\").toggleClass(\"alert-success\",false);\n        $(\"#versionAlert\").toggleClass(\"alert-danger\",true);\n        $(\"#versionAlert\").html(\"<i class='fas fa-wrench'></i>&nbsp;&nbsp;<strong>Update available!</strong>\"+\n            \" Download it from <i class='fab fa-github-square'></i>&nbsp;<a href='https://github.com/Creepsky/creepMiner/releases'>github</a>\");\n    } else\n    {\n        $(\"#runningVer\").html(\"<i class='fas fa-check text-success'></i>&nbsp;v&nbsp;\" + runningVer +\".\" + runningBuild);\n        $(\"#latestVer\").html(\"&nbsp;v&nbsp;\" + onlineVer);\n        //$(\"#versionAlert\").html(\"<i class='fas fa-check text-success'></i>&nbsp;&nbsp;You are running a current version of creepMiner.\");\n    }\n\treturn current\n}\n\n// progress bar\nfunction setProgress(progressBar, progress) {\n\tvar valueFixed = parseFloat(progress).toFixed();\n\n\tif (valueFixed >= 100) {\n\t\tvalueFixed = 100;\n\t\tprogressBar.removeClass(\"active\");\n\t}\n\telse if (valueFixed < 100) {\n\t\tif (valueFixed < 0)\n\t\t\tvalueFixed = 0;\n\n\t\tif (!progressBar.hasClass(\"active\"))\n\t\t\tprogressBar.addClass(\"active\");\n\t}\n\n\tprogressBar.css(\"width\", valueFixed + \"%\").attr(\"aria-valuenow\", valueFixed);\n\tprogressBar.html(\"\");\n}\n\n// verify progress bar\nfunction setProgressVerify(progressBar, progress) {\n\tvar valueFixed = parseFloat(progress).toFixed();\n\n\tif (valueFixed >= 100) {\n\t\tvalueFixed = 100;\n\t\tprogressBar.removeClass(\"active\");\n\t}\n\telse if (valueFixed < 100) {\n\t\tif (valueFixed < 0)\n\t\t\tvalueFixed = 0;\n\n\t\tif (!progressBar.hasClass(\"active\"))\n\t\t\tprogressBar.addClass(\"active\");\n\t}\n\n\tprogressBar.css(\"width\", valueFixed + \"%\").attr(\"aria-valuenow\", valueFixed);\n\tprogressBar.html(valueFixed + \" % Verified\");\n}\n\n// initializing settings\nfunction initSettings(container, onChange) {\n\toutput = {};\n\tloggers.forEach(function (element, index, array) {\n\t\telement[1][0].toUpperCase();\n\t\tvar cmb = $(\"<select id='cmb_\" + element[0] + \"' name='cmb_\" + element[0] + \"' class='selectpicker form-control'></select>\");\n\t\tcreateLoggerCombobox(cmb);\n\t\tif (onChange)\n\t\t\tcmb.change(function () {\n\t\t\t\tonChange();\n\t\t\t});\n\n\t\tvar div = $(\"<div class='form-group row'></div>\");\n\t\tvar label = $(\"<label for='cmb_\" + element[0] + \"' class='col-md-12 col-lg-3 col-form-label'>\" + element[1] + \"</label>\");\n\n\t\tdiv.append(label);\n\t\tdiv.append(\"<div class='col-md-12 col-lg-9'>\")\n\t\tdiv.find(\"div\").append(cmb);\n\n\t\tcmb.val(element[2]);\n\t\toutput[element[0]] = cmb;\n\n\t\tcontainer.append(div);\n\t});\n\treturn output;\n}\n\n// create combo boxes for logger\nfunction createLoggerCombobox(cmb) {\n\tcmb.empty();\n\tlevels.forEach(function (element, index, array) {\n\t\tcmb.append(\"<option value=\" + index + \">\" + element + \"</option>\");\n\t});\n}\n\n// initializing tooltip\n$(document).ready(function() {\n  $('[data-toggle=\"tooltip\"]').tooltip();\n});\n\n// stylesheet selector\n(function($)\n {\n  var $links = $('link[rel*=alternate][title]');\n  var el = document.getElementById('themeSelector');\n  var options= '<a class=\"dropdown-item\" onclick=\"eraseCookie(\\'theme\\');\" style=\"cursor:pointer\">Default</a><div class=\"dropdown-divider\"></div>';\n  $links.each(function(index,value){\n   options +='<a class=\"dropdown-item\" onclick=\"SwitchTheme(\\''+$(this).attr('title')+'\\'); location.reload();\" style=\"cursor:pointer\">'+$(this).attr('title')+'</a>';\n  });\n  $links.remove();\n\n  el.innerHTML = options;\n }\n)(jQuery);\n\n// dynamically switch bootswatch themes\nfunction SwitchTheme (name){\n $('link[rel*=jquery]').remove();\n //console.log(name);\n $('head').append('<link rel=\"stylesheet jquery\" href=\"https://bootswatch.com/4/'+ name +'/bootstrap.min.css\" type=\"text/css\" />');\n document.cookie = \"theme = https://bootswatch.com/4/\"+name+\"/bootstrap.min.css;\";\n}\n\n// fetch cookie\nfunction getCookie(cname) {\n    var name = cname + \"=\";\n    var decodedCookie = decodeURIComponent(document.cookie);\n    var ca = decodedCookie.split(';');\n    for(var i = 0; i <ca.length; i++) {\n        var c = ca[i];\n        while (c.charAt(0) == ' ') {\n            c = c.substring(1);\n        }\n        if (c.indexOf(name) == 0) {\n            return c.substring(name.length, c.length);\n        }\n    }\n    return \"\";\n}\n\n// to add new cookies, use this to create future cookies - will be used later on\nfunction createCookie(name,value,days) {\n\tif (days) {\n\t\tvar date = new Date();\n\t\tdate.setTime(date.getTime()+(days*24*60*60*1000));\n\t\tvar expires = \"; expires=\"+date.toGMTString();\n\t}\n\telse var expires = \"\";\n\tdocument.cookie = name+\"=\"+value+expires+\"; path=/\";\n}\n\n// remove cookie\nfunction eraseCookie(name) {\n\twindow.location.reload(false);\n\tcreateCookie(name,\"\",-1);\n}\n\n// set the title in header and replace the server-name element with server name\ndocument.getElementById('server-name').innerHTML = servername;\ndocument.title = servername;\n\n// if master miner is set show and hide some elements\nif (container == 'true') {\n    var dElement = document.getElementsByClassName('d-container'), i;\n    for (var i = 0; i < dElement.length; i ++) {\n        dElement[i].style.display = 'inline';\n    }\n}\n\n// if master miner is set show and hide some elements\nif (MasterMiner == 'true') {\n\tvar mmElement = document.getElementsByClassName('mm-show'), i;\n\tfor (var i = 0; i < mmElement.length; i ++) {\n\t    mmElement[i].style.display = 'inline';\n\t}\n\tvar mmHideElements = document.getElementsByClassName('mm-hide'), i;\n\tfor (var i = 0; i < mmHideElements.length; i ++) {\n\t    mmHideElements[i].style.display = 'none';\n\t}\n}\n\n// master miner menu - WIP\n$.getJSON('https://next.json-generator.com/api/json/get/VJs_LJEAN', function(data) {\n    var builddata = function() {\n        var source = [];\n        var items = [];\n        for (i = 0; i < data.length; i++) {\n            var item = data[i];\n            var label = item[\"name\"];\n            var parentid = item[\"parent_id\"];\n            var icon = item[\"icon\"];\n            var id = item[\"id\"];\n            var url = item[\"url\"];\n\n            if (items[parentid]) {\n                var item = {\n                    parentid: parentid,\n                    label: label,\n                    url: url,\n                    icon: icon,\n                    item: item\n                };\n                if (!items[parentid].items) {\n                    items[parentid].items = [];\n                }\n                items[parentid].items[items[parentid].items.length] = item;\n                items[id] = item;\n            } else {\n                items[id] = {\n                    parentid: parentid,\n                    label: label,\n                    url: url,\n                    icon: icon,\n                    item: item\n                };\n                source[id] = items[id];\n            }\n        }\n        return source;\n    }\n    // build dynamic menu from json payload\n    var buildMenu = function(menu, source) {\n        var isFirst = true;\n        $.each(source, function() {\n            if (this.label) {\n                if (!isFirst) {\n                    var divider = $('<div class=\"dropdown-divider\"></div>');\n                    menu.append(divider);\n                }\n                var parent = $('<a class=\"dropdown-item\" href=\"' + this.url + '\" target=\"_blank\"><i class=\"text-muted ' + this.icon + '\"></i>  ' + this.label + '</a>');\n                menu.append(parent);\n                if (this.items && this.items.length > 0) {\n                    $.each(this.items, function() {\n                        var child = $('<a class=\"dropdown-item\" href=\"' + this.url + '\" target=\"_blank\"><i class=\"text-muted ' + this.icon + '\" ></i>  ' + this.label + '</a>');\n                        menu.append(child);\n                    });\n                }\n                isFirst = false;\n            }\n        });\n    }\n    var source = builddata();\n    //console.log(source);\n    buildMenu($('#dynamic-menu'), source);\n});\n"
  },
  {
    "path": "resources/public/js/plotfiles.js",
    "content": "var plotDirList = $(\"#plotDirList\");\nvar plotFileDiv = $(\"#plotFileDiv\");\nvar plotDirElements = [];\n\nvar activePlotDir = null;\nvar confirmedPlotfiles = [];\nvar current_selected = null;\n\nvar isChecking=false;\nvar isCheckingAll=false;\n\nwindow.onload = function (evt) {\n    $(\"#btnPlots\").addClass('active');\n    parsePlots();\n    fillDirs();\n    connect(connectCallback);\n}\n\nfunction connectCallback(msg) {\n    data = msg[\"data\"];\n\n    if (data) {\n        if (data == \"ping\") {\n            return;\n        }\n\n        var response = JSON.parse(data);\n\n        switch (response[\"type\"]) {\n            case \"new block\":\n                resetProgress();\n                resetLineTypes();\n                confirmedPlotfiles = [];\n                checkVersion(response[\"runningVersion\"], response[\"onlineVersion\"], response[\"runningBuild\"]);\n                break;\n            case \"plotdir-progress\":\n                setDirProgress(response[\"dir\"], response[\"value\"]);\n                break;\n            case \"nonce confirmed\":\n                nonceConfirmed(response[\"plotfile\"]);\n                break;\n            case \"plotdirs-rescan\":\n                plotdirs = response[\"plotdirs\"];\n                parsePlots();\n                fillDirs();\n                break;\n            case \"plotcheck-result\":\n                setPlotIntegrity(response);\n                break;\n            case \"totalPlotcheck-result\":\n                setTotalPlotIntegrity(response);\n                break;\n            default:\n                break;\n        }\n    }\n}\n\nfunction createProgressBar(id) {\n    var progresStr = '<div class=\"progress\">';\n    progresStr += '<div id=\"pb-' + id + '\" class=\"progress-bar progress-bar-success progress-bar-striped bg-success\" role=\"progressbar\" aria-valuenow=\"100\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width:100%\">';\n    progresStr += '</div></div>';\n    return progresStr;\n}\n\nfunction createDirLine(dirElement, index) {\n    var line = $('<a href=\"#\" class=\"list-group-item\"></a>');\n    var removeElement = '<span id=\"removeElement\" data-toggle=\"tooltip\" data-placement=\"bottom\" data-original-title=\"Remove plot directory.\" onclick=\"delPlotDir(\\'' + dirElement[\"path\"] + '\\');\">';\n\n    line.append(dirElement[\"path\"]);\n    line.append(\" (\" + dirElement.plotfiles.length + \" files, \" + dirElement[\"size\"] + \") <small class='float-sm-right'>\" + removeElement + \"<i class='fas fa-minus text-danger'></i></span></small>\");\n    line.append(createProgressBar(index));\n\n    line.click(function () {\n        plotDirList.find('.active').removeClass('active');\n        line.addClass('active');\n        showPlotfiles(plotDirElements[index][\"plotfiles\"]); // Old version: showPlotfiles(dirElement[\"plotfiles\"]);\n        activePlotDir = dirElement;\n        colorConfirmedPlotfiles();\n        current_selected = dirElement;\n    });\n\n    return line;\n}\n\nfunction fillDirs() {\n    plotDirList.empty();\n    plotDirElements.forEach(function (plotDirElement, index, array) {\n        plotDirList.append(plotDirElement[\"element\"]);\n    });\n}\n\nfunction parsePlots() {\n    plotDirElements = [];\n\n    plotdirs.forEach(function (plotDir, index, array) {\n        var element = {\n            \"path\": plotDir[\"path\"],\n            \"size\": plotDir[\"size\"],\n            \"plotfiles\": []\n        };\n\n        plotDir[\"plotfiles\"].forEach(function (plotFile, index, array) {\n            var path = plotFile[\"path\"];\n            var filename = path.replace(/^.*[\\\\\\/]/, '');\n            var filename_tokens = filename.split(\"_\");\n            var account = filename_tokens[0];\n            var start_nonce = filename_tokens[1];\n            var nonces = filename_tokens[2];\n            var staggersize = filename_tokens[3];\n            var size = plotFile[\"size\"];\n            var lineFile = createPlotfileLine(account, start_nonce, nonces, staggersize, size, path);\n\n            var fileElement = {\n                \"path\": path,\n                \"size\": size,\n                \"element\": lineFile,\n                \"lineType\": null,\n                \"setLineType\": function (type) {\n                    fileElement.element.addClass(type);\n                    fileElement.lineType = type;\n                },\n                \"resetLineType\": function () {\n                    if (fileElement.lineType) {\n                        fileElement.element.removeClass(fileElement.lineType);\n                        fileElement.lineType = null;\n                    }\n                }\n            };\n\n            element[\"plotfiles\"].push(fileElement);\n        });\n\n        element[\"element\"] = createDirLine(element, index);\n        element[\"setProgress\"] = function (progress) {\n            setProgress($(\"#pb-\" + index), progress);\n        };\n        element[\"progressBarType\"] = \"\";\n        element[\"resetProgressBarType\"] = function () {\n            if (element[\"progressBarType\"].length > 0)\n                $(\"#pb-\" + index).removeClass(element[\"progressBarType\"]);\n        };\n        element[\"setProgressBarType\"] = function (type) {\n            element.resetProgressBarType();\n            $(\"#pb-\" + index).addClass(type);\n            element[\"progressBarType\"] = type;\n        }\n\n        plotDirElements.push(element);\n    });\n}\n\nfunction checkPlotFile(account, start_nonce, nonces, staggersize, path) {\n    if(!isChecking && !isCheckingAll)\n    {\n        isChecking=true;\n        var butId = account + \"_\" + start_nonce + \"_\" + nonces + \"_\" + staggersize;\n        $(\"#\"+butId).html(\"<i class='fas fa-spinner fa-pulse'></i>\");\n        $.get(encodeURI(\"/checkPlotFile/\" + path));\n    }\n}\n\nfunction checkAllPlotFiles(account, start_nonce, nonces, staggersize, path) {\n    if(!isCheckingAll)\n    {\n        isCheckingAll=true;\n        $(\"#CheckAllButton\").html(\"<i class='fas fa-spinner fa-pulse'></i>\");\n        $.get('/checkPlotFile/all');\n    }\n}\n\nfunction setPlotIntegrity(checkPlotResult) {\n    isChecking=false;\n    var integrity = Math.floor(Number(checkPlotResult[\"plotIntegrity\"])*100)/100;\n    //find the corresponding element in the plotDirElements and write the integrity into it.\n    plotDirElements.forEach(function (element, indexDir, arrayFold) {\n        element[\"plotfiles\"].forEach( function(fileElement, index, array) {\n            if(fileElement[\"element\"].find(\"#\"+checkPlotResult[\"plotID\"])[0]){\n                if (integrity==100)\n                {\n                    plotDirElements[indexDir][\"plotfiles\"][index][\"element\"].find(\"#\"+checkPlotResult[\"plotID\"]).\n                        html(\"<i class='fas fa-check'></i>&nbsp;&nbsp;\" + integrity + \"%\");\n                    plotDirElements[indexDir][\"plotfiles\"][index][\"element\"].find(\"#\"+checkPlotResult[\"plotID\"]).\n                        toggleClass('btn-info btn-danger',false);\n                    plotDirElements[indexDir][\"plotfiles\"][index][\"element\"].find(\"#\"+checkPlotResult[\"plotID\"]).\n                        toggleClass('btn-success',true);\n                }\n                else\n                {\n                    plotDirElements[indexDir][\"plotfiles\"][index][\"element\"].find(\"#\"+checkPlotResult[\"plotID\"]).\n                        html(\"<i class='fas fa-exclamation'></i>&nbsp;&nbsp;\" + integrity + \"%\");\n                    plotDirElements[indexDir][\"plotfiles\"][index][\"element\"].find(\"#\"+checkPlotResult[\"plotID\"]).\n                        toggleClass('btn-info btn-success',false);\n                    plotDirElements[indexDir][\"plotfiles\"][index][\"element\"].find(\"#\"+checkPlotResult[\"plotID\"]).\n                        toggleClass('btn-danger',true);\n                }\n            }\n        });\n});\n}\n\nfunction setTotalPlotIntegrity(totalCheckResult) {\n    isCheckingAll=false;\n    var totIntegrity = Math.round(Number(totalCheckResult[\"totalPlotIntegrity\"])*100)/100;\n    if (totIntegrity==100)\n    {\n        $(\"#CheckAllButton\").html(\"<i class='fas fa-check'></i>&nbsp;&nbsp;\" + totIntegrity + \"% Integrity\");\n        $(\"#CheckAllButton\").toggleClass('btn-info btn-danger',false);\n        $(\"#CheckAllButton\").toggleClass('btn-success',true);\n    }\n    else\n    {\n        $(\"#CheckAllButton\").html(\"<i class='fas fa-exclamation'></i>&nbsp;&nbsp;\" + totIntegrity + \"% Integrity\");\n        $(\"#CheckAllButton\").toggleClass('btn-info btn-success',false);\n        $(\"#CheckAllButton\").toggleClass('btn-danger',true);\n    }\n}\n\nfunction createPlotfileLine(account, start_nonce, nonces, staggersize, size, path) {\n    var line = $(\"<li class='list-group-item d-md-flex align-items-center' style='padding:4px'></li>\");\n    line.append(\"<div class='col-xs-3 col-md-3'>\" + account + \"</div>\");\n    line.append(\"<div class='col-xs-2 col-md-2'>\" + start_nonce + \"</div>\");\n    line.append(\"<div class='col-xs-2 col-md-1'>\" + nonces + \"</div>\");\n    line.append(\"<div class='col-xs-2 col-md-1'>\" + staggersize + \"</div>\");\n    line.append(\"<div class='col-xs-1 col-md-2'>\" + size + \"</div>\");\n    line.append(\"<div class='col-xs-2 col-md-3'><button id='\" + account + \"_\" + start_nonce + \"_\" + nonces + \"_\" + staggersize +\n        \"' type='button' class='btn btn-primary' \" +\n        \"style='padding:2px; margin=0px; width:100%' onclick='checkPlotFile(\\\"\" + account + \"\\\",\" + start_nonce + \",\" +\n        nonces + \",\" + staggersize + \",\\\"\" + path.replace(/\\\\/g,\"\\\\\\\\\") + \"\\\")'><span class='fab fa-superpowers'></span>&nbsp;Validate</button></div>\");\n    return line;\n}\n\nfunction showPlotfiles(files) {\n    plotFileDiv.hide('fast', function () {\n        plotFileDiv.empty();\n\n        plotFileDiv.append(\"<h4 class='card-header text-white bg-primary'>Files</h4>\" +\n            \"<div class='col-lg-12'>\" +\n            \"    <div class='row card-header' style='padding-left:0;padding-right:0'>\" +\n            \"        <div class='col-xs-3 col-md-3'>Account</div>\" +\n            \"        <div class='col-xs-2 col-md-2'>Start nonce</div>\" +\n            \"        <div class='col-xs-2 col-md-1'>Nonces</div>\" +\n            \"        <div class='col-xs-2 col-md-1'>Stagger</div>\" +\n            \"        <div class='col-xs-1 col-md-2'>Size</div>\" +\n            \"        <div class='col-xs-2 col-md-3' data-toggle='tooltip' data-placement='top' data-original-title='Pressing the button will Validate the integrity of 32 random scoops of 32 random nonces in the plot file'>Integrity</div>\" +\n            \"    </div>\" +\n            \"</div>\");\n        files.forEach(function (file, i, arr) {\n            plotFileDiv.append(file[\"element\"]);\n        });\n\n        plotFileDiv.show('slow');\n    });\n}\n\nfunction resetProgress() {\n    plotDirElements.forEach(function (element, index, array) {\n        element.setProgress(0);\n        element.resetProgressBarType();\n    });\n}\n\nfunction setDirProgress(dir, progress) {\n    for (var i = 0; i < plotDirElements.length; ++i) {\n        if (plotDirElements[i][\"path\"] == dir) {\n            plotDirElements[i].setProgress(progress);\n            break;\n        }\n    }\n}\n\nfunction resetLineTypes() {\n    if (activePlotDir) {\n        for (var i = 0; i < activePlotDir.plotfiles.length; ++i) {\n            activePlotDir.plotfiles[i].resetLineType();\n        }\n    }\n}\n\nfunction colorConfirmedPlotfiles() {\n    if (!activePlotDir) {\n        return;\n    }\n\n    for (var j = 0; j < confirmedPlotfiles.length; ++j) {\n        for (var i = 0; i < activePlotDir.plotfiles.length; ++i) {\n            if (activePlotDir.plotfiles[i].path == confirmedPlotfiles[j]) {\n                activePlotDir.plotfiles[i].setLineType('success');\n                break;\n            }\n        }\n    }\n}\n\nfunction nonceConfirmed(plotfile) {\n    var dir = null;\n\n    for (var i = 0; i < plotDirElements.length; ++i) {\n        if (plotfile.length > plotDirElements[i].path.length) {\n            if (plotfile.substring(0, plotDirElements[i].path.length) == plotDirElements[i].path) {\n                plotDirElements[i].setProgressBarType('progress-bar-success');\n                dir = plotfile.substring(0, plotDirElements[i].path.length);\n                break;\n            }\n        }\n    }\n\n    confirmedPlotfiles.push(plotfile);\n    colorConfirmedPlotfiles();\n}\n\nfunction remove_selected_plot_dir() {\n    if (current_selected) {\n        $.get(\"/\");\n    }\n}\n\n$('#removeElement').tooltip();\n\nfunction delPlotDir(path) {\n\tswal( {\n\t\ttitle: 'Remove plot directory',\n\t\thtml: \n        '<p>Are you sure you want to remove this directory?</p>' +\n        'If you are sure, type in <b>YES</b>',\n\t\ttype: 'warning',\n        input: \"text\",\n        inputPlaceholder: \"YES\",\n\t\tshowCancelButton: true,\n\t\tconfirmButtonText: 'Delete',\n\t\tcancelButtonText: 'Cancel',\n        confirmButtonColor: \"#dc3545\",\n        reverseButtons: true,\n\t}).then((result) => {\n        if (result.value.trim().toLowerCase() == 'yes') {\n\t\t\t$.ajax( {\n\t\t\t\ttype: \"POST\",\n                url: \"plotdir/remove\",\n                data: (path),\n                success: function(msg) {\n                    if (!msg.error) {\n                        swal({\n                            title: \"Successfully deleted!\",\n                            text: \"The plot directory has been removed\",\n                            type: \"success\"\n                        });\n                    }\n                    else {\n                        swal({\n                            title: \"Error!\",\n                            text: \"There was an error removing the plot directory: \" + msg.error,\n                            type: \"error\"\n                        } );\n                    }\n                }\n    \t\t} );\n        }\n    } );\n}\n\nfunction addPlotDir() {\n    swal({\n    title: 'Add new directory',\n    html:\n    '<p>Enter your plot location. E.G.</p>' +\n    '<ul class=\"list-group\">' +\n    '<li class=\"list-group-item d-flex justify-content-between align-items-center\">' +\n    '<b>Windows</b>' +\n    '<span class=\"badge badge-primary badge-pill\">D:\\\\plots</span>'+\n    '</li>' +\n    '<li class=\"list-group-item d-flex justify-content-between align-items-center\">' +\n    '<b>linux & MacOS</b>' +\n    '<span class=\"badge badge-primary badge-pill\">/Volume/plots</span>'+\n    '</li>' +\n    '</ul>',\n    input: \"text\",\n    inputPlaceholder: \"Your plot location\",\n    showCancelButton: true,\n    confirmButtonText: \"Add\",\n    cancelButtonText: \"Cancel\",\n    confirmButtonColor: \"#1FAB45\",\n    animation: \"slide-from-top\",\n    buttonsStyling: true\n    }).then((result) => {\n        if (result.value) {\n      \t    $.ajax( {\n                type: \"POST\",\n                url: \"plotdir/add\",\n                data: (result.value),\n                success: function (msg) {\n                    if (!msg.error) {\n                        swal({\n                            title: \"Successfully added!\",\n                            text: \"Your plot directory has been added\",\n                            type: \"success\"\n                        } )\n                    }\n                    else {\n                        swal({\n                            title: \"Error!\",\n                            html: \"<p>In adding the plot directory</p><p>'\" + msg.error + \"'</p><p><b>Check that it is a valid directory!</b><p>\",\n                            type: \"error\"\n                        } )\n                    }\n\n                }\n          } );\n        }\n    } );\n}"
  },
  {
    "path": "resources/public/js/settings.js",
    "content": "var logSetting = {};\n\nfunction update_settings(config) {\n    mining_info_url.val(config['miningInfoUrl'] + ':' + config['miningInfoUrlPort']);\n    submission_url.val(config['poolUrl'] + ':' + config['poolUrlPort']);\n\tif (config['walletUrl'] + ':' + config['walletUrlPort']==\"://:0\")\n\t\twallet_url.val(\"\");\n\telse\n\t\twallet_url.val(config['walletUrl'] + ':' + config['walletUrlPort']);\n\n    intensity.val(config['miningIntensityRaw']);\n    buffer_size.val(config['bufferSizeRaw']);\n    buffer_chunks.val(config['bufferChunks']);\n    plot_readers.val(config['maxPlotReadersRaw']);\n    submission_max_retry.val(config['submissionMaxRetry']);\n    submit_probability.val(config['submitProbability']);\n    max_historical_blocks.val(config['maxHistoricalBlocks']);\n    target_deadline.val(config['targetDeadlineLocal']);\n\n    timeout.val(config['timeout']);\n\n    log_dir.val(config['logDir']);\n\n    for (var key in config['channelPriorities']) {\n        window['cmb_' + key].val(config['channelPriorities'][key].numeric);\n    }\n}\n\nfunction connectCallback(msg) {\n    data = msg[\"data\"];\n\n    if (data) {\n        if (data == \"ping\") {\n            return;\n        }\n\n        var response = JSON.parse(data);\n\n        switch (response[\"type\"]) {\n            case \"config\":\n                update_settings(response);\n                break;\n            case \"new block\":\n                checkVersion(response[\"runningVersion\"], response[\"onlineVersion\"], response[\"runningBuild\"]);\n                break;\n            default:\n                break;\n        }\n    }\n}\n\nwindow.onload = function (evt) {\n    $(\"#btnSettings\").addClass('active');\n    logSetting = initSettings($(\"#settingsDlComboboxes\"));\n\n    mining_info_url = $(\"#mining-info-url\");\n    submission_url = $(\"#submission-url\");\n    wallet_url = $(\"#wallet-url\");\n\n    intensity = $(\"#intensity\");\n    buffer_size = $(\"#buffer-size\");\n    buffer_chunks = $(\"#buffer-chunks\");\n    plot_readers = $(\"#plot-readers\");\n    submission_max_retry = $(\"#submission-max-retry\");\n    submit_probability = $(\"#submit-probability\");\n    max_historical_blocks = $(\"#max-historical-blocks\");\n    target_deadline = $(\"#target-deadline\");\n    timeout = $(\"#timeout\");\n\n    log_dir = $(\"#log-dir\");\n\n    loggers.forEach(function (element) {\n        var id = \"cmb_\" + element[0];\n        window[id] = $(\"#\" + id);\n    });\n\n    connect(connectCallback);\n}\n\nfunction restartMiner() {\n\tswal( {\n\t\ttitle: 'Restart creepMiner',\n\t\thtml:\n        '<p>Are you 100% sure you want to restart?</p>' +\n        'If you are sure, type in <b>restart</b>',\n\t\ttype: 'warning',\n        input: \"text\",\n\t\tshowCancelButton: true,\n\t\tconfirmButtonText: 'Restart',\n\t\tcancelButtonText: 'Cancel',\n        confirmButtonColor: \"#dc3545\",\n        reverseButtons: true,\n\t}).then((result) => {\n        if (result.value.trim().toLowerCase() == 'restart') {\n\t\t\t\t$.ajax( {\n\t\t\t\t\ttype: \"GET\",\n\t                url: \"/restart\",\n\t                success: function(msg){\n\t                    if (!msg.error) {\n\t                        swal({\n\t                            title: \"Successfully queued!\",\n\t                            html: \"<p><b>creepMiner</b> has been restarted,</p> <p>please wait for it to startup.</p>\",\n\t                            type: \"success\"\n\t                        });\n\t                    }\n\t                    else {\n\t                        swal({\n\t                            title: \"Error!\",\n\t                            html: \"There was an error removing the plot directory: \" + msg.error,\n\t                            type: \"error\"\n\t                        });\n\t                    }\n\t                }\n\t    \t\t} );\n        }\n        else {\n\t\t\t\t\tswal({\n\t\t\t\t\t\ttitle: \"Error!\",\n\t\t\t\t\t\thtml: \"<p>In adding the plot directory</p><p>'\" + msg.error + \"'</p><p><b>Check that it is a valid directory!</b><p>\",\n\t\t\t\t\t\ttype: \"error\"\n\t\t\t\t\t})\n\t\t\t\t}\n    });\n}\n"
  },
  {
    "path": "resources/public/login.html",
    "content": "<div class=\"login-container\">\n    <div class=\"row\">\n        <div class=\"col-md-12\">\n            <div class=\"text-center m-b-md\">\n                <h3>Please login to creepMiner</h3>\n                <small>This is the best BURST miner ever!</small>\n            </div>\n            <div class=\"hpanel\">\n                <div class=\"panel-body\">\n                    <form method=\"POST\" action=\"/login\">\n                        <div class=\"form-group\">\n                            <label for=\"creepminer-webserver-user\">Username</label>\n                            <input type=\"username\" class=\"form-control\" id=\"creepminer-webserver-user\" name=\"creepminer-webserver-user\" placeholder=\"creepAdmin\">\n                        </div>\n                        <div class=\"form-group\">\n                            <label for=\"creepminer-webserver-pass\">Password</label>\n                            <input type=\"password\" class=\"form-control\" id=\"creepminer-webserver-pass\" name=\"creepminer-webserver-pass\" placeholder=\"Please enter your password\">\n                        </div>\n                        <div class=\"checkbox\">\n                            <input type=\"checkbox\" class=\"i-checks\" checked>\n                                 Remember login\n                            <p class=\"help-block small\">(if this is a private computer)</p>\n                        </div>\n                        <button type=\"submit\" class=\"btn btn-primary btn-block\">Login</button>\n                    </form>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "resources/public/plotfiles.html",
    "content": "<!-- Modal -->\n<div class=\"modal fade\" id=\"checkAllModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"checkAllModalLabel\" aria-hidden=\"true\">\n  <div class=\"modal-dialog\" role=\"document\">\n    <div class=\"modal-content\">\n      <div class=\"modal-header\">\n        <h5 class=\"modal-title\" id=\"checkAllModalLabel\">Validating all plot files!</h5>\n        <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n          <span aria-hidden=\"true\">&times;</span>\n        </button>\n      </div>\n      <div class=\"modal-body\">\n            <div>\n                <p><i class=\"fas fa-info pull-right\"></i></p>\n                <p>\n                Validating all plots is a intense process and can take a while to run. You may observe the progress by selecting the plot directory.\n                </p>\n            </div>\n      </div>\n      <div class=\"modal-footer\">\n        <button type=\"button\" class=\"btn btn-warning\" onclick=\"checkAllPlotFiles();\" data-dismiss=\"modal\">Okay, do it!</button>\n      </div>\n    </div>\n  </div>\n</div>\n\n<div class=\"row bs-component\">\n    <!-- plot locations -->\n    <div class=\"col-md-3\" style=\"margin:0;padding:0\">\n        <div class=\"col-lg-12\" id=\"container\">\n            <div class=\"btn-group d-flex\" role=\"group\">\n                <!-- rescan btn -->\n                <button type=\"button\" class=\"btn btn-primary w-100\" onclick=\"$.get('/rescanPlotfiles');\">\n                <span data-toggle='tooltip' data-placement='bottom' data-original-title='Rescan plot folders for new or removed plot files.'>\n                    <span class=\"fas fa-sync\"></span>\n                    Rescan\n                </span>\n                </button>\n                <!-- validate btn, trigger modal -->\n                <button type=\"button\" class=\"btn btn-primary w-100\" id=\"CheckAllButton\" data-toggle=\"modal\" data-target=\"#checkAllModal\">\n                <span data-toggle='tooltip' data-placement='bottom' data-original-title='Validate the integrity of all plot files. This may take a while.'>\n                    <span class=\"fab fa-superpowers\"></span>\n                    Validate all\n                </span>\n                </button>\n            </div>\n            <!-- Directories -->\n            <div class=\"card mb-12\">\n                <h4 class=\"card-header bg-success text-white\">\n                    Directories\n                    <small class=\"float-sm-right\" data-toggle=\"tooltip\" data-placement=\"bottom\" data-original-title=\"Add new plot location.\">\n                        <span onclick=\"addPlotDir();\"><i class=\"fas fa-plus\"></i></span>\n                    </small>\n                </h4>\n                <div class=\"card-body\">\n                    <div id=\"plotDirList\" class=\"list-group\"></div>\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <!-- plot files -->\n    <div class=\"col-md-9\">\n        <div class=\"card mb-12\" id=\"plotFileDiv\">\n            <h4 class=\"card-header text-white bg-primary\">Plot file and directories</h4>\n            <div class=\"card-body\">\n                Please select a plot directory, to get a list of plots and relevent information\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "resources/public/settings.html",
    "content": "<div class=\"row bs-component\">\n    <div class=\"col-md-6\">\n        <div class=\"card mb-12\">\n            <h4 class=\"card-header bg-success text-white\">Mining / Processing</h4>\n            <div class=\"card-body\">\n            <div class=\"row\">\n                <div class=\"col-lg-12\">\n                    <form method=\"POST\" action=\"/settings/urls\">\n                        <div class=\"form-group row\">\n                            <label for=\"mining-info-url\" class=\"col-md-12 col-lg-3 col-form-label\">Mining-Info-URL</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"url\" id=\"mining-info-url\" name=\"mining-info-url\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"submission-url\" class=\"col-md-12 col-lg-3 col-form-label\">Submission-URL</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"url\" id=\"submission-url\" name=\"submission-url\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"wallet-url\" class=\"col-md-12 col-lg-3 col-form-label\">Wallet-URL</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"text\" id=\"wallet-url\" name=\"wallet-url\">\n                            </div>\n                        </div>\n                        <button type=\"submit\" class=\"btn btn-primary float-right\">Submit</button>\n                    </form>\n                </div>\n                <div class=\"col-lg-12\">\n                    <form method=\"POST\" action=\"/settings/mining\">\n                        <h4 class=\"row\"></h4>\n                        <div class=\"form-group row\">\n                            <label for=\"intensity\" class=\"col-md-12 col-lg-3 col-form-label\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"The mining intensity sets the amount of verifier threads that verify plot files.\">Intensity</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"number\" id=\"intensity\" name=\"intensity\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"plot-readers\" class=\"col-md-12 col-lg-3 col-form-label\" data-toggle=\"tooltip\" data-placement=\"top\"  title=\"This value sets the amount of asynchronous plot readers. Every plot reader reads a list of plot files inside a plot directory (or device). If this value is 0 (default), as many plot readers will be created as plot devices exist.\">Plot reader</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"number\" id=\"plot-readers\" name=\"plot-readers\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"buffer-size\" class=\"col-md-12 col-lg-3 col-form-label\" data-toggle=\"tooltip\" data-placement=\"top\"  title=\"This is the maximal global amount of RAM used during the mining process.\">Buffer size (MB)</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"number\" id=\"buffer-size\" name=\"buffer-size\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"buffer-size\" class=\"col-md-12 col-lg-3 col-form-label\" data-toggle=\"tooltip\" data-placement=\"top\"  title=\"The number of chunks that the buffer is split into. Every chunk is only used by one memory unit (plot data).\">Buffer chunks</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"number\" id=\"buffer-chunks\" name=\"buffer-chunks\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"submit-probability\" class=\"col-md-12 col-lg-3 col-form-label\" data-toggle=\"tooltip\" data-placement=\"top\"  title=\"This value determines your target deadline of each round such that you submit with a certain probability. E.g. a submit probability of 0.7 causes you to submit in 70% of rounds.\">Submit probability</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"text\" id=\"submit-probability\"  name=\"submit-probability\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"target-deadline\" class=\"col-md-12 col-lg-3 col-form-label\" data-toggle=\"tooltip\" data-placement=\"top\"  title=\"Fixed target deadline that is only used if submit probability is set to 0.\">Target deadline</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"text\" id=\"target-deadline\" name=\"target-deadline\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"submission-max-retry\" class=\"col-md-12 col-lg-3 col-form-label\" data-toggle=\"tooltip\" data-placement=\"top\"  title=\"When the pool doesn't confirm a sent nonce in (timeout) seconds, the miner will retry to send it and wait for another confirmation. This setting determines the maximum number of times it will be retried.\">Submission max retry</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"number\" id=\"submission-max-retry\" name=\"submission-max-retry\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"timeout\" class=\"col-md-12 col-lg-3 col-form-label\" data-toggle=\"tooltip\" data-placement=\"top\"  title=\"Every communication with the server has a maximum waiting time of this many seconds.\">Timeout (seconds)</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"number\" id=\"timeout\" name=\"timeout\">\n                            </div>\n                        </div>\n                        <div class=\"form-group row\">\n                            <label for=\"max-historical-blocks\" class=\"col-md-12 col-lg-3 col-form-label\" data-toggle=\"tooltip\" data-placement=\"top\"  title=\"The number of blocks that are kept in memory to calculate the statistics and graphs on the blocks page.\">Max historical blocks</label>\n                            <div class=\"col-md-12 col-lg-9\">\n                                <input class=\"form-control\" type=\"number\" id=\"max-historical-blocks\" name=\"max-historical-blocks\">\n                            </div>\n                        </div>\n                        <button type=\"submit\" class=\"btn btn-primary float-right\">Submit</button>\n                    </form>\n                </div>\n            </div>\n            </div>\n        </div>\n    </div>\n    <div class=\"col-md-6\">\n        <div class=\"card mb-12\">\n            <h4 class=\"card-header bg-primary text-white\">\n            \tConsole\n\t            <small class=\"float-sm-right\" data-toggle=\"tooltip\" data-placement=\"bottom\" data-original-title=\"Restart creepMiner\">\n\t                <span onclick=\"restartMiner();\"><i class=\"fas fa-sync-alt\"></i></span>\n\t            </small>\n            </h4>\n            <div class=\"card-body\">\n                <form method=\"POST\" action=\"/settings/logging\">\n                    <div id=\"settingsDlComboboxes\"></div>\n                    <div class=\"form-group row\">\n                        <label for=\"log-dir\" class=\"col-md-12 col-lg-3 col-form-label\">Logfile directory</label>\n                        <div class=\"col-md-12 col-lg-9\">\n                            <input class=\"form-control\" type=\"text\" id=\"log-dir\" name=\"log-dir\">\n                        </div>\n                    </div>\n                    <button type=\"submit\" class=\"btn btn-primary float-right\">Submit</button>\n                </form>\n            </div>\n            <br />\n        </div>\n\t\t\t</div>\n</div>"
  },
  {
    "path": "resources/run.sh",
    "content": "#!/bin/sh\nLD_LIBRARY_PATH=$LD_LIBRARY_PATH:lib:/usr/local/lib:$(pwd):$(pwd)/../lib\nexport LD_LIBRARY_PATH\nexport LC_ALL=C\ncd \"$(dirname \"$0\")\"\n./creepMiner\n"
  },
  {
    "path": "resources/screen.sh",
    "content": "#!/bin/sh \ncd \"$(dirname \"$0\")\" \nscreen -dmS creep ./run.sh\n"
  },
  {
    "path": "resources/settingsui/App.xaml",
    "content": "﻿<Application x:Class=\"ConfigEditor.App\"\r\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n             StartupUri=\"MainWindow.xaml\">\r\n    <Application.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml\" />\r\n\t\t\t\t<ResourceDictionary Source=\"pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml\" />\r\n\t\t\t\t<ResourceDictionary Source=\"pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml\" />\r\n\t\t\t\t<ResourceDictionary Source=\"pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml\" />\r\n\t\t\t\t<ResourceDictionary Source=\"pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml\" />\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</Application.Resources>\r\n</Application>\r\n"
  },
  {
    "path": "resources/settingsui/App.xaml.cs",
    "content": "﻿using System.Windows;\r\n\r\nnamespace ConfigEditor\r\n{\r\n\t/// <summary>\r\n\t/// Interaction logic for App.xaml\r\n\t/// </summary>\r\n\tpublic partial class App : Application\r\n    {\r\n    }\r\n}\r\n"
  },
  {
    "path": "resources/settingsui/ConfigEditor.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <PropertyGroup>\r\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\r\n    <Platform Condition=\" '$(Platform)' == '' \">x86</Platform>\r\n    <ProductVersion>8.0.30703</ProductVersion>\r\n    <SchemaVersion>2.0</SchemaVersion>\r\n    <ProjectGuid>{DB3992B4-2E37-4B25-8C42-2E52832788AC}</ProjectGuid>\r\n    <OutputType>WinExe</OutputType>\r\n    <AppDesignerFolder>Properties</AppDesignerFolder>\r\n    <RootNamespace>ConfigEditor</RootNamespace>\r\n    <AssemblyName>ConfigEditor</AssemblyName>\r\n    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>\r\n    <TargetFrameworkProfile>\r\n    </TargetFrameworkProfile>\r\n    <FileAlignment>512</FileAlignment>\r\n    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\r\n    <WarningLevel>4</WarningLevel>\r\n    <PublishUrl>publish\\</PublishUrl>\r\n    <Install>true</Install>\r\n    <InstallFrom>Disk</InstallFrom>\r\n    <UpdateEnabled>false</UpdateEnabled>\r\n    <UpdateMode>Foreground</UpdateMode>\r\n    <UpdateInterval>7</UpdateInterval>\r\n    <UpdateIntervalUnits>Days</UpdateIntervalUnits>\r\n    <UpdatePeriodically>false</UpdatePeriodically>\r\n    <UpdateRequired>false</UpdateRequired>\r\n    <MapFileExtensions>true</MapFileExtensions>\r\n    <ApplicationRevision>0</ApplicationRevision>\r\n    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>\r\n    <IsWebBootstrapper>false</IsWebBootstrapper>\r\n    <UseApplicationTrust>false</UseApplicationTrust>\r\n    <BootstrapperEnabled>true</BootstrapperEnabled>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|x86' \">\r\n    <PlatformTarget>x86</PlatformTarget>\r\n    <DebugSymbols>true</DebugSymbols>\r\n    <DebugType>full</DebugType>\r\n    <Optimize>false</Optimize>\r\n    <OutputPath>bin\\Debug\\</OutputPath>\r\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\r\n    <ErrorReport>prompt</ErrorReport>\r\n    <WarningLevel>4</WarningLevel>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x86' \">\r\n    <PlatformTarget>x86</PlatformTarget>\r\n    <DebugType>pdbonly</DebugType>\r\n    <Optimize>true</Optimize>\r\n    <OutputPath>bin\\Release\\</OutputPath>\r\n    <DefineConstants>TRACE</DefineConstants>\r\n    <ErrorReport>prompt</ErrorReport>\r\n    <WarningLevel>4</WarningLevel>\r\n  </PropertyGroup>\r\n  <PropertyGroup>\r\n    <ApplicationIcon>favicon.ico</ApplicationIcon>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'\">\r\n    <PlatformTarget>AnyCPU</PlatformTarget>\r\n    <OutputPath>bin\\Debug\\</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Release|AnyCPU'\">\r\n    <PlatformTarget>AnyCPU</PlatformTarget>\r\n    <OutputPath>bin\\Release\\</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Reference Include=\"ControlzEx, Version=3.0.2.4, Culture=neutral, processorArchitecture=MSIL\">\r\n      <HintPath>..\\packages\\ControlzEx.3.0.2.4\\lib\\net40\\ControlzEx.dll</HintPath>\r\n    </Reference>\r\n    <Reference Include=\"MahApps.Metro, Version=1.6.1.4, Culture=neutral, processorArchitecture=MSIL\">\r\n      <HintPath>..\\packages\\MahApps.Metro.1.6.1\\lib\\net40\\MahApps.Metro.dll</HintPath>\r\n    </Reference>\r\n    <Reference Include=\"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL\">\r\n      <HintPath>..\\packages\\Newtonsoft.Json.11.0.1\\lib\\net40\\Newtonsoft.Json.dll</HintPath>\r\n    </Reference>\r\n    <Reference Include=\"System\" />\r\n    <Reference Include=\"System.Data\" />\r\n    <Reference Include=\"System.Net\" />\r\n    <Reference Include=\"System.Windows.Interactivity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL\">\r\n      <HintPath>..\\packages\\ControlzEx.3.0.2.4\\lib\\net40\\System.Windows.Interactivity.dll</HintPath>\r\n    </Reference>\r\n    <Reference Include=\"System.Xml\" />\r\n    <Reference Include=\"Microsoft.CSharp\" />\r\n    <Reference Include=\"System.Core\" />\r\n    <Reference Include=\"System.Xml.Linq\" />\r\n    <Reference Include=\"System.Data.DataSetExtensions\" />\r\n    <Reference Include=\"System.Xaml\">\r\n      <RequiredTargetFramework>4.0</RequiredTargetFramework>\r\n    </Reference>\r\n    <Reference Include=\"WindowsBase\" />\r\n    <Reference Include=\"PresentationCore\" />\r\n    <Reference Include=\"PresentationFramework\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ApplicationDefinition Include=\"App.xaml\">\r\n      <Generator>MSBuild:Compile</Generator>\r\n      <SubType>Designer</SubType>\r\n    </ApplicationDefinition>\r\n    <Compile Include=\"Models\\Base.cs\" />\r\n    <Page Include=\"MainWindow.xaml\">\r\n      <Generator>MSBuild:Compile</Generator>\r\n      <SubType>Designer</SubType>\r\n    </Page>\r\n    <Compile Include=\"App.xaml.cs\">\r\n      <DependentUpon>App.xaml</DependentUpon>\r\n      <SubType>Code</SubType>\r\n    </Compile>\r\n    <Compile Include=\"MainWindow.xaml.cs\">\r\n      <DependentUpon>MainWindow.xaml</DependentUpon>\r\n      <SubType>Code</SubType>\r\n    </Compile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"Properties\\AssemblyInfo.cs\">\r\n      <SubType>Code</SubType>\r\n    </Compile>\r\n    <Compile Include=\"Properties\\Resources.Designer.cs\">\r\n      <AutoGen>True</AutoGen>\r\n      <DesignTime>True</DesignTime>\r\n      <DependentUpon>Resources.resx</DependentUpon>\r\n    </Compile>\r\n    <Compile Include=\"Properties\\Settings.Designer.cs\">\r\n      <AutoGen>True</AutoGen>\r\n      <DependentUpon>Settings.settings</DependentUpon>\r\n      <DesignTimeSharedInput>True</DesignTimeSharedInput>\r\n    </Compile>\r\n    <EmbeddedResource Include=\"Properties\\Resources.resx\">\r\n      <Generator>ResXFileCodeGenerator</Generator>\r\n      <LastGenOutput>Resources.Designer.cs</LastGenOutput>\r\n    </EmbeddedResource>\r\n    <None Include=\"app.config\" />\r\n    <None Include=\"packages.config\" />\r\n    <None Include=\"Properties\\Settings.settings\">\r\n      <Generator>SettingsSingleFileGenerator</Generator>\r\n      <LastGenOutput>Settings.Designer.cs</LastGenOutput>\r\n    </None>\r\n    <AppDesigner Include=\"Properties\\\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Resource Include=\"favicon.ico\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <BootstrapperPackage Include=\"Microsoft.Net.Framework.3.5.SP1\">\r\n      <Visible>False</Visible>\r\n      <ProductName>.NET Framework 3.5 SP1</ProductName>\r\n      <Install>false</Install>\r\n    </BootstrapperPackage>\r\n  </ItemGroup>\r\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\r\n</Project>"
  },
  {
    "path": "resources/settingsui/MainWindow.xaml",
    "content": "﻿<Controls:MetroWindow x:Class=\"ConfigEditor.MainWindow\"\r\n                      xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n                      xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n                      xmlns:Controls=\"clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro\"\r\n\t\t\t\t\t\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\"\r\n\t\t\t\t\t\txmlns:Behaviours=\"clr-namespace:MahApps.Metro.Behaviours;assembly=MahApps.Metro\"\r\n                      Title=\"creepMiner settings\"\r\n                      Height=\"450\"\r\n                      Width=\"600\">\r\n\r\n\t<i:Interaction.Behaviors>\r\n\t\t<Behaviours:BorderlessWindowBehavior />\r\n\t</i:Interaction.Behaviors>\r\n\t\r\n\t<Grid>\r\n\t\t<TabControl>\r\n\t\t\t<!-- mining tab -->\r\n\t\t\t<TabItem Header=\"mining\">\r\n\t\t\t\t<Grid Margin=\"5,0,5,0\">\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"*\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"32\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t<!-- URI settings -->\r\n\t\t\t\t\t<GroupBox Grid.Row=\"0\">\r\n\t\t\t\t\t\t<GroupBox.Header>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"URL's\" />\r\n\t\t\t\t\t\t</GroupBox.Header>\r\n\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t<Label Width=\"50\" Content=\"Pool\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"miningInfo\" Width=\"175\" />\r\n\t\t\t\t\t\t\t<Label Width=\"5\" />\r\n\t\t\t\t\t\t\t<Label Width=\"50\" Content=\"Wallet\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"wallet\" Width=\"175\" />\r\n\t\t\t\t\t\t\t<!-- If solo mining enabled, use miner address for submission else always use pool-->\r\n\t\t\t\t\t\t\t<!--<Label Width=\"80\">Submission</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"submission\" Width=\"100\"></TextBox>-->\r\n\t\t\t\t\t\t\t<Label Width=\"5\" />\r\n\t\t\t\t\t\t\t<Label Width=\"80\" Content=\"Solo mining\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"20\" VerticalAlignment=\"Center\" Name=\"chPool\"/>\r\n\t\t\t\t\t\t\t<TextBox Name=\"submission\" Width=\"0\" />\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</GroupBox>\r\n\t\t\t\t\t<!-- Basic settings -->\r\n\t\t\t\t\t<GroupBox Grid.Row=\"1\" Margin=\"0,5,0,214\">\r\n\t\t\t\t\t\t<GroupBox.Header>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"Basic settings\" />\r\n\t\t\t\t\t\t</GroupBox.Header>\r\n\t\t\t\t\t\t<WrapPanel>\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"CPU/GPU\" />\r\n                            <ComboBox  Width=\"70\"  IsEditable=\"True\" Name=\"cbProcessorType\" ItemsSource=\"{Binding ProcessorType}\" DisplayMemberPath=\"Name\" />\r\n                            <Label Width=\"70\" Content=\"Instructions\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"79\" Name=\"cbCPU\" ItemsSource=\"{Binding Path=CPUInstSet}\" DisplayMemberPath=\"Name\" SelectedItem=\"{Binding Name, Mode=TwoWay}\" />\r\n\t\t\t\t\t\t\t<Label Width=\"100\" />\r\n\t\t\t\t\t\t\t<Label Width=\"75\" Content=\"GPU Device\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"gpuDevice\" Width=\"20\" />\r\n\t\t\t\t\t\t\t<Label Width=\"55\" Content=\"Platform\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"gpuPlatform\" Width=\"20\" />\r\n\t\t\t\t\t\t</WrapPanel>\r\n\t\t\t\t\t</GroupBox>\r\n\t\t\t\t\t<!-- Basic settings -->\r\n\t\t\t\t\t<GroupBox Grid.Row=\"1\" Margin=\"0,72,0,87\">\r\n\t\t\t\t\t\t<GroupBox.Header>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"Advanced settings\" />\r\n\t\t\t\t\t\t</GroupBox.Header>\r\n\t\t\t\t\t\t<WrapPanel>\r\n\t\t\t\t\t\t\t<Label Width=\"85\">Buffer Chunks</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"bufferChunkCount\" Width=\"40\" />\r\n\t\t\t\t\t\t\t<Label Width=\"70\">Intensity</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"intensity\" Width=\"30\" />\r\n\t\t\t\t\t\t\t<Label Width=\"70\"># Readers</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"maxPlotReaders\" Width=\"30\" />\r\n\t\t\t\t\t\t\t<Label Width=\"55\"># Retrys</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"submissionMaxRetry\" Width=\"30\" />\r\n\t\t\t\t\t\t\t<Label Width=\"80\">Info interval</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"getMiningInfoInterval\" Width=\"30\" />\r\n\t\t\t\t\t\t\t<Label Width=\"85\">Buffer size</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"maxBufferSizeMB\" Width=\"40\" />\r\n\t\t\t\t\t\t\t<Label Width=\"70\">HDD Wake</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"wakeUpTime\" Width=\"30\" />\r\n\t\t\t\t\t\t\t<Label Width=\"70\">Wallet retry</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"walletRequestTries\" Width=\"30\" /> \r\n\t\t\t\t\t\t\t<Label Width=\"55\">Time</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"walletRequestRetryWaitTime\" Width=\"30\" />\r\n\t\t\t\t\t\t\t<Label Width=\"80\">Probability</Label>\r\n\t\t\t\t\t\t\t<TextBox Name=\"submitProbability\" Width=\"30\" />\r\n\t\t\t\t\t\t\t<Label Width=\"85\" Content=\"Deadline\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"targetDeadline\" Width=\"140\" />\r\n\t\t\t\t\t\t</WrapPanel>\r\n\t\t\t\t\t</GroupBox>\r\n\t\t\t\t\t<!-- Basic settings -->\r\n\t\t\t\t\t<GroupBox Grid.Row=\"1\" Margin=\"0,199,0,19\">\r\n\t\t\t\t\t\t<GroupBox.Header>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"x settings\" />\r\n\t\t\t\t\t\t</GroupBox.Header>\r\n\t\t\t\t\t\t<WrapPanel>\r\n\t\t\t\t\t\t\t<Label Width=\"60\" Content=\"Timeout\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"timeout\" Width=\"30\" />\r\n\t\t\t\t\t\t\t<Label Width=\"60\" Content=\"Rescan\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"30\" VerticalAlignment=\"Center\" Name=\"chRescanEveryBlock\" />\r\n\t\t\t\t\t\t\t<Label Width=\"60\" Content=\"Insecure\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"30\" VerticalAlignment=\"Center\" Name=\"chUseInsecurePlotfiles\" />\r\n\t\t\t\t\t\t\t<Label Width=\"100\" />\r\n\t\t\t\t\t\t\t<Label Width=\"70\" Content=\"Benchmark\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"30\" VerticalAlignment=\"Center\" Name=\"chBenchmark\" />\r\n\t\t\t\t\t\t\t<Label Width=\"50\" Content=\"interval\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"interval\" Width=\"30\" />\r\n\t\t\t\t\t\t</WrapPanel>\r\n\t\t\t\t\t</GroupBox>\r\n\t\t\t\t</Grid>\r\n\t\t\t</TabItem>\r\n\t\t\t<!-- logging tab -->\r\n\t\t\t<TabItem Header=\"logging\">\r\n\t\t\t\t<Grid Margin=\"5,0,5,0\">\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"*\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"32\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t<!-- Basic settings -->\r\n\t\t\t\t\t<GroupBox Grid.Row=\"0\">\r\n\t\t\t\t\t\t<GroupBox.Header>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"Basic settings\" />\r\n\t\t\t\t\t\t</GroupBox.Header>\r\n\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t<Label Width=\"90\" Content=\"Progress bar\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"30\" VerticalAlignment=\"Center\" Name=\"chFancy\"/>\r\n\t\t\t\t\t\t\t<Label Width=\"90\" Content=\"Enable colors\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"30\" VerticalAlignment=\"Center\" Name=\"chuseColors\"/>\r\n\t\t\t\t\t\t\t<Label Width=\"110\" Content=\"Always at bottom\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"100\" VerticalAlignment=\"Center\" Name=\"chSteady\"/>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</GroupBox>\r\n\t\t\t\t\t<!-- Console settings -->\r\n\t\t\t\t\t<GroupBox Grid.Row=\"1\" Margin=\"0,5,0,134\">\r\n\t\t\t\t\t\t<GroupBox.Header>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"Console settings\" />\r\n\t\t\t\t\t\t</GroupBox.Header>\r\n\t\t\t\t\t\t<WrapPanel>\r\n\t\t\t\t\t\t\t<Label Width=\"70\" Content=\"Config\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"100\" ItemsSource=\"{Binding Path=LogConfig }\" DisplayMemberPath=\"Name\"  Name=\"cbConfig\" />\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"General\" />\r\n\t\t\t\t\t\t\t<ComboBox  Width=\"100\" ItemsSource=\"{Binding LogGeneral, Mode=OneWay}\" DisplayMemberPath=\"Name\" Name=\"cbGeneral\" />\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Miner\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"100\" ItemsSource=\"{Binding LogMiner, Mode=OneWay}\" DisplayMemberPath=\"Name\" Name=\"cbMiner\" />\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Submitter\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"100\" ItemsSource=\"{Binding LogNonceSubmitter, Mode=OneWay}\" DisplayMemberPath=\"Name\" Name=\"cbNonceSubmitter\" />\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Reader\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"100\" ItemsSource=\"{Binding LogPlotReader, Mode=OneWay}\" DisplayMemberPath=\"Name\" Name=\"cbPlotReader\" />\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Verifier\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"100\" ItemsSource=\"{Binding LogPlotVerifier, Mode=OneWay}\" DisplayMemberPath=\"Name\" Name=\"cbPlotVerifier\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Server\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"100\" ItemsSource=\"{Binding LogServer, Mode=OneWay}\" DisplayMemberPath=\"Name\" Name=\"cbServer\" />\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Sessions\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"100\" ItemsSource=\"{Binding LogSession, Mode=OneWay}\" DisplayMemberPath=\"Name\" Name=\"cbSession\" />\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Socket\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"100\" ItemsSource=\"{Binding LogSocket, Mode=OneWay}\" DisplayMemberPath=\"Name\" Name=\"cbSocket\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Wallet\" />\r\n\t\t\t\t\t\t\t<ComboBox Width=\"100\" ItemsSource=\"{Binding LogWallet, Mode=OneWay}\" DisplayMemberPath=\"Name\" Name=\"cbWallet\" />\r\n\t\t\t\t\t\t</WrapPanel>\r\n\t\t\t\t\t</GroupBox>\r\n\t\t\t\t\t<!-- Console settings -->\r\n\t\t\t\t\t<GroupBox Grid.Row=\"1\" Margin=\"0,152,0,64\">\r\n\t\t\t\t\t\t<GroupBox.Header>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"Log file\" />\r\n\t\t\t\t\t\t</GroupBox.Header>\r\n\t\t\t\t\t\t<WrapPanel>\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Enabled\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"30\" VerticalAlignment=\"Center\" Name=\"chLogfile\"/>\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Directory\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"txtFirst\" Width=\"300\"></TextBox>\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Button Content=\"Browse\" HorizontalAlignment=\"Center\" />\r\n\t\t\t\t\t\t</WrapPanel>\r\n\t\t\t\t\t</GroupBox>\r\n\t\t\t\t</Grid>\r\n\t\t\t</TabItem>\r\n\t\t\t<!-- webserver tab -->\r\n\t\t\t<TabItem Header=\"webserver\">\r\n\t\t\t\t<Grid Margin=\"5,0,5,0\">\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"*\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"32\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t<!-- Basic settings -->\r\n\t\t\t\t\t<GroupBox Grid.Row=\"0\">\r\n\t\t\t\t\t\t<GroupBox.Header>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"Basic settings\" />\r\n\t\t\t\t\t\t</GroupBox.Header>\r\n\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t<Label  Width=\"100\" Content=\"Enabled\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"20\" VerticalAlignment=\"Center\" Name=\"chStart\"/>\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"75\" Content=\"Listen\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"url\" Width=\"200\"></TextBox >\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Button Content=\"Credentials\" HorizontalAlignment=\"Center\" />\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</GroupBox>\r\n\t\t\t\t\t<!-- Advanced settings -->\r\n\t\t\t\t\t<GroupBox Grid.Row=\"1\" Margin=\"0,5,0,184\">\r\n\t\t\t\t\t\t<GroupBox.Header>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"Advanced settings\" />\r\n\t\t\t\t\t\t</GroupBox.Header>\r\n\t\t\t\t\t\t<WrapPanel>\r\n\t\t\t\t\t\t\t<Label  Width=\"100\" Content=\"Cumulate Plots\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"40\" VerticalAlignment=\"Center\" Name=\"chCumulatePlotsizes\"/>\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"100\" Content=\"Forward names\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"40\" VerticalAlignment=\"Center\" Name=\"chForwardMinerNames\"/>\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"100\" Content=\"All Deadlines\" />\r\n\t\t\t\t\t\t\t<CheckBox Width=\"40\" VerticalAlignment=\"Center\" Name=\"chCalculateEveryDeadile\"/>\r\n\t\t\t\t\t\t\t<Label Width=\"100\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"100\" Content=\"Max connections\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"activeConnections\" Width=\"40\"></TextBox>\r\n\t\t\t\t\t\t\t<Label  Width=\"40\"></Label>\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Username\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"user\" Width=\"100\">whumphrey</TextBox>\r\n\t\t\t\t\t\t\t<Label Width=\"10\" />\r\n\t\t\t\t\t\t\t<Label  Width=\"70\" Content=\"Password\" />\r\n\t\t\t\t\t\t\t<TextBox Name=\"pass\" Width=\"100\">*************</TextBox>\r\n\t\t\t\t\t\t</WrapPanel>\r\n\t\t\t\t\t</GroupBox>\r\n\t\t\t\t</Grid>\r\n\t\t\t</TabItem>\r\n\r\n\t\t</TabControl>\r\n\t\t<!--<Button Margin=\"4\" Padding=\"2\" Width=\"128\" HorizontalAlignment=\"Right\" Content=\"Save\"/>\r\n\t\t<Button Margin=\"4\" Padding=\"2\" HorizontalAlignment=\"Right\" Content=\"Close\"/>-->\r\n\t\t<Button Content=\"Save\" HorizontalAlignment=\"Left\" Margin=\"507,382,0,0\" VerticalAlignment=\"Top\" Width=\"75\" Click=\"Button_Click\" />\r\n\t</Grid>\r\n</Controls:MetroWindow>"
  },
  {
    "path": "resources/settingsui/MainWindow.xaml.cs",
    "content": "﻿using ConfigEditor.Models;\r\nusing Newtonsoft.Json;\r\nusing Newtonsoft.Json.Linq;\r\nusing System.Collections.ObjectModel;\r\nusing System.IO;\r\nusing System.Reflection;\r\nusing System.Windows;\r\nusing MahApps.Metro.Controls;\r\n\r\nnamespace ConfigEditor\r\n{\r\n\tpublic partial class MainWindow : MetroWindow\r\n\t/// <summary>\r\n\t/// Interaction logic for MainWindow.xaml\r\n\t/// </summary>\r\n    {\r\n        public ObservableCollection<Base> ProcessorType { get; set; }\r\n        public ObservableCollection<Base> LogConfig { get; set; }\r\n        public ObservableCollection<Base> LogGeneral { get; set; }\r\n        public ObservableCollection<Base> LogMiner { get; set; }\r\n        public ObservableCollection<Base> LogNonceSubmitter { get; set; }\r\n        public ObservableCollection<Base> LogPlotReader { get; set; }\r\n        public ObservableCollection<Base> LogPlotVerifier { get; set; }\r\n        public ObservableCollection<Base> LogServer { get; set; }\r\n        public ObservableCollection<Base> LogSession { get; set; }\r\n        public ObservableCollection<Base> LogSocket { get; set; }\r\n        public ObservableCollection<Base> LogWallet { get; set; }\r\n\r\n        public Base ProcessorTypeSelected { get; set; }\r\n\r\n        public ObservableCollection<Base> CPUInstSet { get; set; }\r\n        public Base CpuSelected { get; set; }\r\n\r\n        public JObject Config { get; set; }\r\n\r\n        public MainWindow()\r\n        {\r\n\t\t\tInitializeComponent();\r\n            string executableLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);\r\n            string path = Path.Combine(executableLocation, \"mining.conf\");\r\n            var json = File.ReadAllText(path);\r\n\r\n            Config = JsonConvert.DeserializeObject<JObject>(json);\r\n            ProcessorTypeSelected = new Base(\"CPU\");\r\n\r\n            miningInfo.Text = Config[\"mining\"][\"urls\"][\"miningInfo\"].ToString();\r\n\t\t\tsubmission.Text = Config[\"mining\"][\"urls\"][\"submission\"].ToString();\r\n\t\t\twallet.Text = Config[\"mining\"][\"urls\"][\"wallet\"].ToString();\r\n\r\n            if (submission.Text == wallet.Text)\r\n            {\r\n                chPool.IsChecked = true;\r\n            }\r\n\r\n\t\t\tbufferChunkCount.Text = Config[\"mining\"][\"bufferChunkCount\"].ToString();\r\n\t\t\tgetMiningInfoInterval.Text = Config[\"mining\"][\"getMiningInfoInterval\"].ToString();\r\n\t\t\tgpuDevice.Text = Config[\"mining\"][\"gpuDevice\"].ToString();\r\n\r\n\t\t\tgpuPlatform.Text = Config[\"mining\"][\"gpuPlatform\"].ToString();\r\n\t\t\tintensity.Text = Config[\"mining\"][\"intensity\"].ToString();\r\n\t\t\tmaxBufferSizeMB.Text = Config[\"mining\"][\"maxBufferSizeMB\"].ToString();\r\n\r\n\t\t\tmaxPlotReaders.Text = Config[\"mining\"][\"maxPlotReaders\"].ToString();\r\n\t\t\tsubmissionMaxRetry.Text = Config[\"mining\"][\"submissionMaxRetry\"].ToString();\r\n\t\t\tsubmitProbability.Text = Config[\"mining\"][\"submitProbability\"].ToString();\r\n\r\n\t\t\ttargetDeadline.Text = Config[\"mining\"][\"targetDeadline\"].ToString();\r\n\t\t\ttimeout.Text = Config[\"mining\"][\"timeout\"].ToString();\r\n\t\t\twakeUpTime.Text = Config[\"mining\"][\"wakeUpTime\"].ToString();\r\n\r\n\t\t\twalletRequestRetryWaitTime.Text = Config[\"mining\"][\"walletRequestRetryWaitTime\"].ToString();\r\n\t\t\twalletRequestTries.Text = Config[\"mining\"][\"walletRequestTries\"].ToString();\r\n\r\n\t\t\tchRescanEveryBlock.IsChecked = Config[\"mining\"][\"rescanEveryBlock\"].ToObject<bool>();\r\n\t\t\tchUseInsecurePlotfiles.IsChecked = Config[\"mining\"][\"useInsecurePlotfiles\"].ToObject<bool>();\r\n\r\n\t\t\tchBenchmark.IsChecked = Config[\"mining\"][\"benchmark\"][\"active\"].ToObject<bool>();\r\n\t\t\tinterval.Text = Config[\"mining\"][\"benchmark\"][\"interval\"].ToString();\r\n\r\n\t\t\tchStart.IsChecked = Config[\"webserver\"][\"start\"].ToObject<bool>();\r\n\t\t\tactiveConnections.Text = Config[\"webserver\"][\"activeConnections\"].ToString();\r\n\r\n\t\t\tchForwardMinerNames.IsChecked = Config[\"webserver\"][\"forwardMinerNames\"].ToObject<bool>();\r\n\t\t\tchCumulatePlotsizes.IsChecked = Config[\"webserver\"][\"cumulatePlotsizes\"].ToObject<bool>();\r\n\t\t\tchCalculateEveryDeadile.IsChecked = Config[\"webserver\"][\"calculateEveryDeadline\"].ToObject<bool>();\r\n\r\n\t\t\turl.Text = Config[\"webserver\"][\"url\"].ToString();\r\n\t\t\tuser.Text = Config[\"webserver\"][\"credentials\"][\"user\"].ToString();\r\n\t\t\tpass.Text = Config[\"webserver\"][\"credentials\"][\"pass\"].ToString();\r\n\r\n\t\t\tchLogfile.IsChecked = Config[\"logging\"][\"logfile\"].ToObject<bool>();\r\n\t\t\ttxtFirst.Text = Config[\"logging\"][\"path\"].ToString();\r\n\r\n\t\t\tchuseColors.IsChecked = Config[\"logging\"][\"useColors\"].ToObject<bool>();\r\n\t\t\tchFancy.IsChecked = Config[\"logging\"][\"progressBar\"][\"fancy\"].ToObject<bool>();\r\n\t\t\tchSteady.IsChecked = Config[\"logging\"][\"progressBar\"][\"steady\"].ToObject<bool>();\r\n\r\n\t\t\tthis.LogConfig = new ObservableCollection<Base>();\r\n            this.LogGeneral = new ObservableCollection<Base>();\r\n            this.LogMiner = new ObservableCollection<Base>();\r\n            this.LogNonceSubmitter = new ObservableCollection<Base>();\r\n            this.LogPlotReader = new ObservableCollection<Base>();\r\n            this.LogPlotVerifier = new ObservableCollection<Base>();\r\n            this.LogServer = new ObservableCollection<Base>();\r\n            this.LogSession = new ObservableCollection<Base>();\r\n            this.LogSocket = new ObservableCollection<Base>();\r\n            this.LogWallet = new ObservableCollection<Base>();\r\n            this.CPUInstSet = new ObservableCollection<Base>();\r\n            this.ProcessorType = new ObservableCollection<Base>();\r\n\r\n            this.LogConfig.Add(new Base(\"off\"));\r\n            this.LogConfig.Add(new Base(\"fatal\"));\r\n            this.LogConfig.Add(new Base(\"critical\"));\r\n            this.LogConfig.Add(new Base(\"error\"));\r\n            this.LogConfig.Add(new Base(\"warning\"));\r\n            this.LogConfig.Add(new Base(\"notice\"));\r\n            this.LogConfig.Add(new Base(\"information\"));\r\n            this.LogConfig.Add(new Base(\"debug\"));\r\n            this.LogConfig.Add(new Base(\"trace\"));\r\n            this.LogConfig.Add(new Base(\"all\"));\r\n\r\n            this.LogGeneral.Add(new Base(\"off\"));\r\n            this.LogGeneral.Add(new Base(\"fatal\"));\r\n            this.LogGeneral.Add(new Base(\"critical\"));\r\n            this.LogGeneral.Add(new Base(\"error\"));\r\n            this.LogGeneral.Add(new Base(\"warning\"));\r\n            this.LogGeneral.Add(new Base(\"notice\"));\r\n            this.LogGeneral.Add(new Base(\"information\"));\r\n            this.LogGeneral.Add(new Base(\"debug\"));\r\n            this.LogGeneral.Add(new Base(\"trace\"));\r\n            this.LogGeneral.Add(new Base(\"all\"));\r\n\r\n            this.LogMiner.Add(new Base(\"off\"));\r\n            this.LogMiner.Add(new Base(\"fatal\"));\r\n            this.LogMiner.Add(new Base(\"critical\"));\r\n            this.LogMiner.Add(new Base(\"error\"));\r\n            this.LogMiner.Add(new Base(\"warning\"));\r\n            this.LogMiner.Add(new Base(\"notice\"));\r\n            this.LogMiner.Add(new Base(\"information\"));\r\n            this.LogMiner.Add(new Base(\"debug\"));\r\n            this.LogMiner.Add(new Base(\"trace\"));\r\n            this.LogMiner.Add(new Base(\"all\"));\r\n\r\n            this.LogNonceSubmitter.Add(new Base(\"off\"));\r\n            this.LogNonceSubmitter.Add(new Base(\"fatal\"));\r\n            this.LogNonceSubmitter.Add(new Base(\"critical\"));\r\n            this.LogNonceSubmitter.Add(new Base(\"error\"));\r\n            this.LogNonceSubmitter.Add(new Base(\"warning\"));\r\n            this.LogNonceSubmitter.Add(new Base(\"notice\"));\r\n            this.LogNonceSubmitter.Add(new Base(\"information\"));\r\n            this.LogNonceSubmitter.Add(new Base(\"debug\"));\r\n            this.LogNonceSubmitter.Add(new Base(\"trace\"));\r\n            this.LogNonceSubmitter.Add(new Base(\"all\"));\r\n\r\n            this.LogPlotReader.Add(new Base(\"off\"));\r\n            this.LogPlotReader.Add(new Base(\"fatal\"));\r\n            this.LogPlotReader.Add(new Base(\"critical\"));\r\n            this.LogPlotReader.Add(new Base(\"error\"));\r\n            this.LogPlotReader.Add(new Base(\"warning\"));\r\n            this.LogPlotReader.Add(new Base(\"notice\"));\r\n            this.LogPlotReader.Add(new Base(\"information\"));\r\n            this.LogPlotReader.Add(new Base(\"debug\"));\r\n            this.LogPlotReader.Add(new Base(\"trace\"));\r\n            this.LogPlotReader.Add(new Base(\"all\"));\r\n\r\n            this.LogPlotVerifier.Add(new Base(\"off\"));\r\n            this.LogPlotVerifier.Add(new Base(\"fatal\"));\r\n            this.LogPlotVerifier.Add(new Base(\"critical\"));\r\n            this.LogPlotVerifier.Add(new Base(\"error\"));\r\n            this.LogPlotVerifier.Add(new Base(\"warning\"));\r\n            this.LogPlotVerifier.Add(new Base(\"notice\"));\r\n            this.LogPlotVerifier.Add(new Base(\"information\"));\r\n            this.LogPlotVerifier.Add(new Base(\"debug\"));\r\n            this.LogPlotVerifier.Add(new Base(\"trace\"));\r\n            this.LogPlotVerifier.Add(new Base(\"all\"));\r\n\r\n            this.LogServer.Add(new Base(\"off\"));\r\n            this.LogServer.Add(new Base(\"fatal\"));\r\n            this.LogServer.Add(new Base(\"critical\"));\r\n            this.LogServer.Add(new Base(\"error\"));\r\n            this.LogServer.Add(new Base(\"warning\"));\r\n            this.LogServer.Add(new Base(\"notice\"));\r\n            this.LogServer.Add(new Base(\"information\"));\r\n            this.LogServer.Add(new Base(\"debug\"));\r\n            this.LogServer.Add(new Base(\"trace\"));\r\n            this.LogServer.Add(new Base(\"all\"));\r\n\r\n            this.LogSession.Add(new Base(\"off\"));\r\n            this.LogSession.Add(new Base(\"fatal\"));\r\n            this.LogSession.Add(new Base(\"critical\"));\r\n            this.LogSession.Add(new Base(\"error\"));\r\n            this.LogSession.Add(new Base(\"warning\"));\r\n            this.LogSession.Add(new Base(\"notice\"));\r\n            this.LogSession.Add(new Base(\"information\"));\r\n            this.LogSession.Add(new Base(\"debug\"));\r\n            this.LogSession.Add(new Base(\"trace\"));\r\n            this.LogSession.Add(new Base(\"all\"));\r\n\r\n            this.LogSocket.Add(new Base(\"off\"));\r\n            this.LogSocket.Add(new Base(\"fatal\"));\r\n            this.LogSocket.Add(new Base(\"critical\"));\r\n            this.LogSocket.Add(new Base(\"error\"));\r\n            this.LogSocket.Add(new Base(\"warning\"));\r\n            this.LogSocket.Add(new Base(\"notice\"));\r\n            this.LogSocket.Add(new Base(\"information\"));\r\n            this.LogSocket.Add(new Base(\"debug\"));\r\n            this.LogSocket.Add(new Base(\"trace\"));\r\n            this.LogSocket.Add(new Base(\"all\"));\r\n\r\n            this.LogWallet.Add(new Base(\"off\"));\r\n            this.LogWallet.Add(new Base(\"fatal\"));\r\n            this.LogWallet.Add(new Base(\"critical\"));\r\n            this.LogWallet.Add(new Base(\"error\"));\r\n            this.LogWallet.Add(new Base(\"warning\"));\r\n            this.LogWallet.Add(new Base(\"notice\"));\r\n            this.LogWallet.Add(new Base(\"information\"));\r\n            this.LogWallet.Add(new Base(\"debug\"));\r\n            this.LogWallet.Add(new Base(\"trace\"));\r\n            this.LogWallet.Add(new Base(\"all\"));\r\n\r\n            this.CPUInstSet.Add(new Base(\"AUTO\"));\r\n            this.CPUInstSet.Add(new Base(\"SSE2\"));\r\n            this.CPUInstSet.Add(new Base(\"SSE4\"));\r\n            this.CPUInstSet.Add(new Base(\"AVX\"));\r\n\t\t\tthis.CPUInstSet.Add(new Base(\"AVX2\"));\r\n\r\n            this.ProcessorType.Add(new Base(\"CPU\"));\r\n            this.ProcessorType.Add(new Base(\"CUDA\"));\r\n            this.ProcessorType.Add(new Base(\"OPENCL\"));\r\n\r\n            DataContext = this;\r\n        }\r\n\r\n        private void Button_Click(object sender, RoutedEventArgs ex)\r\n        {\r\n            this.Config[\"mining\"][\"urls\"][\"submission\"] = (chPool.IsChecked.HasValue && chPool.IsChecked.Value) ?  wallet.Text : miningInfo.Text;\r\n            this.Config[\"mining\"][\"urls\"][\"miningInfo\"] = miningInfo.Text;\r\n            this.Config[\"mining\"][\"urls\"][\"wallet\"] = wallet.Text;\r\n\r\n            this.Config[\"mining\"][\"bufferChunkCount\"] = bufferChunkCount.Text;\r\n\t\t\tthis.Config[\"mining\"][\"getMiningInfoInterval\"] = getMiningInfoInterval.Text;\r\n\t\t\tthis.Config[\"mining\"][\"gpuDevice\"] = gpuDevice.Text;\r\n\r\n\t\t\tthis.Config[\"mining\"][\"gpuPlatform\"] = gpuPlatform.Text;\r\n\t\t\tthis.Config[\"mining\"][\"intensity\"] = intensity.Text;\r\n\t\t\tthis.Config[\"mining\"][\"maxBufferSizeMB\"] = maxBufferSizeMB.Text;\r\n\r\n\t\t\tthis.Config[\"mining\"][\"maxPlotReaders\"] = maxPlotReaders.Text;\r\n\t\t\tthis.Config[\"mining\"][\"submissionMaxRetry\"] = submissionMaxRetry.Text;\r\n\t\t\tthis.Config[\"mining\"][\"submitProbability\"] = submitProbability.Text;\r\n\r\n\t\t\tthis.Config[\"mining\"][\"targetDeadline\"] = targetDeadline.Text;\r\n\t\t\tthis.Config[\"mining\"][\"timeout\"] = timeout.Text;\r\n\t\t\tthis.Config[\"mining\"][\"wakeUpTime\"] = wakeUpTime.Text;\r\n\r\n\t\t\tthis.Config[\"mining\"][\"walletRequestRetryWaitTime\"] = walletRequestRetryWaitTime.Text;\r\n\t\t\tthis.Config[\"mining\"][\"walletRequestTries\"] = walletRequestTries.Text;\r\n\r\n\t\t\tthis.Config[\"mining\"][\"rescanEveryBlock\"] = (chRescanEveryBlock.IsChecked.HasValue && chRescanEveryBlock.IsChecked.Value) ? \"true\" : \"false\";\r\n\t\t\tthis.Config[\"mining\"][\"useInsecurePlotfiles\"] = (chUseInsecurePlotfiles.IsChecked.HasValue && chUseInsecurePlotfiles.IsChecked.Value) ? \"true\" : \"false\";\r\n\r\n\t\t\tthis.Config[\"mining\"][\"benchmark\"][\"active\"] = (chBenchmark.IsChecked.HasValue && chBenchmark.IsChecked.Value) ? \"true\" : \"false\";\r\n\r\n\t\t\tthis.Config[\"webserver\"][\"start\"] = (chStart.IsChecked.HasValue && chStart.IsChecked.Value) ? \"true\" : \"false\";\r\n\t\t\tthis.Config[\"webserver\"][\"activeConnections\"] = activeConnections.Text;\r\n\r\n\t\t\tthis.Config[\"webserver\"][\"forwardMinerNames\"] = (chForwardMinerNames.IsChecked.HasValue && chForwardMinerNames.IsChecked.Value) ? \"true\" : \"false\";\r\n\t\t\tthis.Config[\"webserver\"][\"cumulatePlotsizes\"] = (chCumulatePlotsizes.IsChecked.HasValue && chCumulatePlotsizes.IsChecked.Value) ? \"true\" : \"false\";\r\n\t\t\tthis.Config[\"webserver\"][\"calculateEveryDeadline\"] = (chCalculateEveryDeadile.IsChecked.HasValue && chCalculateEveryDeadile.IsChecked.Value) ? \"true\" : \"false\";\r\n\r\n\t\t\tthis.Config[\"webserver\"][\"url\"] = url.Text;\r\n\t\t\tthis.Config[\"webserver\"][\"credentials\"][\"pass\"] = pass.Text;\r\n\t\t\tthis.Config[\"webserver\"][\"credentials\"][\"user\"] = user.Text;\r\n\r\n\t\t\tthis.Config[\"logging\"][\"logfile\"] = (chLogfile.IsChecked.HasValue && chLogfile.IsChecked.Value) ? \"true\" : \"false\";\r\n\t\t\tthis.Config[\"logging\"][\"path\"] = txtFirst.Text;\r\n\r\n\t\t\tthis.Config[\"logging\"][\"useColors\"] = (chuseColors.IsChecked.HasValue && chuseColors.IsChecked.Value) ? \"true\" : \"false\";\r\n\t\t\tthis.Config[\"logging\"][\"progressBar\"][\"fancy\"] = (chFancy.IsChecked.HasValue && chFancy.IsChecked.Value) ? \"true\" : \"false\";\r\n\t\t\tthis.Config[\"logging\"][\"progressBar\"][\"steady\"] = (chSteady.IsChecked.HasValue && chSteady.IsChecked.Value) ? \"true\" : \"false\";\r\n\r\n            this.Config[\"logging\"][\"config\"] = cbConfig.Text;\r\n            this.Config[\"logging\"][\"general\"] = cbGeneral.Text;\r\n            this.Config[\"logging\"][\"miner\"] = cbGeneral.Text;\r\n\r\n            string executableLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);\r\n            string path = Path.Combine(executableLocation, \"mining.conf\");\r\n\r\n\t\t\tvar Settings = new JsonSerializerSettings() { Formatting = Formatting.Indented };\r\n\t\t\tFile.WriteAllText(path, JsonConvert.SerializeObject(Config, Settings));\r\n            ;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "resources/settingsui/Models/Base.cs",
    "content": "﻿using System.ComponentModel;\r\n\r\nnamespace ConfigEditor.Models\r\n{\r\n\tpublic class Base\r\n    {\r\n        private string name;\r\n\r\n\r\n        public string Name\r\n        {\r\n            get { return name; }\r\n            set\r\n            {\r\n                if (name != value)\r\n                {\r\n                    name = value;\r\n                }\r\n            }\r\n        }\r\n\r\n        public Base(string name)\r\n        {\r\n            this.Name = name;\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "resources/settingsui/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\r\nusing System.Runtime.InteropServices;\r\nusing System.Windows;\r\n\r\n[assembly: AssemblyTitle(\"ConfigEditor\")]\r\n[assembly: AssemblyDescription(\"\")]\r\n[assembly: AssemblyConfiguration(\"\")]\r\n[assembly: AssemblyCompany(\"cmTeam\")]\r\n[assembly: AssemblyProduct(\"ConfigEditor\")]\r\n[assembly: AssemblyCopyright(\"Copyright © cm 2018\")]\r\n[assembly: AssemblyTrademark(\"\")]\r\n[assembly: AssemblyCulture(\"\")]\r\n[assembly: ComVisible(false)]\r\n[assembly: ThemeInfo(\r\n\tResourceDictionaryLocation.None,\r\n\tResourceDictionaryLocation.SourceAssembly \r\n)]\r\n[assembly: AssemblyVersion(\"1.0.0.0\")]\r\n[assembly: AssemblyFileVersion(\"1.0.0.0\")]"
  },
  {
    "path": "resources/settingsui/Properties/Resources.Designer.cs",
    "content": "﻿namespace ConfigEditor.Properties {    \r\n    \r\n    /// <summary>\r\n    ///   A strongly-typed resource class, for looking up localized strings, etc.\r\n    /// </summary>\r\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"15.0.0.0\")]\r\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\r\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\r\n    internal class Resources {\r\n        \r\n        private static global::System.Resources.ResourceManager resourceMan;\r\n        \r\n        private static global::System.Globalization.CultureInfo resourceCulture;\r\n        \r\n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\r\n        internal Resources() {\r\n        }\r\n        \r\n        /// <summary>\r\n        ///   Returns the cached ResourceManager instance used by this class.\r\n        /// </summary>\r\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\r\n        internal static global::System.Resources.ResourceManager ResourceManager {\r\n            get {\r\n                if (object.ReferenceEquals(resourceMan, null)) {\r\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"ConfigEditor.Properties.Resources\", typeof(Resources).Assembly);\r\n                    resourceMan = temp;\r\n                }\r\n                return resourceMan;\r\n            }\r\n        }\r\n        \r\n        /// <summary>\r\n        ///   Overrides the current thread's CurrentUICulture property for all\r\n        ///   resource lookups using this strongly typed resource class.\r\n        /// </summary>\r\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\r\n        internal static global::System.Globalization.CultureInfo Culture {\r\n            get {\r\n                return resourceCulture;\r\n            }\r\n            set {\r\n                resourceCulture = value;\r\n            }\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "resources/settingsui/Properties/Resources.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<root>\r\n  <!-- \r\n    Microsoft ResX Schema \r\n    \r\n    Version 2.0\r\n    \r\n    The primary goals of this format is to allow a simple XML format \r\n    that is mostly human readable. The generation and parsing of the \r\n    various data types are done through the TypeConverter classes \r\n    associated with the data types.\r\n    \r\n    Example:\r\n    \r\n    ... ado.net/XML headers & schema ...\r\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\r\n    <resheader name=\"version\">2.0</resheader>\r\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\r\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\r\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\r\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\r\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\r\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\r\n    </data>\r\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\r\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\r\n        <comment>This is a comment</comment>\r\n    </data>\r\n                \r\n    There are any number of \"resheader\" rows that contain simple \r\n    name/value pairs.\r\n    \r\n    Each data row contains a name, and value. The row also contains a \r\n    type or mimetype. Type corresponds to a .NET class that support \r\n    text/value conversion through the TypeConverter architecture. \r\n    Classes that don't support this are serialized and stored with the \r\n    mimetype set.\r\n    \r\n    The mimetype is used for serialized objects, and tells the \r\n    ResXResourceReader how to depersist the object. This is currently not \r\n    extensible. For a given mimetype the value must be set accordingly:\r\n    \r\n    Note - application/x-microsoft.net.object.binary.base64 is the format \r\n    that the ResXResourceWriter will generate, however the reader can \r\n    read any of the formats listed below.\r\n    \r\n    mimetype: application/x-microsoft.net.object.binary.base64\r\n    value   : The object must be serialized with \r\n            : System.Serialization.Formatters.Binary.BinaryFormatter\r\n            : and then encoded with base64 encoding.\r\n    \r\n    mimetype: application/x-microsoft.net.object.soap.base64\r\n    value   : The object must be serialized with \r\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\r\n            : and then encoded with base64 encoding.\r\n\r\n    mimetype: application/x-microsoft.net.object.bytearray.base64\r\n    value   : The object must be serialized into a byte array \r\n            : using a System.ComponentModel.TypeConverter\r\n            : and then encoded with base64 encoding.\r\n    -->\r\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\r\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\r\n      <xsd:complexType>\r\n        <xsd:choice maxOccurs=\"unbounded\">\r\n          <xsd:element name=\"metadata\">\r\n            <xsd:complexType>\r\n              <xsd:sequence>\r\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\r\n              </xsd:sequence>\r\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\r\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\r\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\r\n            </xsd:complexType>\r\n          </xsd:element>\r\n          <xsd:element name=\"assembly\">\r\n            <xsd:complexType>\r\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\r\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\r\n            </xsd:complexType>\r\n          </xsd:element>\r\n          <xsd:element name=\"data\">\r\n            <xsd:complexType>\r\n              <xsd:sequence>\r\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\r\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\r\n              </xsd:sequence>\r\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\r\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\r\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\r\n            </xsd:complexType>\r\n          </xsd:element>\r\n          <xsd:element name=\"resheader\">\r\n            <xsd:complexType>\r\n              <xsd:sequence>\r\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\r\n              </xsd:sequence>\r\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\r\n            </xsd:complexType>\r\n          </xsd:element>\r\n        </xsd:choice>\r\n      </xsd:complexType>\r\n    </xsd:element>\r\n  </xsd:schema>\r\n  <resheader name=\"resmimetype\">\r\n    <value>text/microsoft-resx</value>\r\n  </resheader>\r\n  <resheader name=\"version\">\r\n    <value>2.0</value>\r\n  </resheader>\r\n  <resheader name=\"reader\">\r\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r\n  </resheader>\r\n  <resheader name=\"writer\">\r\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r\n  </resheader>\r\n</root>"
  },
  {
    "path": "resources/settingsui/Properties/Settings.Designer.cs",
    "content": "﻿namespace ConfigEditor.Properties {\r\n    \r\n    \r\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\r\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator\", \"15.6.0.0\")]\r\n    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {\r\n        \r\n        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));\r\n        \r\n        public static Settings Default {\r\n            get {\r\n                return defaultInstance;\r\n            }\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "resources/settingsui/Properties/Settings.settings",
    "content": "﻿<?xml version='1.0' encoding='utf-8'?>\r\n<SettingsFile xmlns=\"uri:settings\" CurrentProfile=\"(Default)\">\r\n  <Profiles>\r\n    <Profile Name=\"(Default)\" />\r\n  </Profiles>\r\n  <Settings />\r\n</SettingsFile>"
  },
  {
    "path": "resources/settingsui/app.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<configuration>\r\n<startup><supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.0\"/></startup></configuration>\r\n"
  },
  {
    "path": "resources/settingsui/packages.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<packages>\r\n  <package id=\"ControlzEx\" version=\"3.0.2.4\" targetFramework=\"net40\" />\r\n  <package id=\"MahApps.Metro\" version=\"1.6.1\" targetFramework=\"net40\" />\r\n  <package id=\"Newtonsoft.Json\" version=\"11.0.1\" targetFramework=\"net40\" />\r\n</packages>"
  },
  {
    "path": "src/Declarations.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"Declarations.hpp\"\n#include <string>\n#include <Poco/String.h>\n#include <Poco/StringTokenizer.h>\n#include <Poco/NumberParser.h>\n#include \"logging/MinerLogger.hpp\"\n#include \"webserver/RequestHandler.hpp\"\n\nstd::string Burst::Settings::cpuInstructionSet;\nBurst::ProjectData Burst::Settings::project(\"creepMiner\",\n\tBurst::Version(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION));\n\n#ifdef USE_SSE4\nconst bool Burst::Settings::sse4 = true;\n#else\nconst bool Burst::Settings::sse4 = false;\n#endif\n\n#ifdef USE_AVX\nconst bool Burst::Settings::avx = true;\n#else\nconst bool Burst::Settings::avx = false;\n#endif\n\n#ifdef USE_AVX2\nconst bool Burst::Settings::avx2 = true;\n#else\nconst bool Burst::Settings::avx2 = false;\n#endif\n\n#ifdef USE_CUDA\nconst bool Burst::Settings::cuda = true;\n#else\nconst bool Burst::Settings::cuda = false;\n#endif\n\n#ifdef USE_OPENCL\nconst bool Burst::Settings::openCl = true;\n#else\nconst bool Burst::Settings::openCl = false;\n#endif\n\nvoid Burst::Version::updateLiterals()\n{\n\tliteral = std::to_string(major) + \".\" + std::to_string(minor) + \".\" + std::to_string(build);\n\tliteralVerbose = literal + \".\" + std::to_string(revision);\n}\n\nBurst::Version::Version(uint32_t major, uint32_t minor, uint32_t build, uint32_t revision)\n\t: major{major}, minor{minor}, build{build}, revision{revision}\n{\n\tupdateLiterals();\n}\n\nBurst::Version::Version(std::string version)\n{\n\t// trim left and right spaces\n\tPoco::trimInPlace(version);\n\n\t// remove all spaces inside\n\tPoco::replaceInPlace(version, \" \", \"\");\n\n\tPoco::StringTokenizer tokenizer{ version, \".\" };\n\n\t// need major.minor.build (3 to 4 parts, concatenated by a dot)\n\tif (tokenizer.count() >= 3)\n\t{\n\t\ttry\n\t\t{\n\t\t\tconst auto& majorStr = tokenizer[0];\n\t\t\tconst auto& minorStr = tokenizer[1];\n\t\t\tconst auto& buildStr = tokenizer[2];\n\n\t\t\tmajor = Poco::NumberParser::parseUnsigned(majorStr);\n\t\t\tminor = Poco::NumberParser::parseUnsigned(minorStr);\n\t\t\tbuild = Poco::NumberParser::parseUnsigned(buildStr);\n\n\t\t\tif (tokenizer.count() == 4)\n\t\t\t{\n\t\t\t\tconst auto& revisionStr = tokenizer[3];\n\t\t\t\trevision = Poco::NumberParser::parseUnsigned(revisionStr);\n\t\t\t}\n\t\t\telse\n\t\t\t\trevision = 0;\n\n\t\t\tupdateLiterals();\n\t\t}\n\t\tcatch (Poco::Exception& exc)\n\t\t{\n\t\t\tmajor = 0;\n\t\t\tminor = 0;\n\t\t\tbuild = 0;\n\t\t\trevision = 0;\n\t\t\tliteral = \"\";\n\n\t\t\tlog_error(MinerLogger::general, \"Could not parse version from string! (%s)\", version);\n\t\t\tlog_exception(MinerLogger::general, exc);\n\t\t}\n\t}\n}\n\nbool Burst::Version::operator>(const Version& rhs) const\n{\n\t// <this> vs <other>\n\t//\n\t// >2<.0.0 vs >1<.5.0\n\tif (major > rhs.major)\n\t\treturn true;\n\n\t// >1<.5.0 vs >2<.0.0\n\tif (major < rhs.major)\n\t\treturn false;\n\n\t// 1.>5<.0 vs 1.>4<.0\n\tif (minor > rhs.minor)\n\t\treturn true;\n\n\t// 1.>4<.0 vs 1.>5<.0\n\tif (minor < rhs.minor)\n\t\treturn false;\n\n\t// 1.5.>6< vs 1.5.>4<\n\tif (build > rhs.build)\n\t\treturn true;\n\n\t// 1.5.>4< vs 1.5.>6<\n\tif (build < rhs.build)\n\t\treturn false;\n\n\t// 1.5.6.>6< vs 1.5.6.>1<\n\tif (revision > rhs.revision)\n\t\treturn true;\n\n\t// 1.5.6.>1< vs 1.5.6.>6<\n\treturn false;\n}\n\nbool Burst::Version::operator==(const Version& rhs) const\n{\n\treturn major == rhs.major &&\n\t\tminor == rhs.minor &&\n\t\tbuild == rhs.build &&\n\t\trevision == rhs.revision;\n}\n\nbool Burst::Version::operator!=(const Version& rhs) const\n{\n\treturn !(*this == rhs);\n}\n\nvoid Burst::ProjectData::refreshNameAndVersion()\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tnameAndVersion = this->name + \" \" + this->version_.literal;\n\tnameAndVersionVerbose = this->name + \" \" +\n\t\t(this->version_.revision > 0 ? this->version_.literalVerbose : this->version_.literal) + \" \" +\n\t\tSettings::osFamily + \" \" + Settings::arch;\n\n\tif (!Settings::cpuInstructionSet.empty())\n\t\tnameAndVersionVerbose += std::string(\" \") + Settings::cpuInstructionSet;\n}\n\nvoid Burst::ProjectData::refreshAndCheckOnlineVersion(Poco::Timer& timer)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tconst std::string host = \"https://github.com/Creepsky/creepMiner\";\n\tonlineVersion_ = Burst::RequestHandler::fetchOnlineVersion();\n\tif (onlineVersion_ > version_)\n\t\tlog_system(MinerLogger::general, \"There is a new version (%s) on\\n\\t%s\", onlineVersion_.literal, host);\n}\n\nstd::string Burst::ProjectData::getOnlineVersion() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn onlineVersion_.literal;\n}\n\nconst Burst::Version& Burst::ProjectData::getVersion() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn version_;\n}\n\nBurst::ProjectData::ProjectData(std::string&& name, Version version)\n\t: name{std::move(name)}, version_{std::move(version)}, onlineVersion_{ std::move(version) }\n{\n\trefreshNameAndVersion();\n}\n\nvoid Burst::Settings::setCpuInstructionSet(std::string cpuInstructionSet)\n{\n\tcpuInstructionSet = std::move(cpuInstructionSet);\n\tproject.refreshNameAndVersion();\n}\n"
  },
  {
    "path": "src/Declarations.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <cstdint>\n#include <array>\n#include <string>\n#include <Poco/Platform.h>\n#include <Poco/Types.h>\n#include <Poco/Timer.h>\n\nnamespace Burst\n{\n\tclass MinerShabal;\n\tclass Miner;\n\tclass MinerLogger;\n\tclass MinerConfig;\n\tclass MinerProtocol;\n\tclass PlotReader;\n\n\tstruct Version\n\t{\n\t\tVersion(uint32_t major, uint32_t minor, uint32_t build, uint32_t revision);\n\t\tVersion(std::string version);\n\n\t\tbool operator>(const Version& rhs) const;\n\t\tbool operator==(const Version& rhs) const;\n\t\tbool operator!=(const Version& rhs) const;\n\n\t\tuint32_t major, minor, build, revision;\n\t\tstd::string literal, literalVerbose;\n\n\tprivate:\n\t\tvoid updateLiterals();\n\t};\n\n\tstruct ProjectData\n\t{\n\t\tProjectData(std::string&& name, Version version);\n\t\tvoid refreshNameAndVersion();\n\t\tvoid refreshAndCheckOnlineVersion(Poco::Timer& timer);\n\t\tstd::string getOnlineVersion() const;\n\t\tconst Version& getVersion() const;\n\t\tstd::string name;\n\t\tstd::string nameAndVersion;\n\t\tstd::string nameAndVersionVerbose;\n\tprivate:\n\t\tVersion version_;\n\t\tVersion onlineVersion_;\n\t\tmutable Poco::Mutex mutex_;\n\t};\n\n\tnamespace Settings\n\t{\n\t\t// 32 bytes, half of scoop\n\t\tconstexpr size_t hashSize = 32;\n\t\t// there are 4096 scoops inside a plot (nonce)\n\t\tconstexpr size_t scoopPerPlot = 4096;\n\t\t// every scoop consists of 2 hashes\n\t\tconstexpr size_t hashPerScoop = 2;\n\t\t// 64 bytes, whole scoop, two hashes\n\t\tconstexpr size_t scoopSize = hashSize * hashPerScoop;\n\t\t// 262144 bytes, a nonce, 4096 scoops\n\t\tconstexpr size_t plotSize = scoopSize * scoopPerPlot;\n\t\t// 96 bytes, a scoop and the gensig\n\t\tconstexpr size_t plotScoopSize = scoopSize + hashSize;\n\n#if defined POCO_OS_FAMILY_BSD\n\t\tstatic constexpr auto osFamily = \"BSD\";\n#elif defined POCO_OS_FAMILY_UNIX\n\t\tstatic constexpr auto osFamily = \"Unix\";\n#elif defined POCO_OS_FAMILY_WINDOWS\n\t\tstatic constexpr auto osFamily = \"Windows\";\n#else\n\t\tstatic constexpr auto osFamily = \"\";\n#endif\n\n#if POCO_ARCH == POCO_ARCH_IA64 || POCO_ARCH == POCO_ARCH_AMD64 || POCO_ARCH == POCO_ARCH_AARCH64\n\t\tstatic constexpr auto arch = \"x64\";\n#else\n\t\tstatic constexpr auto arch = \"x32\";\n#endif\n\n\t\textern std::string cpuInstructionSet;\n\t\textern ProjectData project;\n\n\t\textern const bool sse4, avx, avx2, cuda, openCl;\n\n\t\tvoid setCpuInstructionSet(std::string cpuInstructionSet);\n\t};\n\n\ttemplate <size_t Sz>\n\tusing BytesArray = std::array<uint8_t, Sz>;\n\tusing ScoopData = BytesArray<Settings::scoopSize>;\n\tusing GensigData = BytesArray<Settings::hashSize>;\n\tusing HashData = BytesArray<Settings::hashSize>;\n\n\tusing AccountId = Poco::UInt64;\n\tusing Nonce = Poco::UInt64;\n\n\tenum class LogOutputType\n\t{\n\t\tTerminal,\n\t\tService\n\t};\n}\n"
  },
  {
    "path": "src/MinerUtil.cpp",
    "content": "// ==========================================================================\r\n// \r\n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\r\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\r\n// \r\n// This program is free software; you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation; either version 3 of the License, or\r\n// (at your option) any later version.\r\n// \r\n// This program is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\r\n// GNU General Public License for more details.\r\n// \r\n// You should have received a copy of the GNU General Public License\r\n// along with this program; if not, write to the Free Software Foundation,\r\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\r\n// \r\n// ==========================================================================\r\n\r\n#include \"MinerUtil.hpp\"\r\n#include <sstream>\r\n#include <iomanip>\r\n#include <algorithm>\r\n#include \"Declarations.hpp\"\r\n#include \"logging/MinerLogger.hpp\"\r\n#include <Poco/URI.h>\r\n#include <Poco/Net/HTTPClientSession.h>\r\n#include \"mining/Deadline.hpp\"\r\n#include <Poco/JSON/Object.h>\r\n#include \"mining/MinerConfig.hpp\"\r\n#include \"mining/MinerData.hpp\"\r\n#include \"plots/PlotReader.hpp\"\r\n#include <Poco/JSON/Parser.h>\r\n#include <locale>\r\n#include <regex>\r\n#include <Poco/FileStream.h>\r\n#include <Poco/Crypto/CipherKey.h>\r\n#include <Poco/Crypto/Cipher.h>\r\n#include <Poco/Crypto/CipherFactory.h>\r\n#include <Poco/Random.h>\r\n#include <Poco/NestedDiagnosticContext.h>\r\n#include \"wallet/Account.hpp\"\r\n#include <Poco/HMACEngine.h>\r\n#include <Poco/SHA1Engine.h>\r\n#include <Poco/File.h>\r\n#include <fstream>\r\n#include \"plots/PlotSizes.hpp\"\r\n#include <chrono>\r\n#include <Poco/StreamCopier.h>\r\n#include <Poco/HexBinaryEncoder.h>\r\n#include <Poco/HexBinaryDecoder.h>\r\n#include <Poco/StringTokenizer.h>\r\n\r\n#if defined(_WIN32)\r\n#include <Windows.h>\r\n#include <conio.h>\r\n#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))\r\n#include <unistd.h>\r\n#include <sys/types.h>\r\n#include <sys/param.h>\r\n#include <termios.h>\r\n#if defined(BSD)\r\n#include <sys/sysctl.h>\r\n#endif\r\n#endif\r\n\r\n#define _FILE_OFFSET_BITS 64\r\n\r\n#if defined __APPLE__\r\n#define LSEEK64 lseek\r\n#elif defined __linux__\r\n#define LSEEK64 lseek64\r\n#endif\r\n\r\n// cpuinfo stuff (sse2, sse4, ...)\r\n#ifdef _WIN32\r\n//  Windows\r\n#define cpuid(info, x) __cpuidex(info, x, 0)\r\n#else\r\n#if defined __arm__ || defined __aarch64__\r\nvoid cpuid(int info[4], int InfoType)\r\n{}\r\n#else\r\n//  GCC Intrinsics\r\n#include <cpuid.h>\r\nvoid cpuid(int info[4], int InfoType)\r\n{\r\n\t__cpuid_count(InfoType, 0, info[0], info[1], info[2], info[3]);\r\n}\r\n#endif\r\n#endif\r\n\r\nbool Burst::isNumberStr(const std::string& str)\r\n{\r\n\treturn std::all_of(str.begin(), str.end(), ::isdigit);\r\n}\r\n\r\nstd::vector<std::string> Burst::splitStr(const std::string& s, char delim)\r\n{\r\n\tstd::vector<std::string> elems;\r\n\tsplitStr(s, delim, elems);\r\n\treturn elems;\r\n}\r\n\r\nstd::vector<std::string> Burst::splitStr(const std::string& s, const std::string& delim)\r\n{\r\n\tstd::vector<std::string> tokens;\r\n\tstd::string::size_type lastPos = 0;\r\n\tconst auto length = s.length();\r\n\r\n\tusing SizeType  = std::vector<std::string>::size_type;\r\n\r\n\twhile(lastPos < length + 1)\r\n\t{\r\n\t\tauto pos = s.find_first_of(delim, lastPos);\r\n\r\n\t\tif(pos == std::string::npos)\r\n\t\t\tpos = length;\r\n\r\n\t\tif(pos != lastPos)\r\n\t\t\ttokens.emplace_back(s.data() + lastPos,\r\n\t\t\tstatic_cast<SizeType>(pos-lastPos));\r\n\r\n\t\tlastPos = pos + 1;\r\n\t}\r\n\r\n\treturn tokens;\r\n}\r\n\r\nstd::vector<std::string>& Burst::splitStr(const std::string& s, char delim, std::vector<std::string>& elems)\r\n{\r\n\tstd::stringstream ss(s);\r\n\tstd::string item;\r\n\r\n\twhile (std::getline(ss, item, delim))\r\n\t\telems.push_back(item);\r\n\r\n\treturn elems;\r\n}\r\n\r\nBurst::PlotCheckResult Burst::isValidPlotFile(const std::string& filePath)\r\n{\r\n\ttry\r\n\t{\r\n\t\tPoco::Path path{filePath};\r\n\r\n\t\tif (!path.getExtension().empty())\r\n\t\t\treturn PlotCheckResult::InvalidParameter;\r\n\r\n\t\tconst auto fileName = path.getBaseName();\r\n\t\tconst auto accountIdStr = getAccountIdFromPlotFile(fileName);\r\n\t\tconst auto nonceStartStr = getStartNonceFromPlotFile(fileName);\r\n\t\tconst auto nonceCountStr = getNonceCountFromPlotFile(fileName);\r\n\t\tconst auto staggerStr = getStaggerSizeFromPlotFile(fileName);\r\n\r\n\t\tif (accountIdStr.empty() ||\r\n\t\t\tnonceStartStr.empty() ||\r\n\t\t\tnonceCountStr.empty())\r\n\t\t\treturn PlotCheckResult::EmptyParameter;\r\n\r\n\t\tconst volatile auto accountId = std::stoull(accountIdStr);\r\n\t\tstd::stoull(nonceStartStr);\r\n\t\tconst volatile auto nonceCount = std::stoull(nonceCountStr);\r\n\t\tPoco::UInt64 staggerSize = 0;\r\n\r\n\t\tif (!staggerStr.empty())\r\n\t\t\tstaggerSize = std::stoull(staggerStr);\r\n\r\n\t\t// values are 0\r\n\t\tif (accountId == 0 ||\r\n\t\t\tnonceCount == 0)\r\n\t\t\treturn PlotCheckResult::InvalidParameter;\r\n\r\n\t\tif (!staggerStr.empty() && staggerSize == 0)\r\n\t\t\treturn PlotCheckResult::InvalidParameter;\r\n\r\n\t\t// only do these checks if the user dont want to use insecure plotfiles (should be default)\r\n\t\tif (!MinerConfig::getConfig().useInsecurePlotfiles())\r\n\t\t{\r\n\t\t\t// stagger not multiplier of nonce count\r\n\t\t\tif (!staggerStr.empty() && nonceCount % staggerSize != 0)\r\n\t\t\t\treturn PlotCheckResult::WrongStaggersize;\r\n\r\n\t\t\tPoco::File file{filePath};\r\n\t\t\r\n\t\t\t// file is incomplete\r\n\t\t\tif (nonceCount * Settings::plotSize != file.getSize())\r\n\t\t\t\treturn PlotCheckResult::Incomplete;\r\n\r\n\t\t\tstd::ifstream alternativeFileData{filePath + \":stream\"};\r\n\r\n\t\t\tif (alternativeFileData)\r\n\t\t\t{\r\n\t\t\t\tstd::string content(std::istreambuf_iterator<char>(alternativeFileData), {});\r\n\t\t\t\talternativeFileData.close();\r\n\r\n\t\t\t\tconst auto noncesWrote = reinterpret_cast<const Poco::UInt64*>(content.data());\r\n\r\n\t\t\t\tif (*noncesWrote != nonceCount)\r\n\t\t\t\t\treturn PlotCheckResult::Incomplete;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn PlotCheckResult::Ok;\r\n\t}\r\n\tcatch (...)\r\n\t{\r\n\t\treturn PlotCheckResult::Error;\r\n\t}\r\n}\r\n\r\nstd::string Burst::getAccountIdFromPlotFile(const std::string& path)\r\n{\r\n\treturn getInformationFromPlotFile(path, 0);\r\n}\r\n\r\nstd::string Burst::getNonceCountFromPlotFile(const std::string& path)\r\n{\r\n\treturn getInformationFromPlotFile(path, 2);\r\n}\r\n\r\nstd::string Burst::getStaggerSizeFromPlotFile(const std::string& path)\r\n{\r\n\treturn getInformationFromPlotFile(path, 3);\r\n}\r\n\r\nstd::string Burst::getVersionFromPlotFile(const std::string& path)\r\n{\r\n\treturn getInformationFromPlotFile(path, 4);\r\n}\r\n\r\nstd::string Burst::getStartNonceFromPlotFile(const std::string& path)\r\n{\r\n\treturn getInformationFromPlotFile(path, 1);\r\n}\r\n\r\nstd::string Burst::deadlineFormat(Poco::UInt64 seconds)\r\n{\r\n\tconst auto secs = seconds;\r\n\tconst auto mins = secs / 60;\r\n\tconst auto hours = mins / 60;\r\n\tconst auto day = hours / 24;\r\n\tconst auto months = day / 30;\r\n\tconst auto years = months / 12;\r\n\t\r\n\tstd::stringstream ss;\r\n\t\r\n\tss.imbue(std::locale(\"\"));\r\n\tss << std::fixed;\r\n\t\r\n\tif (years > 0)\r\n\t\tss << years << \"y \";\r\n\tif (months > 0)\r\n\t\tss << months % 12 << \"m \";\r\n\tif (day > 0)\r\n\t\tss << day % 30 << \"d \";\r\n\r\n\tss << std::setw(2) << std::setfill('0');\r\n\tss << hours % 24 << ':';\r\n\tss << std::setw(2) << std::setfill('0');\r\n\tss << mins % 60 << ':';\r\n\tss << std::setw(2) << std::setfill('0');\r\n\tss << secs % 60;\r\n\r\n\treturn ss.str();\r\n}\r\n\r\nPoco::UInt64 Burst::deadlineFragment(Poco::UInt64 seconds, Burst::DeadlineFragment fragment)\r\n{\r\n\tconst auto secs = seconds;\r\n\tconst auto mins = secs / 60;\r\n\tconst auto hours = mins / 60;\r\n\tconst auto day = hours / 24;\r\n\tconst auto months = day / 30;\r\n\tconst auto years = months / 12;\r\n\r\n\tswitch (fragment)\r\n\t{\r\n\tcase DeadlineFragment::Years: return years;\r\n\tcase DeadlineFragment::Months: return months % 12;\r\n\tcase DeadlineFragment::Days: return day % 30;\r\n\tcase DeadlineFragment::Hours: return hours % 24;\r\n\tcase DeadlineFragment::Minutes: return mins % 60;\r\n\tcase DeadlineFragment::Seconds: return secs % 60;\r\n\tdefault: return 0;\r\n\t}\r\n}\r\n\r\nPoco::UInt64 Burst::formatDeadline(const std::string& format)\r\n{\r\n\tif (format.empty())\r\n\t\treturn 0;\r\n\r\n\tauto tokens = splitStr(format, ' ');\r\n\r\n\tif (tokens.empty())\r\n\t\treturn 0;\r\n\r\n\tPoco::UInt64 deadline = 0u;\r\n\tstd::locale loc;\r\n\r\n\tconst std::regex years(\"\\\\d*y\");\r\n\tconst std::regex months(\"\\\\d*m\");\r\n\tconst std::regex days(\"\\\\d*d\");\r\n\tconst std::regex hms(R\"(\\d\\d:\\d\\d:\\d\\d)\");\r\n\r\n\tconst auto extractFunction = [](const std::string& token, uint32_t conversion, uint32_t postfixSize = 1)\r\n\t{\r\n\t\treturn Poco::NumberParser::parseUnsigned64(token.substr(0, token.size() - postfixSize)) * conversion;\r\n\t};\r\n\r\n\tfor (auto& token : tokens)\r\n\t{\r\n\t\tif (regex_match(token, years))\r\n\t\t\tdeadline += extractFunction(token, 60 * 60 * 24 * 30 * 12);\r\n\t\telse if (regex_match(token, months))\r\n\t\t\tdeadline += extractFunction(token, 60 * 60 * 24 * 30);\r\n\t\telse if (regex_match(token, days))\r\n\t\t\tdeadline += extractFunction(token, 60 * 60 * 24);\r\n\t\telse if (regex_match(token, hms))\r\n\t\t{\r\n\t\t\tauto subTokens = splitStr(token, ':');\r\n\r\n\t\t\tdeadline += extractFunction(subTokens[0], 60 * 60, 0);\r\n\t\t\tdeadline += extractFunction(subTokens[1], 60, 0);\r\n\t\t\tdeadline += extractFunction(subTokens[2], 1, 0);\r\n\t\t}\r\n\t}\r\n\r\n\treturn deadline;\r\n}\r\n\r\nstd::string Burst::gbToString(Poco::UInt64 size)\r\n{\r\n\treturn memToString(size, MemoryUnit::Gigabyte, 2);\r\n}\r\n\r\nstd::string Burst::memToString(Poco::UInt64 size, MemoryUnit factor, Poco::UInt8 precision)\r\n{\t\r\n\tstd::stringstream ss;\r\n\tss << std::fixed << std::setprecision(precision);\r\n\tss << static_cast<double>(size) / static_cast<Poco::UInt64>(factor);\r\n\treturn ss.str();\r\n}\r\n\r\nstd::string Burst::memToString(Poco::UInt64 size, Poco::UInt8 precision)\r\n{\r\n\tif (size >= static_cast<Poco::UInt64>(MemoryUnit::Exabyte))\r\n\t\treturn memToString(size, MemoryUnit::Exabyte, precision) + \" EB\";\r\n\telse if (size >= static_cast<Poco::UInt64>(MemoryUnit::Petabyte))\r\n\t\treturn memToString(size, MemoryUnit::Petabyte, precision) + \" PB\";\r\n\telse if (size >= static_cast<Poco::UInt64>(MemoryUnit::Terabyte))\r\n\t\treturn memToString(size, MemoryUnit::Terabyte, precision) + \" TB\";\r\n\telse if (size >= static_cast<Poco::UInt64>(MemoryUnit::Gigabyte))\r\n\t\treturn memToString(size, MemoryUnit::Gigabyte, precision) + \" GB\";\r\n\telse\r\n\t\treturn memToString(size, MemoryUnit::Megabyte, precision) + \" MB\";\r\n}\r\n\r\nstd::string Burst::getInformationFromPlotFile(const std::string& path, Poco::UInt8 index)\r\n{\r\n\tauto filenamePos = path.find_last_of(\"/\\\\\");\r\n\r\n\tif (filenamePos == std::string::npos)\r\n\t\tfilenamePos = 0;\r\n\r\n\tauto fileNamePart = splitStr(path.substr(filenamePos + 1, path.length() - (filenamePos + 1)), '_');\r\n\r\n\tif (index >= fileNamePart.size())\r\n\t\treturn \"\";\r\n\r\n\treturn fileNamePart[index];\r\n}\r\n\r\nstd::string Burst::encrypt(const std::string& decrypted, const std::string& algorithm, std::string& key, std::string& salt, Poco::UInt32 iterations)\r\n{\r\n\tpoco_ndc(encryptAES256);\r\n\t\r\n\tif (decrypted.empty())\r\n\t\treturn \"\";\r\n\t\r\n\tif (iterations == 0)\r\n\t\treturn \"\";\r\n\r\n\ttry\r\n\t{\r\n\t\t// all valid chars for the salt\r\n\t\tstd::string validChars = \"abcdefghijklmnopqrstuvwxyz\";\r\n\t\tvalidChars += Poco::toUpper(validChars);\r\n\t\tvalidChars += \"0123456789\";\r\n\t\tvalidChars += \"()[]*/+-#'~?&$!\";\r\n\r\n\t\tconst auto createRandomCharSequence = [&validChars](size_t lenght)\r\n\t\t{\r\n\t\t\tstd::stringstream stream;\r\n\t\t\tPoco::Random random;\r\n\r\n\t\t\trandom.seed();\r\n\r\n\t\t\tfor (auto i = 0u; i < lenght; ++i)\r\n\t\t\t\tstream << validChars[random.next(static_cast<uint32_t>(validChars.size()))];\r\n\r\n\t\t\treturn stream.str();\r\n\t\t};\r\n\r\n\t\t// we create a 30 chars long key if the param key is empty\r\n\t\tif (key.empty())\r\n\t\t\tkey = createRandomCharSequence(30);\r\n\r\n\t\t// we create a 15 chars long salt if the param salt is empty\r\n\t\tif (salt.empty())\r\n\t\t\tsalt = createRandomCharSequence(15);\r\n\r\n\t\tconst Poco::Crypto::CipherKey cipherKey(algorithm, key, salt, iterations);\r\n\t\tauto& factory = Poco::Crypto::CipherFactory::defaultFactory();\r\n\t\tauto cipher = factory.createCipher(cipherKey);\r\n\t\t\r\n\t\treturn cipher->encryptString(decrypted, Poco::Crypto::Cipher::ENC_BINHEX_NO_LF);\r\n\t}\r\n\tcatch (Poco::Exception& exc)\r\n\t{\r\n\t\tlog_error(MinerLogger::general, \"Error encrypting the passphrase!\\n%s\", exc.displayText());\r\n\t\tlog_current_stackframe(MinerLogger::general);\r\n\r\n\t\treturn \"\";\r\n\t}\r\n}\r\n\r\nstd::string Burst::decrypt(const std::string& encrypted, const std::string& algorithm, const std::string& key, const std::string& salt, Poco::UInt32 iterations)\r\n{\r\n\tpoco_ndc(decryptAES256);\r\n\r\n\tif (iterations == 0)\r\n\t\treturn \"\";\r\n\r\n\ttry\r\n\t{\r\n\t\tconst Poco::Crypto::CipherKey cipherKey(algorithm, key, salt, iterations);\r\n\t\tauto& factory = Poco::Crypto::CipherFactory::defaultFactory();\r\n\t\tauto cipher = factory.createCipher(cipherKey);\r\n\t\treturn cipher->decryptString(encrypted, Poco::Crypto::Cipher::ENC_BINHEX_NO_LF);\r\n\t}\r\n\tcatch (Poco::Exception& exc)\r\n\t{\r\n\t\tlog_error(MinerLogger::general, \"Error decrypting the passphrase!\\n%s\", exc.displayText());\r\n\t\tlog_current_stackframe(MinerLogger::general);\r\n\r\n\t\treturn \"\";\r\n\t}\r\n}\r\n\r\nPoco::Timespan Burst::secondsToTimespan(const float seconds)\r\n{\r\n\tconst auto secondsInt = static_cast<long>(seconds);\r\n\tconst auto microSeconds = static_cast<long>((seconds - secondsInt) * 100000);\r\n\treturn Poco::Timespan{secondsInt, microSeconds};\r\n}\r\n\r\nstd::unique_ptr<Poco::Net::HTTPClientSession> Burst::createSession(const Poco::URI& uri)\r\n{\r\n\treturn nullptr;\r\n}\r\n\r\nPoco::Net::SocketAddress Burst::getHostAddress(const Poco::URI& uri)\r\n{\r\n\tPoco::Net::SocketAddress address{uri.getHost() + ':' + std::to_string(uri.getPort())};\r\n\treturn address;\r\n}\r\n\r\nstd::string Burst::serializeDeadline(const Deadline& deadline, const std::string& delimiter)\r\n{\r\n\treturn deadline.getAccountName() + delimiter +\r\n\t\tstd::to_string(deadline.getBlock()) + delimiter +\r\n\t\tstd::to_string(deadline.getDeadline()) + delimiter +\r\n\t\tstd::to_string(deadline.getNonce());\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonDeadline(const Deadline& deadline)\r\n{\r\n\tPoco::JSON::Object json;\r\n\tjson.set(\"nonce\", std::to_string(deadline.getNonce()));\r\n\tjson.set(\"deadline\", deadlineFormat(deadline.getDeadline()));\r\n\tjson.set(\"account\", deadline.getAccountName());\r\n\tjson.set(\"accountId\", std::to_string(deadline.getAccountId()));\r\n\tjson.set(\"plotfile\", deadline.getPlotFile());\r\n\tjson.set(\"deadlineNum\", std::to_string(deadline.getDeadline()));\r\n\tjson.set(\"blockheight\", std::to_string(deadline.getBlock()));\r\n\tjson.set(\"miner\", deadline.getMiner());\r\n\tjson.set(\"worker\", deadline.getWorker());\r\n\tjson.set(\"ip\", deadline.getIp().toString());\r\n\treturn json;\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonDeadline(const Deadline& deadline, const std::string& type)\r\n{\r\n\tauto json = createJsonDeadline(deadline);\r\n\tjson.set(\"type\", type);\r\n\tjson.set(\"time\", getTime());\r\n\treturn json;\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonNewBlock(const MinerData& data)\r\n{\r\n\tPoco::JSON::Object json;\r\n\tconst auto blockPtr = data.getBlockData();\r\n\r\n\tif (blockPtr == nullptr)\r\n\t\treturn json;\r\n\r\n\tauto& block = *blockPtr;\r\n\tconst auto bestOverall = data.getBestDeadlineOverall();\r\n\tconst auto bestHistorical = data.getBestDeadlineOverall(true);\r\n\r\n\tjson.set(\"type\", \"new block\");\r\n\tjson.set(\"block\", std::to_string(block.getBlockheight()));\r\n\tjson.set(\"scoop\", std::to_string(block.getScoop()));\r\n\tjson.set(\"targetDeadline\", std::to_string(block.getBlockTargetDeadline()));\r\n\tjson.set(\"baseTarget\", std::to_string(block.getBasetarget()));\r\n\tjson.set(\"gensigStr\", block.getGensigStr());\r\n\tjson.set(\"time\", getTime());\r\n\tjson.set(\"startTime\", std::to_string( std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count() ));\r\n\tjson.set(\"blocksMined\", std::to_string(data.getBlocksMined()));\r\n\tjson.set(\"blocksWon\", std::to_string(data.getBlocksWon()));\r\n\tjson.set(\"onlineVersion\", Settings::project.getOnlineVersion());\r\n\tjson.set(\"runningVersion\", Settings::project.getVersion().literal);\r\n\tjson.set(\"runningBuild\", Settings::project.getVersion().revision);\r\n\r\n\tif (bestOverall != nullptr)\r\n\t\tjson.set(\"bestOverall\", createJsonDeadline(*bestOverall));\r\n\telse\r\n\t\tjson.set(\"bestOverall\", Poco::JSON::Object());\r\n\r\n\tif (bestHistorical != nullptr)\r\n\t\tjson.set(\"bestHistorical\", createJsonDeadline(*bestHistorical));\r\n\telse\r\n\t\tjson.set(\"bestHistorical\", Poco::JSON::Object());\r\n\r\n\tjson.set(\"deadlinesConfirmed\", std::to_string(data.getConfirmedDeadlines()));\r\n\tjson.set(\"deadlinesAvg\", deadlineFormat(data.getAverageDeadline()));\r\n\r\n\t//Read roundTimes and BlockTimes from blockdata\r\n\tPoco::JSON::Array roundTimeHistory;\r\n\tPoco::JSON::Array blockTimeHistory;\r\n\tauto nRTimes = 0;\r\n\tauto sumRTimes = 0.0;\r\n\tauto maxRoundTime = 0.0;\r\n\tauto nBTimes = 0;\r\n\tauto sumBTimes = 0.0;\r\n\tauto maxBlockTime = 0ull;\r\n\tconst auto historicalBlockData = data.getAllHistoricalBlockData();\r\n\r\n\tfor (auto& historicalRoundTime : historicalBlockData)\r\n\t{\r\n\t\tconst auto roundTime = historicalRoundTime->getRoundTime();\r\n\t\tif (roundTime > 0)\r\n\t\t{\r\n\t\t\tPoco::JSON::Array jsonRoundTimeHistory;\r\n\t\t\tjsonRoundTimeHistory.add(std::to_string(historicalRoundTime->getBlockheight()));\r\n\t\t\tjsonRoundTimeHistory.add(std::to_string(roundTime));\r\n\t\t\troundTimeHistory.add(jsonRoundTimeHistory);\r\n\t\t\tnRTimes++;\r\n\t\t\tsumRTimes += roundTime;\r\n\t\t\tif (roundTime > maxRoundTime) maxRoundTime = roundTime;\r\n\t\t}\r\n\t\tconst auto blockTime = historicalRoundTime->getBlockTime();\r\n\t\tPoco::JSON::Array jsonBlockTimeHistory;\r\n\t\tjsonBlockTimeHistory.add(std::to_string(historicalRoundTime->getBlockheight()));\r\n\t\tjsonBlockTimeHistory.add(std::to_string(blockTime));\r\n\t\tblockTimeHistory.add(jsonBlockTimeHistory);\r\n\t\tnBTimes++;\r\n\t\tsumBTimes += blockTime;\r\n\t\tif (blockTime > maxBlockTime)\r\n\t\t\tmaxBlockTime = blockTime;\r\n\t}\r\n\tauto meanRoundTime = 0.0;\r\n\tif (nRTimes > 0)\r\n\t\tmeanRoundTime = sumRTimes / static_cast<double>(nRTimes);\r\n\r\n\tauto meanBlockTime = 0.0;\r\n\tif (nBTimes > 0)\r\n\t\tmeanBlockTime = sumBTimes / static_cast<double>(nBTimes);\r\n\r\n\tjson.set(\"meanBlockTime\", std::to_string(meanBlockTime));\r\n\tjson.set(\"maxBlockTime\", std::to_string(maxBlockTime));\r\n\tjson.set(\"blockTimeHistory\", blockTimeHistory);\r\n\tjson.set(\"meanRoundTime\", std::to_string(meanRoundTime));\r\n\tjson.set(\"maxRoundTime\", std::to_string(maxRoundTime));\r\n\tjson.set(\"roundTimeHistory\", roundTimeHistory);\r\n\t\t\r\n\t//get deadlines from blockdata\r\n\tPoco::JSON::Array bestDeadlines;\r\n\tauto maxDeadline = 0ull;\r\n\tauto nDeadlines = 0;\r\n\tauto totalTarget = 0.0;\r\n\tauto nTargets = 0;\r\n\r\n\tfor (auto& historicalDeadline : historicalBlockData)\r\n\t{\r\n\t\tif (historicalDeadline->getBestDeadline() != nullptr)\r\n\t\t{\r\n\t\t\tconst auto thisDL = historicalDeadline->getBestDeadline()->getDeadline();\r\n\t\t\tPoco::JSON::Array jsonBestDeadline;\r\n\t\t\tjsonBestDeadline.add(std::to_string(historicalDeadline->getBlockheight()));\r\n\t\t\tjsonBestDeadline.add(std::to_string(thisDL));\r\n\t\t\tbestDeadlines.add(jsonBestDeadline);\r\n\r\n\t\t\tif( thisDL > maxDeadline )\r\n\t\t\t\tmaxDeadline = thisDL;\r\n\r\n\t\t\tnDeadlines++;\r\n\t\t\tif (historicalDeadline->getBlockTime() > meanRoundTime)\r\n\t\t\t{\r\n\t\t\t\ttotalTarget += static_cast<double>(thisDL) / (18325193796.0f / static_cast<double>(historicalDeadline->getBasetarget()));\r\n\t\t\t\tnTargets++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tjson.set(\"nRoundsSubmitted\", std::to_string(nDeadlines));\r\n\r\n\t//calc deadline performance\r\n\tif (nTargets > 0)\r\n\t{\r\n\t\tconst auto deadlinePerformance = MinerConfig::getConfig().getDeadlinePerformanceFac() * static_cast<double>((nTargets - 1)) / totalTarget;\r\n\t\tjson.set(\"deadlinePerformance\", deadlinePerformance);\r\n\t}\r\n\telse {\r\n\t\tjson.set(\"deadlinePerformance\", 0);\r\n\t}\r\n\r\n\t//Calculate Deadline distribution from blockdata\r\n\tif (nDeadlines > 0) \r\n\t{\r\n\t\tconst auto nClasses = static_cast<size_t>(ceil(sqrt(nDeadlines)));\r\n\t\tconst auto classWidth = static_cast<Poco::UInt64>(ceil(\r\n\t\t\tstatic_cast<double>(maxDeadline) / static_cast<double>(nClasses)) + 1);\r\n\t\tstd::map<Poco::UInt64, Poco::UInt64> deadlineBins;\r\n\r\n\t\tfor (auto& historicalDeadline : historicalBlockData)\r\n\t\t{\r\n\t\t\tif (historicalDeadline->getBestDeadline() != nullptr)\r\n\t\t\t{\r\n\t\t\t\tconst auto thisDl = historicalDeadline->getBestDeadline()->getDeadline();\r\n\t\t\t\tauto bin = static_cast<Poco::UInt64>(floor(static_cast<double>(thisDl) / classWidth));\r\n\r\n\t\t\t\tif (bin > nClasses - 1)\r\n\t\t\t\t\tbin = nClasses - 1;\r\n\r\n\t\t\t\tdeadlineBins[bin]++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tPoco::JSON::Array deadlineDistribution;\r\n\r\n\t\tfor (const auto& iClass : deadlineBins)\r\n\t\t{\r\n\t\t\tPoco::JSON::Array jsonDeadlineDistribution;\r\n\t\t\tjsonDeadlineDistribution.add(std::to_string(iClass.first * classWidth));\r\n\t\t\tjsonDeadlineDistribution.add(std::to_string(iClass.second));\r\n\t\t\tdeadlineDistribution.add(jsonDeadlineDistribution);\r\n\t\t}\r\n\r\n\t\tjson.set(\"dlDistBarWidth\", std::to_string(classWidth));\r\n\t\tjson.set(\"deadlineDistribution\", deadlineDistribution);\r\n\t} else \r\n\t{\r\n\t\tPoco::JSON::Array deadlineDistribution;\t\r\n\t\tPoco::JSON::Array jsonDeadlineDistribution;\r\n\t\tjsonDeadlineDistribution.add(std::to_string(0));\r\n\t\tjsonDeadlineDistribution.add(std::to_string(0));\r\n\t\tdeadlineDistribution.add(jsonDeadlineDistribution);\r\n\t\tjson.set(\"deadlineDistribution\", deadlineDistribution);\r\n\t}\r\n\r\n\r\n\t//Read difficulties from blockdata\r\n\tPoco::JSON::Array difficultyHistory;\r\n\tauto nDiffs = 0;\r\n\tauto sumDiffs = 0.0;\r\n\r\n\tfor (auto& historicalDifficulty : historicalBlockData)\r\n\t{\r\n\t\tconst auto blockDiff = 18325193796.0f / static_cast<float>(historicalDifficulty->getBasetarget());\r\n\t\tPoco::JSON::Array jsonDifficultyHistory;\r\n\t\tjsonDifficultyHistory.add(std::to_string(historicalDifficulty->getBlockheight()));\r\n\t\tjsonDifficultyHistory.add(std::to_string(blockDiff));\r\n\t\tdifficultyHistory.add(jsonDifficultyHistory);\r\n\t\tnDiffs++;\r\n\t\tsumDiffs += blockDiff;\r\n\t}\r\n\r\n\tjson.set(\"numHistoricals\", std::to_string(nDiffs));\r\n\tjson.set(\"meanDifficulty\",std::to_string(sumDiffs/static_cast<double>(nDiffs)));\r\n\tjson.set(\"difficultyHistory\", difficultyHistory);\r\n\tjson.set(\"bestDeadlines\", bestDeadlines);\r\n\tjson.set(\"difficulty\", std::to_string(block.getDifficulty()));\r\n\tjson.set(\"difficultyDifference\", std::to_string(data.getDifficultyDifference()));\r\n\r\n\tconst auto diffToJson = [&json](const HighscoreValue<Poco::UInt64>& diff, const std::string& id) {\r\n\t\tPoco::JSON::Object jsonDiff;\r\n\t\tjsonDiff.set(\"blockheight\", std::to_string(diff.height));\r\n\t\tjsonDiff.set(\"value\", std::to_string(diff.value));\r\n\t\tjson.set(id, jsonDiff);\r\n\t};\r\n\r\n\tdiffToJson(data.getLowestDifficulty(), \"lowestDifficulty\");\r\n\tdiffToJson(data.getHighestDifficulty(), \"highestDifficulty\");\r\n\r\n\treturn json;\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonConfig()\r\n{\r\n\tPoco::JSON::Object json;\r\n\tconst auto targetDeadline = MinerConfig::getConfig().getTargetDeadline();\r\n\r\n\tjson.set(\"type\", \"config\");\r\n\tjson.set(\"poolUrl\", MinerConfig::getConfig().getPoolUrl().getCanonical(true));\r\n\tjson.set(\"poolUrlPort\", std::to_string(MinerConfig::getConfig().getPoolUrl().getPort()));\r\n\tjson.set(\"miningInfoUrl\", MinerConfig::getConfig().getMiningInfoUrl().getCanonical(true));\r\n\tjson.set(\"miningInfoUrlPort\", std::to_string(MinerConfig::getConfig().getMiningInfoUrl().getPort()));\r\n\tjson.set(\"walletUrl\", MinerConfig::getConfig().getWalletUrl().getCanonical(true));\r\n\tjson.set(\"walletUrlPort\", std::to_string(MinerConfig::getConfig().getWalletUrl().getPort()));\r\n\tjson.set(\"totalPlotSize\", memToString(PlotSizes::getTotalBytes(PlotSizes::Type::Combined), 2));\r\n\tjson.set(\"timeout\", MinerConfig::getConfig().getTimeout());\r\n\tjson.set(\"bufferSize\", memToString(MinerConfig::getConfig().getMaxBufferSize(), 0));\r\n\tjson.set(\"bufferSizeRaw\", std::to_string(MinerConfig::getConfig().getMaxBufferSizeRaw()));\r\n\tjson.set(\"bufferChunks\", std::to_string(MinerConfig::getConfig().getBufferChunkCount()));\r\n\tjson.set(\"targetDeadline\", deadlineFormat(targetDeadline));\r\n\tjson.set(\"submitProbability\", MinerConfig::getConfig().getSubmitProbability());\r\n\tjson.set(\"maxHistoricalBlocks\", MinerConfig::getConfig().getMaxHistoricalBlocks());\r\n\tjson.set(\"maxPlotReaders\", std::to_string(MinerConfig::getConfig().getMaxPlotReaders()));\r\n\tjson.set(\"maxPlotReadersRaw\", std::to_string(MinerConfig::getConfig().getMaxPlotReaders(false)));\r\n\tjson.set(\"miningIntensity\", std::to_string(MinerConfig::getConfig().getMiningIntensity()));\r\n\tjson.set(\"miningIntensityRaw\", std::to_string(MinerConfig::getConfig().getMiningIntensity(false)));\r\n\tjson.set(\"submissionMaxRetry\", std::to_string(MinerConfig::getConfig().getSubmissionMaxRetry()));\r\n\r\n\tconst auto addTargetDeadline = [&json](const std::string& id, auto value) {\r\n\t\tjson.set(\"targetDeadline\" + id, deadlineFormat(value));\r\n\t\tjson.set(\"targetDeadline\" + id + \"Raw\", std::to_string(value));\r\n\t};\r\n\r\n\taddTargetDeadline(\"Combined\", MinerConfig::getConfig().getTargetDeadline());\r\n\taddTargetDeadline(\"Local\", MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Local));\r\n\taddTargetDeadline(\"Pool\", MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Pool));\r\n\r\n\tjson.set(\"logDir\", MinerConfig::getConfig().getLogDir());\r\n\r\n\tPoco::JSON::Object json_channel_priorities;\r\n\r\n\tfor (auto& channel_priority : MinerLogger::getChannelPriorities())\r\n\t{\r\n\t\tPoco::JSON::Object json_channel_priority;\r\n\t\tjson_channel_priority.set(\"numeric\",\r\n\t\t\tstatic_cast<int>(MinerLogger::getStringToPriority(channel_priority.second)));\r\n\t\tjson_channel_priority.set(\"alphaNumeric\", channel_priority.second);\r\n\t\tjson_channel_priorities.set(channel_priority.first, json_channel_priority);\r\n\t}\r\n\r\n\tjson.set(\"channelPriorities\", json_channel_priorities);\r\n\r\n\treturn json;\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonProgress(float progressRead, float progressVerification)\r\n{\r\n\tPoco::JSON::Object json;\r\n\tjson.set(\"type\", \"progress\");\r\n\tjson.set(\"value\", progressRead);\r\n\tjson.set(\"valueVerification\", progressVerification);\r\n\treturn json;\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonLastWinner(const MinerData& data)\r\n{\r\n\tconst auto block = data.getBlockData();\r\n\r\n\tif (block == nullptr || block->getLastWinner() == nullptr)\r\n\t\treturn Poco::JSON::Object{};\r\n\r\n\treturn *block->getLastWinner()->toJSON();\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonShutdown()\r\n{\r\n\tPoco::JSON::Object json;\r\n\tjson.set(\"shutdown\", true);\r\n\treturn json;\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonWonBlocks(const MinerData& data)\r\n{\r\n\tPoco::JSON::Object json;\r\n\tjson.set(\"type\", \"blocksWonUpdate\");\r\n\tjson.set(\"blocksWon\", std::to_string(data.getBlocksWon()));\r\n\treturn json;\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonPlotDir(const PlotDir& plotDir)\r\n{\r\n\tPoco::JSON::Object json;\r\n\r\n\tjson.set(\"path\", plotDir.getPath());\r\n\r\n\tPoco::JSON::Array jsonPlotFiles;\r\n\r\n\tfor (const auto& plotFile : plotDir.getPlotfiles())\r\n\t{\r\n\t\tPoco::JSON::Object jsonPlotFile;\r\n\r\n\t\tjsonPlotFile.set(\"path\", plotFile->getPath());\r\n\t\tjsonPlotFile.set(\"size\", memToString(plotFile->getSize(), 2));\r\n\r\n\t\tjsonPlotFiles.add(jsonPlotFile);\r\n\t}\r\n\r\n\tjson.set(\"plotfiles\", jsonPlotFiles);\r\n\tjson.set(\"size\", memToString(plotDir.getSize(), 2));\r\n\r\n\treturn json;\r\n}\r\n\r\nPoco::JSON::Array Burst::createJsonPlotDirs()\r\n{\r\n\tPoco::JSON::Array jsonPlotDirs;\r\n\r\n\tMinerConfig::getConfig().forPlotDirs([&jsonPlotDirs](PlotDir& plotDir)\r\n\t{\r\n\t\tjsonPlotDirs.add(createJsonPlotDir(plotDir));\r\n\r\n\t\tfor (const auto& relatedPlotDir : plotDir.getRelatedDirs())\r\n\t\t\tjsonPlotDirs.add(createJsonPlotDir(*relatedPlotDir));\r\n\r\n\t\treturn true;\r\n\t});\r\n\r\n\treturn jsonPlotDirs;\r\n}\r\n\r\nPoco::JSON::Object Burst::createJsonPlotDirsRescan()\r\n{\r\n\tPoco::JSON::Object jsonPlotRescan;\r\n\tjsonPlotRescan.set(\"type\", \"plotdirs-rescan\");\r\n\tjsonPlotRescan.set(\"plotdirs\", createJsonPlotDirs());\r\n\treturn jsonPlotRescan;\r\n}\r\n\r\nstd::string Burst::getTime()\r\n{\r\n\tstd::stringstream ss;\r\n\r\n#if defined(__linux__) && __GNUC__ < 5\r\n\ttime_t rawtime;\r\n\tstruct tm * timeinfo;\r\n\tchar buffer [80];\r\n\r\n\ttime (&rawtime);\r\n\ttimeinfo = localtime (&rawtime);\r\n\r\n\tstrftime (buffer, 80, \"%X\",timeinfo);\r\n\r\n\tss << buffer;\r\n#elif defined(_WIN32)\r\n\tconst auto now = std::chrono::system_clock::now();\r\n\tauto nowC = std::chrono::system_clock::to_time_t(now);\r\n\t//ss.imbue(std::locale());\r\n\tstruct tm timeinfo{};\r\n\tlocaltime_s(&timeinfo, &nowC);\r\n\tss << std::put_time(&timeinfo, \"%X\");\r\n#else \r\n\tconst auto now = std::chrono::system_clock::now();\r\n\tauto nowC = std::chrono::system_clock::to_time_t(now);\r\n\t//ss.imbue(std::locale());\r\n\tss << std::put_time(std::localtime(&nowC), \"%X\");\r\n#endif\r\n\r\n\treturn ss.str();\r\n}\r\n\r\nstd::string Burst::getFilenameWithtimestamp(const std::string& name, const std::string& ending)\r\n{\r\n\treturn Poco::format(\"%s_%s.%s\",\r\n\t\tname, Poco::DateTimeFormatter::format(Poco::Timestamp(), \"%Y%m%d_%H%M%s\"), ending);\r\n}\r\n\r\nstd::string Burst::hashHmacSha1(const std::string& plain, const std::string& passphrase)\r\n{\r\n\tPoco::HMACEngine<Poco::SHA1Engine> engine{ passphrase };\r\n\tengine.update(plain);\r\n\tauto& digest = engine.digest();\r\n\treturn Poco::DigestEngine::digestToHex(digest);\r\n}\r\n\r\nstd::string Burst::createTruncatedString(const std::string& string, size_t padding, size_t size)\r\n{\r\n\tstd::string padded_string;\r\n\r\n\tfor (size_t i = 0; i < string.size(); i += size)\r\n\t{\r\n\t\tconst auto max_size = std::min(size, string.size());\r\n\r\n\t\tpadded_string += string.substr(i, max_size);\r\n\r\n\t\t// reached the end of the string\r\n\t\tif (i >= string.size())\r\n\t\t\tbreak;\r\n\t\telse if (i + size < string.size())\r\n\t\t{\r\n\t\t\tpadded_string += '\\n';\r\n\t\t\tpadded_string += std::string(padding, ' ');\r\n\t\t}\r\n\t}\r\n\r\n\treturn padded_string;\r\n}\r\n\r\nbool Burst::cpuHasInstructionSet(CpuInstructionSet cpuInstructionSet)\r\n{\r\n\tconst auto instructionSets = cpuGetInstructionSets();\r\n\r\n\tswitch (cpuInstructionSet)\r\n\t{\r\n\tcase Sse2: return (instructionSets & Sse2) == Sse2;\r\n\tcase Sse4: return (instructionSets & Sse4) == Sse4;\r\n\tcase Avx: return (instructionSets & Avx) == Avx;\r\n\tcase Avx2: return (instructionSets & Avx2) == Avx2;\r\n\tdefault: return false;\r\n\t}\r\n}\r\n\r\nint Burst::cpuGetInstructionSets()\r\n{\r\n#if defined __arm__ || defined __aarch64__\r\n\treturn Sse2;\r\n#elif defined __GNUC__\r\n\tauto instructionSets = 0;\r\n\r\n\tif (__builtin_cpu_supports(\"sse2\"))\r\n\t\tinstructionSets += Sse2;\r\n\r\n\tif (__builtin_cpu_supports(\"sse4.1\"))\r\n\t\tinstructionSets += Sse4;\r\n\r\n\tif (__builtin_cpu_supports(\"avx\"))\r\n\t\tinstructionSets += Avx;\r\n\r\n\tif (__builtin_cpu_supports(\"avx2\"))\r\n\t\tinstructionSets += Avx2;\r\n\r\n\treturn instructionSets;\r\n#else\r\n\tint info[4];\r\n\tcpuid(info, 0);\r\n\tconst auto nIds = info[0];\r\n\r\n\tauto hasSse2 = false;\r\n\tauto hasSse4 = false;\r\n\tauto hasAvx = false;\r\n\tauto hasAvx2 = false;\r\n\r\n\t//  Detect Features\r\n\tif (nIds >= 0x00000001)\r\n\t{\r\n\t\tcpuid(info, 0x00000001);\r\n\t\thasSse2 = (info[3] & 1 << 26) != 0;\r\n\t\thasSse4 = (info[2] & 1 << 19) != 0 || (info[2] & 1 << 20) != 0;\r\n\t\thasAvx = (info[2] & 1 << 28) != 0;\r\n\t}\r\n\r\n\tif (nIds >= 0x00000007)\r\n\t{\r\n\t\tcpuid(info, 0x00000007);\r\n\t\thasAvx2 = (info[1] & (static_cast<int>(1) << 5)) != 0;\r\n\t}\r\n\r\n\tauto instructionSets = 0;\r\n\r\n\tif (hasSse2)\r\n\t\tinstructionSets += Sse2;\r\n\r\n\tif (hasSse4)\r\n\t\tinstructionSets += Sse4;\r\n\r\n\tif (hasAvx)\r\n\t\tinstructionSets += Avx;\r\n\r\n\tif (hasAvx2)\r\n\t\tinstructionSets += Avx2;\r\n\r\n\treturn instructionSets;\r\n#endif\r\n}\r\n\r\nsize_t Burst::getMemorySize()\r\n{\r\n\t/*\r\n\t * Author:  David Robert Nadeau\r\n\t * Site:    http://NadeauSoftware.com/\r\n\t * License: Creative Commons Attribution 3.0 Unported License\r\n\t *          http://creativecommons.org/licenses/by/3.0/deed.en_US\r\n\t */\r\n\r\n\r\n#if defined(_WIN32) && (defined(__CYGWIN__) || defined(__CYGWIN32__))\r\n\t/* Cygwin under Windows. ------------------------------------ */\r\n\t/* New 64-bit MEMORYSTATUSEX isn't available.  Use old 32.bit */\r\n\tMEMORYSTATUS status;\r\n\tstatus.dwLength = sizeof(status);\r\n\tGlobalMemoryStatus(&status);\r\n\treturn (size_t)status.dwTotalPhys;\r\n\r\n#elif defined(_WIN32)\r\n\t/* Windows. ------------------------------------------------- */\r\n\t/* Use new 64-bit MEMORYSTATUSEX, not old 32-bit MEMORYSTATUS */\r\n\tMEMORYSTATUSEX status;\r\n\tstatus.dwLength = sizeof(status);\r\n\tGlobalMemoryStatusEx(&status);\r\n\treturn static_cast<size_t>(status.ullTotalPhys);\r\n\r\n#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))\r\n\t/* UNIX variants. ------------------------------------------- */\r\n\t/* Prefer sysctl() over sysconf() except sysctl() HW_REALMEM and HW_PHYSMEM */\r\n\r\n#if defined(CTL_HW) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM64))\r\n\tint mib[2];\r\n\tmib[0] = CTL_HW;\r\n#if defined(HW_MEMSIZE)\r\n\tmib[1] = HW_MEMSIZE;            /* OSX. --------------------- */\r\n#elif defined(HW_PHYSMEM64)\r\n\tmib[1] = HW_PHYSMEM64;          /* NetBSD, OpenBSD. --------- */\r\n#endif\r\n\tint64_t size = 0;               /* 64-bit */\r\n\tsize_t len = sizeof(size);\r\n\tif (sysctl(mib, 2, &size, &len, NULL, 0) == 0)\r\n\t\treturn (size_t)size;\r\n\treturn 0L;\t\t\t/* Failed? */\r\n\r\n#elif defined(_SC_AIX_REALMEM)\r\n\t/* AIX. ----------------------------------------------------- */\r\n\treturn (size_t)sysconf(_SC_AIX_REALMEM) * (size_t)1024L;\r\n\r\n#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)\r\n\t/* FreeBSD, Linux, OpenBSD, and Solaris. -------------------- */\r\n\treturn (size_t)sysconf(_SC_PHYS_PAGES) *\r\n\t\t(size_t)sysconf(_SC_PAGESIZE);\r\n\r\n#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE)\r\n\t/* Legacy. -------------------------------------------------- */\r\n\treturn (size_t)sysconf(_SC_PHYS_PAGES) *\r\n\t\t(size_t)sysconf(_SC_PAGE_SIZE);\r\n\r\n#elif defined(CTL_HW) && (defined(HW_PHYSMEM) || defined(HW_REALMEM))\r\n\t/* DragonFly BSD, FreeBSD, NetBSD, OpenBSD, and OSX. -------- */\r\n\tint mib[2];\r\n\tmib[0] = CTL_HW;\r\n#if defined(HW_REALMEM)\r\n\tmib[1] = HW_REALMEM;\t\t/* FreeBSD. ----------------- */\r\n#elif defined(HW_PYSMEM)\r\n\tmib[1] = HW_PHYSMEM;\t\t/* Others. ------------------ */\r\n#endif\r\n\tunsigned int size = 0;\t\t/* 32-bit */\r\n\tsize_t len = sizeof(size);\r\n\tif (sysctl(mib, 2, &size, &len, NULL, 0) == 0)\r\n\t\treturn (size_t)size;\r\n\treturn 0L;\t\t\t/* Failed? */\r\n#endif /* sysctl and sysconf variants */\r\n\r\n#else\r\n\treturn 0L;\t\t\t/* Unknown OS. */\r\n#endif\r\n}\r\n\r\n// https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin\r\nvoid Burst::setStdInEcho(bool enable)\r\n{\r\n#ifdef WIN32\r\n\tconst auto hStdin = GetStdHandle(STD_INPUT_HANDLE);\r\n\tDWORD mode;\r\n\tGetConsoleMode(hStdin, &mode);\r\n\r\n\tif (!enable)\r\n\t\tmode &= ~ENABLE_ECHO_INPUT;\r\n\telse\r\n\t\tmode |= ENABLE_ECHO_INPUT;\r\n\r\n\tSetConsoleMode(hStdin, mode);\r\n\r\n#else\r\n\tstruct termios tty;\r\n\ttcgetattr(STDIN_FILENO, &tty);\r\n\tif (!enable)\r\n\t\ttty.c_lflag &= ~ECHO;\r\n\telse\r\n\t\ttty.c_lflag |= ECHO;\r\n\r\n\t(void)tcsetattr(STDIN_FILENO, TCSANOW, &tty);\r\n#endif\r\n}\r\n\r\nPoco::Path Burst::getMinerHomeDir()\r\n{\r\n\tPoco::Path minerRootPath(Poco::Path::home());\r\n\tminerRootPath.pushDirectory(\".creepMiner\");\r\n\treturn minerRootPath.parseDirectory(minerRootPath.toString());\r\n}\r\n\r\nPoco::Path Burst::getMinerHomeDir(const std::string& filename)\r\n{\r\n\treturn getMinerHomeDir().append(filename);\r\n}\r\n\r\nstd::string Burst::toHex(const std::string& plainText)\r\n{\r\n\tstd::stringstream sstream;\r\n\tPoco::HexBinaryEncoder hex{sstream};\r\n\thex << plainText;\r\n\thex.close();\r\n\treturn sstream.str();\r\n}\r\n\r\nstd::string Burst::fromHex(const std::string& codedText)\r\n{\r\n\tstd::stringstream sstream;\r\n\tsstream << codedText;\r\n\tPoco::HexBinaryDecoder hex{sstream};\r\n\tstd::string out;\r\n\tPoco::StreamCopier::copyToString(hex, out);\r\n\treturn out;\r\n}\r\n\r\nstd::string Burst::createBuildFeatures()\r\n{\r\n\tusing namespace Burst::Settings;\r\n\r\n\tstd::stringstream sstream;\r\n\r\n\tconst auto checkAndPrint = [&](const bool flag, const std::string& text) {\r\n\t\tsstream << ' ' << (flag ? '+' : '-') << text;\r\n\t};\r\n\r\n\tcheckAndPrint(cuda, \"CUDA\");\r\n\tcheckAndPrint(openCl, \"OpenCL\");\r\n\tcheckAndPrint(sse4, \"SSE4\");\r\n\tcheckAndPrint(avx, \"AVX\");\r\n\tcheckAndPrint(avx2, \"AVX2\");\r\n\r\n\treturn sstream.str();\r\n}\r\n\r\nstd::string Burst::jsonToString(const Poco::JSON::Object& json)\r\n{\r\n\tstatic std::stringstream sstream;\r\n\tsstream.str(\"\");\r\n\tPoco::JSON::Stringifier::condense(json, sstream);\r\n\treturn sstream.str();\r\n}\r\n\r\nBurst::LowLevelFileStream::LowLevelFileStream(const LowLevelFileStream& other)\r\n\t: handle_{other.handle_}\r\n{\r\n}\r\n\r\nBurst::LowLevelFileStream::LowLevelFileStream(LowLevelFileStream&& other) noexcept\r\n\t: handle_{other.handle_}\r\n{\r\n}\r\n\r\nBurst::LowLevelFileStream& Burst::LowLevelFileStream::operator=(const LowLevelFileStream& other)\r\n{\r\n\tif (this == &other)\r\n\t\treturn *this;\r\n\thandle_ = other.handle_;\r\n\treturn *this;\r\n}\r\n\r\nBurst::LowLevelFileStream& Burst::LowLevelFileStream::operator=(LowLevelFileStream&& other) noexcept\r\n{\r\n\tif (this == &other)\r\n\t\treturn *this;\r\n\thandle_ = other.handle_;\r\n\treturn *this;\r\n}\r\n\r\nBurst::LowLevelFileStream::LowLevelFileStream(const std::string& path)\r\n{\r\n#ifdef _WIN32\r\n        handle_ = CreateFileA(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,\r\n                                             OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, nullptr);\r\n#else\r\n        handle_ = open(path.c_str(), O_RDONLY);\r\n#endif\r\n}\r\n\r\nBurst::LowLevelFileStream::~LowLevelFileStream()\r\n{\r\n#ifdef _WIN32\r\n\tCloseHandle(handle_);\r\n#else\r\n\tclose(handle_);\r\n#endif\r\n}\r\n\r\nbool Burst::LowLevelFileStream::seekg(const size_t offset) const\r\n{\r\n#ifdef _WIN32\r\n\tLARGE_INTEGER winOffset; \r\n\twinOffset.QuadPart = static_cast<LONGLONG>(offset);\r\n\treturn SetFilePointerEx(handle_, winOffset, nullptr, FILE_BEGIN);\r\n#else\r\n\treturn LSEEK64(handle_, offset, SEEK_SET) == offset;\r\n#endif\r\n}\r\n\r\nbool Burst::LowLevelFileStream::read(char* buffer, const size_t bytes) const\r\n{\r\n#ifdef _WIN32\r\n\tDWORD bytesRead = 0;\r\n\tReadFile(handle_, buffer, static_cast<DWORD>(bytes), &bytesRead, nullptr);\r\n\treturn bytesRead == bytes;\r\n#else\r\n\treturn ::read(handle_, buffer, bytes) == bytes;\r\n#endif\r\n}\r\n\r\nBurst::LowLevelFileStream::operator bool() const\r\n{\r\n#ifdef _WIN32\r\n\treturn handle_ != INVALID_HANDLE_VALUE;\r\n#else\r\n\treturn handle_ >= 0;\r\n#endif\r\n}\r\n"
  },
  {
    "path": "src/MinerUtil.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <string>\n#include <vector>\n#include <sstream>\n#include <iomanip>\n#include <Poco/Timespan.h>\n#include <memory>\n#include <Poco/Net/SocketAddress.h>\n#include <array>\n#include <Poco/JSON/Array.h>\n#include <Poco/Path.h>\n\nnamespace Poco\n{\n\tclass URI;\n\tclass TaskManager;\n\tnamespace Net { class HTTPClientSession; }\n\tnamespace JSON { class Object; }\n}\n\nnamespace Burst\n{\n\tclass PlotDir;\n\tclass PlotReadProgress;\n\tclass BlockData;\n\tclass Deadline;\n\tclass MinerData;\n\t\n\tenum class MemoryUnit : Poco::UInt64\n\t{\n\t\tMegabyte = 1048576,\n\t\tGigabyte = 1073741824,\n\t\tTerabyte = 1099511627776,\n\t\tPetabyte = 1125899906842624,\n\t\tExabyte = 1152921504606846976\n\t};\n\n\ttemplate <typename T, size_t SZ>\n\tstd::string byteArrayToStr(const std::array<T, SZ>& arr)\n\t{\n\t\tstd::stringstream stream;\n\t\tfor (size_t i = 0; i < SZ; i++)\n\t\t{\n\t\t\tstream << std::setfill('0') << std::setw(sizeof(T) * 2) << std::hex << static_cast<size_t>(arr[i]);\n\t\t}\n\t\treturn stream.str();\n\t}\n\n\tenum class PlotCheckResult\n\t{\n\t\tOk,\n\t\tError,\n\t\tEmptyParameter,\n\t\tInvalidParameter,\n\t\tWrongStaggersize,\n\t\tIncomplete\n\t};\n\n\tenum class DeadlineFragment\n\t{\n\t\tYears,\n\t\tMonths,\n\t\tDays,\n\t\tHours,\n\t\tMinutes,\n\t\tSeconds\n\t};\n\n\tenum CpuInstructionSet\n\t{\n\t\tSse2 = 1 << 0,\n\t\tSse4 = 1 << 1,\n\t\tAvx = 1 << 2,\n\t\tAvx2 = 1 << 3\n\t};\n\n\tbool isNumberStr(const std::string& str);\n\tstd::vector<std::string>& splitStr(const std::string& s, char delim, std::vector<std::string>& elems);\n\tstd::vector<std::string> splitStr(const std::string& s, char delim);\n\tstd::vector<std::string> splitStr(const std::string& s, const std::string& delim);\n\tPlotCheckResult isValidPlotFile(const std::string& filePath);\n\tstd::string getAccountIdFromPlotFile(const std::string& path);\n\tstd::string getStartNonceFromPlotFile(const std::string& path);\n\tstd::string getNonceCountFromPlotFile(const std::string& path);\n\tstd::string getStaggerSizeFromPlotFile(const std::string& path);\n\tstd::string getVersionFromPlotFile(const std::string& path);\n\tstd::string deadlineFormat(Poco::UInt64 seconds);\n\tPoco::UInt64 deadlineFragment(Poco::UInt64 seconds, DeadlineFragment fragment);\n\tPoco::UInt64 formatDeadline(const std::string& format);\n\tstd::string gbToString(Poco::UInt64 size);\n\tstd::string memToString(Poco::UInt64 size, MemoryUnit factor, Poco::UInt8 precision);\n\tstd::string memToString(Poco::UInt64 size, Poco::UInt8 precision);\n\tstd::string getInformationFromPlotFile(const std::string& path, Poco::UInt8 index);\n\tstd::string encrypt(const std::string& decrypted, const std::string& algorithm, std::string& key, std::string& salt, Poco::UInt32 iterations);\n\tstd::string decrypt(const std::string& encrypted, const std::string& algorithm, const std::string& key, const std::string& salt, Poco::UInt32 iterations);\n\n\ttemplate <typename T, typename U>\n\tvoid transferSession(T& from, U& to)\n\t{\n\t\tauto socket = from.transferSession();\n\n\t\tif (socket != nullptr)\n\t\t\tto = std::move(socket);\n\t}\n\n\tPoco::Timespan secondsToTimespan(float seconds);\n\tstd::unique_ptr<Poco::Net::HTTPClientSession> createSession(const Poco::URI& uri);\n\tPoco::Net::SocketAddress getHostAddress(const Poco::URI& uri);\n\tstd::string serializeDeadline(const Deadline& deadline, const std::string& delimiter = \":\");\n\n\tPoco::JSON::Object createJsonDeadline(const Deadline& deadline);\n\tPoco::JSON::Object createJsonDeadline(const Deadline& deadline, const std::string& type);\n\tPoco::JSON::Object createJsonNewBlock(const MinerData& data);\n\tPoco::JSON::Object createJsonConfig();\n\tPoco::JSON::Object createJsonProgress(float progressRead, float progressVerification);\n\tPoco::JSON::Object createJsonLastWinner(const MinerData& data);\n\tPoco::JSON::Object createJsonShutdown();\n\tPoco::JSON::Object createJsonWonBlocks(const MinerData& data);\n\tPoco::JSON::Object createJsonPlotDir(const PlotDir& plotDir);\n\tPoco::JSON::Array createJsonPlotDirs();\n\tPoco::JSON::Object createJsonPlotDirsRescan();\n\n\tstd::string getTime();\n\tstd::string getFilenameWithtimestamp(const std::string& name, const std::string& ending);\n\n\tstd::string hashHmacSha1(const std::string& plain, const std::string& passphrase);\n\n\t/*\n\t * \\brief Creates a string that is padded and locked on a specific size.\n\t * \\param string The string, that is sized.\n\t * \\param padding The padding from left side of the string.\n\t * \\param size The max. size of the string. Every time the string exceeds the size,\n\t * it gets wrapped into a new line.\n\t */\n\tstd::string createTruncatedString(const std::string& string, size_t padding, size_t size);\n\n\ttemplate <typename T>\n\tstd::string numberToString(T number)\n\t{\n\t\tstd::stringstream sstream;\n\t\tsstream.imbue(std::locale(\"\"));\n\n\t\tsstream << number;\n\t\treturn sstream.str();\n\t}\n\n\tbool cpuHasInstructionSet(CpuInstructionSet cpuInstructionSet);\n\tint cpuGetInstructionSets();\n\n\tsize_t getMemorySize();\n\tvoid setStdInEcho(bool enable);\n\n\tPoco::Path getMinerHomeDir();\n\tPoco::Path getMinerHomeDir(const std::string& filename);\n\n\tstd::string toHex(const std::string& plainText);\n\tstd::string fromHex(const std::string& codedText);\n\n\tstd::string createBuildFeatures();\n\n\tstd::string jsonToString(const Poco::JSON::Object& json);\n\n\tclass LowLevelFileStream\n\t{\n\tpublic:\n\t\tLowLevelFileStream(const LowLevelFileStream& other);\n\t\tLowLevelFileStream(LowLevelFileStream&& other) noexcept;\n\t\tLowLevelFileStream(const std::string& path);\n\t\tLowLevelFileStream& operator=(const LowLevelFileStream& other);\n\t\tLowLevelFileStream& operator=(LowLevelFileStream&& other) noexcept;\n\t\t~LowLevelFileStream();\n\n\t\tbool seekg(size_t offset) const;\n\t\tbool read(char* buffer, size_t bytes) const;\n\t\toperator bool() const;\n\n\tprivate:\n#ifdef _WIN32\n\t\tvoid* handle_;\n#else\n\t\tint handle_;\n#endif\n\t};\n}\n"
  },
  {
    "path": "src/extlibs/json.hpp",
    "content": "/*\n    __ _____ _____ _____\n __|  |   __|     |   | |  JSON for Modern C++\n|  |  |__   |  |  | | | |  version 2.1.1\n|_____|_____|_____|_|___|  https://github.com/nlohmann/json\n\nLicensed under the MIT License <http://opensource.org/licenses/MIT>.\nCopyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.\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*/\n\n#ifndef NLOHMANN_JSON_HPP\n#define NLOHMANN_JSON_HPP\n\n#include <algorithm> // all_of, copy, fill, find, for_each, generate_n, none_of, remove, reverse, transform\n#include <array> // array\n#include <cassert> // assert\n#include <ciso646> // and, not, or\n#include <clocale> // lconv, localeconv\n#include <cmath> // isfinite, labs, ldexp, signbit\n#include <cstddef> // nullptr_t, ptrdiff_t, size_t\n#include <cstdint> // int64_t, uint64_t\n#include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull\n#include <cstring> // memcpy, strlen\n#include <forward_list> // forward_list\n#include <functional> // function, hash, less\n#include <initializer_list> // initializer_list\n#include <iomanip> // hex\n#include <iosfwd>   // istream, ostream\n#include <iterator> // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator\n#include <limits> // numeric_limits\n#include <locale> // locale\n#include <map> // map\n#include <memory> // addressof, allocator, allocator_traits, unique_ptr\n#include <numeric> // accumulate\n#include <sstream> // stringstream\n#include <string> // getline, stoi, string, to_string\n#include <type_traits> // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type\n#include <utility> // declval, forward, make_pair, move, pair, swap\n#include <valarray> // valarray\n#include <vector> // vector\n\n// exclude unsupported compilers\n#if defined(__clang__)\n#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400\n#error \"unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers\"\n#endif\n#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))\n#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900\n#error \"unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers\"\n#endif\n#endif\n\n// disable float-equal warnings on GCC/clang\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wfloat-equal\"\n#endif\n\n// disable documentation warnings on clang\n#if defined(__clang__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wdocumentation\"\n#endif\n\n// allow for portable deprecation warnings\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n#define JSON_DEPRECATED __attribute__((deprecated))\n#elif defined(_MSC_VER)\n#define JSON_DEPRECATED __declspec(deprecated)\n#else\n#define JSON_DEPRECATED\n#endif\n\n// allow to disable exceptions\n#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION)\n#define JSON_THROW(exception) throw exception\n#define JSON_TRY try\n#define JSON_CATCH(exception) catch(exception)\n#else\n#define JSON_THROW(exception) std::abort()\n#define JSON_TRY if(true)\n#define JSON_CATCH(exception) if(false)\n#endif\n\n// manual branch prediction\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n#define JSON_LIKELY(x)      __builtin_expect(!!(x), 1)\n#define JSON_UNLIKELY(x)    __builtin_expect(!!(x), 0)\n#else\n#define JSON_LIKELY(x)      x\n#define JSON_UNLIKELY(x)    x\n#endif\n\n// cpp language standard detection\n#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464\n#define JSON_HAS_CPP_17\n#define JSON_HAS_CPP_14\n#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)\n#define JSON_HAS_CPP_14\n#endif\n\n/*!\n@brief namespace for Niels Lohmann\n@see https://github.com/nlohmann\n@since version 1.0.0\n*/\nnamespace nlohmann\n{\n\ttemplate<typename = void, typename = void>\n\tstruct adl_serializer;\n\n\t// forward declaration of basic_json (required to split the class)\n\ttemplate<template<typename U, typename V, typename... Args> class ObjectType =\n\t\tstd::map,\n\t\ttemplate<typename U, typename... Args> class ArrayType = std::vector,\n\t\tclass StringType = std::string, class BooleanType = bool,\n\t\tclass NumberIntegerType = std::int64_t,\n\t\tclass NumberUnsignedType = std::uint64_t,\n\t\tclass NumberFloatType = double,\n\t\ttemplate<typename U> class AllocatorType = std::allocator,\n\t\ttemplate<typename T, typename SFINAE = void> class JSONSerializer =\n\t\tadl_serializer>\n\t\tclass basic_json;\n\n\t// Ugly macros to avoid uglier copy-paste when specializing basic_json\n\t// This is only temporary and will be removed in 3.0\n\n#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \\\n    template<template<typename, typename, typename...> class ObjectType,   \\\n             template<typename, typename...> class ArrayType,              \\\n             class StringType, class BooleanType, class NumberIntegerType, \\\n             class NumberUnsignedType, class NumberFloatType,              \\\n             template<typename> class AllocatorType,                       \\\n             template<typename, typename = void> class JSONSerializer>\n\n#define NLOHMANN_BASIC_JSON_TPL                                            \\\n    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \\\n    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \\\n    AllocatorType, JSONSerializer>\n\n\n\t/*!\n\t@brief unnamed namespace with internal helper functions\n\n\tThis namespace collects some functions that could not be defined inside the\n\t@ref basic_json class.\n\n\t@since version 2.1.0\n\t*/\n\tnamespace detail\n\t{\n\t\t////////////////\n\t\t// exceptions //\n\t\t////////////////\n\n\t\t/*!\n\t\t@brief general exception of the @ref basic_json class\n\n\t\tThis class is an extension of `std::exception` objects with a member @a id for\n\t\texception ids. It is used as the base class for all exceptions thrown by the\n\t\t@ref basic_json class. This class can hence be used as \"wildcard\" to catch\n\t\texceptions.\n\n\t\tSubclasses:\n\t\t- @ref parse_error for exceptions indicating a parse error\n\t\t- @ref invalid_iterator for exceptions indicating errors with iterators\n\t\t- @ref type_error for exceptions indicating executing a member function with\n\t\ta wrong type\n\t\t- @ref out_of_range for exceptions indicating access out of the defined range\n\t\t- @ref other_error for exceptions indicating other library errors\n\n\t\t@internal\n\t\t@note To have nothrow-copy-constructible exceptions, we internally use\n\t\t`std::runtime_error` which can cope with arbitrary-length error messages.\n\t\tIntermediate strings are built with static functions and then passed to\n\t\tthe actual constructor.\n\t\t@endinternal\n\n\t\t@liveexample{The following code shows how arbitrary library exceptions can be\n\t\tcaught.,exception}\n\n\t\t@since version 3.0.0\n\t\t*/\n\t\tclass exception : public std::exception\n\t\t{\n\t\tpublic:\n\t\t\t/// returns the explanatory string\n\t\t\tconst char* what() const noexcept override\n\t\t\t{\n\t\t\t\treturn m.what();\n\t\t\t}\n\n\t\t\t/// the id of the exception\n\t\t\tconst int id;\n\n\t\tprotected:\n\t\t\texception(int id_, const char* what_arg) : id(id_), m(what_arg) {}\n\n\t\t\tstatic std::string name(const std::string& ename, int id_)\n\t\t\t{\n\t\t\t\treturn \"[json.exception.\" + ename + \".\" + std::to_string(id_) + \"] \";\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// an exception object as storage for error messages\n\t\t\tstd::runtime_error m;\n\t\t};\n\n\t\t/*!\n\t\t@brief exception indicating a parse error\n\n\t\tThis excpetion is thrown by the library when a parse error occurs. Parse errors\n\t\tcan occur during the deserialization of JSON text, CBOR, MessagePack, as well\n\t\tas when using JSON Patch.\n\n\t\tMember @a byte holds the byte index of the last read character in the input\n\t\tfile.\n\n\t\tExceptions have ids 1xx.\n\n\t\tname / id                      | example message | description\n\t\t------------------------------ | --------------- | -------------------------\n\t\tjson.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.\n\t\tjson.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\\uxxxx` entries (\"surrogate pairs\"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.\n\t\tjson.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.\n\t\tjson.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.\n\t\tjson.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one \"op\" member, whose value indicates the operation to perform. Its value must be one of \"add\", \"remove\", \"replace\", \"move\", \"copy\", or \"test\"; other values are errors.\n\t\tjson.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number wihtout a leading `0`.\n\t\tjson.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.\n\t\tjson.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.\n\t\tjson.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.\n\t\tjson.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.\n\t\tjson.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xf8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.\n\t\tjson.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.\n\n\t\t@note For an input with n bytes, 1 is the index of the first character and n+1\n\t\tis the index of the terminating null byte or the end of file. This also\n\t\tholds true when reading a byte vector (CBOR or MessagePack).\n\n\t\t@liveexample{The following code shows how a `parse_error` exception can be\n\t\tcaught.,parse_error}\n\n\t\t@sa @ref exception for the base class of the library exceptions\n\t\t@sa @ref invalid_iterator for exceptions indicating errors with iterators\n\t\t@sa @ref type_error for exceptions indicating executing a member function with\n\t\ta wrong type\n\t\t@sa @ref out_of_range for exceptions indicating access out of the defined range\n\t\t@sa @ref other_error for exceptions indicating other library errors\n\n\t\t@since version 3.0.0\n\t\t*/\n\t\tclass parse_error : public exception\n\t\t{\n\t\tpublic:\n\t\t\t/*!\n\t\t\t@brief create a parse error exception\n\t\t\t@param[in] id_       the id of the exception\n\t\t\t@param[in] byte_     the byte index where the error occurred (or 0 if the\n\t\t\tposition cannot be determined)\n\t\t\t@param[in] what_arg  the explanatory string\n\t\t\t@return parse_error object\n\t\t\t*/\n\t\t\tstatic parse_error create(int id_, std::size_t byte_, const std::string& what_arg)\n\t\t\t{\n\t\t\t\tstd::string w = exception::name(\"parse_error\", id_) + \"parse error\" +\n\t\t\t\t\t(byte_ != 0 ? (\" at \" + std::to_string(byte_)) : \"\") +\n\t\t\t\t\t\": \" + what_arg;\n\t\t\t\treturn parse_error(id_, byte_, w.c_str());\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief byte index of the parse error\n\n\t\t\tThe byte index of the last read character in the input file.\n\n\t\t\t@note For an input with n bytes, 1 is the index of the first character and\n\t\t\tn+1 is the index of the terminating null byte or the end of file.\n\t\t\tThis also holds true when reading a byte vector (CBOR or MessagePack).\n\t\t\t*/\n\t\t\tconst std::size_t byte;\n\n\t\tprivate:\n\t\t\tparse_error(int id_, std::size_t byte_, const char* what_arg)\n\t\t\t\t: exception(id_, what_arg), byte(byte_) {}\n\t\t};\n\n\t\t/*!\n\t\t@brief exception indicating errors with iterators\n\n\t\tThis exception is thrown if iterators passed to a library function do not match\n\t\tthe expected semantics.\n\n\t\tExceptions have ids 2xx.\n\n\t\tname / id                           | example message | description\n\t\t----------------------------------- | --------------- | -------------------------\n\t\tjson.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.\n\t\tjson.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.\n\t\tjson.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.\n\t\tjson.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.\n\t\tjson.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.\n\t\tjson.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.\n\t\tjson.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.\n\t\tjson.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.\n\t\tjson.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.\n\t\tjson.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.\n\t\tjson.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.\n\t\tjson.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.\n\t\tjson.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.\n\t\tjson.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().\n\n\t\t@liveexample{The following code shows how an `invalid_iterator` exception can be\n\t\tcaught.,invalid_iterator}\n\n\t\t@sa @ref exception for the base class of the library exceptions\n\t\t@sa @ref parse_error for exceptions indicating a parse error\n\t\t@sa @ref type_error for exceptions indicating executing a member function with\n\t\ta wrong type\n\t\t@sa @ref out_of_range for exceptions indicating access out of the defined range\n\t\t@sa @ref other_error for exceptions indicating other library errors\n\n\t\t@since version 3.0.0\n\t\t*/\n\t\tclass invalid_iterator : public exception\n\t\t{\n\t\tpublic:\n\t\t\tstatic invalid_iterator create(int id_, const std::string& what_arg)\n\t\t\t{\n\t\t\t\tstd::string w = exception::name(\"invalid_iterator\", id_) + what_arg;\n\t\t\t\treturn invalid_iterator(id_, w.c_str());\n\t\t\t}\n\n\t\tprivate:\n\t\t\tinvalid_iterator(int id_, const char* what_arg)\n\t\t\t\t: exception(id_, what_arg) {}\n\t\t};\n\n\t\t/*!\n\t\t@brief exception indicating executing a member function with a wrong type\n\n\t\tThis exception is thrown in case of a type error; that is, a library function is\n\t\texecuted on a JSON value whose type does not match the expected semantics.\n\n\t\tExceptions have ids 3xx.\n\n\t\tname / id                     | example message | description\n\t\t----------------------------- | --------------- | -------------------------\n\t\tjson.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.\n\t\tjson.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.\n\t\tjson.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.\n\t\tjson.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.\n\t\tjson.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.\n\t\tjson.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.\n\t\tjson.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.\n\t\tjson.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.\n\t\tjson.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.\n\t\tjson.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.\n\t\tjson.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.\n\t\tjson.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.\n\t\tjson.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.\n\t\tjson.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.\n\t\tjson.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.\n\n\t\t@liveexample{The following code shows how a `type_error` exception can be\n\t\tcaught.,type_error}\n\n\t\t@sa @ref exception for the base class of the library exceptions\n\t\t@sa @ref parse_error for exceptions indicating a parse error\n\t\t@sa @ref invalid_iterator for exceptions indicating errors with iterators\n\t\t@sa @ref out_of_range for exceptions indicating access out of the defined range\n\t\t@sa @ref other_error for exceptions indicating other library errors\n\n\t\t@since version 3.0.0\n\t\t*/\n\t\tclass type_error : public exception\n\t\t{\n\t\tpublic:\n\t\t\tstatic type_error create(int id_, const std::string& what_arg)\n\t\t\t{\n\t\t\t\tstd::string w = exception::name(\"type_error\", id_) + what_arg;\n\t\t\t\treturn type_error(id_, w.c_str());\n\t\t\t}\n\n\t\tprivate:\n\t\t\ttype_error(int id_, const char* what_arg) : exception(id_, what_arg) {}\n\t\t};\n\n\t\t/*!\n\t\t@brief exception indicating access out of the defined range\n\n\t\tThis exception is thrown in case a library function is called on an input\n\t\tparameter that exceeds the expected range, for instance in case of array\n\t\tindices or nonexisting object keys.\n\n\t\tExceptions have ids 4xx.\n\n\t\tname / id                       | example message | description\n\t\t------------------------------- | --------------- | -------------------------\n\t\tjson.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.\n\t\tjson.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.\n\t\tjson.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.\n\t\tjson.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.\n\t\tjson.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.\n\t\tjson.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.\n\n\t\t@liveexample{The following code shows how an `out_of_range` exception can be\n\t\tcaught.,out_of_range}\n\n\t\t@sa @ref exception for the base class of the library exceptions\n\t\t@sa @ref parse_error for exceptions indicating a parse error\n\t\t@sa @ref invalid_iterator for exceptions indicating errors with iterators\n\t\t@sa @ref type_error for exceptions indicating executing a member function with\n\t\ta wrong type\n\t\t@sa @ref other_error for exceptions indicating other library errors\n\n\t\t@since version 3.0.0\n\t\t*/\n\t\tclass out_of_range : public exception\n\t\t{\n\t\tpublic:\n\t\t\tstatic out_of_range create(int id_, const std::string& what_arg)\n\t\t\t{\n\t\t\t\tstd::string w = exception::name(\"out_of_range\", id_) + what_arg;\n\t\t\t\treturn out_of_range(id_, w.c_str());\n\t\t\t}\n\n\t\tprivate:\n\t\t\tout_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}\n\t\t};\n\n\t\t/*!\n\t\t@brief exception indicating other library errors\n\n\t\tThis exception is thrown in case of errors that cannot be classified with the\n\t\tother exception types.\n\n\t\tExceptions have ids 5xx.\n\n\t\tname / id                      | example message | description\n\t\t------------------------------ | --------------- | -------------------------\n\t\tjson.exception.other_error.501 | unsuccessful: {\"op\":\"test\",\"path\":\"/baz\", \"value\":\"bar\"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.\n\t\tjson.exception.other_error.502 | invalid object size for conversion | Some conversions to user-defined types impose constraints on the object size (e.g. std::pair)\n\n\t\t@sa @ref exception for the base class of the library exceptions\n\t\t@sa @ref parse_error for exceptions indicating a parse error\n\t\t@sa @ref invalid_iterator for exceptions indicating errors with iterators\n\t\t@sa @ref type_error for exceptions indicating executing a member function with\n\t\ta wrong type\n\t\t@sa @ref out_of_range for exceptions indicating access out of the defined range\n\n\t\t@liveexample{The following code shows how an `other_error` exception can be\n\t\tcaught.,other_error}\n\n\t\t@since version 3.0.0\n\t\t*/\n\t\tclass other_error : public exception\n\t\t{\n\t\tpublic:\n\t\t\tstatic other_error create(int id_, const std::string& what_arg)\n\t\t\t{\n\t\t\t\tstd::string w = exception::name(\"other_error\", id_) + what_arg;\n\t\t\t\treturn other_error(id_, w.c_str());\n\t\t\t}\n\n\t\tprivate:\n\t\t\tother_error(int id_, const char* what_arg) : exception(id_, what_arg) {}\n\t\t};\n\n\n\n\t\t///////////////////////////\n\t\t// JSON type enumeration //\n\t\t///////////////////////////\n\n\t\t/*!\n\t\t@brief the JSON type enumeration\n\n\t\tThis enumeration collects the different JSON types. It is internally used to\n\t\tdistinguish the stored values, and the functions @ref basic_json::is_null(),\n\t\t@ref basic_json::is_object(), @ref basic_json::is_array(),\n\t\t@ref basic_json::is_string(), @ref basic_json::is_boolean(),\n\t\t@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),\n\t\t@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),\n\t\t@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and\n\t\t@ref basic_json::is_structured() rely on it.\n\n\t\t@note There are three enumeration entries (number_integer, number_unsigned, and\n\t\tnumber_float), because the library distinguishes these three types for numbers:\n\t\t@ref basic_json::number_unsigned_t is used for unsigned integers,\n\t\t@ref basic_json::number_integer_t is used for signed integers, and\n\t\t@ref basic_json::number_float_t is used for floating-point numbers or to\n\t\tapproximate integers which do not fit in the limits of their respective type.\n\n\t\t@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON\n\t\tvalue with the default value for a given type\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tenum class value_t : uint8_t\n\t\t{\n\t\t\tnull,             ///< null value\n\t\t\tobject,           ///< object (unordered set of name/value pairs)\n\t\t\tarray,            ///< array (ordered collection of values)\n\t\t\tstring,           ///< string value\n\t\t\tboolean,          ///< boolean value\n\t\t\tnumber_integer,   ///< number value (signed integer)\n\t\t\tnumber_unsigned,  ///< number value (unsigned integer)\n\t\t\tnumber_float,     ///< number value (floating-point)\n\t\t\tdiscarded         ///< discarded by the the parser callback function\n\t\t};\n\n\t\t/*!\n\t\t@brief comparison operator for JSON types\n\n\t\tReturns an ordering that is similar to Python:\n\t\t- order: null < boolean < number < object < array < string\n\t\t- furthermore, each type is not smaller than itself\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tinline bool operator<(const value_t lhs, const value_t rhs) noexcept\n\t\t{\n\t\t\tstatic constexpr std::array<uint8_t, 8> order = { {\n\t\t\t\t\t0, // null\n\t\t\t\t\t3, // object\n\t\t\t\t\t4, // array\n\t\t\t\t\t5, // string\n\t\t\t\t\t1, // boolean\n\t\t\t\t\t2, // integer\n\t\t\t\t\t2, // unsigned\n\t\t\t\t\t2, // float\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// discarded values are not comparable\n\t\t\treturn lhs != value_t::discarded and rhs != value_t::discarded and\n\t\t\t\torder[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];\n\t\t}\n\n\n\t\t/////////////\n\t\t// helpers //\n\t\t/////////////\n\n\t\ttemplate<typename> struct is_basic_json : std::false_type {};\n\n\t\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\t\tstruct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};\n\n\t\t// alias templates to reduce boilerplate\n\t\ttemplate<bool B, typename T = void>\n\t\tusing enable_if_t = typename std::enable_if<B, T>::type;\n\n\t\ttemplate<typename T>\n\t\tusing uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;\n\n\t\t// implementation of C++14 index_sequence and affiliates\n\t\t// source: https://stackoverflow.com/a/32223343\n\t\ttemplate<std::size_t... Ints>\n\t\tstruct index_sequence\n\t\t{\n\t\t\tusing type = index_sequence;\n\t\t\tusing value_type = std::size_t;\n\t\t\tstatic constexpr std::size_t size() noexcept\n\t\t\t{\n\t\t\t\treturn sizeof...(Ints);\n\t\t\t}\n\t\t};\n\n\t\ttemplate<class Sequence1, class Sequence2>\n\t\tstruct merge_and_renumber;\n\n\t\ttemplate<std::size_t... I1, std::size_t... I2>\n\t\tstruct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>\n\t\t\t: index_sequence < I1..., (sizeof...(I1)+I2)... >\n\t\t{};\n\n\t\ttemplate<std::size_t N>\n\t\tstruct make_index_sequence\n\t\t\t: merge_and_renumber < typename make_index_sequence < N / 2 >::type,\n\t\t\ttypename make_index_sequence < N - N / 2 >::type >\n\t\t{};\n\n\t\ttemplate<> struct make_index_sequence<0> : index_sequence<> { };\n\t\ttemplate<> struct make_index_sequence<1> : index_sequence<0> { };\n\n\t\ttemplate<typename... Ts>\n\t\tusing index_sequence_for = make_index_sequence<sizeof...(Ts)>;\n\n\t\t/*\n\t\tImplementation of two C++17 constructs: conjunction, negation. This is needed\n\t\tto avoid evaluating all the traits in a condition\n\n\t\tFor example: not std::is_same<void, T>::value and has_value_type<T>::value\n\t\twill not compile when T = void (on MSVC at least). Whereas\n\t\tconjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will\n\t\tstop evaluating if negation<...>::value == false\n\n\t\tPlease note that those constructs must be used with caution, since symbols can\n\t\tbecome very long quickly (which can slow down compilation and cause MSVC\n\t\tinternal compiler errors). Only use it when you have to (see example ahead).\n\t\t*/\n\t\ttemplate<class...> struct conjunction : std::true_type {};\n\t\ttemplate<class B1> struct conjunction<B1> : B1 {};\n\t\ttemplate<class B1, class... Bn>\n\t\tstruct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};\n\n\t\ttemplate<class B> struct negation : std::integral_constant < bool, !B::value > {};\n\n\t\t// dispatch utility (taken from ranges-v3)\n\t\ttemplate<unsigned N> struct priority_tag : priority_tag < N - 1 > {};\n\t\ttemplate<> struct priority_tag<0> {};\n\n\n\t\t//////////////////\n\t\t// constructors //\n\t\t//////////////////\n\n\t\ttemplate<value_t> struct external_constructor;\n\n\t\ttemplate<>\n\t\tstruct external_constructor<value_t::boolean>\n\t\t{\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept\n\t\t\t{\n\t\t\t\tj.m_type = value_t::boolean;\n\t\t\t\tj.m_value = b;\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\t\t};\n\n\t\ttemplate<>\n\t\tstruct external_constructor<value_t::string>\n\t\t{\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)\n\t\t\t{\n\t\t\t\tj.m_type = value_t::string;\n\t\t\t\tj.m_value = s;\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)\n\t\t\t{\n\t\t\t\tj.m_type = value_t::string;\n\t\t\t\tj.m_value = std::move(s);\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\t\t};\n\n\t\ttemplate<>\n\t\tstruct external_constructor<value_t::number_float>\n\t\t{\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept\n\t\t\t{\n\t\t\t\tj.m_type = value_t::number_float;\n\t\t\t\tj.m_value = val;\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\t\t};\n\n\t\ttemplate<>\n\t\tstruct external_constructor<value_t::number_unsigned>\n\t\t{\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept\n\t\t\t{\n\t\t\t\tj.m_type = value_t::number_unsigned;\n\t\t\t\tj.m_value = val;\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\t\t};\n\n\t\ttemplate<>\n\t\tstruct external_constructor<value_t::number_integer>\n\t\t{\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept\n\t\t\t{\n\t\t\t\tj.m_type = value_t::number_integer;\n\t\t\t\tj.m_value = val;\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\t\t};\n\n\t\ttemplate<>\n\t\tstruct external_constructor<value_t::array>\n\t\t{\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)\n\t\t\t{\n\t\t\t\tj.m_type = value_t::array;\n\t\t\t\tj.m_value = arr;\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)\n\t\t\t{\n\t\t\t\tj.m_type = value_t::array;\n\t\t\t\tj.m_value = std::move(arr);\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\n\t\t\ttemplate<typename BasicJsonType, typename CompatibleArrayType,\n\t\t\t\tenable_if_t<not std::is_same<CompatibleArrayType,\n\t\t\t\ttypename BasicJsonType::array_t>::value,\n\t\t\t\tint> = 0>\n\t\t\t\tstatic void construct(BasicJsonType& j, const CompatibleArrayType& arr)\n\t\t\t{\n\t\t\t\tusing std::begin;\n\t\t\t\tusing std::end;\n\t\t\t\tj.m_type = value_t::array;\n\t\t\t\tj.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, const std::vector<bool>& arr)\n\t\t\t{\n\t\t\t\tj.m_type = value_t::array;\n\t\t\t\tj.m_value = value_t::array;\n\t\t\t\tj.m_value.array->reserve(arr.size());\n\t\t\t\tfor (bool x : arr)\n\t\t\t\t{\n\t\t\t\t\tj.m_value.array->push_back(x);\n\t\t\t\t}\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\n\t\t\ttemplate<typename BasicJsonType, typename T,\n\t\t\t\tenable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>\n\t\t\t\tstatic void construct(BasicJsonType& j, const std::valarray<T>& arr)\n\t\t\t{\n\t\t\t\tj.m_type = value_t::array;\n\t\t\t\tj.m_value = value_t::array;\n\t\t\t\tj.m_value.array->resize(arr.size());\n\t\t\t\tstd::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\t\t};\n\n\t\ttemplate<>\n\t\tstruct external_constructor<value_t::object>\n\t\t{\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)\n\t\t\t{\n\t\t\t\tj.m_type = value_t::object;\n\t\t\t\tj.m_value = obj;\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\n\t\t\ttemplate<typename BasicJsonType>\n\t\t\tstatic void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)\n\t\t\t{\n\t\t\t\tj.m_type = value_t::object;\n\t\t\t\tj.m_value = std::move(obj);\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\n\t\t\ttemplate<typename BasicJsonType, typename CompatibleObjectType,\n\t\t\t\tenable_if_t<not std::is_same<CompatibleObjectType,\n\t\t\t\ttypename BasicJsonType::object_t>::value, int> = 0>\n\t\t\t\tstatic void construct(BasicJsonType& j, const CompatibleObjectType& obj)\n\t\t\t{\n\t\t\t\tusing std::begin;\n\t\t\t\tusing std::end;\n\n\t\t\t\tj.m_type = value_t::object;\n\t\t\t\tj.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));\n\t\t\t\tj.assert_invariant();\n\t\t\t}\n\t\t};\n\n\n\t\t////////////////////////\n\t\t// has_/is_ functions //\n\t\t////////////////////////\n\n\t\t/*!\n\t\t@brief Helper to determine whether there's a key_type for T.\n\n\t\tThis helper is used to tell associative containers apart from other containers\n\t\tsuch as sequence containers. For instance, `std::map` passes the test as it\n\t\tcontains a `mapped_type`, whereas `std::vector` fails the test.\n\n\t\t@sa http://stackoverflow.com/a/7728728/266378\n\t\t@since version 1.0.0, overworked in version 2.0.6\n\t\t*/\n#define NLOHMANN_JSON_HAS_HELPER(type)                                        \\\n    template<typename T> struct has_##type {                                  \\\n    private:                                                                  \\\n        template<typename U, typename = typename U::type>                     \\\n        static int detect(U &&);                                              \\\n        static void detect(...);                                              \\\n    public:                                                                   \\\n        static constexpr bool value =                                         \\\n                std::is_integral<decltype(detect(std::declval<T>()))>::value; \\\n    }\n\n\t\tNLOHMANN_JSON_HAS_HELPER(mapped_type);\n\t\tNLOHMANN_JSON_HAS_HELPER(key_type);\n\t\tNLOHMANN_JSON_HAS_HELPER(value_type);\n\t\tNLOHMANN_JSON_HAS_HELPER(iterator);\n\n#undef NLOHMANN_JSON_HAS_HELPER\n\n\n\t\ttemplate<bool B, class RealType, class CompatibleObjectType>\n\t\tstruct is_compatible_object_type_impl : std::false_type {};\n\n\t\ttemplate<class RealType, class CompatibleObjectType>\n\t\tstruct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>\n\t\t{\n\t\t\tstatic constexpr auto value =\n\t\t\t\tstd::is_constructible<typename RealType::key_type, typename CompatibleObjectType::key_type>::value and\n\t\t\t\tstd::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;\n\t\t};\n\n\t\ttemplate<class BasicJsonType, class CompatibleObjectType>\n\t\tstruct is_compatible_object_type\n\t\t{\n\t\t\tstatic auto constexpr value = is_compatible_object_type_impl <\n\t\t\t\tconjunction<negation<std::is_same<void, CompatibleObjectType>>,\n\t\t\t\thas_mapped_type<CompatibleObjectType>,\n\t\t\t\thas_key_type<CompatibleObjectType>>::value,\n\t\t\t\ttypename BasicJsonType::object_t, CompatibleObjectType >::value;\n\t\t};\n\n\t\ttemplate<typename BasicJsonType, typename T>\n\t\tstruct is_basic_json_nested_type\n\t\t{\n\t\t\tstatic auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or\n\t\t\t\tstd::is_same<T, typename BasicJsonType::const_iterator>::value or\n\t\t\t\tstd::is_same<T, typename BasicJsonType::reverse_iterator>::value or\n\t\t\t\tstd::is_same<T, typename BasicJsonType::const_reverse_iterator>::value;\n\t\t};\n\n\t\ttemplate<class BasicJsonType, class CompatibleArrayType>\n\t\tstruct is_compatible_array_type\n\t\t{\n\t\t\tstatic auto constexpr value =\n\t\t\t\tconjunction<negation<std::is_same<void, CompatibleArrayType>>,\n\t\t\t\tnegation<is_compatible_object_type<\n\t\t\t\tBasicJsonType, CompatibleArrayType>>,\n\t\t\t\tnegation<std::is_constructible<typename BasicJsonType::string_t,\n\t\t\t\tCompatibleArrayType>>,\n\t\t\t\tnegation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>,\n\t\t\t\thas_value_type<CompatibleArrayType>,\n\t\t\t\thas_iterator<CompatibleArrayType>>::value;\n\t\t};\n\n\t\ttemplate<bool, typename, typename>\n\t\tstruct is_compatible_integer_type_impl : std::false_type {};\n\n\t\ttemplate<typename RealIntegerType, typename CompatibleNumberIntegerType>\n\t\tstruct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>\n\t\t{\n\t\t\t// is there an assert somewhere on overflows?\n\t\t\tusing RealLimits = std::numeric_limits<RealIntegerType>;\n\t\t\tusing CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;\n\n\t\t\tstatic constexpr auto value =\n\t\t\t\tstd::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and\n\t\t\t\tCompatibleLimits::is_integer and\n\t\t\t\tRealLimits::is_signed == CompatibleLimits::is_signed;\n\t\t};\n\n\t\ttemplate<typename RealIntegerType, typename CompatibleNumberIntegerType>\n\t\tstruct is_compatible_integer_type\n\t\t{\n\t\t\tstatic constexpr auto value =\n\t\t\t\tis_compatible_integer_type_impl <\n\t\t\t\tstd::is_integral<CompatibleNumberIntegerType>::value and\n\t\t\t\tnot std::is_same<bool, CompatibleNumberIntegerType>::value,\n\t\t\t\tRealIntegerType, CompatibleNumberIntegerType > ::value;\n\t\t};\n\n\n\t\t// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists\n\t\ttemplate<typename BasicJsonType, typename T>\n\t\tstruct has_from_json\n\t\t{\n\t\tprivate:\n\t\t\t// also check the return type of from_json\n\t\t\ttemplate<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(\n\t\t\t\tstd::declval<BasicJsonType>(), std::declval<T&>()))>::value>>\n\t\t\t\tstatic int detect(U&&);\n\t\t\tstatic void detect(...);\n\n\t\tpublic:\n\t\t\tstatic constexpr bool value = std::is_integral<decltype(\n\t\t\t\tdetect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;\n\t\t};\n\n\t\t// This trait checks if JSONSerializer<T>::from_json(json const&) exists\n\t\t// this overload is used for non-default-constructible user-defined-types\n\t\ttemplate<typename BasicJsonType, typename T>\n\t\tstruct has_non_default_from_json\n\t\t{\n\t\tprivate:\n\t\t\ttemplate <\n\t\t\t\ttypename U,\n\t\t\t\ttypename = enable_if_t<std::is_same<\n\t\t\t\tT, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>\n\t\t\t\tstatic int detect(U&&);\n\t\t\tstatic void detect(...);\n\n\t\tpublic:\n\t\t\tstatic constexpr bool value = std::is_integral<decltype(detect(\n\t\t\t\tstd::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;\n\t\t};\n\n\t\t// This trait checks if BasicJsonType::json_serializer<T>::to_json exists\n\t\ttemplate<typename BasicJsonType, typename T>\n\t\tstruct has_to_json\n\t\t{\n\t\tprivate:\n\t\t\ttemplate<typename U, typename = decltype(uncvref_t<U>::to_json(\n\t\t\t\tstd::declval<BasicJsonType&>(), std::declval<T>()))>\n\t\t\t\tstatic int detect(U&&);\n\t\t\tstatic void detect(...);\n\n\t\tpublic:\n\t\t\tstatic constexpr bool value = std::is_integral<decltype(detect(\n\t\t\t\tstd::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;\n\t\t};\n\n\n\t\t/////////////\n\t\t// to_json //\n\t\t/////////////\n\n\t\ttemplate<typename BasicJsonType, typename T, enable_if_t<\n\t\t\tstd::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>\n\t\t\tvoid to_json(BasicJsonType& j, T b) noexcept\n\t\t{\n\t\t\texternal_constructor<value_t::boolean>::construct(j, b);\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename CompatibleString,\n\t\t\tenable_if_t<std::is_constructible<typename BasicJsonType::string_t,\n\t\t\tCompatibleString>::value, int> = 0>\n\t\t\tvoid to_json(BasicJsonType& j, const CompatibleString& s)\n\t\t{\n\t\t\texternal_constructor<value_t::string>::construct(j, s);\n\t\t}\n\n\t\ttemplate <typename BasicJsonType>\n\t\tvoid to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)\n\t\t{\n\t\t\texternal_constructor<value_t::string>::construct(j, std::move(s));\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename FloatType,\n\t\t\tenable_if_t<std::is_floating_point<FloatType>::value, int> = 0>\n\t\t\tvoid to_json(BasicJsonType& j, FloatType val) noexcept\n\t\t{\n\t\t\texternal_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));\n\t\t}\n\n\t\ttemplate <\n\t\t\ttypename BasicJsonType, typename CompatibleNumberUnsignedType,\n\t\t\tenable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t,\n\t\t\tCompatibleNumberUnsignedType>::value, int> = 0 >\n\t\t\tvoid to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept\n\t\t{\n\t\t\texternal_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));\n\t\t}\n\n\t\ttemplate <\n\t\t\ttypename BasicJsonType, typename CompatibleNumberIntegerType,\n\t\t\tenable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t,\n\t\t\tCompatibleNumberIntegerType>::value, int> = 0 >\n\t\t\tvoid to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept\n\t\t{\n\t\t\texternal_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename EnumType,\n\t\t\tenable_if_t<std::is_enum<EnumType>::value, int> = 0>\n\t\t\tvoid to_json(BasicJsonType& j, EnumType e) noexcept\n\t\t{\n\t\t\tusing underlying_type = typename std::underlying_type<EnumType>::type;\n\t\t\texternal_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));\n\t\t}\n\n\t\ttemplate<typename BasicJsonType>\n\t\tvoid to_json(BasicJsonType& j, const std::vector<bool>& e)\n\t\t{\n\t\t\texternal_constructor<value_t::array>::construct(j, e);\n\t\t}\n\n\t\ttemplate <\n\t\t\ttypename BasicJsonType, typename CompatibleArrayType,\n\t\t\tenable_if_t <\n\t\t\tis_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or\n\t\t\tstd::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,\n\t\t\tint > = 0 >\n\t\t\tvoid to_json(BasicJsonType& j, const CompatibleArrayType& arr)\n\t\t{\n\t\t\texternal_constructor<value_t::array>::construct(j, arr);\n\t\t}\n\n\t\ttemplate <typename BasicJsonType, typename T,\n\t\t\tenable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>\n\t\t\tvoid to_json(BasicJsonType& j, std::valarray<T> arr)\n\t\t{\n\t\t\texternal_constructor<value_t::array>::construct(j, std::move(arr));\n\t\t}\n\n\t\ttemplate <typename BasicJsonType>\n\t\tvoid to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)\n\t\t{\n\t\t\texternal_constructor<value_t::array>::construct(j, std::move(arr));\n\t\t}\n\n\t\ttemplate <\n\t\t\ttypename BasicJsonType, typename CompatibleObjectType,\n\t\t\tenable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,\n\t\t\tint> = 0 >\n\t\t\tvoid to_json(BasicJsonType& j, const CompatibleObjectType& obj)\n\t\t{\n\t\t\texternal_constructor<value_t::object>::construct(j, obj);\n\t\t}\n\n\t\ttemplate <typename BasicJsonType>\n\t\tvoid to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)\n\t\t{\n\t\t\texternal_constructor<value_t::object>::construct(j, std::move(obj));\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename T, std::size_t N,\n\t\t\tenable_if_t<not std::is_constructible<\n\t\t\ttypename BasicJsonType::string_t, T(&)[N]>::value,\n\t\t\tint> = 0>\n\t\t\tvoid to_json(BasicJsonType& j, T(&arr)[N])\n\t\t{\n\t\t\texternal_constructor<value_t::array>::construct(j, arr);\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename... Args>\n\t\tvoid to_json(BasicJsonType& j, const std::pair<Args...>& p)\n\t\t{\n\t\t\tj = { p.first, p.second };\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename Tuple, std::size_t... Idx>\n\t\tvoid to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)\n\t\t{\n\t\t\tj = { std::get<Idx>(t)... };\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename... Args>\n\t\tvoid to_json(BasicJsonType& j, const std::tuple<Args...>& t)\n\t\t{\n\t\t\tto_json_tuple_impl(j, t, index_sequence_for<Args...> {});\n\t\t}\n\n\t\t///////////////\n\t\t// from_json //\n\t\t///////////////\n\n\t\t// overloads for basic_json template parameters\n\t\ttemplate<typename BasicJsonType, typename ArithmeticType,\n\t\t\tenable_if_t<std::is_arithmetic<ArithmeticType>::value and\n\t\t\tnot std::is_same<ArithmeticType,\n\t\t\ttypename BasicJsonType::boolean_t>::value,\n\t\t\tint> = 0>\n\t\t\tvoid get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)\n\t\t{\n\t\t\tswitch (static_cast<value_t>(j))\n\t\t\t{\n\t\t\tcase value_t::number_unsigned:\n\t\t\t{\n\t\t\t\tval = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase value_t::number_integer:\n\t\t\t{\n\t\t\t\tval = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase value_t::number_float:\n\t\t\t{\n\t\t\t\tval = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(type_error::create(302, \"type must be number, but is \" + std::string(j.type_name())));\n\t\t\t}\n\t\t}\n\n\t\ttemplate<typename BasicJsonType>\n\t\tvoid from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)\n\t\t{\n\t\t\tif (JSON_UNLIKELY(not j.is_boolean()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(302, \"type must be boolean, but is \" + std::string(j.type_name())));\n\t\t\t}\n\t\t\tb = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();\n\t\t}\n\n\t\ttemplate<typename BasicJsonType>\n\t\tvoid from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)\n\t\t{\n\t\t\tif (JSON_UNLIKELY(not j.is_string()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(302, \"type must be string, but is \" + std::string(j.type_name())));\n\t\t\t}\n\t\t\ts = *j.template get_ptr<const typename BasicJsonType::string_t*>();\n\t\t}\n\n\t\ttemplate<typename BasicJsonType>\n\t\tvoid from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)\n\t\t{\n\t\t\tget_arithmetic_value(j, val);\n\t\t}\n\n\t\ttemplate<typename BasicJsonType>\n\t\tvoid from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)\n\t\t{\n\t\t\tget_arithmetic_value(j, val);\n\t\t}\n\n\t\ttemplate<typename BasicJsonType>\n\t\tvoid from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)\n\t\t{\n\t\t\tget_arithmetic_value(j, val);\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename EnumType,\n\t\t\tenable_if_t<std::is_enum<EnumType>::value, int> = 0>\n\t\t\tvoid from_json(const BasicJsonType& j, EnumType& e)\n\t\t{\n\t\t\ttypename std::underlying_type<EnumType>::type val;\n\t\t\tget_arithmetic_value(j, val);\n\t\t\te = static_cast<EnumType>(val);\n\t\t}\n\n\t\ttemplate<typename BasicJsonType>\n\t\tvoid from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)\n\t\t{\n\t\t\tif (JSON_UNLIKELY(not j.is_array()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(j.type_name())));\n\t\t\t}\n\t\t\tarr = *j.template get_ptr<const typename BasicJsonType::array_t*>();\n\t\t}\n\n\t\t// forward_list doesn't have an insert method\n\t\ttemplate<typename BasicJsonType, typename T, typename Allocator,\n\t\t\tenable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>\n\t\t\tvoid from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)\n\t\t{\n\t\t\tif (JSON_UNLIKELY(not j.is_array()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(j.type_name())));\n\t\t\t}\n\t\t\tstd::transform(j.rbegin(), j.rend(),\n\t\t\t\tstd::front_inserter(l), [](const BasicJsonType & i)\n\t\t\t{\n\t\t\t\treturn i.template get<T>();\n\t\t\t});\n\t\t}\n\n\t\t// valarray doesn't have an insert method\n\t\ttemplate<typename BasicJsonType, typename T,\n\t\t\tenable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>\n\t\t\tvoid from_json(const BasicJsonType& j, std::valarray<T>& l)\n\t\t{\n\t\t\tif (JSON_UNLIKELY(not j.is_array()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(j.type_name())));\n\t\t\t}\n\t\t\tl.resize(j.size());\n\t\t\tstd::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename CompatibleArrayType>\n\t\tvoid from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)\n\t\t{\n\t\t\tusing std::end;\n\n\t\t\tstd::transform(j.begin(), j.end(),\n\t\t\t\tstd::inserter(arr, end(arr)), [](const BasicJsonType & i)\n\t\t\t{\n\t\t\t\t// get<BasicJsonType>() returns *this, this won't call a from_json\n\t\t\t\t// method when value_type is BasicJsonType\n\t\t\t\treturn i.template get<typename CompatibleArrayType::value_type>();\n\t\t\t});\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename CompatibleArrayType>\n\t\tauto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)\n\t\t\t-> decltype(\n\t\t\t\tarr.reserve(std::declval<typename CompatibleArrayType::size_type>()),\n\t\t\t\tvoid())\n\t\t{\n\t\t\tusing std::end;\n\n\t\t\tarr.reserve(j.size());\n\t\t\tstd::transform(j.begin(), j.end(),\n\t\t\t\tstd::inserter(arr, end(arr)), [](const BasicJsonType & i)\n\t\t\t{\n\t\t\t\t// get<BasicJsonType>() returns *this, this won't call a from_json\n\t\t\t\t// method when value_type is BasicJsonType\n\t\t\t\treturn i.template get<typename CompatibleArrayType::value_type>();\n\t\t\t});\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename T, std::size_t N>\n\t\tvoid from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)\n\t\t{\n\t\t\tfor (std::size_t i = 0; i < N; ++i)\n\t\t\t{\n\t\t\t\tarr[i] = j.at(i).template get<T>();\n\t\t\t}\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename CompatibleArrayType,\n\t\t\tenable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and\n\t\t\tstd::is_convertible<BasicJsonType, typename CompatibleArrayType::value_type>::value and\n\t\t\tnot std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>\n\t\t\tvoid from_json(const BasicJsonType& j, CompatibleArrayType& arr)\n\t\t{\n\t\t\tif (JSON_UNLIKELY(not j.is_array()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(j.type_name())));\n\t\t\t}\n\n\t\t\tfrom_json_array_impl(j, arr, priority_tag<2> {});\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename CompatibleObjectType,\n\t\t\tenable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>\n\t\t\tvoid from_json(const BasicJsonType& j, CompatibleObjectType& obj)\n\t\t{\n\t\t\tif (JSON_UNLIKELY(not j.is_object()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(302, \"type must be object, but is \" + std::string(j.type_name())));\n\t\t\t}\n\n\t\t\tauto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();\n\t\t\tusing value_type = typename CompatibleObjectType::value_type;\n\t\t\tstd::transform(\n\t\t\t\tinner_object->begin(), inner_object->end(),\n\t\t\t\tstd::inserter(obj, obj.begin()),\n\t\t\t\t[](typename BasicJsonType::object_t::value_type const & p)\n\t\t\t{\n\t\t\t\treturn value_type(p.first, p.second.template get<typename CompatibleObjectType::mapped_type>());\n\t\t\t});\n\t\t}\n\n\t\t// overload for arithmetic types, not chosen for basic_json template arguments\n\t\t// (BooleanType, etc..); note: Is it really necessary to provide explicit\n\t\t// overloads for boolean_t etc. in case of a custom BooleanType which is not\n\t\t// an arithmetic type?\n\t\ttemplate<typename BasicJsonType, typename ArithmeticType,\n\t\t\tenable_if_t <\n\t\t\tstd::is_arithmetic<ArithmeticType>::value and\n\t\t\tnot std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and\n\t\t\tnot std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and\n\t\t\tnot std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and\n\t\t\tnot std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,\n\t\t\tint> = 0>\n\t\t\tvoid from_json(const BasicJsonType& j, ArithmeticType& val)\n\t\t{\n\t\t\tswitch (static_cast<value_t>(j))\n\t\t\t{\n\t\t\tcase value_t::number_unsigned:\n\t\t\t{\n\t\t\t\tval = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase value_t::number_integer:\n\t\t\t{\n\t\t\t\tval = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase value_t::number_float:\n\t\t\t{\n\t\t\t\tval = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase value_t::boolean:\n\t\t\t{\n\t\t\t\tval = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(type_error::create(302, \"type must be number, but is \" + std::string(j.type_name())));\n\t\t\t}\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename A1, typename A2>\n\t\tvoid from_json(const BasicJsonType& j, std::pair<A1, A2>& p)\n\t\t{\n\t\t\tp = { j.at(0).template get<A1>(), j.at(1).template get<A2>() };\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename Tuple, std::size_t... Idx>\n\t\tvoid from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)\n\t\t{\n\t\t\tt = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);\n\t\t}\n\n\t\ttemplate<typename BasicJsonType, typename... Args>\n\t\tvoid from_json(const BasicJsonType& j, std::tuple<Args...>& t)\n\t\t{\n\t\t\tfrom_json_tuple_impl(j, t, index_sequence_for<Args...> {});\n\t\t}\n\n\t\tstruct to_json_fn\n\t\t{\n\t\tprivate:\n\t\t\ttemplate<typename BasicJsonType, typename T>\n\t\t\tauto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward<T>(val))))\n\t\t\t\t-> decltype(to_json(j, std::forward<T>(val)), void())\n\t\t\t{\n\t\t\t\treturn to_json(j, std::forward<T>(val));\n\t\t\t}\n\n\t\t\ttemplate<typename BasicJsonType, typename T>\n\t\t\tvoid call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept\n\t\t\t{\n\t\t\t\tstatic_assert(sizeof(BasicJsonType) == 0,\n\t\t\t\t\t\"could not find to_json() method in T's namespace\");\n\t\t\t}\n\n\t\tpublic:\n\t\t\ttemplate<typename BasicJsonType, typename T>\n\t\t\tvoid operator()(BasicJsonType& j, T&& val) const\n\t\t\t\tnoexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))\n\t\t\t{\n\t\t\t\treturn call(j, std::forward<T>(val), priority_tag<1> {});\n\t\t\t}\n\t\t};\n\n\t\tstruct from_json_fn\n\t\t{\n\t\tprivate:\n\t\t\ttemplate<typename BasicJsonType, typename T>\n\t\t\tauto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const\n\t\t\t\tnoexcept(noexcept(from_json(j, val)))\n\t\t\t\t-> decltype(from_json(j, val), void())\n\t\t\t{\n\t\t\t\treturn from_json(j, val);\n\t\t\t}\n\n\t\t\ttemplate<typename BasicJsonType, typename T>\n\t\t\tvoid call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept\n\t\t\t{\n\t\t\t\tstatic_assert(sizeof(BasicJsonType) == 0,\n\t\t\t\t\t\"could not find from_json() method in T's namespace\");\n\t\t\t}\n\n\t\tpublic:\n\t\t\ttemplate<typename BasicJsonType, typename T>\n\t\t\tvoid operator()(const BasicJsonType& j, T& val) const\n\t\t\t\tnoexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))\n\t\t\t{\n\t\t\t\treturn call(j, val, priority_tag<1> {});\n\t\t\t}\n\t\t};\n\n\t\t// taken from ranges-v3\n\t\ttemplate<typename T>\n\t\tstruct static_const\n\t\t{\n\t\t\tstatic constexpr T value{};\n\t\t};\n\n\t\ttemplate<typename T>\n\t\tconstexpr T static_const<T>::value;\n\n\t\t////////////////////\n\t\t// input adapters //\n\t\t////////////////////\n\n\t\t/*!\n\t\t@brief abstract input adapter interface\n\n\t\tProduces a stream of std::char_traits<char>::int_type characters from a\n\t\tstd::istream, a buffer, or some other input type.  Accepts the return of exactly\n\t\tone non-EOF character for future input.  The int_type characters returned\n\t\tconsist of all valid char values as positive values (typically unsigned char),\n\t\tplus an EOF value outside that range, specified by the value of the function\n\t\tstd::char_traits<char>::eof().  This value is typically -1, but could be any\n\t\tarbitrary value which is not a valid char value.\n\t\t*/\n\t\tstruct input_adapter_protocol\n\t\t{\n\t\t\t/// get a character [0,255] or std::char_traits<char>::eof().\n\t\t\tvirtual std::char_traits<char>::int_type get_character() = 0;\n\t\t\t/// restore the last non-eof() character to input\n\t\t\tvirtual void unget_character() = 0;\n\t\t\tvirtual ~input_adapter_protocol() = default;\n\t\t};\n\n\t\t/// a type to simplify interfaces\n\t\tusing input_adapter_t = std::shared_ptr<input_adapter_protocol>;\n\n\t\t/*!\n\t\tInput adapter for a (caching) istream. Ignores a UFT Byte Order Mark at\n\t\tbeginning of input. Does not support changing the underlying std::streambuf\n\t\tin mid-input. Maintains underlying std::istream and std::streambuf to support\n\t\tsubsequent use of standard std::istream operations to process any input\n\t\tcharacters following those used in parsing the JSON input.  Clears the\n\t\tstd::istream flags; any input errors (e.g., EOF) will be detected by the first\n\t\tsubsequent call for input from the std::istream.\n\t\t*/\n\t\tclass input_stream_adapter : public input_adapter_protocol\n\t\t{\n\t\tpublic:\n\t\t\t~input_stream_adapter() override\n\t\t\t{\n\t\t\t\t// clear stream flags; we use underlying streambuf I/O, do not\n\t\t\t\t// maintain ifstream flags\n\t\t\t\tis.clear();\n\t\t\t}\n\n\t\t\texplicit input_stream_adapter(std::istream& i)\n\t\t\t\t: is(i), sb(*i.rdbuf())\n\t\t\t{\n\t\t\t\t// ignore Byte Order Mark at start of input\n\t\t\t\tstd::char_traits<char>::int_type c;\n\t\t\t\tif ((c = get_character()) == 0xEF)\n\t\t\t\t{\n\t\t\t\t\tif ((c = get_character()) == 0xBB)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ((c = get_character()) == 0xBF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn; // Ignore BOM\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (c != std::char_traits<char>::eof())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tis.unget();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tis.putback('\\xBB');\n\t\t\t\t\t}\n\t\t\t\t\telse if (c != std::char_traits<char>::eof())\n\t\t\t\t\t{\n\t\t\t\t\t\tis.unget();\n\t\t\t\t\t}\n\t\t\t\t\tis.putback('\\xEF');\n\t\t\t\t}\n\t\t\t\telse if (c != std::char_traits<char>::eof())\n\t\t\t\t{\n\t\t\t\t\tis.unget(); // Not BOM. Process as usual.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// delete because of pointer members\n\t\t\tinput_stream_adapter(const input_stream_adapter&) = delete;\n\t\t\tinput_stream_adapter& operator=(input_stream_adapter&) = delete;\n\n\t\t\t// std::istream/std::streambuf use std::char_traits<char>::to_int_type, to\n\t\t\t// ensure that std::char_traits<char>::eof() and the character 0xff do not\n\t\t\t// end up as the same value, eg. 0xffffffff.\n\t\t\tstd::char_traits<char>::int_type get_character() override\n\t\t\t{\n\t\t\t\treturn sb.sbumpc();\n\t\t\t}\n\n\t\t\tvoid unget_character() override\n\t\t\t{\n\t\t\t\tsb.sungetc();  // is.unget() avoided for performance\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// the associated input stream\n\t\t\tstd::istream& is;\n\t\t\tstd::streambuf& sb;\n\t\t};\n\n\t\t/// input adapter for buffer input\n\t\tclass input_buffer_adapter : public input_adapter_protocol\n\t\t{\n\t\tpublic:\n\t\t\tinput_buffer_adapter(const char* b, const std::size_t l)\n\t\t\t\t: cursor(b), limit(b + l), start(b)\n\t\t\t{\n\t\t\t\t// skip byte order mark\n\t\t\t\tif (l >= 3 and b[0] == '\\xEF' and b[1] == '\\xBB' and b[2] == '\\xBF')\n\t\t\t\t{\n\t\t\t\t\tcursor += 3;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// delete because of pointer members\n\t\t\tinput_buffer_adapter(const input_buffer_adapter&) = delete;\n\t\t\tinput_buffer_adapter& operator=(input_buffer_adapter&) = delete;\n\n\t\t\tstd::char_traits<char>::int_type get_character() noexcept override\n\t\t\t{\n\t\t\t\tif (JSON_LIKELY(cursor < limit))\n\t\t\t\t{\n\t\t\t\t\treturn std::char_traits<char>::to_int_type(*(cursor++));\n\t\t\t\t}\n\n\t\t\t\treturn std::char_traits<char>::eof();\n\t\t\t}\n\n\t\t\tvoid unget_character() noexcept override\n\t\t\t{\n\t\t\t\tif (JSON_LIKELY(cursor > start))\n\t\t\t\t{\n\t\t\t\t\t--cursor;\n\t\t\t\t}\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// pointer to the current character\n\t\t\tconst char* cursor;\n\t\t\t/// pointer past the last character\n\t\t\tconst char* limit;\n\t\t\t/// pointer to the first character\n\t\t\tconst char* start;\n\t\t};\n\n\t\tclass input_adapter\n\t\t{\n\t\tpublic:\n\t\t\t// native support\n\n\t\t\t/// input adapter for input stream\n\t\t\tinput_adapter(std::istream& i)\n\t\t\t\t: ia(std::make_shared<input_stream_adapter>(i)) {}\n\n\t\t\t/// input adapter for input stream\n\t\t\tinput_adapter(std::istream&& i)\n\t\t\t\t: ia(std::make_shared<input_stream_adapter>(i)) {}\n\n\t\t\t/// input adapter for buffer\n\t\t\ttemplate<typename CharT,\n\t\t\t\ttypename std::enable_if<\n\t\t\t\tstd::is_pointer<CharT>::value and\n\t\t\t\tstd::is_integral<\n\t\t\t\ttypename std::remove_pointer<CharT>::type>::value and\n\t\t\t\tsizeof(typename std::remove_pointer<CharT>::type) == 1,\n\t\t\t\tint>::type = 0>\n\t\t\t\tinput_adapter(CharT b, std::size_t l)\n\t\t\t\t: ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}\n\n\t\t\t// derived support\n\n\t\t\t/// input adapter for string literal\n\t\t\ttemplate<typename CharT,\n\t\t\t\ttypename std::enable_if<\n\t\t\t\tstd::is_pointer<CharT>::value and\n\t\t\t\tstd::is_integral<\n\t\t\t\ttypename std::remove_pointer<CharT>::type>::value and\n\t\t\t\tsizeof(typename std::remove_pointer<CharT>::type) == 1,\n\t\t\t\tint>::type = 0>\n\t\t\t\tinput_adapter(CharT b)\n\t\t\t\t: input_adapter(reinterpret_cast<const char*>(b),\n\t\t\t\t\tstd::strlen(reinterpret_cast<const char*>(b))) {}\n\n\t\t\t/// input adapter for iterator range with contiguous storage\n\t\t\ttemplate<class IteratorType,\n\t\t\t\ttypename std::enable_if<\n\t\t\t\tstd::is_same<typename std::iterator_traits<IteratorType>::iterator_category,\n\t\t\t\tstd::random_access_iterator_tag>::value,\n\t\t\t\tint>::type = 0>\n\t\t\t\tinput_adapter(IteratorType first, IteratorType last)\n\t\t\t{\n\t\t\t\t// assertion to check that the iterator range is indeed contiguous,\n\t\t\t\t// see http://stackoverflow.com/a/35008842/266378 for more discussion\n\t\t\t\tassert(std::accumulate(\n\t\t\t\t\tfirst, last, std::pair<bool, int>(true, 0),\n\t\t\t\t\t[&first](std::pair<bool, int> res, decltype(*first) val)\n\t\t\t\t{\n\t\t\t\t\tres.first &= (val == *(std::next(std::addressof(*first), res.second++)));\n\t\t\t\t\treturn res;\n\t\t\t\t}).first);\n\n\t\t\t\t// assertion to check that each element is 1 byte long\n\t\t\t\tstatic_assert(\n\t\t\t\t\tsizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,\n\t\t\t\t\t\"each element in the iterator range must have the size of 1 byte\");\n\n\t\t\t\tconst auto len = static_cast<size_t>(std::distance(first, last));\n\t\t\t\tif (JSON_LIKELY(len > 0))\n\t\t\t\t{\n\t\t\t\t\t// there is at least one element: use the address of first\n\t\t\t\t\tia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// the address of first cannot be used: use nullptr\n\t\t\t\t\tia = std::make_shared<input_buffer_adapter>(nullptr, len);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/// input adapter for array\n\t\t\ttemplate<class T, std::size_t N>\n\t\t\tinput_adapter(T(&array)[N])\n\t\t\t\t: input_adapter(std::begin(array), std::end(array)) {}\n\n\t\t\t/// input adapter for contiguous container\n\t\t\ttemplate <\n\t\t\t\tclass ContiguousContainer,\n\t\t\t\ttypename std::enable_if <\n\t\t\t\tnot std::is_pointer<ContiguousContainer>::value and\n\t\t\t\tstd::is_base_of<std::random_access_iterator_tag,\n\t\t\t\ttypename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,\n\t\t\t\tint >::type = 0 >\n\t\t\t\tinput_adapter(const ContiguousContainer& c)\n\t\t\t\t: input_adapter(std::begin(c), std::end(c)) {}\n\n\t\t\toperator input_adapter_t()\n\t\t\t{\n\t\t\t\treturn ia;\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// the actual adapter\n\t\t\tinput_adapter_t ia = nullptr;\n\t\t};\n\n\t\t//////////////////////\n\t\t// lexer and parser //\n\t\t//////////////////////\n\n\t\t/*!\n\t\t@brief lexical analysis\n\n\t\tThis class organizes the lexical analysis during JSON deserialization.\n\t\t*/\n\t\ttemplate<typename BasicJsonType>\n\t\tclass lexer\n\t\t{\n\t\t\tusing number_integer_t = typename BasicJsonType::number_integer_t;\n\t\t\tusing number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n\t\t\tusing number_float_t = typename BasicJsonType::number_float_t;\n\n\t\tpublic:\n\t\t\t/// token types for the parser\n\t\t\tenum class token_type\n\t\t\t{\n\t\t\t\tuninitialized,    ///< indicating the scanner is uninitialized\n\t\t\t\tliteral_true,     ///< the `true` literal\n\t\t\t\tliteral_false,    ///< the `false` literal\n\t\t\t\tliteral_null,     ///< the `null` literal\n\t\t\t\tvalue_string,     ///< a string -- use get_string() for actual value\n\t\t\t\tvalue_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value\n\t\t\t\tvalue_integer,    ///< a signed integer -- use get_number_integer() for actual value\n\t\t\t\tvalue_float,      ///< an floating point number -- use get_number_float() for actual value\n\t\t\t\tbegin_array,      ///< the character for array begin `[`\n\t\t\t\tbegin_object,     ///< the character for object begin `{`\n\t\t\t\tend_array,        ///< the character for array end `]`\n\t\t\t\tend_object,       ///< the character for object end `}`\n\t\t\t\tname_separator,   ///< the name separator `:`\n\t\t\t\tvalue_separator,  ///< the value separator `,`\n\t\t\t\tparse_error,      ///< indicating a parse error\n\t\t\t\tend_of_input,     ///< indicating the end of the input buffer\n\t\t\t\tliteral_or_value  ///< a literal or the begin of a value (only for diagnostics)\n\t\t\t};\n\n\t\t\t/// return name of values of type token_type (only used for errors)\n\t\t\tstatic const char* token_type_name(const token_type t) noexcept\n\t\t\t{\n\t\t\t\tswitch (t)\n\t\t\t\t{\n\t\t\t\tcase token_type::uninitialized:\n\t\t\t\t\treturn \"<uninitialized>\";\n\t\t\t\tcase token_type::literal_true:\n\t\t\t\t\treturn \"true literal\";\n\t\t\t\tcase token_type::literal_false:\n\t\t\t\t\treturn \"false literal\";\n\t\t\t\tcase token_type::literal_null:\n\t\t\t\t\treturn \"null literal\";\n\t\t\t\tcase token_type::value_string:\n\t\t\t\t\treturn \"string literal\";\n\t\t\t\tcase lexer::token_type::value_unsigned:\n\t\t\t\tcase lexer::token_type::value_integer:\n\t\t\t\tcase lexer::token_type::value_float:\n\t\t\t\t\treturn \"number literal\";\n\t\t\t\tcase token_type::begin_array:\n\t\t\t\t\treturn \"'['\";\n\t\t\t\tcase token_type::begin_object:\n\t\t\t\t\treturn \"'{'\";\n\t\t\t\tcase token_type::end_array:\n\t\t\t\t\treturn \"']'\";\n\t\t\t\tcase token_type::end_object:\n\t\t\t\t\treturn \"'}'\";\n\t\t\t\tcase token_type::name_separator:\n\t\t\t\t\treturn \"':'\";\n\t\t\t\tcase token_type::value_separator:\n\t\t\t\t\treturn \"','\";\n\t\t\t\tcase token_type::parse_error:\n\t\t\t\t\treturn \"<parse error>\";\n\t\t\t\tcase token_type::end_of_input:\n\t\t\t\t\treturn \"end of input\";\n\t\t\t\tcase token_type::literal_or_value:\n\t\t\t\t\treturn \"'[', '{', or a literal\";\n\t\t\t\tdefault: // catch non-enum values\n\t\t\t\t\treturn \"unknown token\"; // LCOV_EXCL_LINE\n\t\t\t\t}\n\t\t\t}\n\n\t\t\texplicit lexer(detail::input_adapter_t adapter)\n\t\t\t\t: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}\n\n\t\t\t// delete because of pointer members\n\t\t\tlexer(const lexer&) = delete;\n\t\t\tlexer& operator=(lexer&) = delete;\n\n\t\tprivate:\n\t\t\t/////////////////////\n\t\t\t// locales\n\t\t\t/////////////////////\n\n\t\t\t/// return the locale-dependent decimal point\n\t\t\tstatic char get_decimal_point() noexcept\n\t\t\t{\n\t\t\t\tconst auto loc = localeconv();\n\t\t\t\tassert(loc != nullptr);\n\t\t\t\treturn (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0];\n\t\t\t}\n\n\t\t\t/////////////////////\n\t\t\t// scan functions\n\t\t\t/////////////////////\n\n\t\t\t/*!\n\t\t\t@brief get codepoint from 4 hex characters following `\\u`\n\n\t\t\tFor input \"\\u c1 c2 c3 c4\" the codepoint is:\n\t\t\t(c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4\n\t\t\t= (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)\n\n\t\t\tFurthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'\n\t\t\tmust be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The\n\t\t\tconversion is done by subtracting the offset (0x30, 0x37, and 0x57)\n\t\t\tbetween the ASCII value of the character and the desired integer value.\n\n\t\t\t@return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or\n\t\t\tnon-hex character)\n\t\t\t*/\n\t\t\tint get_codepoint()\n\t\t\t{\n\t\t\t\t// this function only makes sense after reading `\\u`\n\t\t\t\tassert(current == 'u');\n\t\t\t\tint codepoint = 0;\n\n\t\t\t\tconst auto factors = { 12, 8, 4, 0 };\n\t\t\t\tfor (const auto factor : factors)\n\t\t\t\t{\n\t\t\t\t\tget();\n\n\t\t\t\t\tif (current >= '0' and current <= '9')\n\t\t\t\t\t{\n\t\t\t\t\t\tcodepoint += ((current - 0x30) << factor);\n\t\t\t\t\t}\n\t\t\t\t\telse if (current >= 'A' and current <= 'F')\n\t\t\t\t\t{\n\t\t\t\t\t\tcodepoint += ((current - 0x37) << factor);\n\t\t\t\t\t}\n\t\t\t\t\telse if (current >= 'a' and current <= 'f')\n\t\t\t\t\t{\n\t\t\t\t\t\tcodepoint += ((current - 0x57) << factor);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tassert(0x0000 <= codepoint and codepoint <= 0xFFFF);\n\t\t\t\treturn codepoint;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief check if the next byte(s) are inside a given range\n\n\t\t\tAdds the current byte and, for each passed range, reads a new byte and\n\t\t\tchecks if it is inside the range. If a violation was detected, set up an\n\t\t\terror message and return false. Otherwise, return true.\n\n\t\t\t@return true if and only if no range violation was detected\n\t\t\t*/\n\t\t\tbool next_byte_in_range(std::initializer_list<int> ranges)\n\t\t\t{\n\t\t\t\tassert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);\n\t\t\t\tadd(current);\n\n\t\t\t\tfor (auto range = ranges.begin(); range != ranges.end(); ++range)\n\t\t\t\t{\n\t\t\t\t\tget();\n\t\t\t\t\tif (JSON_LIKELY(*range <= current and current <= *(++range)))\n\t\t\t\t\t{\n\t\t\t\t\t\tadd(current);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\terror_message = \"invalid string: ill-formed UTF-8 byte\";\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief scan a string literal\n\n\t\t\tThis function scans a string according to Sect. 7 of RFC 7159. While\n\t\t\tscanning, bytes are escaped and copied into buffer yytext. Then the function\n\t\t\treturns successfully, yytext is *not* null-terminated (as it may contain \\0\n\t\t\tbytes), and yytext.size() is the number of bytes in the string.\n\n\t\t\t@return token_type::value_string if string could be successfully scanned,\n\t\t\ttoken_type::parse_error otherwise\n\n\t\t\t@note In case of errors, variable error_message contains a textual\n\t\t\tdescription.\n\t\t\t*/\n\t\t\ttoken_type scan_string()\n\t\t\t{\n\t\t\t\t// reset yytext (ignore opening quote)\n\t\t\t\treset();\n\n\t\t\t\t// we entered the function by reading an open quote\n\t\t\t\tassert(current == '\\\"');\n\n\t\t\t\twhile (true)\n\t\t\t\t{\n\t\t\t\t\t// get next character\n\t\t\t\t\tswitch (get())\n\t\t\t\t\t{\n\t\t\t\t\t\t// end of file while parsing string\n\t\t\t\t\tcase std::char_traits<char>::eof():\n\t\t\t\t\t{\n\t\t\t\t\t\terror_message = \"invalid string: missing closing quote\";\n\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t}\n\n\t\t\t\t\t// closing quote\n\t\t\t\t\tcase '\\\"':\n\t\t\t\t\t{\n\t\t\t\t\t\treturn token_type::value_string;\n\t\t\t\t\t}\n\n\t\t\t\t\t// escapes\n\t\t\t\t\tcase '\\\\':\n\t\t\t\t\t{\n\t\t\t\t\t\tswitch (get())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// quotation mark\n\t\t\t\t\t\tcase '\\\"':\n\t\t\t\t\t\t\tadd('\\\"');\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t// reverse solidus\n\t\t\t\t\t\tcase '\\\\':\n\t\t\t\t\t\t\tadd('\\\\');\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t// solidus\n\t\t\t\t\t\tcase '/':\n\t\t\t\t\t\t\tadd('/');\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t// backspace\n\t\t\t\t\t\tcase 'b':\n\t\t\t\t\t\t\tadd('\\b');\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t// form feed\n\t\t\t\t\t\tcase 'f':\n\t\t\t\t\t\t\tadd('\\f');\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t// line feed\n\t\t\t\t\t\tcase 'n':\n\t\t\t\t\t\t\tadd('\\n');\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t// carriage return\n\t\t\t\t\t\tcase 'r':\n\t\t\t\t\t\t\tadd('\\r');\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t// tab\n\t\t\t\t\t\tcase 't':\n\t\t\t\t\t\t\tadd('\\t');\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t// unicode escapes\n\t\t\t\t\t\tcase 'u':\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint codepoint;\n\t\t\t\t\t\t\tconst int codepoint1 = get_codepoint();\n\n\t\t\t\t\t\t\tif (JSON_UNLIKELY(codepoint1 == -1))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terror_message = \"invalid string: '\\\\u' must be followed by 4 hex digits\";\n\t\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// check if code point is a high surrogate\n\t\t\t\t\t\t\tif (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// expect next \\uxxxx entry\n\t\t\t\t\t\t\t\tif (JSON_LIKELY(get() == '\\\\' and get() == 'u'))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tconst int codepoint2 = get_codepoint();\n\n\t\t\t\t\t\t\t\t\tif (JSON_UNLIKELY(codepoint2 == -1))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\terror_message = \"invalid string: '\\\\u' must be followed by 4 hex digits\";\n\t\t\t\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// check if codepoint2 is a low surrogate\n\t\t\t\t\t\t\t\t\tif (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tcodepoint =\n\t\t\t\t\t\t\t\t\t\t\t// high surrogate occupies the most significant 22 bits\n\t\t\t\t\t\t\t\t\t\t\t(codepoint1 << 10)\n\t\t\t\t\t\t\t\t\t\t\t// low surrogate occupies the least significant 15 bits\n\t\t\t\t\t\t\t\t\t\t\t+ codepoint2\n\t\t\t\t\t\t\t\t\t\t\t// there is still the 0xD800, 0xDC00 and 0x10000 noise\n\t\t\t\t\t\t\t\t\t\t\t// in the result so we have to subtract with:\n\t\t\t\t\t\t\t\t\t\t\t// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00\n\t\t\t\t\t\t\t\t\t\t\t-0x35FDC00;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\terror_message = \"invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF\";\n\t\t\t\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\terror_message = \"invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF\";\n\t\t\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\terror_message = \"invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF\";\n\t\t\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// only work with first code point\n\t\t\t\t\t\t\t\tcodepoint = codepoint1;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// result of the above calculation yields a proper codepoint\n\t\t\t\t\t\t\tassert(0x00 <= codepoint and codepoint <= 0x10FFFF);\n\n\t\t\t\t\t\t\t// translate code point to bytes\n\t\t\t\t\t\t\tif (codepoint < 0x80)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// 1-byte characters: 0xxxxxxx (ASCII)\n\t\t\t\t\t\t\t\tadd(codepoint);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (codepoint <= 0x7ff)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// 2-byte characters: 110xxxxx 10xxxxxx\n\t\t\t\t\t\t\t\tadd(0xC0 | (codepoint >> 6));\n\t\t\t\t\t\t\t\tadd(0x80 | (codepoint & 0x3F));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (codepoint <= 0xffff)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx\n\t\t\t\t\t\t\t\tadd(0xE0 | (codepoint >> 12));\n\t\t\t\t\t\t\t\tadd(0x80 | ((codepoint >> 6) & 0x3F));\n\t\t\t\t\t\t\t\tadd(0x80 | (codepoint & 0x3F));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n\t\t\t\t\t\t\t\tadd(0xF0 | (codepoint >> 18));\n\t\t\t\t\t\t\t\tadd(0x80 | ((codepoint >> 12) & 0x3F));\n\t\t\t\t\t\t\t\tadd(0x80 | ((codepoint >> 6) & 0x3F));\n\t\t\t\t\t\t\t\tadd(0x80 | (codepoint & 0x3F));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// other characters after escape\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\terror_message = \"invalid string: forbidden character after backslash\";\n\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// invalid control characters\n\t\t\t\t\tcase 0x00:\n\t\t\t\t\tcase 0x01:\n\t\t\t\t\tcase 0x02:\n\t\t\t\t\tcase 0x03:\n\t\t\t\t\tcase 0x04:\n\t\t\t\t\tcase 0x05:\n\t\t\t\t\tcase 0x06:\n\t\t\t\t\tcase 0x07:\n\t\t\t\t\tcase 0x08:\n\t\t\t\t\tcase 0x09:\n\t\t\t\t\tcase 0x0a:\n\t\t\t\t\tcase 0x0b:\n\t\t\t\t\tcase 0x0c:\n\t\t\t\t\tcase 0x0d:\n\t\t\t\t\tcase 0x0e:\n\t\t\t\t\tcase 0x0f:\n\t\t\t\t\tcase 0x10:\n\t\t\t\t\tcase 0x11:\n\t\t\t\t\tcase 0x12:\n\t\t\t\t\tcase 0x13:\n\t\t\t\t\tcase 0x14:\n\t\t\t\t\tcase 0x15:\n\t\t\t\t\tcase 0x16:\n\t\t\t\t\tcase 0x17:\n\t\t\t\t\tcase 0x18:\n\t\t\t\t\tcase 0x19:\n\t\t\t\t\tcase 0x1a:\n\t\t\t\t\tcase 0x1b:\n\t\t\t\t\tcase 0x1c:\n\t\t\t\t\tcase 0x1d:\n\t\t\t\t\tcase 0x1e:\n\t\t\t\t\tcase 0x1f:\n\t\t\t\t\t{\n\t\t\t\t\t\terror_message = \"invalid string: control character must be escaped\";\n\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t}\n\n\t\t\t\t\t// U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))\n\t\t\t\t\tcase 0x20:\n\t\t\t\t\tcase 0x21:\n\t\t\t\t\tcase 0x23:\n\t\t\t\t\tcase 0x24:\n\t\t\t\t\tcase 0x25:\n\t\t\t\t\tcase 0x26:\n\t\t\t\t\tcase 0x27:\n\t\t\t\t\tcase 0x28:\n\t\t\t\t\tcase 0x29:\n\t\t\t\t\tcase 0x2a:\n\t\t\t\t\tcase 0x2b:\n\t\t\t\t\tcase 0x2c:\n\t\t\t\t\tcase 0x2d:\n\t\t\t\t\tcase 0x2e:\n\t\t\t\t\tcase 0x2f:\n\t\t\t\t\tcase 0x30:\n\t\t\t\t\tcase 0x31:\n\t\t\t\t\tcase 0x32:\n\t\t\t\t\tcase 0x33:\n\t\t\t\t\tcase 0x34:\n\t\t\t\t\tcase 0x35:\n\t\t\t\t\tcase 0x36:\n\t\t\t\t\tcase 0x37:\n\t\t\t\t\tcase 0x38:\n\t\t\t\t\tcase 0x39:\n\t\t\t\t\tcase 0x3a:\n\t\t\t\t\tcase 0x3b:\n\t\t\t\t\tcase 0x3c:\n\t\t\t\t\tcase 0x3d:\n\t\t\t\t\tcase 0x3e:\n\t\t\t\t\tcase 0x3f:\n\t\t\t\t\tcase 0x40:\n\t\t\t\t\tcase 0x41:\n\t\t\t\t\tcase 0x42:\n\t\t\t\t\tcase 0x43:\n\t\t\t\t\tcase 0x44:\n\t\t\t\t\tcase 0x45:\n\t\t\t\t\tcase 0x46:\n\t\t\t\t\tcase 0x47:\n\t\t\t\t\tcase 0x48:\n\t\t\t\t\tcase 0x49:\n\t\t\t\t\tcase 0x4a:\n\t\t\t\t\tcase 0x4b:\n\t\t\t\t\tcase 0x4c:\n\t\t\t\t\tcase 0x4d:\n\t\t\t\t\tcase 0x4e:\n\t\t\t\t\tcase 0x4f:\n\t\t\t\t\tcase 0x50:\n\t\t\t\t\tcase 0x51:\n\t\t\t\t\tcase 0x52:\n\t\t\t\t\tcase 0x53:\n\t\t\t\t\tcase 0x54:\n\t\t\t\t\tcase 0x55:\n\t\t\t\t\tcase 0x56:\n\t\t\t\t\tcase 0x57:\n\t\t\t\t\tcase 0x58:\n\t\t\t\t\tcase 0x59:\n\t\t\t\t\tcase 0x5a:\n\t\t\t\t\tcase 0x5b:\n\t\t\t\t\tcase 0x5d:\n\t\t\t\t\tcase 0x5e:\n\t\t\t\t\tcase 0x5f:\n\t\t\t\t\tcase 0x60:\n\t\t\t\t\tcase 0x61:\n\t\t\t\t\tcase 0x62:\n\t\t\t\t\tcase 0x63:\n\t\t\t\t\tcase 0x64:\n\t\t\t\t\tcase 0x65:\n\t\t\t\t\tcase 0x66:\n\t\t\t\t\tcase 0x67:\n\t\t\t\t\tcase 0x68:\n\t\t\t\t\tcase 0x69:\n\t\t\t\t\tcase 0x6a:\n\t\t\t\t\tcase 0x6b:\n\t\t\t\t\tcase 0x6c:\n\t\t\t\t\tcase 0x6d:\n\t\t\t\t\tcase 0x6e:\n\t\t\t\t\tcase 0x6f:\n\t\t\t\t\tcase 0x70:\n\t\t\t\t\tcase 0x71:\n\t\t\t\t\tcase 0x72:\n\t\t\t\t\tcase 0x73:\n\t\t\t\t\tcase 0x74:\n\t\t\t\t\tcase 0x75:\n\t\t\t\t\tcase 0x76:\n\t\t\t\t\tcase 0x77:\n\t\t\t\t\tcase 0x78:\n\t\t\t\t\tcase 0x79:\n\t\t\t\t\tcase 0x7a:\n\t\t\t\t\tcase 0x7b:\n\t\t\t\t\tcase 0x7c:\n\t\t\t\t\tcase 0x7d:\n\t\t\t\t\tcase 0x7e:\n\t\t\t\t\tcase 0x7f:\n\t\t\t\t\t{\n\t\t\t\t\t\tadd(current);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// U+0080..U+07FF: bytes C2..DF 80..BF\n\t\t\t\t\tcase 0xc2:\n\t\t\t\t\tcase 0xc3:\n\t\t\t\t\tcase 0xc4:\n\t\t\t\t\tcase 0xc5:\n\t\t\t\t\tcase 0xc6:\n\t\t\t\t\tcase 0xc7:\n\t\t\t\t\tcase 0xc8:\n\t\t\t\t\tcase 0xc9:\n\t\t\t\t\tcase 0xca:\n\t\t\t\t\tcase 0xcb:\n\t\t\t\t\tcase 0xcc:\n\t\t\t\t\tcase 0xcd:\n\t\t\t\t\tcase 0xce:\n\t\t\t\t\tcase 0xcf:\n\t\t\t\t\tcase 0xd0:\n\t\t\t\t\tcase 0xd1:\n\t\t\t\t\tcase 0xd2:\n\t\t\t\t\tcase 0xd3:\n\t\t\t\t\tcase 0xd4:\n\t\t\t\t\tcase 0xd5:\n\t\t\t\t\tcase 0xd6:\n\t\t\t\t\tcase 0xd7:\n\t\t\t\t\tcase 0xd8:\n\t\t\t\t\tcase 0xd9:\n\t\t\t\t\tcase 0xda:\n\t\t\t\t\tcase 0xdb:\n\t\t\t\t\tcase 0xdc:\n\t\t\t\t\tcase 0xdd:\n\t\t\t\t\tcase 0xde:\n\t\t\t\t\tcase 0xdf:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (JSON_UNLIKELY(not next_byte_in_range({ 0x80, 0xBF })))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// U+0800..U+0FFF: bytes E0 A0..BF 80..BF\n\t\t\t\t\tcase 0xe0:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (JSON_UNLIKELY(not (next_byte_in_range({ 0xA0, 0xBF, 0x80, 0xBF }))))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF\n\t\t\t\t\t// U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF\n\t\t\t\t\tcase 0xe1:\n\t\t\t\t\tcase 0xe2:\n\t\t\t\t\tcase 0xe3:\n\t\t\t\t\tcase 0xe4:\n\t\t\t\t\tcase 0xe5:\n\t\t\t\t\tcase 0xe6:\n\t\t\t\t\tcase 0xe7:\n\t\t\t\t\tcase 0xe8:\n\t\t\t\t\tcase 0xe9:\n\t\t\t\t\tcase 0xea:\n\t\t\t\t\tcase 0xeb:\n\t\t\t\t\tcase 0xec:\n\t\t\t\t\tcase 0xee:\n\t\t\t\t\tcase 0xef:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (JSON_UNLIKELY(not (next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF }))))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// U+D000..U+D7FF: bytes ED 80..9F 80..BF\n\t\t\t\t\tcase 0xed:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (JSON_UNLIKELY(not (next_byte_in_range({ 0x80, 0x9F, 0x80, 0xBF }))))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF\n\t\t\t\t\tcase 0xf0:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (JSON_UNLIKELY(not (next_byte_in_range({ 0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF }))))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF\n\t\t\t\t\tcase 0xf1:\n\t\t\t\t\tcase 0xf2:\n\t\t\t\t\tcase 0xf3:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (JSON_UNLIKELY(not (next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF }))))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF\n\t\t\t\t\tcase 0xf4:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (JSON_UNLIKELY(not (next_byte_in_range({ 0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF }))))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// remaining bytes (80..C1 and F5..FF) are ill-formed\n\t\t\t\t\tdefault:\n\t\t\t\t\t{\n\t\t\t\t\t\terror_message = \"invalid string: ill-formed UTF-8 byte\";\n\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstatic void strtof(float& f, const char* str, char** endptr) noexcept\n\t\t\t{\n\t\t\t\tf = std::strtof(str, endptr);\n\t\t\t}\n\n\t\t\tstatic void strtof(double& f, const char* str, char** endptr) noexcept\n\t\t\t{\n\t\t\t\tf = std::strtod(str, endptr);\n\t\t\t}\n\n\t\t\tstatic void strtof(long double& f, const char* str, char** endptr) noexcept\n\t\t\t{\n\t\t\t\tf = std::strtold(str, endptr);\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief scan a number literal\n\n\t\t\tThis function scans a string according to Sect. 6 of RFC 7159.\n\n\t\t\tThe function is realized with a deterministic finite state machine derived\n\t\t\tfrom the grammar described in RFC 7159. Starting in state \"init\", the\n\t\t\tinput is read and used to determined the next state. Only state \"done\"\n\t\t\taccepts the number. State \"error\" is a trap state to model errors. In the\n\t\t\ttable below, \"anything\" means any character but the ones listed before.\n\n\t\t\tstate    | 0        | 1-9      | e E      | +       | -       | .        | anything\n\t\t\t---------|----------|----------|----------|---------|---------|----------|-----------\n\t\t\tinit     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]\n\t\t\tminus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]\n\t\t\tzero     | done     | done     | exponent | done    | done    | decimal1 | done\n\t\t\tany1     | any1     | any1     | exponent | done    | done    | decimal1 | done\n\t\t\tdecimal1 | decimal2 | [error]  | [error]  | [error] | [error] | [error]  | [error]\n\t\t\tdecimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done\n\t\t\texponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]\n\t\t\tsign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]\n\t\t\tany2     | any2     | any2     | done     | done    | done    | done     | done\n\n\t\t\tThe state machine is realized with one label per state (prefixed with\n\t\t\t\"scan_number_\") and `goto` statements between them. The state machine\n\t\t\tcontains cycles, but any cycle can be left when EOF is read. Therefore,\n\t\t\tthe function is guaranteed to terminate.\n\n\t\t\tDuring scanning, the read bytes are stored in yytext. This string is\n\t\t\tthen converted to a signed integer, an unsigned integer, or a\n\t\t\tfloating-point number.\n\n\t\t\t@return token_type::value_unsigned, token_type::value_integer, or\n\t\t\ttoken_type::value_float if number could be successfully scanned,\n\t\t\ttoken_type::parse_error otherwise\n\n\t\t\t@note The scanner is independent of the current locale. Internally, the\n\t\t\tlocale's decimal point is used instead of `.` to work with the\n\t\t\tlocale-dependent converters.\n\t\t\t*/\n\t\t\ttoken_type scan_number()\n\t\t\t{\n\t\t\t\t// reset yytext to store the number's bytes\n\t\t\t\treset();\n\n\t\t\t\t// the type of the parsed number; initially set to unsigned; will be\n\t\t\t\t// changed if minus sign, decimal point or exponent is read\n\t\t\t\ttoken_type number_type = token_type::value_unsigned;\n\n\t\t\t\t// state (init): we just found out we need to scan a number\n\t\t\t\tswitch (current)\n\t\t\t\t{\n\t\t\t\tcase '-':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_minus;\n\t\t\t\t}\n\n\t\t\t\tcase '0':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_zero;\n\t\t\t\t}\n\n\t\t\t\tcase '1':\n\t\t\t\tcase '2':\n\t\t\t\tcase '3':\n\t\t\t\tcase '4':\n\t\t\t\tcase '5':\n\t\t\t\tcase '6':\n\t\t\t\tcase '7':\n\t\t\t\tcase '8':\n\t\t\t\tcase '9':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_any1;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\t// all other characters are rejected outside scan_number()\n\t\t\t\t\tassert(false); // LCOV_EXCL_LINE\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tscan_number_minus:\n\t\t\t\t// state: we just parsed a leading minus sign\n\t\t\t\tnumber_type = token_type::value_integer;\n\t\t\t\tswitch (get())\n\t\t\t\t{\n\t\t\t\tcase '0':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_zero;\n\t\t\t\t}\n\n\t\t\t\tcase '1':\n\t\t\t\tcase '2':\n\t\t\t\tcase '3':\n\t\t\t\tcase '4':\n\t\t\t\tcase '5':\n\t\t\t\tcase '6':\n\t\t\t\tcase '7':\n\t\t\t\tcase '8':\n\t\t\t\tcase '9':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_any1;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\terror_message = \"invalid number; expected digit after '-'\";\n\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tscan_number_zero:\n\t\t\t\t// state: we just parse a zero (maybe with a leading minus sign)\n\t\t\t\tswitch (get())\n\t\t\t\t{\n\t\t\t\tcase '.':\n\t\t\t\t{\n\t\t\t\t\tadd(decimal_point_char);\n\t\t\t\t\tgoto scan_number_decimal1;\n\t\t\t\t}\n\n\t\t\t\tcase 'e':\n\t\t\t\tcase 'E':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_exponent;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tgoto scan_number_done;\n\t\t\t\t}\n\n\t\t\tscan_number_any1:\n\t\t\t\t// state: we just parsed a number 0-9 (maybe with a leading minus sign)\n\t\t\t\tswitch (get())\n\t\t\t\t{\n\t\t\t\tcase '0':\n\t\t\t\tcase '1':\n\t\t\t\tcase '2':\n\t\t\t\tcase '3':\n\t\t\t\tcase '4':\n\t\t\t\tcase '5':\n\t\t\t\tcase '6':\n\t\t\t\tcase '7':\n\t\t\t\tcase '8':\n\t\t\t\tcase '9':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_any1;\n\t\t\t\t}\n\n\t\t\t\tcase '.':\n\t\t\t\t{\n\t\t\t\t\tadd(decimal_point_char);\n\t\t\t\t\tgoto scan_number_decimal1;\n\t\t\t\t}\n\n\t\t\t\tcase 'e':\n\t\t\t\tcase 'E':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_exponent;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tgoto scan_number_done;\n\t\t\t\t}\n\n\t\t\tscan_number_decimal1:\n\t\t\t\t// state: we just parsed a decimal point\n\t\t\t\tnumber_type = token_type::value_float;\n\t\t\t\tswitch (get())\n\t\t\t\t{\n\t\t\t\tcase '0':\n\t\t\t\tcase '1':\n\t\t\t\tcase '2':\n\t\t\t\tcase '3':\n\t\t\t\tcase '4':\n\t\t\t\tcase '5':\n\t\t\t\tcase '6':\n\t\t\t\tcase '7':\n\t\t\t\tcase '8':\n\t\t\t\tcase '9':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_decimal2;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\terror_message = \"invalid number; expected digit after '.'\";\n\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tscan_number_decimal2:\n\t\t\t\t// we just parsed at least one number after a decimal point\n\t\t\t\tswitch (get())\n\t\t\t\t{\n\t\t\t\tcase '0':\n\t\t\t\tcase '1':\n\t\t\t\tcase '2':\n\t\t\t\tcase '3':\n\t\t\t\tcase '4':\n\t\t\t\tcase '5':\n\t\t\t\tcase '6':\n\t\t\t\tcase '7':\n\t\t\t\tcase '8':\n\t\t\t\tcase '9':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_decimal2;\n\t\t\t\t}\n\n\t\t\t\tcase 'e':\n\t\t\t\tcase 'E':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_exponent;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tgoto scan_number_done;\n\t\t\t\t}\n\n\t\t\tscan_number_exponent:\n\t\t\t\t// we just parsed an exponent\n\t\t\t\tnumber_type = token_type::value_float;\n\t\t\t\tswitch (get())\n\t\t\t\t{\n\t\t\t\tcase '+':\n\t\t\t\tcase '-':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_sign;\n\t\t\t\t}\n\n\t\t\t\tcase '0':\n\t\t\t\tcase '1':\n\t\t\t\tcase '2':\n\t\t\t\tcase '3':\n\t\t\t\tcase '4':\n\t\t\t\tcase '5':\n\t\t\t\tcase '6':\n\t\t\t\tcase '7':\n\t\t\t\tcase '8':\n\t\t\t\tcase '9':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_any2;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\terror_message =\n\t\t\t\t\t\t\"invalid number; expected '+', '-', or digit after exponent\";\n\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tscan_number_sign:\n\t\t\t\t// we just parsed an exponent sign\n\t\t\t\tswitch (get())\n\t\t\t\t{\n\t\t\t\tcase '0':\n\t\t\t\tcase '1':\n\t\t\t\tcase '2':\n\t\t\t\tcase '3':\n\t\t\t\tcase '4':\n\t\t\t\tcase '5':\n\t\t\t\tcase '6':\n\t\t\t\tcase '7':\n\t\t\t\tcase '8':\n\t\t\t\tcase '9':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_any2;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\terror_message = \"invalid number; expected digit after exponent sign\";\n\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tscan_number_any2:\n\t\t\t\t// we just parsed a number after the exponent or exponent sign\n\t\t\t\tswitch (get())\n\t\t\t\t{\n\t\t\t\tcase '0':\n\t\t\t\tcase '1':\n\t\t\t\tcase '2':\n\t\t\t\tcase '3':\n\t\t\t\tcase '4':\n\t\t\t\tcase '5':\n\t\t\t\tcase '6':\n\t\t\t\tcase '7':\n\t\t\t\tcase '8':\n\t\t\t\tcase '9':\n\t\t\t\t{\n\t\t\t\t\tadd(current);\n\t\t\t\t\tgoto scan_number_any2;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tgoto scan_number_done;\n\t\t\t\t}\n\n\t\t\tscan_number_done:\n\t\t\t\t// unget the character after the number (we only read it to know that\n\t\t\t\t// we are done scanning a number)\n\t\t\t\tunget();\n\n\t\t\t\tchar* endptr = nullptr;\n\t\t\t\terrno = 0;\n\n\t\t\t\t// try to parse integers first and fall back to floats\n\t\t\t\tif (number_type == token_type::value_unsigned)\n\t\t\t\t{\n\t\t\t\t\tconst auto x = std::strtoull(yytext.data(), &endptr, 10);\n\n\t\t\t\t\t// we checked the number format before\n\t\t\t\t\tassert(endptr == yytext.data() + yytext.size());\n\n\t\t\t\t\tif (errno == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue_unsigned = static_cast<number_unsigned_t>(x);\n\t\t\t\t\t\tif (value_unsigned == x)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn token_type::value_unsigned;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (number_type == token_type::value_integer)\n\t\t\t\t{\n\t\t\t\t\tconst auto x = std::strtoll(yytext.data(), &endptr, 10);\n\n\t\t\t\t\t// we checked the number format before\n\t\t\t\t\tassert(endptr == yytext.data() + yytext.size());\n\n\t\t\t\t\tif (errno == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue_integer = static_cast<number_integer_t>(x);\n\t\t\t\t\t\tif (value_integer == x)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn token_type::value_integer;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// this code is reached if we parse a floating-point number or if an\n\t\t\t\t// integer conversion above failed\n\t\t\t\tstrtof(value_float, yytext.data(), &endptr);\n\n\t\t\t\t// we checked the number format before\n\t\t\t\tassert(endptr == yytext.data() + yytext.size());\n\n\t\t\t\treturn token_type::value_float;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@param[in] literal_text  the literal text to expect\n\t\t\t@param[in] length        the length of the passed literal text\n\t\t\t@param[in] return_type   the token type to return on success\n\t\t\t*/\n\t\t\ttoken_type scan_literal(const char* literal_text, const std::size_t length,\n\t\t\t\ttoken_type return_type)\n\t\t\t{\n\t\t\t\tassert(current == literal_text[0]);\n\t\t\t\tfor (std::size_t i = 1; i < length; ++i)\n\t\t\t\t{\n\t\t\t\t\tif (JSON_UNLIKELY(get() != literal_text[i]))\n\t\t\t\t\t{\n\t\t\t\t\t\terror_message = \"invalid literal\";\n\t\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn return_type;\n\t\t\t}\n\n\t\t\t/////////////////////\n\t\t\t// input management\n\t\t\t/////////////////////\n\n\t\t\t/// reset yytext; current character is beginning of token\n\t\t\tvoid reset() noexcept\n\t\t\t{\n\t\t\t\tyytext.clear();\n\t\t\t\ttoken_string.clear();\n\t\t\t\ttoken_string.push_back(std::char_traits<char>::to_char_type(current));\n\t\t\t}\n\n\t\t\t/*\n\t\t\t@brief get next character from the input\n\n\t\t\tThis function provides the interface to the used input adapter. It does\n\t\t\tnot throw in case the input reached EOF, but returns a\n\t\t\t`std::char_traits<char>::eof()` in that case.  Stores the scanned characters\n\t\t\tfor use in error messages.\n\n\t\t\t@return character read from the input\n\t\t\t*/\n\t\t\tstd::char_traits<char>::int_type get()\n\t\t\t{\n\t\t\t\t++chars_read;\n\t\t\t\tcurrent = ia->get_character();\n\t\t\t\tif (JSON_LIKELY(current != std::char_traits<char>::eof()))\n\t\t\t\t{\n\t\t\t\t\ttoken_string.push_back(std::char_traits<char>::to_char_type(current));\n\t\t\t\t}\n\t\t\t\treturn current;\n\t\t\t}\n\n\t\t\t/// unget current character (return it again on next get)\n\t\t\tvoid unget()\n\t\t\t{\n\t\t\t\t--chars_read;\n\t\t\t\tif (JSON_LIKELY(current != std::char_traits<char>::eof()))\n\t\t\t\t{\n\t\t\t\t\tia->unget_character();\n\t\t\t\t\tassert(token_string.size() != 0);\n\t\t\t\t\ttoken_string.pop_back();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/// add a character to yytext\n\t\t\tvoid add(int c)\n\t\t\t{\n\t\t\t\tyytext.push_back(std::char_traits<char>::to_char_type(c));\n\t\t\t}\n\n\t\tpublic:\n\t\t\t/////////////////////\n\t\t\t// value getters\n\t\t\t/////////////////////\n\n\t\t\t/// return integer value\n\t\t\tconstexpr number_integer_t get_number_integer() const noexcept\n\t\t\t{\n\t\t\t\treturn value_integer;\n\t\t\t}\n\n\t\t\t/// return unsigned integer value\n\t\t\tconstexpr number_unsigned_t get_number_unsigned() const noexcept\n\t\t\t{\n\t\t\t\treturn value_unsigned;\n\t\t\t}\n\n\t\t\t/// return floating-point value\n\t\t\tconstexpr number_float_t get_number_float() const noexcept\n\t\t\t{\n\t\t\t\treturn value_float;\n\t\t\t}\n\n\t\t\t/// return current string value (implicitly resets the token; useful only once)\n\t\t\tstd::string move_string()\n\t\t\t{\n\t\t\t\treturn std::move(yytext);\n\t\t\t}\n\n\t\t\t/////////////////////\n\t\t\t// diagnostics\n\t\t\t/////////////////////\n\n\t\t\t/// return position of last read token\n\t\t\tconstexpr std::size_t get_position() const noexcept\n\t\t\t{\n\t\t\t\treturn chars_read;\n\t\t\t}\n\n\t\t\t/// return the last read token (for errors only).  Will never contain EOF\n\t\t\t/// (an arbitrary value that is not a valid char value, often -1), because\n\t\t\t/// 255 may legitimately occur.  May contain NUL, which should be escaped.\n\t\t\tstd::string get_token_string() const\n\t\t\t{\n\t\t\t\t// escape control characters\n\t\t\t\tstd::string result;\n\t\t\t\tfor (auto c : token_string)\n\t\t\t\t{\n\t\t\t\t\tif ('\\x00' <= c and c <= '\\x1f')\n\t\t\t\t\t{\n\t\t\t\t\t\t// escape control characters\n\t\t\t\t\t\tstd::stringstream ss;\n\t\t\t\t\t\tss << \"<U+\" << std::setw(4) << std::uppercase << std::setfill('0')\n\t\t\t\t\t\t\t<< std::hex << static_cast<int>(c) << \">\";\n\t\t\t\t\t\tresult += ss.str();\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// add character as is\n\t\t\t\t\t\tresult.push_back(c);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/// return syntax error message\n\t\t\tconstexpr const char* get_error_message() const noexcept\n\t\t\t{\n\t\t\t\treturn error_message;\n\t\t\t}\n\n\t\t\t/////////////////////\n\t\t\t// actual scanner\n\t\t\t/////////////////////\n\n\t\t\ttoken_type scan()\n\t\t\t{\n\t\t\t\t// read next character and ignore whitespace\n\t\t\t\tdo\n\t\t\t\t{\n\t\t\t\t\tget();\n\t\t\t\t} while (current == ' ' or current == '\\t' or current == '\\n' or current == '\\r');\n\n\t\t\t\tswitch (current)\n\t\t\t\t{\n\t\t\t\t\t// structural characters\n\t\t\t\tcase '[':\n\t\t\t\t\treturn token_type::begin_array;\n\t\t\t\tcase ']':\n\t\t\t\t\treturn token_type::end_array;\n\t\t\t\tcase '{':\n\t\t\t\t\treturn token_type::begin_object;\n\t\t\t\tcase '}':\n\t\t\t\t\treturn token_type::end_object;\n\t\t\t\tcase ':':\n\t\t\t\t\treturn token_type::name_separator;\n\t\t\t\tcase ',':\n\t\t\t\t\treturn token_type::value_separator;\n\n\t\t\t\t\t// literals\n\t\t\t\tcase 't':\n\t\t\t\t\treturn scan_literal(\"true\", 4, token_type::literal_true);\n\t\t\t\tcase 'f':\n\t\t\t\t\treturn scan_literal(\"false\", 5, token_type::literal_false);\n\t\t\t\tcase 'n':\n\t\t\t\t\treturn scan_literal(\"null\", 4, token_type::literal_null);\n\n\t\t\t\t\t// string\n\t\t\t\tcase '\\\"':\n\t\t\t\t\treturn scan_string();\n\n\t\t\t\t\t// number\n\t\t\t\tcase '-':\n\t\t\t\tcase '0':\n\t\t\t\tcase '1':\n\t\t\t\tcase '2':\n\t\t\t\tcase '3':\n\t\t\t\tcase '4':\n\t\t\t\tcase '5':\n\t\t\t\tcase '6':\n\t\t\t\tcase '7':\n\t\t\t\tcase '8':\n\t\t\t\tcase '9':\n\t\t\t\t\treturn scan_number();\n\n\t\t\t\t\t// end of input (the null byte is needed when parsing from\n\t\t\t\t\t// string literals)\n\t\t\t\tcase '\\0':\n\t\t\t\tcase std::char_traits<char>::eof():\n\t\t\t\t\treturn token_type::end_of_input;\n\n\t\t\t\t\t// error\n\t\t\t\tdefault:\n\t\t\t\t\terror_message = \"invalid literal\";\n\t\t\t\t\treturn token_type::parse_error;\n\t\t\t\t}\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// input adapter\n\t\t\tdetail::input_adapter_t ia = nullptr;\n\n\t\t\t/// the current character\n\t\t\tstd::char_traits<char>::int_type current = std::char_traits<char>::eof();\n\n\t\t\t/// the number of characters read\n\t\t\tstd::size_t chars_read = 0;\n\n\t\t\t/// raw input token string (for error messages)\n\t\t\tstd::vector<char> token_string{};\n\n\t\t\t/// buffer for variable-length tokens (numbers, strings)\n\t\t\tstd::string yytext{};\n\n\t\t\t/// a description of occurred lexer errors\n\t\t\tconst char* error_message = \"\";\n\n\t\t\t// number values\n\t\t\tnumber_integer_t value_integer = 0;\n\t\t\tnumber_unsigned_t value_unsigned = 0;\n\t\t\tnumber_float_t value_float = 0;\n\n\t\t\t/// the decimal point\n\t\t\tconst char decimal_point_char = '.';\n\t\t};\n\n\t\t/*!\n\t\t@brief syntax analysis\n\n\t\tThis class implements a recursive decent parser.\n\t\t*/\n\t\ttemplate<typename BasicJsonType>\n\t\tclass parser\n\t\t{\n\t\t\tusing number_integer_t = typename BasicJsonType::number_integer_t;\n\t\t\tusing number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n\t\t\tusing number_float_t = typename BasicJsonType::number_float_t;\n\t\t\tusing lexer_t = lexer<BasicJsonType>;\n\t\t\tusing token_type = typename lexer_t::token_type;\n\n\t\tpublic:\n\t\t\tenum class parse_event_t : uint8_t\n\t\t\t{\n\t\t\t\t/// the parser read `{` and started to process a JSON object\n\t\t\t\tobject_start,\n\t\t\t\t/// the parser read `}` and finished processing a JSON object\n\t\t\t\tobject_end,\n\t\t\t\t/// the parser read `[` and started to process a JSON array\n\t\t\t\tarray_start,\n\t\t\t\t/// the parser read `]` and finished processing a JSON array\n\t\t\t\tarray_end,\n\t\t\t\t/// the parser read a key of a value in an object\n\t\t\t\tkey,\n\t\t\t\t/// the parser finished reading a JSON value\n\t\t\t\tvalue\n\t\t\t};\n\n\t\t\tusing parser_callback_t =\n\t\t\t\tstd::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;\n\n\t\t\t/// a parser reading from an input adapter\n\t\t\texplicit parser(detail::input_adapter_t adapter,\n\t\t\t\tconst parser_callback_t cb = nullptr,\n\t\t\t\tconst bool allow_exceptions_ = true)\n\t\t\t\t: callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)\n\t\t\t{}\n\n\t\t\t/*!\n\t\t\t@brief public parser interface\n\n\t\t\t@param[in] strict      whether to expect the last token to be EOF\n\t\t\t@param[in,out] result  parsed JSON value\n\n\t\t\t@throw parse_error.101 in case of an unexpected token\n\t\t\t@throw parse_error.102 if to_unicode fails or surrogate error\n\t\t\t@throw parse_error.103 if to_unicode fails\n\t\t\t*/\n\t\t\tvoid parse(const bool strict, BasicJsonType& result)\n\t\t\t{\n\t\t\t\t// read first token\n\t\t\t\tget_token();\n\n\t\t\t\tparse_internal(true, result);\n\t\t\t\tresult.assert_invariant();\n\n\t\t\t\t// in strict mode, input must be completely read\n\t\t\t\tif (strict)\n\t\t\t\t{\n\t\t\t\t\tget_token();\n\t\t\t\t\texpect(token_type::end_of_input);\n\t\t\t\t}\n\n\t\t\t\t// in case of an error, return discarded value\n\t\t\t\tif (errored)\n\t\t\t\t{\n\t\t\t\t\tresult = value_t::discarded;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// set top-level value to null if it was discarded by the callback\n\t\t\t\t// function\n\t\t\t\tif (result.is_discarded())\n\t\t\t\t{\n\t\t\t\t\tresult = nullptr;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief public accept interface\n\n\t\t\t@param[in] strict  whether to expect the last token to be EOF\n\t\t\t@return whether the input is a proper JSON text\n\t\t\t*/\n\t\t\tbool accept(const bool strict = true)\n\t\t\t{\n\t\t\t\t// read first token\n\t\t\t\tget_token();\n\n\t\t\t\tif (not accept_internal())\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// strict => last token must be EOF\n\t\t\t\treturn not strict or (get_token() == token_type::end_of_input);\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/*!\n\t\t\t@brief the actual parser\n\t\t\t@throw parse_error.101 in case of an unexpected token\n\t\t\t@throw parse_error.102 if to_unicode fails or surrogate error\n\t\t\t@throw parse_error.103 if to_unicode fails\n\t\t\t*/\n\t\t\tvoid parse_internal(bool keep, BasicJsonType& result)\n\t\t\t{\n\t\t\t\t// never parse after a parse error was detected\n\t\t\t\tassert(not errored);\n\n\t\t\t\t// start with a discarded value\n\t\t\t\tif (not result.is_discarded())\n\t\t\t\t{\n\t\t\t\t\tresult.m_value.destroy(result.m_type);\n\t\t\t\t\tresult.m_type = value_t::discarded;\n\t\t\t\t}\n\n\t\t\t\tswitch (last_token)\n\t\t\t\t{\n\t\t\t\tcase token_type::begin_object:\n\t\t\t\t{\n\t\t\t\t\tif (keep)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (callback)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tkeep = callback(depth++, parse_event_t::object_start, result);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (not callback or keep)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// explicitly set result to object to cope with {}\n\t\t\t\t\t\t\tresult.m_type = value_t::object;\n\t\t\t\t\t\t\tresult.m_value = value_t::object;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// read next token\n\t\t\t\t\tget_token();\n\n\t\t\t\t\t// closing } -> we are done\n\t\t\t\t\tif (last_token == token_type::end_object)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (keep and callback and not callback(--depth, parse_event_t::object_end, result))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tresult.m_value.destroy(result.m_type);\n\t\t\t\t\t\t\tresult.m_type = value_t::discarded;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// parse values\n\t\t\t\t\tstd::string key;\n\t\t\t\t\tBasicJsonType value;\n\t\t\t\t\twhile (true)\n\t\t\t\t\t{\n\t\t\t\t\t\t// store key\n\t\t\t\t\t\tif (not expect(token_type::value_string))\n\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\tkey = m_lexer.move_string();\n\n\t\t\t\t\t\tbool keep_tag = false;\n\t\t\t\t\t\tif (keep)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (callback)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBasicJsonType k(key);\n\t\t\t\t\t\t\t\tkeep_tag = callback(depth, parse_event_t::key, k);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkeep_tag = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// parse separator (:)\n\t\t\t\t\t\tget_token();\n\t\t\t\t\t\tif (not expect(token_type::name_separator))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// parse and add value\n\t\t\t\t\t\tget_token();\n\t\t\t\t\t\tvalue.m_value.destroy(value.m_type);\n\t\t\t\t\t\tvalue.m_type = value_t::discarded;\n\t\t\t\t\t\tparse_internal(keep, value);\n\n\t\t\t\t\t\tif (JSON_UNLIKELY(errored))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (keep and keep_tag and not value.is_discarded())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tresult.m_value.object->emplace(std::move(key), std::move(value));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// comma -> next value\n\t\t\t\t\t\tget_token();\n\t\t\t\t\t\tif (last_token == token_type::value_separator)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tget_token();\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// closing }\n\t\t\t\t\t\tif (not expect(token_type::end_object))\n\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\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (keep and callback and not callback(--depth, parse_event_t::object_end, result))\n\t\t\t\t\t{\n\t\t\t\t\t\tresult.m_value.destroy(result.m_type);\n\t\t\t\t\t\tresult.m_type = value_t::discarded;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase token_type::begin_array:\n\t\t\t\t{\n\t\t\t\t\tif (keep)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (callback)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tkeep = callback(depth++, parse_event_t::array_start, result);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (not callback or keep)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// explicitly set result to array to cope with []\n\t\t\t\t\t\t\tresult.m_type = value_t::array;\n\t\t\t\t\t\t\tresult.m_value = value_t::array;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// read next token\n\t\t\t\t\tget_token();\n\n\t\t\t\t\t// closing ] -> we are done\n\t\t\t\t\tif (last_token == token_type::end_array)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (callback and not callback(--depth, parse_event_t::array_end, result))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tresult.m_value.destroy(result.m_type);\n\t\t\t\t\t\t\tresult.m_type = value_t::discarded;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// parse values\n\t\t\t\t\tBasicJsonType value;\n\t\t\t\t\twhile (true)\n\t\t\t\t\t{\n\t\t\t\t\t\t// parse value\n\t\t\t\t\t\tvalue.m_value.destroy(value.m_type);\n\t\t\t\t\t\tvalue.m_type = value_t::discarded;\n\t\t\t\t\t\tparse_internal(keep, value);\n\n\t\t\t\t\t\tif (JSON_UNLIKELY(errored))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (keep and not value.is_discarded())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tresult.m_value.array->push_back(std::move(value));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// comma -> next value\n\t\t\t\t\t\tget_token();\n\t\t\t\t\t\tif (last_token == token_type::value_separator)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tget_token();\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// closing ]\n\t\t\t\t\t\tif (not expect(token_type::end_array))\n\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\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (keep and callback and not callback(--depth, parse_event_t::array_end, result))\n\t\t\t\t\t{\n\t\t\t\t\t\tresult.m_value.destroy(result.m_type);\n\t\t\t\t\t\tresult.m_type = value_t::discarded;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase token_type::literal_null:\n\t\t\t\t{\n\t\t\t\t\tresult.m_type = value_t::null;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase token_type::value_string:\n\t\t\t\t{\n\t\t\t\t\tresult.m_type = value_t::string;\n\t\t\t\t\tresult.m_value = m_lexer.move_string();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase token_type::literal_true:\n\t\t\t\t{\n\t\t\t\t\tresult.m_type = value_t::boolean;\n\t\t\t\t\tresult.m_value = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase token_type::literal_false:\n\t\t\t\t{\n\t\t\t\t\tresult.m_type = value_t::boolean;\n\t\t\t\t\tresult.m_value = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase token_type::value_unsigned:\n\t\t\t\t{\n\t\t\t\t\tresult.m_type = value_t::number_unsigned;\n\t\t\t\t\tresult.m_value = m_lexer.get_number_unsigned();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase token_type::value_integer:\n\t\t\t\t{\n\t\t\t\t\tresult.m_type = value_t::number_integer;\n\t\t\t\t\tresult.m_value = m_lexer.get_number_integer();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase token_type::value_float:\n\t\t\t\t{\n\t\t\t\t\tresult.m_type = value_t::number_float;\n\t\t\t\t\tresult.m_value = m_lexer.get_number_float();\n\n\t\t\t\t\t// throw in case of infinity or NAN\n\t\t\t\t\tif (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float)))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (allow_exceptions)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tJSON_THROW(out_of_range::create(406, \"number overflow parsing '\" +\n\t\t\t\t\t\t\t\tm_lexer.get_token_string() + \"'\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\texpect(token_type::uninitialized);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase token_type::parse_error:\n\t\t\t\t{\n\t\t\t\t\t// using \"uninitialized\" to avoid \"expected\" message\n\t\t\t\t\tif (not expect(token_type::uninitialized))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak; // LCOV_EXCL_LINE\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\t// the last token was unexpected; we expected a value\n\t\t\t\t\tif (not expect(token_type::literal_or_value))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak; // LCOV_EXCL_LINE\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (keep and callback and not callback(depth, parse_event_t::value, result))\n\t\t\t\t{\n\t\t\t\t\tresult.m_type = value_t::discarded;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief the acutal acceptor\n\n\t\t\t@invariant 1. The last token is not yet processed. Therefore, the caller\n\t\t\tof this function must make sure a token has been read.\n\t\t\t2. When this function returns, the last token is processed.\n\t\t\tThat is, the last read character was already considered.\n\n\t\t\tThis invariant makes sure that no token needs to be \"unput\".\n\t\t\t*/\n\t\t\tbool accept_internal()\n\t\t\t{\n\t\t\t\tswitch (last_token)\n\t\t\t\t{\n\t\t\t\tcase token_type::begin_object:\n\t\t\t\t{\n\t\t\t\t\t// read next token\n\t\t\t\t\tget_token();\n\n\t\t\t\t\t// closing } -> we are done\n\t\t\t\t\tif (last_token == token_type::end_object)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// parse values\n\t\t\t\t\twhile (true)\n\t\t\t\t\t{\n\t\t\t\t\t\t// parse key\n\t\t\t\t\t\tif (last_token != token_type::value_string)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// parse separator (:)\n\t\t\t\t\t\tget_token();\n\t\t\t\t\t\tif (last_token != token_type::name_separator)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// parse value\n\t\t\t\t\t\tget_token();\n\t\t\t\t\t\tif (not accept_internal())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// comma -> next value\n\t\t\t\t\t\tget_token();\n\t\t\t\t\t\tif (last_token == token_type::value_separator)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tget_token();\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// closing }\n\t\t\t\t\t\treturn (last_token == token_type::end_object);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcase token_type::begin_array:\n\t\t\t\t{\n\t\t\t\t\t// read next token\n\t\t\t\t\tget_token();\n\n\t\t\t\t\t// closing ] -> we are done\n\t\t\t\t\tif (last_token == token_type::end_array)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// parse values\n\t\t\t\t\twhile (true)\n\t\t\t\t\t{\n\t\t\t\t\t\t// parse value\n\t\t\t\t\t\tif (not accept_internal())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// comma -> next value\n\t\t\t\t\t\tget_token();\n\t\t\t\t\t\tif (last_token == token_type::value_separator)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tget_token();\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// closing ]\n\t\t\t\t\t\treturn (last_token == token_type::end_array);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcase token_type::value_float:\n\t\t\t\t{\n\t\t\t\t\t// reject infinity or NAN\n\t\t\t\t\treturn std::isfinite(m_lexer.get_number_float());\n\t\t\t\t}\n\n\t\t\t\tcase token_type::literal_false:\n\t\t\t\tcase token_type::literal_null:\n\t\t\t\tcase token_type::literal_true:\n\t\t\t\tcase token_type::value_integer:\n\t\t\t\tcase token_type::value_string:\n\t\t\t\tcase token_type::value_unsigned:\n\t\t\t\t\treturn true;\n\n\t\t\t\tdefault: // the last token was unexpected\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/// get next token from lexer\n\t\t\ttoken_type get_token()\n\t\t\t{\n\t\t\t\treturn (last_token = m_lexer.scan());\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@throw parse_error.101 if expected token did not occur\n\t\t\t*/\n\t\t\tbool expect(token_type t)\n\t\t\t{\n\t\t\t\tif (JSON_UNLIKELY(t != last_token))\n\t\t\t\t{\n\t\t\t\t\terrored = true;\n\t\t\t\t\texpected = t;\n\t\t\t\t\tif (allow_exceptions)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow_exception();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t[[noreturn]] void throw_exception() const\n\t\t\t{\n\t\t\t\tstd::string error_msg = \"syntax error - \";\n\t\t\t\tif (last_token == token_type::parse_error)\n\t\t\t\t{\n\t\t\t\t\terror_msg += std::string(m_lexer.get_error_message()) + \"; last read: '\" +\n\t\t\t\t\t\tm_lexer.get_token_string() + \"'\";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror_msg += \"unexpected \" + std::string(lexer_t::token_type_name(last_token));\n\t\t\t\t}\n\n\t\t\t\tif (expected != token_type::uninitialized)\n\t\t\t\t{\n\t\t\t\t\terror_msg += \"; expected \" + std::string(lexer_t::token_type_name(expected));\n\t\t\t\t}\n\n\t\t\t\tJSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// current level of recursion\n\t\t\tint depth = 0;\n\t\t\t/// callback function\n\t\t\tconst parser_callback_t callback = nullptr;\n\t\t\t/// the type of the last read token\n\t\t\ttoken_type last_token = token_type::uninitialized;\n\t\t\t/// the lexer\n\t\t\tlexer_t m_lexer;\n\t\t\t/// whether a syntax error occurred\n\t\t\tbool errored = false;\n\t\t\t/// possible reason for the syntax error\n\t\t\ttoken_type expected = token_type::uninitialized;\n\t\t\t/// whether to throw exceptions in case of errors\n\t\t\tconst bool allow_exceptions = true;\n\t\t};\n\n\t\t///////////////\n\t\t// iterators //\n\t\t///////////////\n\n\t\t/*!\n\t\t@brief an iterator for primitive JSON types\n\n\t\tThis class models an iterator for primitive JSON types (boolean, number,\n\t\tstring). It's only purpose is to allow the iterator/const_iterator classes\n\t\tto \"iterate\" over primitive values. Internally, the iterator is modeled by\n\t\ta `difference_type` variable. Value begin_value (`0`) models the begin,\n\t\tend_value (`1`) models past the end.\n\t\t*/\n\t\tclass primitive_iterator_t\n\t\t{\n\t\tpublic:\n\t\t\tusing difference_type = std::ptrdiff_t;\n\n\t\t\tconstexpr difference_type get_value() const noexcept\n\t\t\t{\n\t\t\t\treturn m_it;\n\t\t\t}\n\n\t\t\t/// set iterator to a defined beginning\n\t\t\tvoid set_begin() noexcept\n\t\t\t{\n\t\t\t\tm_it = begin_value;\n\t\t\t}\n\n\t\t\t/// set iterator to a defined past the end\n\t\t\tvoid set_end() noexcept\n\t\t\t{\n\t\t\t\tm_it = end_value;\n\t\t\t}\n\n\t\t\t/// return whether the iterator can be dereferenced\n\t\t\tconstexpr bool is_begin() const noexcept\n\t\t\t{\n\t\t\t\treturn m_it == begin_value;\n\t\t\t}\n\n\t\t\t/// return whether the iterator is at end\n\t\t\tconstexpr bool is_end() const noexcept\n\t\t\t{\n\t\t\t\treturn m_it == end_value;\n\t\t\t}\n\n\t\t\tfriend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\n\t\t\t{\n\t\t\t\treturn lhs.m_it == rhs.m_it;\n\t\t\t}\n\n\t\t\tfriend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\n\t\t\t{\n\t\t\t\treturn lhs.m_it < rhs.m_it;\n\t\t\t}\n\n\t\t\tprimitive_iterator_t operator+(difference_type i)\n\t\t\t{\n\t\t\t\tauto result = *this;\n\t\t\t\tresult += i;\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tfriend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\n\t\t\t{\n\t\t\t\treturn lhs.m_it - rhs.m_it;\n\t\t\t}\n\n\t\t\tfriend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)\n\t\t\t{\n\t\t\t\treturn os << it.m_it;\n\t\t\t}\n\n\t\t\tprimitive_iterator_t& operator++()\n\t\t\t{\n\t\t\t\t++m_it;\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\tprimitive_iterator_t operator++(int)\n\t\t\t{\n\t\t\t\tauto result = *this;\n\t\t\t\tm_it++;\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tprimitive_iterator_t& operator--()\n\t\t\t{\n\t\t\t\t--m_it;\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\tprimitive_iterator_t operator--(int)\n\t\t\t{\n\t\t\t\tauto result = *this;\n\t\t\t\tm_it--;\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tprimitive_iterator_t& operator+=(difference_type n)\n\t\t\t{\n\t\t\t\tm_it += n;\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\tprimitive_iterator_t& operator-=(difference_type n)\n\t\t\t{\n\t\t\t\tm_it -= n;\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\tprivate:\n\t\t\tstatic constexpr difference_type begin_value = 0;\n\t\t\tstatic constexpr difference_type end_value = begin_value + 1;\n\n\t\t\t/// iterator as signed integer type\n\t\t\tdifference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();\n\t\t};\n\n\t\t/*!\n\t\t@brief an iterator value\n\n\t\t@note This structure could easily be a union, but MSVC currently does not allow\n\t\tunions members with complex constructors, see https://github.com/nlohmann/json/pull/105.\n\t\t*/\n\t\ttemplate<typename BasicJsonType> struct internal_iterator\n\t\t{\n\t\t\t/// iterator for JSON objects\n\t\t\ttypename BasicJsonType::object_t::iterator object_iterator{};\n\t\t\t/// iterator for JSON arrays\n\t\t\ttypename BasicJsonType::array_t::iterator array_iterator{};\n\t\t\t/// generic iterator for all other types\n\t\t\tprimitive_iterator_t primitive_iterator{};\n\t\t};\n\n\t\ttemplate<typename IteratorType> class iteration_proxy;\n\n\t\t/*!\n\t\t@brief a template for a bidirectional iterator for the @ref basic_json class\n\n\t\tThis class implements a both iterators (iterator and const_iterator) for the\n\t\t@ref basic_json class.\n\n\t\t@note An iterator is called *initialized* when a pointer to a JSON value has\n\t\tbeen set (e.g., by a constructor or a copy assignment). If the iterator is\n\t\tdefault-constructed, it is *uninitialized* and most methods are undefined.\n\t\t**The library uses assertions to detect calls on uninitialized iterators.**\n\n\t\t@requirement The class satisfies the following concept requirements:\n\t\t-\n\t\t[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):\n\t\tThe iterator that can be moved can be moved in both directions (i.e.\n\t\tincremented and decremented).\n\n\t\t@since version 1.0.0, simplified in version 2.0.9, change to bidirectional\n\t\titerators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)\n\t\t*/\n\t\ttemplate<typename BasicJsonType>\n\t\tclass iter_impl : public std::iterator<std::bidirectional_iterator_tag, BasicJsonType>\n\t\t{\n\t\t\t/// allow basic_json to access private members\n\t\t\tfriend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;\n\t\t\tfriend BasicJsonType;\n\t\t\tfriend iteration_proxy<iter_impl>;\n\n\t\t\tusing object_t = typename BasicJsonType::object_t;\n\t\t\tusing array_t = typename BasicJsonType::array_t;\n\t\t\t// make sure BasicJsonType is basic_json or const basic_json\n\t\t\tstatic_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,\n\t\t\t\t\"iter_impl only accepts (const) basic_json\");\n\n\t\tpublic:\n\t\t\t/// the type of the values when the iterator is dereferenced\n\t\t\tusing value_type = typename BasicJsonType::value_type;\n\t\t\t/// a type to represent differences between iterators\n\t\t\tusing difference_type = typename BasicJsonType::difference_type;\n\t\t\t/// defines a pointer to the type iterated over (value_type)\n\t\t\tusing pointer = typename std::conditional<std::is_const<BasicJsonType>::value,\n\t\t\t\ttypename BasicJsonType::const_pointer,\n\t\t\t\ttypename BasicJsonType::pointer>::type;\n\t\t\t/// defines a reference to the type iterated over (value_type)\n\t\t\tusing reference =\n\t\t\t\ttypename std::conditional<std::is_const<BasicJsonType>::value,\n\t\t\t\ttypename BasicJsonType::const_reference,\n\t\t\t\ttypename BasicJsonType::reference>::type;\n\n\t\t\t/// default constructor\n\t\t\titer_impl() = default;\n\n\t\t\t/*!\n\t\t\t@brief constructor for a given JSON instance\n\t\t\t@param[in] object  pointer to a JSON object for this iterator\n\t\t\t@pre object != nullptr\n\t\t\t@post The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\texplicit iter_impl(pointer object) noexcept : m_object(object)\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tm_it.object_iterator = typename object_t::iterator();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tm_it.array_iterator = typename array_t::iterator();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tm_it.primitive_iterator = primitive_iterator_t();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@note The conventional copy constructor and copy assignment are implicitly\n\t\t\tdefined. Combined with the following converting constructor and\n\t\t\tassignment, they support: (1) copy from iterator to iterator, (2)\n\t\t\tcopy from const iterator to const iterator, and (3) conversion from\n\t\t\titerator to const iterator. However conversion from const iterator\n\t\t\tto iterator is not defined.\n\t\t\t*/\n\n\t\t\t/*!\n\t\t\t@brief converting constructor\n\t\t\t@param[in] other  non-const iterator to copy from\n\t\t\t@note It is not checked whether @a other is initialized.\n\t\t\t*/\n\t\t\titer_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept\n\t\t\t\t: m_object(other.m_object), m_it(other.m_it) {}\n\n\t\t\t/*!\n\t\t\t@brief converting assignment\n\t\t\t@param[in,out] other  non-const iterator to copy from\n\t\t\t@return const/non-const iterator\n\t\t\t@note It is not checked whether @a other is initialized.\n\t\t\t*/\n\t\t\titer_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept\n\t\t\t{\n\t\t\t\tm_object = other.m_object;\n\t\t\t\tm_it = other.m_it;\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/*!\n\t\t\t@brief set the iterator to the first value\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tvoid set_begin() noexcept\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tm_it.object_iterator = m_object->m_value.object->begin();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tm_it.array_iterator = m_object->m_value.array->begin();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::null:\n\t\t\t\t{\n\t\t\t\t\t// set to end so begin()==end() is true: null is empty\n\t\t\t\t\tm_it.primitive_iterator.set_end();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tm_it.primitive_iterator.set_begin();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief set the iterator past the last value\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tvoid set_end() noexcept\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tm_it.object_iterator = m_object->m_value.object->end();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tm_it.array_iterator = m_object->m_value.array->end();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tm_it.primitive_iterator.set_end();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\tpublic:\n\t\t\t/*!\n\t\t\t@brief return a reference to the value pointed to by the iterator\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\treference operator*() const\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tassert(m_it.object_iterator != m_object->m_value.object->end());\n\t\t\t\t\treturn m_it.object_iterator->second;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tassert(m_it.array_iterator != m_object->m_value.array->end());\n\t\t\t\t\treturn *m_it.array_iterator;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::null:\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tif (JSON_LIKELY(m_it.primitive_iterator.is_begin()))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn *m_object;\n\t\t\t\t\t}\n\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief dereference the iterator\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tpointer operator->() const\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tassert(m_it.object_iterator != m_object->m_value.object->end());\n\t\t\t\t\treturn &(m_it.object_iterator->second);\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tassert(m_it.array_iterator != m_object->m_value.array->end());\n\t\t\t\t\treturn &*m_it.array_iterator;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tif (JSON_LIKELY(m_it.primitive_iterator.is_begin()))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn m_object;\n\t\t\t\t\t}\n\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief post-increment (it++)\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\titer_impl operator++(int)\n\t\t\t{\n\t\t\t\tauto result = *this;\n\t\t\t\t++(*this);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief pre-increment (++it)\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\titer_impl& operator++()\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tstd::advance(m_it.object_iterator, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tstd::advance(m_it.array_iterator, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\t++m_it.primitive_iterator;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief post-decrement (it--)\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\titer_impl operator--(int)\n\t\t\t{\n\t\t\t\tauto result = *this;\n\t\t\t\t--(*this);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief pre-decrement (--it)\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\titer_impl& operator--()\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tstd::advance(m_it.object_iterator, -1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tstd::advance(m_it.array_iterator, -1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\t--m_it.primitive_iterator;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  comparison: equal\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tbool operator==(const iter_impl& other) const\n\t\t\t{\n\t\t\t\t// if objects are not the same, the comparison is undefined\n\t\t\t\tif (JSON_UNLIKELY(m_object != other.m_object))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(212, \"cannot compare iterators of different containers\"));\n\t\t\t\t}\n\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t\treturn (m_it.object_iterator == other.m_it.object_iterator);\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t\treturn (m_it.array_iterator == other.m_it.array_iterator);\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn (m_it.primitive_iterator == other.m_it.primitive_iterator);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  comparison: not equal\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tbool operator!=(const iter_impl& other) const\n\t\t\t{\n\t\t\t\treturn not operator==(other);\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  comparison: smaller\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tbool operator<(const iter_impl& other) const\n\t\t\t{\n\t\t\t\t// if objects are not the same, the comparison is undefined\n\t\t\t\tif (JSON_UNLIKELY(m_object != other.m_object))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(212, \"cannot compare iterators of different containers\"));\n\t\t\t\t}\n\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(213, \"cannot compare order of object iterators\"));\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t\treturn (m_it.array_iterator < other.m_it.array_iterator);\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn (m_it.primitive_iterator < other.m_it.primitive_iterator);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  comparison: less than or equal\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tbool operator<=(const iter_impl& other) const\n\t\t\t{\n\t\t\t\treturn not other.operator < (*this);\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  comparison: greater than\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tbool operator>(const iter_impl& other) const\n\t\t\t{\n\t\t\t\treturn not operator<=(other);\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  comparison: greater than or equal\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tbool operator>=(const iter_impl& other) const\n\t\t\t{\n\t\t\t\treturn not operator<(other);\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  add to iterator\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\titer_impl& operator+=(difference_type i)\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(209, \"cannot use offsets with object iterators\"));\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tstd::advance(m_it.array_iterator, i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tm_it.primitive_iterator += i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  subtract from iterator\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\titer_impl& operator-=(difference_type i)\n\t\t\t{\n\t\t\t\treturn operator+=(-i);\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  add to iterator\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\titer_impl operator+(difference_type i) const\n\t\t\t{\n\t\t\t\tauto result = *this;\n\t\t\t\tresult += i;\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  addition of distance and iterator\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tfriend iter_impl operator+(difference_type i, const iter_impl& it)\n\t\t\t{\n\t\t\t\tauto result = it;\n\t\t\t\tresult += i;\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  subtract from iterator\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\titer_impl operator-(difference_type i) const\n\t\t\t{\n\t\t\t\tauto result = *this;\n\t\t\t\tresult -= i;\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  return difference\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\tdifference_type operator-(const iter_impl& other) const\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(209, \"cannot use offsets with object iterators\"));\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t\treturn m_it.array_iterator - other.m_it.array_iterator;\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn m_it.primitive_iterator - other.m_it.primitive_iterator;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  access to successor\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\treference operator[](difference_type n) const\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tswitch (m_object->m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(208, \"cannot use operator[] for object iterators\"));\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t\treturn *std::next(m_it.array_iterator, n);\n\n\t\t\t\tcase value_t::null:\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tif (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn *m_object;\n\t\t\t\t\t}\n\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  return the key of an object iterator\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\ttypename object_t::key_type key() const\n\t\t\t{\n\t\t\t\tassert(m_object != nullptr);\n\n\t\t\t\tif (JSON_LIKELY(m_object->is_object()))\n\t\t\t\t{\n\t\t\t\t\treturn m_it.object_iterator->first;\n\t\t\t\t}\n\n\t\t\t\tJSON_THROW(invalid_iterator::create(207, \"cannot use key() for non-object iterators\"));\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief  return the value of an iterator\n\t\t\t@pre The iterator is initialized; i.e. `m_object != nullptr`.\n\t\t\t*/\n\t\t\treference value() const\n\t\t\t{\n\t\t\t\treturn operator*();\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// associated JSON instance\n\t\t\tpointer m_object = nullptr;\n\t\t\t/// the actual iterator of the associated instance\n\t\t\tinternal_iterator<typename std::remove_const<BasicJsonType>::type> m_it = {};\n\t\t};\n\n\t\t/// proxy class for the iterator_wrapper functions\n\t\ttemplate<typename IteratorType> class iteration_proxy\n\t\t{\n\t\tprivate:\n\t\t\t/// helper class for iteration\n\t\t\tclass iteration_proxy_internal\n\t\t\t{\n\t\t\tprivate:\n\t\t\t\t/// the iterator\n\t\t\t\tIteratorType anchor;\n\t\t\t\t/// an index for arrays (used to create key names)\n\t\t\t\tstd::size_t array_index = 0;\n\n\t\t\tpublic:\n\t\t\t\texplicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}\n\n\t\t\t\t/// dereference operator (needed for range-based for)\n\t\t\t\titeration_proxy_internal& operator*()\n\t\t\t\t{\n\t\t\t\t\treturn *this;\n\t\t\t\t}\n\n\t\t\t\t/// increment operator (needed for range-based for)\n\t\t\t\titeration_proxy_internal& operator++()\n\t\t\t\t{\n\t\t\t\t\t++anchor;\n\t\t\t\t\t++array_index;\n\n\t\t\t\t\treturn *this;\n\t\t\t\t}\n\n\t\t\t\t/// inequality operator (needed for range-based for)\n\t\t\t\tbool operator!=(const iteration_proxy_internal& o) const noexcept\n\t\t\t\t{\n\t\t\t\t\treturn anchor != o.anchor;\n\t\t\t\t}\n\n\t\t\t\t/// return key of the iterator\n\t\t\t\tstd::string key() const\n\t\t\t\t{\n\t\t\t\t\tassert(anchor.m_object != nullptr);\n\n\t\t\t\t\tswitch (anchor.m_object->type())\n\t\t\t\t\t{\n\t\t\t\t\t\t// use integer array index as key\n\t\t\t\t\tcase value_t::array:\n\t\t\t\t\t\treturn std::to_string(array_index);\n\n\t\t\t\t\t\t// use key from the object\n\t\t\t\t\tcase value_t::object:\n\t\t\t\t\t\treturn anchor.key();\n\n\t\t\t\t\t\t// use an empty key for all primitive types\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/// return value of the iterator\n\t\t\t\ttypename IteratorType::reference value() const\n\t\t\t\t{\n\t\t\t\t\treturn anchor.value();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t/// the container to iterate\n\t\t\ttypename IteratorType::reference container;\n\n\t\tpublic:\n\t\t\t/// construct iteration proxy from a container\n\t\t\texplicit iteration_proxy(typename IteratorType::reference cont)\n\t\t\t\t: container(cont) {}\n\n\t\t\t/// return iterator begin (needed for range-based for)\n\t\t\titeration_proxy_internal begin() noexcept\n\t\t\t{\n\t\t\t\treturn iteration_proxy_internal(container.begin());\n\t\t\t}\n\n\t\t\t/// return iterator end (needed for range-based for)\n\t\t\titeration_proxy_internal end() noexcept\n\t\t\t{\n\t\t\t\treturn iteration_proxy_internal(container.end());\n\t\t\t}\n\t\t};\n\n\t\t/*!\n\t\t@brief a template for a reverse iterator class\n\n\t\t@tparam Base the base iterator type to reverse. Valid types are @ref\n\t\titerator (to create @ref reverse_iterator) and @ref const_iterator (to\n\t\tcreate @ref const_reverse_iterator).\n\n\t\t@requirement The class satisfies the following concept requirements:\n\t\t-\n\t\t[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):\n\t\tThe iterator that can be moved can be moved in both directions (i.e.\n\t\tincremented and decremented).\n\t\t- [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):\n\t\tIt is possible to write to the pointed-to element (only if @a Base is\n\t\t@ref iterator).\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate<typename Base>\n\t\tclass json_reverse_iterator : public std::reverse_iterator<Base>\n\t\t{\n\t\tpublic:\n\t\t\tusing difference_type = std::ptrdiff_t;\n\t\t\t/// shortcut to the reverse iterator adaptor\n\t\t\tusing base_iterator = std::reverse_iterator<Base>;\n\t\t\t/// the reference type for the pointed-to element\n\t\t\tusing reference = typename Base::reference;\n\n\t\t\t/// create reverse iterator from iterator\n\t\t\tjson_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept\n\t\t\t\t: base_iterator(it) {}\n\n\t\t\t/// create reverse iterator from base class\n\t\t\tjson_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}\n\n\t\t\t/// post-increment (it++)\n\t\t\tjson_reverse_iterator operator++(int)\n\t\t\t{\n\t\t\t\treturn static_cast<json_reverse_iterator>(base_iterator::operator++(1));\n\t\t\t}\n\n\t\t\t/// pre-increment (++it)\n\t\t\tjson_reverse_iterator& operator++()\n\t\t\t{\n\t\t\t\treturn static_cast<json_reverse_iterator&>(base_iterator::operator++());\n\t\t\t}\n\n\t\t\t/// post-decrement (it--)\n\t\t\tjson_reverse_iterator operator--(int)\n\t\t\t{\n\t\t\t\treturn static_cast<json_reverse_iterator>(base_iterator::operator--(1));\n\t\t\t}\n\n\t\t\t/// pre-decrement (--it)\n\t\t\tjson_reverse_iterator& operator--()\n\t\t\t{\n\t\t\t\treturn static_cast<json_reverse_iterator&>(base_iterator::operator--());\n\t\t\t}\n\n\t\t\t/// add to iterator\n\t\t\tjson_reverse_iterator& operator+=(difference_type i)\n\t\t\t{\n\t\t\t\treturn static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));\n\t\t\t}\n\n\t\t\t/// add to iterator\n\t\t\tjson_reverse_iterator operator+(difference_type i) const\n\t\t\t{\n\t\t\t\treturn static_cast<json_reverse_iterator>(base_iterator::operator+(i));\n\t\t\t}\n\n\t\t\t/// subtract from iterator\n\t\t\tjson_reverse_iterator operator-(difference_type i) const\n\t\t\t{\n\t\t\t\treturn static_cast<json_reverse_iterator>(base_iterator::operator-(i));\n\t\t\t}\n\n\t\t\t/// return difference\n\t\t\tdifference_type operator-(const json_reverse_iterator& other) const\n\t\t\t{\n\t\t\t\treturn base_iterator(*this) - base_iterator(other);\n\t\t\t}\n\n\t\t\t/// access to successor\n\t\t\treference operator[](difference_type n) const\n\t\t\t{\n\t\t\t\treturn *(this->operator+(n));\n\t\t\t}\n\n\t\t\t/// return the key of an object iterator\n\t\t\tauto key() const -> decltype(std::declval<Base>().key())\n\t\t\t{\n\t\t\t\tauto it = --this->base();\n\t\t\t\treturn it.key();\n\t\t\t}\n\n\t\t\t/// return the value of an iterator\n\t\t\treference value() const\n\t\t\t{\n\t\t\t\tauto it = --this->base();\n\t\t\t\treturn it.operator * ();\n\t\t\t}\n\t\t};\n\n\t\t/////////////////////\n\t\t// output adapters //\n\t\t/////////////////////\n\n\t\t/// abstract output adapter interface\n\t\ttemplate<typename CharType> struct output_adapter_protocol\n\t\t{\n\t\t\tvirtual void write_character(CharType c) = 0;\n\t\t\tvirtual void write_characters(const CharType* s, std::size_t length) = 0;\n\t\t\tvirtual ~output_adapter_protocol() = default;\n\t\t};\n\n\t\t/// a type to simplify interfaces\n\t\ttemplate<typename CharType>\n\t\tusing output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;\n\n\t\t/// output adapter for byte vectors\n\t\ttemplate<typename CharType>\n\t\tclass output_vector_adapter : public output_adapter_protocol<CharType>\n\t\t{\n\t\tpublic:\n\t\t\texplicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {}\n\n\t\t\tvoid write_character(CharType c) override\n\t\t\t{\n\t\t\t\tv.push_back(c);\n\t\t\t}\n\n\t\t\tvoid write_characters(const CharType* s, std::size_t length) override\n\t\t\t{\n\t\t\t\tstd::copy(s, s + length, std::back_inserter(v));\n\t\t\t}\n\n\t\tprivate:\n\t\t\tstd::vector<CharType>& v;\n\t\t};\n\n\t\t/// output adapter for output streams\n\t\ttemplate<typename CharType>\n\t\tclass output_stream_adapter : public output_adapter_protocol<CharType>\n\t\t{\n\t\tpublic:\n\t\t\texplicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {}\n\n\t\t\tvoid write_character(CharType c) override\n\t\t\t{\n\t\t\t\tstream.put(c);\n\t\t\t}\n\n\t\t\tvoid write_characters(const CharType* s, std::size_t length) override\n\t\t\t{\n\t\t\t\tstream.write(s, static_cast<std::streamsize>(length));\n\t\t\t}\n\n\t\tprivate:\n\t\t\tstd::basic_ostream<CharType>& stream;\n\t\t};\n\n\t\t/// output adapter for basic_string\n\t\ttemplate<typename CharType>\n\t\tclass output_string_adapter : public output_adapter_protocol<CharType>\n\t\t{\n\t\tpublic:\n\t\t\texplicit output_string_adapter(std::basic_string<CharType>& s) : str(s) {}\n\n\t\t\tvoid write_character(CharType c) override\n\t\t\t{\n\t\t\t\tstr.push_back(c);\n\t\t\t}\n\n\t\t\tvoid write_characters(const CharType* s, std::size_t length) override\n\t\t\t{\n\t\t\t\tstr.append(s, length);\n\t\t\t}\n\n\t\tprivate:\n\t\t\tstd::basic_string<CharType>& str;\n\t\t};\n\n\t\ttemplate<typename CharType>\n\t\tclass output_adapter\n\t\t{\n\t\tpublic:\n\t\t\toutput_adapter(std::vector<CharType>& vec)\n\t\t\t\t: oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}\n\n\t\t\toutput_adapter(std::basic_ostream<CharType>& s)\n\t\t\t\t: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}\n\n\t\t\toutput_adapter(std::basic_string<CharType>& s)\n\t\t\t\t: oa(std::make_shared<output_string_adapter<CharType>>(s)) {}\n\n\t\t\toperator output_adapter_t<CharType>()\n\t\t\t{\n\t\t\t\treturn oa;\n\t\t\t}\n\n\t\tprivate:\n\t\t\toutput_adapter_t<CharType> oa = nullptr;\n\t\t};\n\n\t\t//////////////////////////////\n\t\t// binary reader and writer //\n\t\t//////////////////////////////\n\n\t\t/*!\n\t\t@brief deserialization of CBOR and MessagePack values\n\t\t*/\n\t\ttemplate<typename BasicJsonType>\n\t\tclass binary_reader\n\t\t{\n\t\t\tusing number_integer_t = typename BasicJsonType::number_integer_t;\n\t\t\tusing number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n\n\t\tpublic:\n\t\t\t/*!\n\t\t\t@brief create a binary reader\n\n\t\t\t@param[in] adapter  input adapter to read from\n\t\t\t*/\n\t\t\texplicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))\n\t\t\t{\n\t\t\t\tassert(ia);\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief create a JSON value from CBOR input\n\n\t\t\t@param[in] strict  whether to expect the input to be consumed completed\n\t\t\t@return JSON value created from CBOR input\n\n\t\t\t@throw parse_error.110 if input ended unexpectedly or the end of file was\n\t\t\tnot reached when @a strict was set to true\n\t\t\t@throw parse_error.112 if unsupported byte was read\n\t\t\t*/\n\t\t\tBasicJsonType parse_cbor(const bool strict)\n\t\t\t{\n\t\t\t\tconst auto res = parse_cbor_internal();\n\t\t\t\tif (strict)\n\t\t\t\t{\n\t\t\t\t\tget();\n\t\t\t\t\tcheck_eof(true);\n\t\t\t\t}\n\t\t\t\treturn res;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief create a JSON value from MessagePack input\n\n\t\t\t@param[in] strict  whether to expect the input to be consumed completed\n\t\t\t@return JSON value created from MessagePack input\n\n\t\t\t@throw parse_error.110 if input ended unexpectedly or the end of file was\n\t\t\tnot reached when @a strict was set to true\n\t\t\t@throw parse_error.112 if unsupported byte was read\n\t\t\t*/\n\t\t\tBasicJsonType parse_msgpack(const bool strict)\n\t\t\t{\n\t\t\t\tconst auto res = parse_msgpack_internal();\n\t\t\t\tif (strict)\n\t\t\t\t{\n\t\t\t\t\tget();\n\t\t\t\t\tcheck_eof(true);\n\t\t\t\t}\n\t\t\t\treturn res;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief determine system byte order\n\n\t\t\t@return true if and only if system's byte order is little endian\n\n\t\t\t@note from http://stackoverflow.com/a/1001328/266378\n\t\t\t*/\n\t\t\tstatic constexpr bool little_endianess(int num = 1) noexcept\n\t\t\t{\n\t\t\t\treturn (*reinterpret_cast<char*>(&num) == 1);\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/*!\n\t\t\t@param[in] get_char  whether a new character should be retrieved from the\n\t\t\tinput (true, default) or whether the last read\n\t\t\tcharacter should be considered instead\n\t\t\t*/\n\t\t\tBasicJsonType parse_cbor_internal(const bool get_char = true)\n\t\t\t{\n\t\t\t\tswitch (get_char ? get() : current)\n\t\t\t\t{\n\t\t\t\t\t// EOF\n\t\t\t\tcase std::char_traits<char>::eof():\n\t\t\t\t\tJSON_THROW(parse_error::create(110, chars_read, \"unexpected end of input\"));\n\n\t\t\t\t\t// Integer 0x00..0x17 (0..23)\n\t\t\t\tcase 0x00:\n\t\t\t\tcase 0x01:\n\t\t\t\tcase 0x02:\n\t\t\t\tcase 0x03:\n\t\t\t\tcase 0x04:\n\t\t\t\tcase 0x05:\n\t\t\t\tcase 0x06:\n\t\t\t\tcase 0x07:\n\t\t\t\tcase 0x08:\n\t\t\t\tcase 0x09:\n\t\t\t\tcase 0x0a:\n\t\t\t\tcase 0x0b:\n\t\t\t\tcase 0x0c:\n\t\t\t\tcase 0x0d:\n\t\t\t\tcase 0x0e:\n\t\t\t\tcase 0x0f:\n\t\t\t\tcase 0x10:\n\t\t\t\tcase 0x11:\n\t\t\t\tcase 0x12:\n\t\t\t\tcase 0x13:\n\t\t\t\tcase 0x14:\n\t\t\t\tcase 0x15:\n\t\t\t\tcase 0x16:\n\t\t\t\tcase 0x17:\n\t\t\t\t\treturn static_cast<number_unsigned_t>(current);\n\n\t\t\t\tcase 0x18: // Unsigned integer (one-byte uint8_t follows)\n\t\t\t\t\treturn get_number<uint8_t>();\n\n\t\t\t\tcase 0x19: // Unsigned integer (two-byte uint16_t follows)\n\t\t\t\t\treturn get_number<uint16_t>();\n\n\t\t\t\tcase 0x1a: // Unsigned integer (four-byte uint32_t follows)\n\t\t\t\t\treturn get_number<uint32_t>();\n\n\t\t\t\tcase 0x1b: // Unsigned integer (eight-byte uint64_t follows)\n\t\t\t\t\treturn get_number<uint64_t>();\n\n\t\t\t\t\t// Negative integer -1-0x00..-1-0x17 (-1..-24)\n\t\t\t\tcase 0x20:\n\t\t\t\tcase 0x21:\n\t\t\t\tcase 0x22:\n\t\t\t\tcase 0x23:\n\t\t\t\tcase 0x24:\n\t\t\t\tcase 0x25:\n\t\t\t\tcase 0x26:\n\t\t\t\tcase 0x27:\n\t\t\t\tcase 0x28:\n\t\t\t\tcase 0x29:\n\t\t\t\tcase 0x2a:\n\t\t\t\tcase 0x2b:\n\t\t\t\tcase 0x2c:\n\t\t\t\tcase 0x2d:\n\t\t\t\tcase 0x2e:\n\t\t\t\tcase 0x2f:\n\t\t\t\tcase 0x30:\n\t\t\t\tcase 0x31:\n\t\t\t\tcase 0x32:\n\t\t\t\tcase 0x33:\n\t\t\t\tcase 0x34:\n\t\t\t\tcase 0x35:\n\t\t\t\tcase 0x36:\n\t\t\t\tcase 0x37:\n\t\t\t\t\treturn static_cast<int8_t>(0x20 - 1 - current);\n\n\t\t\t\tcase 0x38: // Negative integer (one-byte uint8_t follows)\n\t\t\t\t{\n\t\t\t\t\t// must be uint8_t !\n\t\t\t\t\treturn static_cast<number_integer_t>(-1) - get_number<uint8_t>();\n\t\t\t\t}\n\n\t\t\t\tcase 0x39: // Negative integer -1-n (two-byte uint16_t follows)\n\t\t\t\t{\n\t\t\t\t\treturn static_cast<number_integer_t>(-1) - get_number<uint16_t>();\n\t\t\t\t}\n\n\t\t\t\tcase 0x3a: // Negative integer -1-n (four-byte uint32_t follows)\n\t\t\t\t{\n\t\t\t\t\treturn static_cast<number_integer_t>(-1) - get_number<uint32_t>();\n\t\t\t\t}\n\n\t\t\t\tcase 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)\n\t\t\t\t{\n\t\t\t\t\treturn static_cast<number_integer_t>(-1) -\n\t\t\t\t\t\tstatic_cast<number_integer_t>(get_number<uint64_t>());\n\t\t\t\t}\n\n\t\t\t\t// UTF-8 string (0x00..0x17 bytes follow)\n\t\t\t\tcase 0x60:\n\t\t\t\tcase 0x61:\n\t\t\t\tcase 0x62:\n\t\t\t\tcase 0x63:\n\t\t\t\tcase 0x64:\n\t\t\t\tcase 0x65:\n\t\t\t\tcase 0x66:\n\t\t\t\tcase 0x67:\n\t\t\t\tcase 0x68:\n\t\t\t\tcase 0x69:\n\t\t\t\tcase 0x6a:\n\t\t\t\tcase 0x6b:\n\t\t\t\tcase 0x6c:\n\t\t\t\tcase 0x6d:\n\t\t\t\tcase 0x6e:\n\t\t\t\tcase 0x6f:\n\t\t\t\tcase 0x70:\n\t\t\t\tcase 0x71:\n\t\t\t\tcase 0x72:\n\t\t\t\tcase 0x73:\n\t\t\t\tcase 0x74:\n\t\t\t\tcase 0x75:\n\t\t\t\tcase 0x76:\n\t\t\t\tcase 0x77:\n\t\t\t\tcase 0x78: // UTF-8 string (one-byte uint8_t for n follows)\n\t\t\t\tcase 0x79: // UTF-8 string (two-byte uint16_t for n follow)\n\t\t\t\tcase 0x7a: // UTF-8 string (four-byte uint32_t for n follow)\n\t\t\t\tcase 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)\n\t\t\t\tcase 0x7f: // UTF-8 string (indefinite length)\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_string();\n\t\t\t\t}\n\n\t\t\t\t// array (0x00..0x17 data items follow)\n\t\t\t\tcase 0x80:\n\t\t\t\tcase 0x81:\n\t\t\t\tcase 0x82:\n\t\t\t\tcase 0x83:\n\t\t\t\tcase 0x84:\n\t\t\t\tcase 0x85:\n\t\t\t\tcase 0x86:\n\t\t\t\tcase 0x87:\n\t\t\t\tcase 0x88:\n\t\t\t\tcase 0x89:\n\t\t\t\tcase 0x8a:\n\t\t\t\tcase 0x8b:\n\t\t\t\tcase 0x8c:\n\t\t\t\tcase 0x8d:\n\t\t\t\tcase 0x8e:\n\t\t\t\tcase 0x8f:\n\t\t\t\tcase 0x90:\n\t\t\t\tcase 0x91:\n\t\t\t\tcase 0x92:\n\t\t\t\tcase 0x93:\n\t\t\t\tcase 0x94:\n\t\t\t\tcase 0x95:\n\t\t\t\tcase 0x96:\n\t\t\t\tcase 0x97:\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_array(current & 0x1f);\n\t\t\t\t}\n\n\t\t\t\tcase 0x98: // array (one-byte uint8_t for n follows)\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_array(get_number<uint8_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0x99: // array (two-byte uint16_t for n follow)\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_array(get_number<uint16_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0x9a: // array (four-byte uint32_t for n follow)\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_array(get_number<uint32_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0x9b: // array (eight-byte uint64_t for n follow)\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_array(get_number<uint64_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0x9f: // array (indefinite length)\n\t\t\t\t{\n\t\t\t\t\tBasicJsonType result = value_t::array;\n\t\t\t\t\twhile (get() != 0xff)\n\t\t\t\t\t{\n\t\t\t\t\t\tresult.push_back(parse_cbor_internal(false));\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\t// map (0x00..0x17 pairs of data items follow)\n\t\t\t\tcase 0xa0:\n\t\t\t\tcase 0xa1:\n\t\t\t\tcase 0xa2:\n\t\t\t\tcase 0xa3:\n\t\t\t\tcase 0xa4:\n\t\t\t\tcase 0xa5:\n\t\t\t\tcase 0xa6:\n\t\t\t\tcase 0xa7:\n\t\t\t\tcase 0xa8:\n\t\t\t\tcase 0xa9:\n\t\t\t\tcase 0xaa:\n\t\t\t\tcase 0xab:\n\t\t\t\tcase 0xac:\n\t\t\t\tcase 0xad:\n\t\t\t\tcase 0xae:\n\t\t\t\tcase 0xaf:\n\t\t\t\tcase 0xb0:\n\t\t\t\tcase 0xb1:\n\t\t\t\tcase 0xb2:\n\t\t\t\tcase 0xb3:\n\t\t\t\tcase 0xb4:\n\t\t\t\tcase 0xb5:\n\t\t\t\tcase 0xb6:\n\t\t\t\tcase 0xb7:\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_object(current & 0x1f);\n\t\t\t\t}\n\n\t\t\t\tcase 0xb8: // map (one-byte uint8_t for n follows)\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_object(get_number<uint8_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0xb9: // map (two-byte uint16_t for n follow)\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_object(get_number<uint16_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0xba: // map (four-byte uint32_t for n follow)\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_object(get_number<uint32_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0xbb: // map (eight-byte uint64_t for n follow)\n\t\t\t\t{\n\t\t\t\t\treturn get_cbor_object(get_number<uint64_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0xbf: // map (indefinite length)\n\t\t\t\t{\n\t\t\t\t\tBasicJsonType result = value_t::object;\n\t\t\t\t\twhile (get() != 0xff)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto key = get_cbor_string();\n\t\t\t\t\t\tresult[key] = parse_cbor_internal();\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tcase 0xf4: // false\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tcase 0xf5: // true\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tcase 0xf6: // null\n\t\t\t\t{\n\t\t\t\t\treturn value_t::null;\n\t\t\t\t}\n\n\t\t\t\tcase 0xf9: // Half-Precision Float (two-byte IEEE 754)\n\t\t\t\t{\n\t\t\t\t\tconst int byte1 = get();\n\t\t\t\t\tcheck_eof();\n\t\t\t\t\tconst int byte2 = get();\n\t\t\t\t\tcheck_eof();\n\n\t\t\t\t\t// code from RFC 7049, Appendix D, Figure 3:\n\t\t\t\t\t// As half-precision floating-point numbers were only added\n\t\t\t\t\t// to IEEE 754 in 2008, today's programming platforms often\n\t\t\t\t\t// still only have limited support for them. It is very\n\t\t\t\t\t// easy to include at least decoding support for them even\n\t\t\t\t\t// without such support. An example of a small decoder for\n\t\t\t\t\t// half-precision floating-point numbers in the C language\n\t\t\t\t\t// is shown in Fig. 3.\n\t\t\t\t\tconst int half = (byte1 << 8) + byte2;\n\t\t\t\t\tconst int exp = (half >> 10) & 0x1f;\n\t\t\t\t\tconst int mant = half & 0x3ff;\n\t\t\t\t\tdouble val;\n\t\t\t\t\tif (exp == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tval = std::ldexp(mant, -24);\n\t\t\t\t\t}\n\t\t\t\t\telse if (exp != 31)\n\t\t\t\t\t{\n\t\t\t\t\t\tval = std::ldexp(mant + 1024, exp - 25);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tval = (mant == 0) ? std::numeric_limits<double>::infinity()\n\t\t\t\t\t\t\t: std::numeric_limits<double>::quiet_NaN();\n\t\t\t\t\t}\n\t\t\t\t\treturn (half & 0x8000) != 0 ? -val : val;\n\t\t\t\t}\n\n\t\t\t\tcase 0xfa: // Single-Precision Float (four-byte IEEE 754)\n\t\t\t\t{\n\t\t\t\t\treturn get_number<float>();\n\t\t\t\t}\n\n\t\t\t\tcase 0xfb: // Double-Precision Float (eight-byte IEEE 754)\n\t\t\t\t{\n\t\t\t\t\treturn get_number<double>();\n\t\t\t\t}\n\n\t\t\t\tdefault: // anything else (0xFF is handled inside the other types)\n\t\t\t\t{\n\t\t\t\t\tstd::stringstream ss;\n\t\t\t\t\tss << std::setw(2) << std::setfill('0') << std::hex << current;\n\t\t\t\t\tJSON_THROW(parse_error::create(112, chars_read, \"error reading CBOR; last byte: 0x\" + ss.str()));\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tBasicJsonType parse_msgpack_internal()\n\t\t\t{\n\t\t\t\tswitch (get())\n\t\t\t\t{\n\t\t\t\t\t// EOF\n\t\t\t\tcase std::char_traits<char>::eof():\n\t\t\t\t\tJSON_THROW(parse_error::create(110, chars_read, \"unexpected end of input\"));\n\n\t\t\t\t\t// positive fixint\n\t\t\t\tcase 0x00:\n\t\t\t\tcase 0x01:\n\t\t\t\tcase 0x02:\n\t\t\t\tcase 0x03:\n\t\t\t\tcase 0x04:\n\t\t\t\tcase 0x05:\n\t\t\t\tcase 0x06:\n\t\t\t\tcase 0x07:\n\t\t\t\tcase 0x08:\n\t\t\t\tcase 0x09:\n\t\t\t\tcase 0x0a:\n\t\t\t\tcase 0x0b:\n\t\t\t\tcase 0x0c:\n\t\t\t\tcase 0x0d:\n\t\t\t\tcase 0x0e:\n\t\t\t\tcase 0x0f:\n\t\t\t\tcase 0x10:\n\t\t\t\tcase 0x11:\n\t\t\t\tcase 0x12:\n\t\t\t\tcase 0x13:\n\t\t\t\tcase 0x14:\n\t\t\t\tcase 0x15:\n\t\t\t\tcase 0x16:\n\t\t\t\tcase 0x17:\n\t\t\t\tcase 0x18:\n\t\t\t\tcase 0x19:\n\t\t\t\tcase 0x1a:\n\t\t\t\tcase 0x1b:\n\t\t\t\tcase 0x1c:\n\t\t\t\tcase 0x1d:\n\t\t\t\tcase 0x1e:\n\t\t\t\tcase 0x1f:\n\t\t\t\tcase 0x20:\n\t\t\t\tcase 0x21:\n\t\t\t\tcase 0x22:\n\t\t\t\tcase 0x23:\n\t\t\t\tcase 0x24:\n\t\t\t\tcase 0x25:\n\t\t\t\tcase 0x26:\n\t\t\t\tcase 0x27:\n\t\t\t\tcase 0x28:\n\t\t\t\tcase 0x29:\n\t\t\t\tcase 0x2a:\n\t\t\t\tcase 0x2b:\n\t\t\t\tcase 0x2c:\n\t\t\t\tcase 0x2d:\n\t\t\t\tcase 0x2e:\n\t\t\t\tcase 0x2f:\n\t\t\t\tcase 0x30:\n\t\t\t\tcase 0x31:\n\t\t\t\tcase 0x32:\n\t\t\t\tcase 0x33:\n\t\t\t\tcase 0x34:\n\t\t\t\tcase 0x35:\n\t\t\t\tcase 0x36:\n\t\t\t\tcase 0x37:\n\t\t\t\tcase 0x38:\n\t\t\t\tcase 0x39:\n\t\t\t\tcase 0x3a:\n\t\t\t\tcase 0x3b:\n\t\t\t\tcase 0x3c:\n\t\t\t\tcase 0x3d:\n\t\t\t\tcase 0x3e:\n\t\t\t\tcase 0x3f:\n\t\t\t\tcase 0x40:\n\t\t\t\tcase 0x41:\n\t\t\t\tcase 0x42:\n\t\t\t\tcase 0x43:\n\t\t\t\tcase 0x44:\n\t\t\t\tcase 0x45:\n\t\t\t\tcase 0x46:\n\t\t\t\tcase 0x47:\n\t\t\t\tcase 0x48:\n\t\t\t\tcase 0x49:\n\t\t\t\tcase 0x4a:\n\t\t\t\tcase 0x4b:\n\t\t\t\tcase 0x4c:\n\t\t\t\tcase 0x4d:\n\t\t\t\tcase 0x4e:\n\t\t\t\tcase 0x4f:\n\t\t\t\tcase 0x50:\n\t\t\t\tcase 0x51:\n\t\t\t\tcase 0x52:\n\t\t\t\tcase 0x53:\n\t\t\t\tcase 0x54:\n\t\t\t\tcase 0x55:\n\t\t\t\tcase 0x56:\n\t\t\t\tcase 0x57:\n\t\t\t\tcase 0x58:\n\t\t\t\tcase 0x59:\n\t\t\t\tcase 0x5a:\n\t\t\t\tcase 0x5b:\n\t\t\t\tcase 0x5c:\n\t\t\t\tcase 0x5d:\n\t\t\t\tcase 0x5e:\n\t\t\t\tcase 0x5f:\n\t\t\t\tcase 0x60:\n\t\t\t\tcase 0x61:\n\t\t\t\tcase 0x62:\n\t\t\t\tcase 0x63:\n\t\t\t\tcase 0x64:\n\t\t\t\tcase 0x65:\n\t\t\t\tcase 0x66:\n\t\t\t\tcase 0x67:\n\t\t\t\tcase 0x68:\n\t\t\t\tcase 0x69:\n\t\t\t\tcase 0x6a:\n\t\t\t\tcase 0x6b:\n\t\t\t\tcase 0x6c:\n\t\t\t\tcase 0x6d:\n\t\t\t\tcase 0x6e:\n\t\t\t\tcase 0x6f:\n\t\t\t\tcase 0x70:\n\t\t\t\tcase 0x71:\n\t\t\t\tcase 0x72:\n\t\t\t\tcase 0x73:\n\t\t\t\tcase 0x74:\n\t\t\t\tcase 0x75:\n\t\t\t\tcase 0x76:\n\t\t\t\tcase 0x77:\n\t\t\t\tcase 0x78:\n\t\t\t\tcase 0x79:\n\t\t\t\tcase 0x7a:\n\t\t\t\tcase 0x7b:\n\t\t\t\tcase 0x7c:\n\t\t\t\tcase 0x7d:\n\t\t\t\tcase 0x7e:\n\t\t\t\tcase 0x7f:\n\t\t\t\t\treturn static_cast<number_unsigned_t>(current);\n\n\t\t\t\t\t// fixmap\n\t\t\t\tcase 0x80:\n\t\t\t\tcase 0x81:\n\t\t\t\tcase 0x82:\n\t\t\t\tcase 0x83:\n\t\t\t\tcase 0x84:\n\t\t\t\tcase 0x85:\n\t\t\t\tcase 0x86:\n\t\t\t\tcase 0x87:\n\t\t\t\tcase 0x88:\n\t\t\t\tcase 0x89:\n\t\t\t\tcase 0x8a:\n\t\t\t\tcase 0x8b:\n\t\t\t\tcase 0x8c:\n\t\t\t\tcase 0x8d:\n\t\t\t\tcase 0x8e:\n\t\t\t\tcase 0x8f:\n\t\t\t\t{\n\t\t\t\t\treturn get_msgpack_object(current & 0x0f);\n\t\t\t\t}\n\n\t\t\t\t// fixarray\n\t\t\t\tcase 0x90:\n\t\t\t\tcase 0x91:\n\t\t\t\tcase 0x92:\n\t\t\t\tcase 0x93:\n\t\t\t\tcase 0x94:\n\t\t\t\tcase 0x95:\n\t\t\t\tcase 0x96:\n\t\t\t\tcase 0x97:\n\t\t\t\tcase 0x98:\n\t\t\t\tcase 0x99:\n\t\t\t\tcase 0x9a:\n\t\t\t\tcase 0x9b:\n\t\t\t\tcase 0x9c:\n\t\t\t\tcase 0x9d:\n\t\t\t\tcase 0x9e:\n\t\t\t\tcase 0x9f:\n\t\t\t\t{\n\t\t\t\t\treturn get_msgpack_array(current & 0x0f);\n\t\t\t\t}\n\n\t\t\t\t// fixstr\n\t\t\t\tcase 0xa0:\n\t\t\t\tcase 0xa1:\n\t\t\t\tcase 0xa2:\n\t\t\t\tcase 0xa3:\n\t\t\t\tcase 0xa4:\n\t\t\t\tcase 0xa5:\n\t\t\t\tcase 0xa6:\n\t\t\t\tcase 0xa7:\n\t\t\t\tcase 0xa8:\n\t\t\t\tcase 0xa9:\n\t\t\t\tcase 0xaa:\n\t\t\t\tcase 0xab:\n\t\t\t\tcase 0xac:\n\t\t\t\tcase 0xad:\n\t\t\t\tcase 0xae:\n\t\t\t\tcase 0xaf:\n\t\t\t\tcase 0xb0:\n\t\t\t\tcase 0xb1:\n\t\t\t\tcase 0xb2:\n\t\t\t\tcase 0xb3:\n\t\t\t\tcase 0xb4:\n\t\t\t\tcase 0xb5:\n\t\t\t\tcase 0xb6:\n\t\t\t\tcase 0xb7:\n\t\t\t\tcase 0xb8:\n\t\t\t\tcase 0xb9:\n\t\t\t\tcase 0xba:\n\t\t\t\tcase 0xbb:\n\t\t\t\tcase 0xbc:\n\t\t\t\tcase 0xbd:\n\t\t\t\tcase 0xbe:\n\t\t\t\tcase 0xbf:\n\t\t\t\t\treturn get_msgpack_string();\n\n\t\t\t\tcase 0xc0: // nil\n\t\t\t\t\treturn value_t::null;\n\n\t\t\t\tcase 0xc2: // false\n\t\t\t\t\treturn false;\n\n\t\t\t\tcase 0xc3: // true\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase 0xca: // float 32\n\t\t\t\t\treturn get_number<float>();\n\n\t\t\t\tcase 0xcb: // float 64\n\t\t\t\t\treturn get_number<double>();\n\n\t\t\t\tcase 0xcc: // uint 8\n\t\t\t\t\treturn get_number<uint8_t>();\n\n\t\t\t\tcase 0xcd: // uint 16\n\t\t\t\t\treturn get_number<uint16_t>();\n\n\t\t\t\tcase 0xce: // uint 32\n\t\t\t\t\treturn get_number<uint32_t>();\n\n\t\t\t\tcase 0xcf: // uint 64\n\t\t\t\t\treturn get_number<uint64_t>();\n\n\t\t\t\tcase 0xd0: // int 8\n\t\t\t\t\treturn get_number<int8_t>();\n\n\t\t\t\tcase 0xd1: // int 16\n\t\t\t\t\treturn get_number<int16_t>();\n\n\t\t\t\tcase 0xd2: // int 32\n\t\t\t\t\treturn get_number<int32_t>();\n\n\t\t\t\tcase 0xd3: // int 64\n\t\t\t\t\treturn get_number<int64_t>();\n\n\t\t\t\tcase 0xd9: // str 8\n\t\t\t\tcase 0xda: // str 16\n\t\t\t\tcase 0xdb: // str 32\n\t\t\t\t\treturn get_msgpack_string();\n\n\t\t\t\tcase 0xdc: // array 16\n\t\t\t\t{\n\t\t\t\t\treturn get_msgpack_array(get_number<uint16_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0xdd: // array 32\n\t\t\t\t{\n\t\t\t\t\treturn get_msgpack_array(get_number<uint32_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0xde: // map 16\n\t\t\t\t{\n\t\t\t\t\treturn get_msgpack_object(get_number<uint16_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0xdf: // map 32\n\t\t\t\t{\n\t\t\t\t\treturn get_msgpack_object(get_number<uint32_t>());\n\t\t\t\t}\n\n\t\t\t\t// positive fixint\n\t\t\t\tcase 0xe0:\n\t\t\t\tcase 0xe1:\n\t\t\t\tcase 0xe2:\n\t\t\t\tcase 0xe3:\n\t\t\t\tcase 0xe4:\n\t\t\t\tcase 0xe5:\n\t\t\t\tcase 0xe6:\n\t\t\t\tcase 0xe7:\n\t\t\t\tcase 0xe8:\n\t\t\t\tcase 0xe9:\n\t\t\t\tcase 0xea:\n\t\t\t\tcase 0xeb:\n\t\t\t\tcase 0xec:\n\t\t\t\tcase 0xed:\n\t\t\t\tcase 0xee:\n\t\t\t\tcase 0xef:\n\t\t\t\tcase 0xf0:\n\t\t\t\tcase 0xf1:\n\t\t\t\tcase 0xf2:\n\t\t\t\tcase 0xf3:\n\t\t\t\tcase 0xf4:\n\t\t\t\tcase 0xf5:\n\t\t\t\tcase 0xf6:\n\t\t\t\tcase 0xf7:\n\t\t\t\tcase 0xf8:\n\t\t\t\tcase 0xf9:\n\t\t\t\tcase 0xfa:\n\t\t\t\tcase 0xfb:\n\t\t\t\tcase 0xfc:\n\t\t\t\tcase 0xfd:\n\t\t\t\tcase 0xfe:\n\t\t\t\tcase 0xff:\n\t\t\t\t\treturn static_cast<int8_t>(current);\n\n\t\t\t\tdefault: // anything else\n\t\t\t\t{\n\t\t\t\t\tstd::stringstream ss;\n\t\t\t\t\tss << std::setw(2) << std::setfill('0') << std::hex << current;\n\t\t\t\t\tJSON_THROW(parse_error::create(112, chars_read,\n\t\t\t\t\t\t\"error reading MessagePack; last byte: 0x\" + ss.str()));\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief get next character from the input\n\n\t\t\tThis function provides the interface to the used input adapter. It does\n\t\t\tnot throw in case the input reached EOF, but returns a -'ve valued\n\t\t\t`std::char_traits<char>::eof()` in that case.\n\n\t\t\t@return character read from the input\n\t\t\t*/\n\t\t\tint get()\n\t\t\t{\n\t\t\t\t++chars_read;\n\t\t\t\treturn (current = ia->get_character());\n\t\t\t}\n\n\t\t\t/*\n\t\t\t@brief read a number from the input\n\n\t\t\t@tparam NumberType the type of the number\n\n\t\t\t@return number of type @a NumberType\n\n\t\t\t@note This function needs to respect the system's endianess, because\n\t\t\tbytes in CBOR and MessagePack are stored in network order (big\n\t\t\tendian) and therefore need reordering on little endian systems.\n\n\t\t\t@throw parse_error.110 if input has less than `sizeof(NumberType)` bytes\n\t\t\t*/\n\t\t\ttemplate<typename NumberType> NumberType get_number()\n\t\t\t{\n\t\t\t\t// step 1: read input into array with system's byte order\n\t\t\t\tstd::array<uint8_t, sizeof(NumberType)> vec;\n\t\t\t\tfor (std::size_t i = 0; i < sizeof(NumberType); ++i)\n\t\t\t\t{\n\t\t\t\t\tget();\n\t\t\t\t\tcheck_eof();\n\n\t\t\t\t\t// reverse byte order prior to conversion if necessary\n\t\t\t\t\tif (is_little_endian)\n\t\t\t\t\t{\n\t\t\t\t\t\tvec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tvec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// step 2: convert array into number of type T and return\n\t\t\t\tNumberType result;\n\t\t\t\tstd::memcpy(&result, vec.data(), sizeof(NumberType));\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief create a string by reading characters from the input\n\n\t\t\t@param[in] len number of bytes to read\n\n\t\t\t@note We can not reserve @a len bytes for the result, because @a len\n\t\t\tmay be too large. Usually, @ref check_eof() detects the end of\n\t\t\tthe input before we run out of string memory.\n\n\t\t\t@return string created by reading @a len bytes\n\n\t\t\t@throw parse_error.110 if input has less than @a len bytes\n\t\t\t*/\n\t\t\ttemplate<typename NumberType>\n\t\t\tstd::string get_string(const NumberType len)\n\t\t\t{\n\t\t\t\tstd::string result;\n\t\t\t\tstd::generate_n(std::back_inserter(result), len, [this]()\n\t\t\t\t{\n\t\t\t\t\tget();\n\t\t\t\t\tcheck_eof();\n\t\t\t\t\treturn static_cast<char>(current);\n\t\t\t\t});\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief reads a CBOR string\n\n\t\t\tThis function first reads starting bytes to determine the expected\n\t\t\tstring length and then copies this number of bytes into a string.\n\t\t\tAdditionally, CBOR's strings with indefinite lengths are supported.\n\n\t\t\t@return string\n\n\t\t\t@throw parse_error.110 if input ended\n\t\t\t@throw parse_error.113 if an unexpected byte is read\n\t\t\t*/\n\t\t\tstd::string get_cbor_string()\n\t\t\t{\n\t\t\t\tcheck_eof();\n\n\t\t\t\tswitch (current)\n\t\t\t\t{\n\t\t\t\t\t// UTF-8 string (0x00..0x17 bytes follow)\n\t\t\t\tcase 0x60:\n\t\t\t\tcase 0x61:\n\t\t\t\tcase 0x62:\n\t\t\t\tcase 0x63:\n\t\t\t\tcase 0x64:\n\t\t\t\tcase 0x65:\n\t\t\t\tcase 0x66:\n\t\t\t\tcase 0x67:\n\t\t\t\tcase 0x68:\n\t\t\t\tcase 0x69:\n\t\t\t\tcase 0x6a:\n\t\t\t\tcase 0x6b:\n\t\t\t\tcase 0x6c:\n\t\t\t\tcase 0x6d:\n\t\t\t\tcase 0x6e:\n\t\t\t\tcase 0x6f:\n\t\t\t\tcase 0x70:\n\t\t\t\tcase 0x71:\n\t\t\t\tcase 0x72:\n\t\t\t\tcase 0x73:\n\t\t\t\tcase 0x74:\n\t\t\t\tcase 0x75:\n\t\t\t\tcase 0x76:\n\t\t\t\tcase 0x77:\n\t\t\t\t{\n\t\t\t\t\treturn get_string(current & 0x1f);\n\t\t\t\t}\n\n\t\t\t\tcase 0x78: // UTF-8 string (one-byte uint8_t for n follows)\n\t\t\t\t{\n\t\t\t\t\treturn get_string(get_number<uint8_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0x79: // UTF-8 string (two-byte uint16_t for n follow)\n\t\t\t\t{\n\t\t\t\t\treturn get_string(get_number<uint16_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0x7a: // UTF-8 string (four-byte uint32_t for n follow)\n\t\t\t\t{\n\t\t\t\t\treturn get_string(get_number<uint32_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)\n\t\t\t\t{\n\t\t\t\t\treturn get_string(get_number<uint64_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0x7f: // UTF-8 string (indefinite length)\n\t\t\t\t{\n\t\t\t\t\tstd::string result;\n\t\t\t\t\twhile (get() != 0xff)\n\t\t\t\t\t{\n\t\t\t\t\t\tcheck_eof();\n\t\t\t\t\t\tresult.push_back(static_cast<char>(current));\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tstd::stringstream ss;\n\t\t\t\t\tss << std::setw(2) << std::setfill('0') << std::hex << current;\n\t\t\t\t\tJSON_THROW(parse_error::create(113, chars_read, \"expected a CBOR string; last byte: 0x\" + ss.str()));\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttemplate<typename NumberType>\n\t\t\tBasicJsonType get_cbor_array(const NumberType len)\n\t\t\t{\n\t\t\t\tBasicJsonType result = value_t::array;\n\t\t\t\tstd::generate_n(std::back_inserter(*result.m_value.array), len, [this]()\n\t\t\t\t{\n\t\t\t\t\treturn parse_cbor_internal();\n\t\t\t\t});\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\ttemplate<typename NumberType>\n\t\t\tBasicJsonType get_cbor_object(const NumberType len)\n\t\t\t{\n\t\t\t\tBasicJsonType result = value_t::object;\n\t\t\t\tstd::generate_n(std::inserter(*result.m_value.object,\n\t\t\t\t\tresult.m_value.object->end()),\n\t\t\t\t\tlen, [this]()\n\t\t\t\t{\n\t\t\t\t\tget();\n\t\t\t\t\tauto key = get_cbor_string();\n\t\t\t\t\tauto val = parse_cbor_internal();\n\t\t\t\t\treturn std::make_pair(std::move(key), std::move(val));\n\t\t\t\t});\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief reads a MessagePack string\n\n\t\t\tThis function first reads starting bytes to determine the expected\n\t\t\tstring length and then copies this number of bytes into a string.\n\n\t\t\t@return string\n\n\t\t\t@throw parse_error.110 if input ended\n\t\t\t@throw parse_error.113 if an unexpected byte is read\n\t\t\t*/\n\t\t\tstd::string get_msgpack_string()\n\t\t\t{\n\t\t\t\tcheck_eof();\n\n\t\t\t\tswitch (current)\n\t\t\t\t{\n\t\t\t\t\t// fixstr\n\t\t\t\tcase 0xa0:\n\t\t\t\tcase 0xa1:\n\t\t\t\tcase 0xa2:\n\t\t\t\tcase 0xa3:\n\t\t\t\tcase 0xa4:\n\t\t\t\tcase 0xa5:\n\t\t\t\tcase 0xa6:\n\t\t\t\tcase 0xa7:\n\t\t\t\tcase 0xa8:\n\t\t\t\tcase 0xa9:\n\t\t\t\tcase 0xaa:\n\t\t\t\tcase 0xab:\n\t\t\t\tcase 0xac:\n\t\t\t\tcase 0xad:\n\t\t\t\tcase 0xae:\n\t\t\t\tcase 0xaf:\n\t\t\t\tcase 0xb0:\n\t\t\t\tcase 0xb1:\n\t\t\t\tcase 0xb2:\n\t\t\t\tcase 0xb3:\n\t\t\t\tcase 0xb4:\n\t\t\t\tcase 0xb5:\n\t\t\t\tcase 0xb6:\n\t\t\t\tcase 0xb7:\n\t\t\t\tcase 0xb8:\n\t\t\t\tcase 0xb9:\n\t\t\t\tcase 0xba:\n\t\t\t\tcase 0xbb:\n\t\t\t\tcase 0xbc:\n\t\t\t\tcase 0xbd:\n\t\t\t\tcase 0xbe:\n\t\t\t\tcase 0xbf:\n\t\t\t\t{\n\t\t\t\t\treturn get_string(current & 0x1f);\n\t\t\t\t}\n\n\t\t\t\tcase 0xd9: // str 8\n\t\t\t\t{\n\t\t\t\t\treturn get_string(get_number<uint8_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0xda: // str 16\n\t\t\t\t{\n\t\t\t\t\treturn get_string(get_number<uint16_t>());\n\t\t\t\t}\n\n\t\t\t\tcase 0xdb: // str 32\n\t\t\t\t{\n\t\t\t\t\treturn get_string(get_number<uint32_t>());\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tstd::stringstream ss;\n\t\t\t\t\tss << std::setw(2) << std::setfill('0') << std::hex << current;\n\t\t\t\t\tJSON_THROW(parse_error::create(113, chars_read,\n\t\t\t\t\t\t\"expected a MessagePack string; last byte: 0x\" + ss.str()));\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttemplate<typename NumberType>\n\t\t\tBasicJsonType get_msgpack_array(const NumberType len)\n\t\t\t{\n\t\t\t\tBasicJsonType result = value_t::array;\n\t\t\t\tstd::generate_n(std::back_inserter(*result.m_value.array), len, [this]()\n\t\t\t\t{\n\t\t\t\t\treturn parse_msgpack_internal();\n\t\t\t\t});\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\ttemplate<typename NumberType>\n\t\t\tBasicJsonType get_msgpack_object(const NumberType len)\n\t\t\t{\n\t\t\t\tBasicJsonType result = value_t::object;\n\t\t\t\tstd::generate_n(std::inserter(*result.m_value.object,\n\t\t\t\t\tresult.m_value.object->end()),\n\t\t\t\t\tlen, [this]()\n\t\t\t\t{\n\t\t\t\t\tget();\n\t\t\t\t\tauto key = get_msgpack_string();\n\t\t\t\t\tauto val = parse_msgpack_internal();\n\t\t\t\t\treturn std::make_pair(std::move(key), std::move(val));\n\t\t\t\t});\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief check if input ended\n\t\t\t@throw parse_error.110 if input ended\n\t\t\t*/\n\t\t\tvoid check_eof(const bool expect_eof = false) const\n\t\t\t{\n\t\t\t\tif (expect_eof)\n\t\t\t\t{\n\t\t\t\t\tif (JSON_UNLIKELY(current != std::char_traits<char>::eof()))\n\t\t\t\t\t{\n\t\t\t\t\t\tJSON_THROW(parse_error::create(110, chars_read, \"expected end of input\"));\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\tif (JSON_UNLIKELY(current == std::char_traits<char>::eof()))\n\t\t\t\t\t{\n\t\t\t\t\t\tJSON_THROW(parse_error::create(110, chars_read, \"unexpected end of input\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// input adapter\n\t\t\tinput_adapter_t ia = nullptr;\n\n\t\t\t/// the current character\n\t\t\tint current = std::char_traits<char>::eof();\n\n\t\t\t/// the number of characters read\n\t\t\tstd::size_t chars_read = 0;\n\n\t\t\t/// whether we can assume little endianess\n\t\t\tconst bool is_little_endian = little_endianess();\n\t\t};\n\n\t\t/*!\n\t\t@brief serialization to CBOR and MessagePack values\n\t\t*/\n\t\ttemplate<typename BasicJsonType, typename CharType>\n\t\tclass binary_writer\n\t\t{\n\t\tpublic:\n\t\t\t/*!\n\t\t\t@brief create a binary writer\n\n\t\t\t@param[in] adapter  output adapter to write to\n\t\t\t*/\n\t\t\texplicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)\n\t\t\t{\n\t\t\t\tassert(oa);\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief[in] j  JSON value to serialize\n\t\t\t*/\n\t\t\tvoid write_cbor(const BasicJsonType& j)\n\t\t\t{\n\t\t\t\tswitch (j.type())\n\t\t\t\t{\n\t\t\t\tcase value_t::null:\n\t\t\t\t{\n\t\t\t\t\toa->write_character(static_cast<CharType>(0xf6));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::boolean:\n\t\t\t\t{\n\t\t\t\t\toa->write_character(j.m_value.boolean\n\t\t\t\t\t\t? static_cast<CharType>(0xf5)\n\t\t\t\t\t\t: static_cast<CharType>(0xf4));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_integer:\n\t\t\t\t{\n\t\t\t\t\tif (j.m_value.number_integer >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// CBOR does not differentiate between positive signed\n\t\t\t\t\t\t// integers and unsigned integers. Therefore, we used the\n\t\t\t\t\t\t// code from the value_t::number_unsigned case here.\n\t\t\t\t\t\tif (j.m_value.number_integer <= 0x17)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\twrite_number(static_cast<uint8_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x18));\n\t\t\t\t\t\t\twrite_number(static_cast<uint8_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x19));\n\t\t\t\t\t\t\twrite_number(static_cast<uint16_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x1a));\n\t\t\t\t\t\t\twrite_number(static_cast<uint32_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x1b));\n\t\t\t\t\t\t\twrite_number(static_cast<uint64_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\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// The conversions below encode the sign in the first\n\t\t\t\t\t\t// byte, and the value is converted to a positive number.\n\t\t\t\t\t\tconst auto positive_number = -1 - j.m_value.number_integer;\n\t\t\t\t\t\tif (j.m_value.number_integer >= -24)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\twrite_number(static_cast<uint8_t>(0x20 + positive_number));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (positive_number <= (std::numeric_limits<uint8_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x38));\n\t\t\t\t\t\t\twrite_number(static_cast<uint8_t>(positive_number));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (positive_number <= (std::numeric_limits<uint16_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x39));\n\t\t\t\t\t\t\twrite_number(static_cast<uint16_t>(positive_number));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (positive_number <= (std::numeric_limits<uint32_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x3a));\n\t\t\t\t\t\t\twrite_number(static_cast<uint32_t>(positive_number));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x3b));\n\t\t\t\t\t\t\twrite_number(static_cast<uint64_t>(positive_number));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_unsigned:\n\t\t\t\t{\n\t\t\t\t\tif (j.m_value.number_unsigned <= 0x17)\n\t\t\t\t\t{\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(j.m_value.number_unsigned));\n\t\t\t\t\t}\n\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x18));\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(j.m_value.number_unsigned));\n\t\t\t\t\t}\n\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x19));\n\t\t\t\t\t\twrite_number(static_cast<uint16_t>(j.m_value.number_unsigned));\n\t\t\t\t\t}\n\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x1a));\n\t\t\t\t\t\twrite_number(static_cast<uint32_t>(j.m_value.number_unsigned));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x1b));\n\t\t\t\t\t\twrite_number(static_cast<uint64_t>(j.m_value.number_unsigned));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_float: // Double-Precision Float\n\t\t\t\t{\n\t\t\t\t\toa->write_character(static_cast<CharType>(0xfb));\n\t\t\t\t\twrite_number(j.m_value.number_float);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::string:\n\t\t\t\t{\n\t\t\t\t\t// step 1: write control byte and the string length\n\t\t\t\t\tconst auto N = j.m_value.string->size();\n\t\t\t\t\tif (N <= 0x17)\n\t\t\t\t\t{\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(0x60 + N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x78));\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xffff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x79));\n\t\t\t\t\t\twrite_number(static_cast<uint16_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xffffffff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x7a));\n\t\t\t\t\t\twrite_number(static_cast<uint32_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\t// LCOV_EXCL_START\n\t\t\t\t\telse if (N <= 0xffffffffffffffff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x7b));\n\t\t\t\t\t\twrite_number(static_cast<uint64_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\t// LCOV_EXCL_STOP\n\n\t\t\t\t\t// step 2: write the string\n\t\t\t\t\toa->write_characters(\n\t\t\t\t\t\treinterpret_cast<const CharType*>(j.m_value.string->c_str()),\n\t\t\t\t\t\tj.m_value.string->size());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\t// step 1: write control byte and the array size\n\t\t\t\t\tconst auto N = j.m_value.array->size();\n\t\t\t\t\tif (N <= 0x17)\n\t\t\t\t\t{\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(0x80 + N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x98));\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xffff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x99));\n\t\t\t\t\t\twrite_number(static_cast<uint16_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xffffffff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x9a));\n\t\t\t\t\t\twrite_number(static_cast<uint32_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\t// LCOV_EXCL_START\n\t\t\t\t\telse if (N <= 0xffffffffffffffff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0x9b));\n\t\t\t\t\t\twrite_number(static_cast<uint64_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\t// LCOV_EXCL_STOP\n\n\t\t\t\t\t// step 2: write each element\n\t\t\t\t\tfor (const auto& el : *j.m_value.array)\n\t\t\t\t\t{\n\t\t\t\t\t\twrite_cbor(el);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\t// step 1: write control byte and the object size\n\t\t\t\t\tconst auto N = j.m_value.object->size();\n\t\t\t\t\tif (N <= 0x17)\n\t\t\t\t\t{\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(0xa0 + N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xb8));\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xffff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xb9));\n\t\t\t\t\t\twrite_number(static_cast<uint16_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xffffffff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xba));\n\t\t\t\t\t\twrite_number(static_cast<uint32_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\t// LCOV_EXCL_START\n\t\t\t\t\telse if (N <= 0xffffffffffffffff)\n\t\t\t\t\t{\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xbb));\n\t\t\t\t\t\twrite_number(static_cast<uint64_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\t// LCOV_EXCL_STOP\n\n\t\t\t\t\t// step 2: write each element\n\t\t\t\t\tfor (const auto& el : *j.m_value.object)\n\t\t\t\t\t{\n\t\t\t\t\t\twrite_cbor(el.first);\n\t\t\t\t\t\twrite_cbor(el.second);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief[in] j  JSON value to serialize\n\t\t\t*/\n\t\t\tvoid write_msgpack(const BasicJsonType& j)\n\t\t\t{\n\t\t\t\tswitch (j.type())\n\t\t\t\t{\n\t\t\t\tcase value_t::null: // nil\n\t\t\t\t{\n\t\t\t\t\toa->write_character(static_cast<CharType>(0xc0));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::boolean: // true and false\n\t\t\t\t{\n\t\t\t\t\toa->write_character(j.m_value.boolean\n\t\t\t\t\t\t? static_cast<CharType>(0xc3)\n\t\t\t\t\t\t: static_cast<CharType>(0xc2));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_integer:\n\t\t\t\t{\n\t\t\t\t\tif (j.m_value.number_integer >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// MessagePack does not differentiate between positive\n\t\t\t\t\t\t// signed integers and unsigned integers. Therefore, we used\n\t\t\t\t\t\t// the code from the value_t::number_unsigned case here.\n\t\t\t\t\t\tif (j.m_value.number_unsigned < 128)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// positive fixnum\n\t\t\t\t\t\t\twrite_number(static_cast<uint8_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// uint 8\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xcc));\n\t\t\t\t\t\t\twrite_number(static_cast<uint8_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// uint 16\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xcd));\n\t\t\t\t\t\t\twrite_number(static_cast<uint16_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// uint 32\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xce));\n\t\t\t\t\t\t\twrite_number(static_cast<uint32_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// uint 64\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xcf));\n\t\t\t\t\t\t\twrite_number(static_cast<uint64_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (j.m_value.number_integer >= -32)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// negative fixnum\n\t\t\t\t\t\t\twrite_number(static_cast<int8_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and\n\t\t\t\t\t\t\tj.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// int 8\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xd0));\n\t\t\t\t\t\t\twrite_number(static_cast<int8_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and\n\t\t\t\t\t\t\tj.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// int 16\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xd1));\n\t\t\t\t\t\t\twrite_number(static_cast<int16_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and\n\t\t\t\t\t\t\tj.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// int 32\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xd2));\n\t\t\t\t\t\t\twrite_number(static_cast<int32_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and\n\t\t\t\t\t\t\tj.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// int 64\n\t\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xd3));\n\t\t\t\t\t\t\twrite_number(static_cast<int64_t>(j.m_value.number_integer));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_unsigned:\n\t\t\t\t{\n\t\t\t\t\tif (j.m_value.number_unsigned < 128)\n\t\t\t\t\t{\n\t\t\t\t\t\t// positive fixnum\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(j.m_value.number_integer));\n\t\t\t\t\t}\n\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())\n\t\t\t\t\t{\n\t\t\t\t\t\t// uint 8\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xcc));\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(j.m_value.number_integer));\n\t\t\t\t\t}\n\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())\n\t\t\t\t\t{\n\t\t\t\t\t\t// uint 16\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xcd));\n\t\t\t\t\t\twrite_number(static_cast<uint16_t>(j.m_value.number_integer));\n\t\t\t\t\t}\n\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())\n\t\t\t\t\t{\n\t\t\t\t\t\t// uint 32\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xce));\n\t\t\t\t\t\twrite_number(static_cast<uint32_t>(j.m_value.number_integer));\n\t\t\t\t\t}\n\t\t\t\t\telse if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())\n\t\t\t\t\t{\n\t\t\t\t\t\t// uint 64\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xcf));\n\t\t\t\t\t\twrite_number(static_cast<uint64_t>(j.m_value.number_integer));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_float: // float 64\n\t\t\t\t{\n\t\t\t\t\toa->write_character(static_cast<CharType>(0xcb));\n\t\t\t\t\twrite_number(j.m_value.number_float);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::string:\n\t\t\t\t{\n\t\t\t\t\t// step 1: write control byte and the string length\n\t\t\t\t\tconst auto N = j.m_value.string->size();\n\t\t\t\t\tif (N <= 31)\n\t\t\t\t\t{\n\t\t\t\t\t\t// fixstr\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(0xa0 | N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 255)\n\t\t\t\t\t{\n\t\t\t\t\t\t// str 8\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xd9));\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 65535)\n\t\t\t\t\t{\n\t\t\t\t\t\t// str 16\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xda));\n\t\t\t\t\t\twrite_number(static_cast<uint16_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 4294967295)\n\t\t\t\t\t{\n\t\t\t\t\t\t// str 32\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xdb));\n\t\t\t\t\t\twrite_number(static_cast<uint32_t>(N));\n\t\t\t\t\t}\n\n\t\t\t\t\t// step 2: write the string\n\t\t\t\t\toa->write_characters(\n\t\t\t\t\t\treinterpret_cast<const CharType*>(j.m_value.string->c_str()),\n\t\t\t\t\t\tj.m_value.string->size());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\t// step 1: write control byte and the array size\n\t\t\t\t\tconst auto N = j.m_value.array->size();\n\t\t\t\t\tif (N <= 15)\n\t\t\t\t\t{\n\t\t\t\t\t\t// fixarray\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(0x90 | N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xffff)\n\t\t\t\t\t{\n\t\t\t\t\t\t// array 16\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xdc));\n\t\t\t\t\t\twrite_number(static_cast<uint16_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 0xffffffff)\n\t\t\t\t\t{\n\t\t\t\t\t\t// array 32\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xdd));\n\t\t\t\t\t\twrite_number(static_cast<uint32_t>(N));\n\t\t\t\t\t}\n\n\t\t\t\t\t// step 2: write each element\n\t\t\t\t\tfor (const auto& el : *j.m_value.array)\n\t\t\t\t\t{\n\t\t\t\t\t\twrite_msgpack(el);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\t// step 1: write control byte and the object size\n\t\t\t\t\tconst auto N = j.m_value.object->size();\n\t\t\t\t\tif (N <= 15)\n\t\t\t\t\t{\n\t\t\t\t\t\t// fixmap\n\t\t\t\t\t\twrite_number(static_cast<uint8_t>(0x80 | (N & 0xf)));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 65535)\n\t\t\t\t\t{\n\t\t\t\t\t\t// map 16\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xde));\n\t\t\t\t\t\twrite_number(static_cast<uint16_t>(N));\n\t\t\t\t\t}\n\t\t\t\t\telse if (N <= 4294967295)\n\t\t\t\t\t{\n\t\t\t\t\t\t// map 32\n\t\t\t\t\t\toa->write_character(static_cast<CharType>(0xdf));\n\t\t\t\t\t\twrite_number(static_cast<uint32_t>(N));\n\t\t\t\t\t}\n\n\t\t\t\t\t// step 2: write each element\n\t\t\t\t\tfor (const auto& el : *j.m_value.object)\n\t\t\t\t\t{\n\t\t\t\t\t\twrite_msgpack(el.first);\n\t\t\t\t\t\twrite_msgpack(el.second);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/*\n\t\t\t@brief write a number to output input\n\n\t\t\t@param[in] n number of type @a NumberType\n\t\t\t@tparam NumberType the type of the number\n\n\t\t\t@note This function needs to respect the system's endianess, because bytes\n\t\t\tin CBOR and MessagePack are stored in network order (big endian) and\n\t\t\ttherefore need reordering on little endian systems.\n\t\t\t*/\n\t\t\ttemplate<typename NumberType> void write_number(NumberType n)\n\t\t\t{\n\t\t\t\t// step 1: write number to array of length NumberType\n\t\t\t\tstd::array<CharType, sizeof(NumberType)> vec;\n\t\t\t\tstd::memcpy(vec.data(), &n, sizeof(NumberType));\n\n\t\t\t\t// step 2: write array to output (with possible reordering)\n\t\t\t\tif (is_little_endian)\n\t\t\t\t{\n\t\t\t\t\t// reverse byte order prior to conversion if necessary\n\t\t\t\t\tstd::reverse(vec.begin(), vec.end());\n\t\t\t\t}\n\n\t\t\t\toa->write_characters(vec.data(), sizeof(NumberType));\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// whether we can assume little endianess\n\t\t\tconst bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();\n\n\t\t\t/// the output\n\t\t\toutput_adapter_t<CharType> oa = nullptr;\n\t\t};\n\n\t\t///////////////////\n\t\t// serialization //\n\t\t///////////////////\n\n\t\ttemplate<typename BasicJsonType>\n\t\tclass serializer\n\t\t{\n\t\t\tusing string_t = typename BasicJsonType::string_t;\n\t\t\tusing number_float_t = typename BasicJsonType::number_float_t;\n\t\t\tusing number_integer_t = typename BasicJsonType::number_integer_t;\n\t\t\tusing number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n\t\tpublic:\n\t\t\t/*!\n\t\t\t@param[in] s  output stream to serialize to\n\t\t\t@param[in] ichar  indentation character to use\n\t\t\t*/\n\t\t\tserializer(output_adapter_t<char> s, const char ichar)\n\t\t\t\t: o(std::move(s)), loc(std::localeconv()),\n\t\t\t\tthousands_sep(loc->thousands_sep == nullptr ? '\\0' : loc->thousands_sep[0]),\n\t\t\t\tdecimal_point(loc->decimal_point == nullptr ? '\\0' : loc->decimal_point[0]),\n\t\t\t\tindent_char(ichar), indent_string(512, indent_char) {}\n\n\t\t\t// delete because of pointer members\n\t\t\tserializer(const serializer&) = delete;\n\t\t\tserializer& operator=(const serializer&) = delete;\n\n\t\t\t/*!\n\t\t\t@brief internal implementation of the serialization function\n\n\t\t\tThis function is called by the public member function dump and organizes\n\t\t\tthe serialization internally. The indentation level is propagated as\n\t\t\tadditional parameter. In case of arrays and objects, the function is\n\t\t\tcalled recursively.\n\n\t\t\t- strings and object keys are escaped using `escape_string()`\n\t\t\t- integer numbers are converted implicitly via `operator<<`\n\t\t\t- floating-point numbers are converted to a string using `\"%g\"` format\n\n\t\t\t@param[in] val             value to serialize\n\t\t\t@param[in] pretty_print    whether the output shall be pretty-printed\n\t\t\t@param[in] indent_step     the indent level\n\t\t\t@param[in] current_indent  the current indent level (only used internally)\n\t\t\t*/\n\t\t\tvoid dump(const BasicJsonType& val, const bool pretty_print,\n\t\t\t\tconst bool ensure_ascii,\n\t\t\t\tconst unsigned int indent_step,\n\t\t\t\tconst unsigned int current_indent = 0)\n\t\t\t{\n\t\t\t\tswitch (val.m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tif (val.m_value.object->empty())\n\t\t\t\t\t{\n\t\t\t\t\t\to->write_characters(\"{}\", 2);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (pretty_print)\n\t\t\t\t\t{\n\t\t\t\t\t\to->write_characters(\"{\\n\", 2);\n\n\t\t\t\t\t\t// variable to hold indentation for recursive calls\n\t\t\t\t\t\tconst auto new_indent = current_indent + indent_step;\n\t\t\t\t\t\tif (JSON_UNLIKELY(indent_string.size() < new_indent))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tindent_string.resize(indent_string.size() * 2, ' ');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// first n-1 elements\n\t\t\t\t\t\tauto i = val.m_value.object->cbegin();\n\t\t\t\t\t\tfor (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\to->write_characters(indent_string.c_str(), new_indent);\n\t\t\t\t\t\t\to->write_character('\\\"');\n\t\t\t\t\t\t\tdump_escaped(i->first, ensure_ascii);\n\t\t\t\t\t\t\to->write_characters(\"\\\": \", 3);\n\t\t\t\t\t\t\tdump(i->second, true, ensure_ascii, indent_step, new_indent);\n\t\t\t\t\t\t\to->write_characters(\",\\n\", 2);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// last element\n\t\t\t\t\t\tassert(i != val.m_value.object->cend());\n\t\t\t\t\t\tassert(std::next(i) == val.m_value.object->cend());\n\t\t\t\t\t\to->write_characters(indent_string.c_str(), new_indent);\n\t\t\t\t\t\to->write_character('\\\"');\n\t\t\t\t\t\tdump_escaped(i->first, ensure_ascii);\n\t\t\t\t\t\to->write_characters(\"\\\": \", 3);\n\t\t\t\t\t\tdump(i->second, true, ensure_ascii, indent_step, new_indent);\n\n\t\t\t\t\t\to->write_character('\\n');\n\t\t\t\t\t\to->write_characters(indent_string.c_str(), current_indent);\n\t\t\t\t\t\to->write_character('}');\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\to->write_character('{');\n\n\t\t\t\t\t\t// first n-1 elements\n\t\t\t\t\t\tauto i = val.m_value.object->cbegin();\n\t\t\t\t\t\tfor (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\to->write_character('\\\"');\n\t\t\t\t\t\t\tdump_escaped(i->first, ensure_ascii);\n\t\t\t\t\t\t\to->write_characters(\"\\\":\", 2);\n\t\t\t\t\t\t\tdump(i->second, false, ensure_ascii, indent_step, current_indent);\n\t\t\t\t\t\t\to->write_character(',');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// last element\n\t\t\t\t\t\tassert(i != val.m_value.object->cend());\n\t\t\t\t\t\tassert(std::next(i) == val.m_value.object->cend());\n\t\t\t\t\t\to->write_character('\\\"');\n\t\t\t\t\t\tdump_escaped(i->first, ensure_ascii);\n\t\t\t\t\t\to->write_characters(\"\\\":\", 2);\n\t\t\t\t\t\tdump(i->second, false, ensure_ascii, indent_step, current_indent);\n\n\t\t\t\t\t\to->write_character('}');\n\t\t\t\t\t}\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tif (val.m_value.array->empty())\n\t\t\t\t\t{\n\t\t\t\t\t\to->write_characters(\"[]\", 2);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (pretty_print)\n\t\t\t\t\t{\n\t\t\t\t\t\to->write_characters(\"[\\n\", 2);\n\n\t\t\t\t\t\t// variable to hold indentation for recursive calls\n\t\t\t\t\t\tconst auto new_indent = current_indent + indent_step;\n\t\t\t\t\t\tif (JSON_UNLIKELY(indent_string.size() < new_indent))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tindent_string.resize(indent_string.size() * 2, ' ');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// first n-1 elements\n\t\t\t\t\t\tfor (auto i = val.m_value.array->cbegin();\n\t\t\t\t\t\t\ti != val.m_value.array->cend() - 1; ++i)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\to->write_characters(indent_string.c_str(), new_indent);\n\t\t\t\t\t\t\tdump(*i, true, ensure_ascii, indent_step, new_indent);\n\t\t\t\t\t\t\to->write_characters(\",\\n\", 2);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// last element\n\t\t\t\t\t\tassert(not val.m_value.array->empty());\n\t\t\t\t\t\to->write_characters(indent_string.c_str(), new_indent);\n\t\t\t\t\t\tdump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);\n\n\t\t\t\t\t\to->write_character('\\n');\n\t\t\t\t\t\to->write_characters(indent_string.c_str(), current_indent);\n\t\t\t\t\t\to->write_character(']');\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\to->write_character('[');\n\n\t\t\t\t\t\t// first n-1 elements\n\t\t\t\t\t\tfor (auto i = val.m_value.array->cbegin();\n\t\t\t\t\t\t\ti != val.m_value.array->cend() - 1; ++i)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdump(*i, false, ensure_ascii, indent_step, current_indent);\n\t\t\t\t\t\t\to->write_character(',');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// last element\n\t\t\t\t\t\tassert(not val.m_value.array->empty());\n\t\t\t\t\t\tdump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);\n\n\t\t\t\t\t\to->write_character(']');\n\t\t\t\t\t}\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::string:\n\t\t\t\t{\n\t\t\t\t\to->write_character('\\\"');\n\t\t\t\t\tdump_escaped(*val.m_value.string, ensure_ascii);\n\t\t\t\t\to->write_character('\\\"');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::boolean:\n\t\t\t\t{\n\t\t\t\t\tif (val.m_value.boolean)\n\t\t\t\t\t{\n\t\t\t\t\t\to->write_characters(\"true\", 4);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\to->write_characters(\"false\", 5);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_integer:\n\t\t\t\t{\n\t\t\t\t\tdump_integer(val.m_value.number_integer);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_unsigned:\n\t\t\t\t{\n\t\t\t\t\tdump_integer(val.m_value.number_unsigned);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_float:\n\t\t\t\t{\n\t\t\t\t\tdump_float(val.m_value.number_float);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::discarded:\n\t\t\t\t{\n\t\t\t\t\to->write_characters(\"<discarded>\", 11);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::null:\n\t\t\t\t{\n\t\t\t\t\to->write_characters(\"null\", 4);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/*!\n\t\t\t@brief returns the number of expected bytes following in UTF-8 string\n\n\t\t\t@param[in]  u  the first byte of a UTF-8 string\n\t\t\t@return  the number of expected bytes following\n\t\t\t*/\n\t\t\tstatic constexpr std::size_t bytes_following(const uint8_t u)\n\t\t\t{\n\t\t\t\treturn ((u <= 127) ? 0\n\t\t\t\t\t: ((192 <= u and u <= 223) ? 1\n\t\t\t\t\t\t: ((224 <= u and u <= 239) ? 2\n\t\t\t\t\t\t\t: ((240 <= u and u <= 247) ? 3 : std::string::npos))));\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief calculates the extra space to escape a JSON string\n\n\t\t\t@param[in] s  the string to escape\n\t\t\t@param[in] ensure_ascii  whether to escape non-ASCII characters with\n\t\t\t\\uXXXX sequences\n\t\t\t@return the number of characters required to escape string @a s\n\n\t\t\t@complexity Linear in the length of string @a s.\n\t\t\t*/\n\t\t\tstatic std::size_t extra_space(const string_t& s,\n\t\t\t\tconst bool ensure_ascii) noexcept\n\t\t\t{\n\t\t\t\tstd::size_t res = 0;\n\n\t\t\t\tfor (std::size_t i = 0; i < s.size(); ++i)\n\t\t\t\t{\n\t\t\t\t\tswitch (s[i])\n\t\t\t\t\t{\n\t\t\t\t\t\t// control characters that can be escaped with a backslash\n\t\t\t\t\tcase '\"':\n\t\t\t\t\tcase '\\\\':\n\t\t\t\t\tcase '\\b':\n\t\t\t\t\tcase '\\f':\n\t\t\t\t\tcase '\\n':\n\t\t\t\t\tcase '\\r':\n\t\t\t\t\tcase '\\t':\n\t\t\t\t\t{\n\t\t\t\t\t\t// from c (1 byte) to \\x (2 bytes)\n\t\t\t\t\t\tres += 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// control characters that need \\uxxxx escaping\n\t\t\t\t\tcase 0x00:\n\t\t\t\t\tcase 0x01:\n\t\t\t\t\tcase 0x02:\n\t\t\t\t\tcase 0x03:\n\t\t\t\t\tcase 0x04:\n\t\t\t\t\tcase 0x05:\n\t\t\t\t\tcase 0x06:\n\t\t\t\t\tcase 0x07:\n\t\t\t\t\tcase 0x0b:\n\t\t\t\t\tcase 0x0e:\n\t\t\t\t\tcase 0x0f:\n\t\t\t\t\tcase 0x10:\n\t\t\t\t\tcase 0x11:\n\t\t\t\t\tcase 0x12:\n\t\t\t\t\tcase 0x13:\n\t\t\t\t\tcase 0x14:\n\t\t\t\t\tcase 0x15:\n\t\t\t\t\tcase 0x16:\n\t\t\t\t\tcase 0x17:\n\t\t\t\t\tcase 0x18:\n\t\t\t\t\tcase 0x19:\n\t\t\t\t\tcase 0x1a:\n\t\t\t\t\tcase 0x1b:\n\t\t\t\t\tcase 0x1c:\n\t\t\t\t\tcase 0x1d:\n\t\t\t\t\tcase 0x1e:\n\t\t\t\t\tcase 0x1f:\n\t\t\t\t\t{\n\t\t\t\t\t\t// from c (1 byte) to \\uxxxx (6 bytes)\n\t\t\t\t\t\tres += 5;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ensure_ascii and (s[i] & 0x80 or s[i] == 0x7F))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst auto bytes = bytes_following(static_cast<uint8_t>(s[i]));\n\t\t\t\t\t\t\tif (bytes == std::string::npos)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// invalid characters are treated as is, so no\n\t\t\t\t\t\t\t\t// additional space will be used\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (bytes == 3)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// codepoints that need 4 bytes (i.e., 3 additional\n\t\t\t\t\t\t\t\t// bytes) in UTF-8 need a surrogate pair when \\u\n\t\t\t\t\t\t\t\t// escaping is used: from 4 bytes to \\uxxxx\\uxxxx\n\t\t\t\t\t\t\t\t// (12 bytes)\n\t\t\t\t\t\t\t\tres += (12 - bytes - 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// from x bytes to \\uxxxx (6 bytes)\n\t\t\t\t\t\t\t\tres += (6 - bytes - 1);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// skip the additional bytes\n\t\t\t\t\t\t\ti += bytes;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn res;\n\t\t\t}\n\n\t\t\tstatic void escape_codepoint(int codepoint, string_t& result, std::size_t& pos)\n\t\t\t{\n\t\t\t\t// expecting a proper codepoint\n\t\t\t\tassert(0x00 <= codepoint and codepoint <= 0x10FFFF);\n\n\t\t\t\t// the last written character was the backslash before the 'u'\n\t\t\t\tassert(result[pos] == '\\\\');\n\n\t\t\t\t// write the 'u'\n\t\t\t\tresult[++pos] = 'u';\n\n\t\t\t\t// convert a number 0..15 to its hex representation (0..f)\n\t\t\t\tstatic const std::array<char, 16> hexify =\n\t\t\t\t{\n\t\t\t\t\t{\n\t\t\t\t\t\t'0', '1', '2', '3', '4', '5', '6', '7',\n\t\t\t\t\t\t'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tif (codepoint < 0x10000)\n\t\t\t\t{\n\t\t\t\t\t// codepoints U+0000..U+FFFF can be represented as \\uxxxx.\n\t\t\t\t\tresult[++pos] = hexify[(codepoint >> 12) & 0x0F];\n\t\t\t\t\tresult[++pos] = hexify[(codepoint >> 8) & 0x0F];\n\t\t\t\t\tresult[++pos] = hexify[(codepoint >> 4) & 0x0F];\n\t\t\t\t\tresult[++pos] = hexify[codepoint & 0x0F];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// codepoints U+10000..U+10FFFF need a surrogate pair to be\n\t\t\t\t\t// represented as \\uxxxx\\uxxxx.\n\t\t\t\t\t// http://www.unicode.org/faq/utf_bom.html#utf16-4\n\t\t\t\t\tcodepoint -= 0x10000;\n\t\t\t\t\tconst int high_surrogate = 0xD800 | ((codepoint >> 10) & 0x3FF);\n\t\t\t\t\tconst int low_surrogate = 0xDC00 | (codepoint & 0x3FF);\n\t\t\t\t\tresult[++pos] = hexify[(high_surrogate >> 12) & 0x0F];\n\t\t\t\t\tresult[++pos] = hexify[(high_surrogate >> 8) & 0x0F];\n\t\t\t\t\tresult[++pos] = hexify[(high_surrogate >> 4) & 0x0F];\n\t\t\t\t\tresult[++pos] = hexify[high_surrogate & 0x0F];\n\t\t\t\t\t++pos;  // backslash is already in output\n\t\t\t\t\tresult[++pos] = 'u';\n\t\t\t\t\tresult[++pos] = hexify[(low_surrogate >> 12) & 0x0F];\n\t\t\t\t\tresult[++pos] = hexify[(low_surrogate >> 8) & 0x0F];\n\t\t\t\t\tresult[++pos] = hexify[(low_surrogate >> 4) & 0x0F];\n\t\t\t\t\tresult[++pos] = hexify[low_surrogate & 0x0F];\n\t\t\t\t}\n\n\t\t\t\t++pos;\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief dump escaped string\n\n\t\t\tEscape a string by replacing certain special characters by a sequence of an\n\t\t\tescape character (backslash) and another character and other control\n\t\t\tcharacters by a sequence of \"\\u\" followed by a four-digit hex\n\t\t\trepresentation. The escaped string is written to output stream @a o.\n\n\t\t\t@param[in] s  the string to escape\n\t\t\t@param[in] ensure_ascii  whether to escape non-ASCII characters with\n\t\t\t\\uXXXX sequences\n\n\t\t\t@complexity Linear in the length of string @a s.\n\t\t\t*/\n\t\t\tvoid dump_escaped(const string_t& s, const bool ensure_ascii) const\n\t\t\t{\n\t\t\t\tconst auto space = extra_space(s, ensure_ascii);\n\t\t\t\tif (space == 0)\n\t\t\t\t{\n\t\t\t\t\to->write_characters(s.c_str(), s.size());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// create a result string of necessary size\n\t\t\t\tstring_t result(s.size() + space, '\\\\');\n\t\t\t\tstd::size_t pos = 0;\n\n\t\t\t\tfor (std::size_t i = 0; i < s.size(); ++i)\n\t\t\t\t{\n\t\t\t\t\tswitch (s[i])\n\t\t\t\t\t{\n\t\t\t\t\tcase '\"': // quotation mark (0x22)\n\t\t\t\t\t{\n\t\t\t\t\t\tresult[pos + 1] = '\"';\n\t\t\t\t\t\tpos += 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase '\\\\': // reverse solidus (0x5c)\n\t\t\t\t\t{\n\t\t\t\t\t\t// nothing to change\n\t\t\t\t\t\tpos += 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase '\\b': // backspace (0x08)\n\t\t\t\t\t{\n\t\t\t\t\t\tresult[pos + 1] = 'b';\n\t\t\t\t\t\tpos += 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase '\\f': // formfeed (0x0c)\n\t\t\t\t\t{\n\t\t\t\t\t\tresult[pos + 1] = 'f';\n\t\t\t\t\t\tpos += 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase '\\n': // newline (0x0a)\n\t\t\t\t\t{\n\t\t\t\t\t\tresult[pos + 1] = 'n';\n\t\t\t\t\t\tpos += 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase '\\r': // carriage return (0x0d)\n\t\t\t\t\t{\n\t\t\t\t\t\tresult[pos + 1] = 'r';\n\t\t\t\t\t\tpos += 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase '\\t': // horizontal tab (0x09)\n\t\t\t\t\t{\n\t\t\t\t\t\tresult[pos + 1] = 't';\n\t\t\t\t\t\tpos += 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t{\n\t\t\t\t\t\t// escape control characters (0x00..0x1F) or, if\n\t\t\t\t\t\t// ensure_ascii parameter is used, non-ASCII characters\n\t\t\t\t\t\tif ((0x00 <= s[i] and s[i] <= 0x1F) or\n\t\t\t\t\t\t\t(ensure_ascii and (s[i] & 0x80 or s[i] == 0x7F)))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst auto bytes = bytes_following(static_cast<uint8_t>(s[i]));\n\t\t\t\t\t\t\tif (bytes == std::string::npos)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// copy invalid character as is\n\t\t\t\t\t\t\t\tresult[pos++] = s[i];\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// check that the additional bytes are present\n\t\t\t\t\t\t\tassert(i + bytes < s.size());\n\n\t\t\t\t\t\t\t// to use \\uxxxx escaping, we first need to caluclate\n\t\t\t\t\t\t\t// the codepoint from the UTF-8 bytes\n\t\t\t\t\t\t\tint codepoint = 0;\n\n\t\t\t\t\t\t\tassert(0 <= bytes and bytes <= 3);\n\t\t\t\t\t\t\tswitch (bytes)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcodepoint = s[i] & 0xFF;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcodepoint = ((s[i] & 0x3F) << 6)\n\t\t\t\t\t\t\t\t\t+ (s[i + 1] & 0x7F);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcodepoint = ((s[i] & 0x1F) << 12)\n\t\t\t\t\t\t\t\t\t+ ((s[i + 1] & 0x7F) << 6)\n\t\t\t\t\t\t\t\t\t+ (s[i + 2] & 0x7F);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcodepoint = ((s[i] & 0xF) << 18)\n\t\t\t\t\t\t\t\t\t+ ((s[i + 1] & 0x7F) << 12)\n\t\t\t\t\t\t\t\t\t+ ((s[i + 2] & 0x7F) << 6)\n\t\t\t\t\t\t\t\t\t+ (s[i + 3] & 0x7F);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;  // LCOV_EXCL_LINE\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tescape_codepoint(codepoint, result, pos);\n\t\t\t\t\t\t\ti += bytes;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// all other characters are added as-is\n\t\t\t\t\t\t\tresult[pos++] = s[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tassert(pos == result.size());\n\t\t\t\to->write_characters(result.c_str(), result.size());\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief dump an integer\n\n\t\t\tDump a given integer to output stream @a o. Works internally with\n\t\t\t@a number_buffer.\n\n\t\t\t@param[in] x  integer number (signed or unsigned) to dump\n\t\t\t@tparam NumberType either @a number_integer_t or @a number_unsigned_t\n\t\t\t*/\n\t\t\ttemplate <\n\t\t\t\ttypename NumberType,\n\t\t\t\tdetail::enable_if_t<std::is_same<NumberType, number_unsigned_t>::value or\n\t\t\t\tstd::is_same<NumberType, number_integer_t>::value,\n\t\t\t\tint> = 0 >\n\t\t\t\tvoid dump_integer(NumberType x)\n\t\t\t{\n\t\t\t\t// special case for \"0\"\n\t\t\t\tif (x == 0)\n\t\t\t\t{\n\t\t\t\t\to->write_character('0');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst bool is_negative = (x <= 0) and (x != 0);  // see issue #755\n\t\t\t\tstd::size_t i = 0;\n\n\t\t\t\twhile (x != 0)\n\t\t\t\t{\n\t\t\t\t\t// spare 1 byte for '\\0'\n\t\t\t\t\tassert(i < number_buffer.size() - 1);\n\n\t\t\t\t\tconst auto digit = std::labs(static_cast<long>(x % 10));\n\t\t\t\t\tnumber_buffer[i++] = static_cast<char>('0' + digit);\n\t\t\t\t\tx /= 10;\n\t\t\t\t}\n\n\t\t\t\tif (is_negative)\n\t\t\t\t{\n\t\t\t\t\t// make sure there is capacity for the '-'\n\t\t\t\t\tassert(i < number_buffer.size() - 2);\n\t\t\t\t\tnumber_buffer[i++] = '-';\n\t\t\t\t}\n\n\t\t\t\tstd::reverse(number_buffer.begin(), number_buffer.begin() + i);\n\t\t\t\to->write_characters(number_buffer.data(), i);\n\t\t\t}\n\n\t\t\t/*!\n\t\t\t@brief dump a floating-point number\n\n\t\t\tDump a given floating-point number to output stream @a o. Works internally\n\t\t\twith @a number_buffer.\n\n\t\t\t@param[in] x  floating-point number to dump\n\t\t\t*/\n\t\t\tvoid dump_float(number_float_t x)\n\t\t\t{\n\t\t\t\t// NaN / inf\n\t\t\t\tif (not std::isfinite(x) or std::isnan(x))\n\t\t\t\t{\n\t\t\t\t\to->write_characters(\"null\", 4);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// get number of digits for a text -> float -> text round-trip\n\t\t\t\tstatic constexpr auto d = std::numeric_limits<number_float_t>::digits10;\n\n\t\t\t\t// the actual conversion\n\t\t\t\tstd::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), \"%.*g\", d, x);\n\n\t\t\t\t// negative value indicates an error\n\t\t\t\tassert(len > 0);\n\t\t\t\t// check if buffer was large enough\n\t\t\t\tassert(static_cast<std::size_t>(len) < number_buffer.size());\n\n\t\t\t\t// erase thousands separator\n\t\t\t\tif (thousands_sep != '\\0')\n\t\t\t\t{\n\t\t\t\t\tconst auto end = std::remove(number_buffer.begin(),\n\t\t\t\t\t\tnumber_buffer.begin() + len, thousands_sep);\n\t\t\t\t\tstd::fill(end, number_buffer.end(), '\\0');\n\t\t\t\t\tassert((end - number_buffer.begin()) <= len);\n\t\t\t\t\tlen = (end - number_buffer.begin());\n\t\t\t\t}\n\n\t\t\t\t// convert decimal point to '.'\n\t\t\t\tif (decimal_point != '\\0' and decimal_point != '.')\n\t\t\t\t{\n\t\t\t\t\tconst auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);\n\t\t\t\t\tif (dec_pos != number_buffer.end())\n\t\t\t\t\t{\n\t\t\t\t\t\t*dec_pos = '.';\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\to->write_characters(number_buffer.data(), static_cast<std::size_t>(len));\n\n\t\t\t\t// determine if need to append \".0\"\n\t\t\t\tconst bool value_is_int_like =\n\t\t\t\t\tstd::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,\n\t\t\t\t\t\t[](char c)\n\t\t\t\t{\n\t\t\t\t\treturn (c == '.' or c == 'e');\n\t\t\t\t});\n\n\t\t\t\tif (value_is_int_like)\n\t\t\t\t{\n\t\t\t\t\to->write_characters(\".0\", 2);\n\t\t\t\t}\n\t\t\t}\n\n\t\tprivate:\n\t\t\t/// the output of the serializer\n\t\t\toutput_adapter_t<char> o = nullptr;\n\n\t\t\t/// a (hopefully) large enough character buffer\n\t\t\tstd::array<char, 64> number_buffer{ {} };\n\n\t\t\t/// the locale\n\t\t\tconst std::lconv* loc = nullptr;\n\t\t\t/// the locale's thousand separator character\n\t\t\tconst char thousands_sep = '\\0';\n\t\t\t/// the locale's decimal point character\n\t\t\tconst char decimal_point = '\\0';\n\n\t\t\t/// the indentation character\n\t\t\tconst char indent_char;\n\n\t\t\t/// the indentation string\n\t\t\tstring_t indent_string;\n\t\t};\n\n\t\ttemplate<typename BasicJsonType>\n\t\tclass json_ref\n\t\t{\n\t\tpublic:\n\t\t\tusing value_type = BasicJsonType;\n\n\t\t\tjson_ref(value_type&& value)\n\t\t\t\t: owned_value(std::move(value)),\n\t\t\t\tvalue_ref(&owned_value),\n\t\t\t\tis_rvalue(true)\n\t\t\t{}\n\n\t\t\tjson_ref(const value_type& value)\n\t\t\t\t: value_ref(const_cast<value_type*>(&value)),\n\t\t\t\tis_rvalue(false)\n\t\t\t{}\n\n\t\t\tjson_ref(std::initializer_list<json_ref> init)\n\t\t\t\t: owned_value(init),\n\t\t\t\tvalue_ref(&owned_value),\n\t\t\t\tis_rvalue(true)\n\t\t\t{}\n\n\t\t\ttemplate <class... Args>\n\t\t\tjson_ref(Args&& ... args)\n\t\t\t\t: owned_value(std::forward<Args>(args)...),\n\t\t\t\tvalue_ref(&owned_value),\n\t\t\t\tis_rvalue(true)\n\t\t\t{}\n\n\t\t\t// class should be movable only\n\t\t\tjson_ref(json_ref&&) = default;\n\t\t\tjson_ref(const json_ref&) = delete;\n\t\t\tjson_ref& operator=(const json_ref&) = delete;\n\n\t\t\tvalue_type moved_or_copied() const\n\t\t\t{\n\t\t\t\tif (is_rvalue)\n\t\t\t\t{\n\t\t\t\t\treturn std::move(*value_ref);\n\t\t\t\t}\n\t\t\t\treturn *value_ref;\n\t\t\t}\n\n\t\t\tvalue_type const& operator*() const\n\t\t\t{\n\t\t\t\treturn *static_cast<value_type const*>(value_ref);\n\t\t\t}\n\n\t\t\tvalue_type const* operator->() const\n\t\t\t{\n\t\t\t\treturn static_cast<value_type const*>(value_ref);\n\t\t\t}\n\n\t\tprivate:\n\t\t\tmutable value_type owned_value = nullptr;\n\t\t\tvalue_type* value_ref = nullptr;\n\t\t\tconst bool is_rvalue;\n\t\t};\n\n\t} // namespace detail\n\n\t  /// namespace to hold default `to_json` / `from_json` functions\n\tnamespace\n\t{\n\t\tconstexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;\n\t\tconstexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;\n\t}\n\n\n\t/*!\n\t@brief default JSONSerializer template argument\n\n\tThis serializer ignores the template arguments and uses ADL\n\t([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl))\n\tfor serialization.\n\t*/\n\ttemplate<typename, typename>\n\tstruct adl_serializer\n\t{\n\t\t/*!\n\t\t@brief convert a JSON value to any value type\n\n\t\tThis function is usually called by the `get()` function of the\n\t\t@ref basic_json class (either explicit or via conversion operators).\n\n\t\t@param[in] j         JSON value to read from\n\t\t@param[in,out] val  value to write to\n\t\t*/\n\t\ttemplate<typename BasicJsonType, typename ValueType>\n\t\tstatic void from_json(BasicJsonType&& j, ValueType& val) noexcept(\n\t\t\tnoexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))\n\t\t{\n\t\t\t::nlohmann::from_json(std::forward<BasicJsonType>(j), val);\n\t\t}\n\n\t\t/*!\n\t\t@brief convert any value type to a JSON value\n\n\t\tThis function is usually called by the constructors of the @ref basic_json\n\t\tclass.\n\n\t\t@param[in,out] j  JSON value to write to\n\t\t@param[in] val     value to read from\n\t\t*/\n\t\ttemplate<typename BasicJsonType, typename ValueType>\n\t\tstatic void to_json(BasicJsonType& j, ValueType&& val) noexcept(\n\t\t\tnoexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))\n\t\t{\n\t\t\t::nlohmann::to_json(j, std::forward<ValueType>(val));\n\t\t}\n\t};\n\n\t/*!\n\t@brief JSON Pointer\n\n\tA JSON pointer defines a string syntax for identifying a specific value\n\twithin a JSON document. It can be used with functions `at` and\n\t`operator[]`. Furthermore, JSON pointers are the base for JSON patches.\n\n\t@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)\n\n\t@since version 2.0.0\n\t*/\n\tclass json_pointer\n\t{\n\t\t/// allow basic_json to access private members\n\t\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\t\tfriend class basic_json;\n\n\tpublic:\n\t\t/*!\n\t\t@brief create JSON pointer\n\n\t\tCreate a JSON pointer according to the syntax described in\n\t\t[Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).\n\n\t\t@param[in] s  string representing the JSON pointer; if omitted, the empty\n\t\tstring is assumed which references the whole JSON value\n\n\t\t@throw parse_error.107 if the given JSON pointer @a s is nonempty and\n\t\tdoes not begin with a slash (`/`); see example below\n\n\t\t@throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s\n\t\tis not followed by `0` (representing `~`) or `1` (representing `/`);\n\t\tsee example below\n\n\t\t@liveexample{The example shows the construction several valid JSON\n\t\tpointers as well as the exceptional behavior.,json_pointer}\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\texplicit json_pointer(const std::string& s = \"\") : reference_tokens(split(s)) {}\n\n\t\t/*!\n\t\t@brief return a string representation of the JSON pointer\n\n\t\t@invariant For each JSON pointer `ptr`, it holds:\n\t\t@code {.cpp}\n\t\tptr == json_pointer(ptr.to_string());\n\t\t@endcode\n\n\t\t@return a string representation of the JSON pointer\n\n\t\t@liveexample{The example shows the result of `to_string`.,\n\t\tjson_pointer__to_string}\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\tstd::string to_string() const noexcept\n\t\t{\n\t\t\treturn std::accumulate(reference_tokens.begin(), reference_tokens.end(),\n\t\t\t\tstd::string{},\n\t\t\t\t[](const std::string & a, const std::string & b)\n\t\t\t{\n\t\t\t\treturn a + \"/\" + escape(b);\n\t\t\t});\n\t\t}\n\n\t\t/// @copydoc to_string()\n\t\toperator std::string() const\n\t\t{\n\t\t\treturn to_string();\n\t\t}\n\n\tprivate:\n\t\t/*!\n\t\t@brief remove and return last reference pointer\n\t\t@throw out_of_range.405 if JSON pointer has no parent\n\t\t*/\n\t\tstd::string pop_back()\n\t\t{\n\t\t\tif (JSON_UNLIKELY(is_root()))\n\t\t\t{\n\t\t\t\tJSON_THROW(detail::out_of_range::create(405, \"JSON pointer has no parent\"));\n\t\t\t}\n\n\t\t\tauto last = reference_tokens.back();\n\t\t\treference_tokens.pop_back();\n\t\t\treturn last;\n\t\t}\n\n\t\t/// return whether pointer points to the root document\n\t\tbool is_root() const\n\t\t{\n\t\t\treturn reference_tokens.empty();\n\t\t}\n\n\t\tjson_pointer top() const\n\t\t{\n\t\t\tif (JSON_UNLIKELY(is_root()))\n\t\t\t{\n\t\t\t\tJSON_THROW(detail::out_of_range::create(405, \"JSON pointer has no parent\"));\n\t\t\t}\n\n\t\t\tjson_pointer result = *this;\n\t\t\tresult.reference_tokens = { reference_tokens[0] };\n\t\t\treturn result;\n\t\t}\n\n\n\t\t/*!\n\t\t@brief create and return a reference to the pointed to value\n\n\t\t@complexity Linear in the number of reference tokens.\n\n\t\t@throw parse_error.109 if array index is not a number\n\t\t@throw type_error.313 if value cannot be unflattened\n\t\t*/\n\t\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\t\tNLOHMANN_BASIC_JSON_TPL& get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const;\n\n\t\t/*!\n\t\t@brief return a reference to the pointed to value\n\n\t\t@note This version does not throw if a value is not present, but tries to\n\t\tcreate nested values instead. For instance, calling this function\n\t\twith pointer `\"/this/that\"` on a null value is equivalent to calling\n\t\t`operator[](\"this\").operator[](\"that\")` on that value, effectively\n\t\tchanging the null value to an object.\n\n\t\t@param[in] ptr  a JSON value\n\n\t\t@return reference to the JSON value pointed to by the JSON pointer\n\n\t\t@complexity Linear in the length of the JSON pointer.\n\n\t\t@throw parse_error.106   if an array index begins with '0'\n\t\t@throw parse_error.109   if an array index was not a number\n\t\t@throw out_of_range.404  if the JSON pointer can not be resolved\n\t\t*/\n\t\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\t\tNLOHMANN_BASIC_JSON_TPL& get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const;\n\n\t\t/*!\n\t\t@throw parse_error.106   if an array index begins with '0'\n\t\t@throw parse_error.109   if an array index was not a number\n\t\t@throw out_of_range.402  if the array index '-' is used\n\t\t@throw out_of_range.404  if the JSON pointer can not be resolved\n\t\t*/\n\t\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\t\tNLOHMANN_BASIC_JSON_TPL& get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const;\n\n\t\t/*!\n\t\t@brief return a const reference to the pointed to value\n\n\t\t@param[in] ptr  a JSON value\n\n\t\t@return const reference to the JSON value pointed to by the JSON\n\t\tpointer\n\n\t\t@throw parse_error.106   if an array index begins with '0'\n\t\t@throw parse_error.109   if an array index was not a number\n\t\t@throw out_of_range.402  if the array index '-' is used\n\t\t@throw out_of_range.404  if the JSON pointer can not be resolved\n\t\t*/\n\t\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\t\tconst NLOHMANN_BASIC_JSON_TPL& get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const;\n\n\t\t/*!\n\t\t@throw parse_error.106   if an array index begins with '0'\n\t\t@throw parse_error.109   if an array index was not a number\n\t\t@throw out_of_range.402  if the array index '-' is used\n\t\t@throw out_of_range.404  if the JSON pointer can not be resolved\n\t\t*/\n\t\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\t\tconst NLOHMANN_BASIC_JSON_TPL& get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const;\n\n\t\t/*!\n\t\t@brief split the string input to reference tokens\n\n\t\t@note This function is only called by the json_pointer constructor.\n\t\tAll exceptions below are documented there.\n\n\t\t@throw parse_error.107  if the pointer is not empty or begins with '/'\n\t\t@throw parse_error.108  if character '~' is not followed by '0' or '1'\n\t\t*/\n\t\tstatic std::vector<std::string> split(const std::string& reference_string)\n\t\t{\n\t\t\tstd::vector<std::string> result;\n\n\t\t\t// special case: empty reference string -> no reference tokens\n\t\t\tif (reference_string.empty())\n\t\t\t{\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t// check if nonempty reference string begins with slash\n\t\t\tif (JSON_UNLIKELY(reference_string[0] != '/'))\n\t\t\t{\n\t\t\t\tJSON_THROW(detail::parse_error::create(107, 1,\n\t\t\t\t\t\"JSON pointer must be empty or begin with '/' - was: '\" +\n\t\t\t\t\treference_string + \"'\"));\n\t\t\t}\n\n\t\t\t// extract the reference tokens:\n\t\t\t// - slash: position of the last read slash (or end of string)\n\t\t\t// - start: position after the previous slash\n\t\t\tfor (\n\t\t\t\t// search for the first slash after the first character\n\t\t\t\tstd::size_t slash = reference_string.find_first_of('/', 1),\n\t\t\t\t// set the beginning of the first reference token\n\t\t\t\tstart = 1;\n\t\t\t\t// we can stop if start == string::npos+1 = 0\n\t\t\t\tstart != 0;\n\t\t\t\t// set the beginning of the next reference token\n\t\t\t\t// (will eventually be 0 if slash == std::string::npos)\n\t\t\t\tstart = slash + 1,\n\t\t\t\t// find next slash\n\t\t\t\tslash = reference_string.find_first_of('/', start))\n\t\t\t{\n\t\t\t\t// use the text between the beginning of the reference token\n\t\t\t\t// (start) and the last slash (slash).\n\t\t\t\tauto reference_token = reference_string.substr(start, slash - start);\n\n\t\t\t\t// check reference tokens are properly escaped\n\t\t\t\tfor (std::size_t pos = reference_token.find_first_of('~');\n\t\t\t\t\tpos != std::string::npos;\n\t\t\t\t\tpos = reference_token.find_first_of('~', pos + 1))\n\t\t\t\t{\n\t\t\t\t\tassert(reference_token[pos] == '~');\n\n\t\t\t\t\t// ~ must be followed by 0 or 1\n\t\t\t\t\tif (JSON_UNLIKELY(pos == reference_token.size() - 1 or\n\t\t\t\t\t\t(reference_token[pos + 1] != '0' and\n\t\t\t\t\t\t\treference_token[pos + 1] != '1')))\n\t\t\t\t\t{\n\t\t\t\t\t\tJSON_THROW(detail::parse_error::create(108, 0, \"escape character '~' must be followed with '0' or '1'\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// finally, store the reference token\n\t\t\t\tunescape(reference_token);\n\t\t\t\tresult.push_back(reference_token);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief replace all occurrences of a substring by another string\n\n\t\t@param[in,out] s  the string to manipulate; changed so that all\n\t\toccurrences of @a f are replaced with @a t\n\t\t@param[in]     f  the substring to replace with @a t\n\t\t@param[in]     t  the string to replace @a f\n\n\t\t@pre The search string @a f must not be empty. **This precondition is\n\t\tenforced with an assertion.**\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\tstatic void replace_substring(std::string& s, const std::string& f,\n\t\t\tconst std::string& t)\n\t\t{\n\t\t\tassert(not f.empty());\n\t\t\tfor (auto pos = s.find(f);                // find first occurrence of f\n\t\t\t\tpos != std::string::npos;         // make sure f was found\n\t\t\t\ts.replace(pos, f.size(), t),      // replace with t, and\n\t\t\t\tpos = s.find(f, pos + t.size()))  // find next occurrence of f\n\t\t\t{\n\t\t\t}\n\t\t}\n\n\t\t/// escape \"~\"\" to \"~0\" and \"/\" to \"~1\"\n\t\tstatic std::string escape(std::string s)\n\t\t{\n\t\t\treplace_substring(s, \"~\", \"~0\");\n\t\t\treplace_substring(s, \"/\", \"~1\");\n\t\t\treturn s;\n\t\t}\n\n\t\t/// unescape \"~1\" to tilde and \"~0\" to slash (order is important!)\n\t\tstatic void unescape(std::string& s)\n\t\t{\n\t\t\treplace_substring(s, \"~1\", \"/\");\n\t\t\treplace_substring(s, \"~0\", \"~\");\n\t\t}\n\n\t\t/*!\n\t\t@param[in] reference_string  the reference string to the current value\n\t\t@param[in] value             the value to consider\n\t\t@param[in,out] result        the result object to insert values to\n\n\t\t@note Empty objects or arrays are flattened to `null`.\n\t\t*/\n\t\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\t\tstatic void flatten(const std::string& reference_string,\n\t\t\t\tconst NLOHMANN_BASIC_JSON_TPL& value,\n\t\t\t\tNLOHMANN_BASIC_JSON_TPL& result);\n\n\t\t/*!\n\t\t@param[in] value  flattened JSON\n\n\t\t@return unflattened JSON\n\n\t\t@throw parse_error.109 if array index is not a number\n\t\t@throw type_error.314  if value is not an object\n\t\t@throw type_error.315  if object values are not primitive\n\t\t@throw type_error.313  if value cannot be unflattened\n\t\t*/\n\t\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\t\tstatic NLOHMANN_BASIC_JSON_TPL\n\t\t\tunflatten(const NLOHMANN_BASIC_JSON_TPL& value);\n\n\t\tfriend bool operator==(json_pointer const& lhs,\n\t\t\tjson_pointer const& rhs) noexcept;\n\n\t\tfriend bool operator!=(json_pointer const& lhs,\n\t\t\tjson_pointer const& rhs) noexcept;\n\n\t\t/// the reference tokens\n\t\tstd::vector<std::string> reference_tokens;\n\t};\n\n\t/*!\n\t@brief a class to store JSON values\n\n\t@tparam ObjectType type for JSON objects (`std::map` by default; will be used\n\tin @ref object_t)\n\t@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used\n\tin @ref array_t)\n\t@tparam StringType type for JSON strings and object keys (`std::string` by\n\tdefault; will be used in @ref string_t)\n\t@tparam BooleanType type for JSON booleans (`bool` by default; will be used\n\tin @ref boolean_t)\n\t@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by\n\tdefault; will be used in @ref number_integer_t)\n\t@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c\n\t`uint64_t` by default; will be used in @ref number_unsigned_t)\n\t@tparam NumberFloatType type for JSON floating-point numbers (`double` by\n\tdefault; will be used in @ref number_float_t)\n\t@tparam AllocatorType type of the allocator to use (`std::allocator` by\n\tdefault)\n\t@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`\n\tand `from_json()` (@ref adl_serializer by default)\n\n\t@requirement The class satisfies the following concept requirements:\n\t- Basic\n\t- [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):\n\tJSON values can be default constructed. The result will be a JSON null\n\tvalue.\n\t- [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):\n\tA JSON value can be constructed from an rvalue argument.\n\t- [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):\n\tA JSON value can be copy-constructed from an lvalue expression.\n\t- [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):\n\tA JSON value van be assigned from an rvalue argument.\n\t- [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):\n\tA JSON value can be copy-assigned from an lvalue expression.\n\t- [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):\n\tJSON values can be destructed.\n\t- Layout\n\t- [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):\n\tJSON values have\n\t[standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):\n\tAll non-static data members are private and standard layout types, the\n\tclass has no virtual functions or (virtual) base classes.\n\t- Library-wide\n\t- [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):\n\tJSON values can be compared with `==`, see @ref\n\toperator==(const_reference,const_reference).\n\t- [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):\n\tJSON values can be compared with `<`, see @ref\n\toperator<(const_reference,const_reference).\n\t- [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):\n\tAny JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of\n\tother compatible types, using unqualified function call @ref swap().\n\t- [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):\n\tJSON values can be compared against `std::nullptr_t` objects which are used\n\tto model the `null` value.\n\t- Container\n\t- [Container](http://en.cppreference.com/w/cpp/concept/Container):\n\tJSON values can be used like STL containers and provide iterator access.\n\t- [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);\n\tJSON values can be used like STL containers and provide reverse iterator\n\taccess.\n\n\t@invariant The member variables @a m_value and @a m_type have the following\n\trelationship:\n\t- If `m_type == value_t::object`, then `m_value.object != nullptr`.\n\t- If `m_type == value_t::array`, then `m_value.array != nullptr`.\n\t- If `m_type == value_t::string`, then `m_value.string != nullptr`.\n\tThe invariants are checked by member function assert_invariant().\n\n\t@internal\n\t@note ObjectType trick from http://stackoverflow.com/a/9860911\n\t@endinternal\n\n\t@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange\n\tFormat](http://rfc7159.net/rfc7159)\n\n\t@since version 1.0.0\n\n\t@nosubgrouping\n\t*/\n\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\tclass basic_json\n\t{\n\tprivate:\n\t\ttemplate<detail::value_t> friend struct detail::external_constructor;\n\t\tfriend ::nlohmann::json_pointer;\n\t\tfriend ::nlohmann::detail::parser<basic_json>;\n\t\tfriend ::nlohmann::detail::serializer<basic_json>;\n\t\ttemplate<typename BasicJsonType>\n\t\tfriend class ::nlohmann::detail::iter_impl;\n\t\ttemplate<typename BasicJsonType, typename CharType>\n\t\tfriend class ::nlohmann::detail::binary_writer;\n\t\ttemplate<typename BasicJsonType>\n\t\tfriend class ::nlohmann::detail::binary_reader;\n\n\t\t/// workaround type for MSVC\n\t\tusing basic_json_t = NLOHMANN_BASIC_JSON_TPL;\n\n\t\t// convenience aliases for types residing in namespace detail;\n\t\tusing lexer = ::nlohmann::detail::lexer<basic_json>;\n\t\tusing parser = ::nlohmann::detail::parser<basic_json>;\n\n\t\tusing primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;\n\t\ttemplate<typename BasicJsonType>\n\t\tusing internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;\n\t\ttemplate<typename BasicJsonType>\n\t\tusing iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;\n\t\ttemplate<typename Iterator>\n\t\tusing iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;\n\t\ttemplate<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;\n\n\t\ttemplate<typename CharType>\n\t\tusing output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;\n\n\t\tusing binary_reader = ::nlohmann::detail::binary_reader<basic_json>;\n\t\ttemplate<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;\n\n\t\tusing serializer = ::nlohmann::detail::serializer<basic_json>;\n\n\tpublic:\n\t\tusing value_t = detail::value_t;\n\t\t// forward declarations\n\t\tusing json_pointer = ::nlohmann::json_pointer;\n\t\ttemplate<typename T, typename SFINAE>\n\t\tusing json_serializer = JSONSerializer<T, SFINAE>;\n\n\t\tusing initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;\n\n\t\t////////////////\n\t\t// exceptions //\n\t\t////////////////\n\n\t\t/// @name exceptions\n\t\t/// Classes to implement user-defined exceptions.\n\t\t/// @{\n\n\t\t/// @copydoc detail::exception\n\t\tusing exception = detail::exception;\n\t\t/// @copydoc detail::parse_error\n\t\tusing parse_error = detail::parse_error;\n\t\t/// @copydoc detail::invalid_iterator\n\t\tusing invalid_iterator = detail::invalid_iterator;\n\t\t/// @copydoc detail::type_error\n\t\tusing type_error = detail::type_error;\n\t\t/// @copydoc detail::out_of_range\n\t\tusing out_of_range = detail::out_of_range;\n\t\t/// @copydoc detail::other_error\n\t\tusing other_error = detail::other_error;\n\n\t\t/// @}\n\n\n\t\t/////////////////////\n\t\t// container types //\n\t\t/////////////////////\n\n\t\t/// @name container types\n\t\t/// The canonic container types to use @ref basic_json like any other STL\n\t\t/// container.\n\t\t/// @{\n\n\t\t/// the type of elements in a basic_json container\n\t\tusing value_type = basic_json;\n\n\t\t/// the type of an element reference\n\t\tusing reference = value_type&;\n\t\t/// the type of an element const reference\n\t\tusing const_reference = const value_type&;\n\n\t\t/// a type to represent differences between iterators\n\t\tusing difference_type = std::ptrdiff_t;\n\t\t/// a type to represent container sizes\n\t\tusing size_type = std::size_t;\n\n\t\t/// the allocator type\n\t\tusing allocator_type = AllocatorType<basic_json>;\n\n\t\t/// the type of an element pointer\n\t\tusing pointer = typename std::allocator_traits<allocator_type>::pointer;\n\t\t/// the type of an element const pointer\n\t\tusing const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;\n\n\t\t/// an iterator for a basic_json container\n\t\tusing iterator = iter_impl<basic_json>;\n\t\t/// a const iterator for a basic_json container\n\t\tusing const_iterator = iter_impl<const basic_json>;\n\t\t/// a reverse iterator for a basic_json container\n\t\tusing reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;\n\t\t/// a const reverse iterator for a basic_json container\n\t\tusing const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;\n\n\t\t/// @}\n\n\n\t\t/*!\n\t\t@brief returns the allocator associated with the container\n\t\t*/\n\t\tstatic allocator_type get_allocator()\n\t\t{\n\t\t\treturn allocator_type();\n\t\t}\n\n\t\t/*!\n\t\t@brief returns version information on the library\n\n\t\tThis function returns a JSON object with information about the library,\n\t\tincluding the version number and information on the platform and compiler.\n\n\t\t@return JSON object holding version information\n\t\tkey         | description\n\t\t----------- | ---------------\n\t\t`compiler`  | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).\n\t\t`copyright` | The copyright line for the library as string.\n\t\t`name`      | The name of the library as string.\n\t\t`platform`  | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.\n\t\t`url`       | The URL of the project as string.\n\t\t`version`   | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).\n\n\t\t@liveexample{The following code shows an example output of the `meta()`\n\t\tfunction.,meta}\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges to any JSON value.\n\n\t\t@complexity Constant.\n\n\t\t@since 2.1.0\n\t\t*/\n\t\tstatic basic_json meta()\n\t\t{\n\t\t\tbasic_json result;\n\n\t\t\tresult[\"copyright\"] = \"(C) 2013-2017 Niels Lohmann\";\n\t\t\tresult[\"name\"] = \"JSON for Modern C++\";\n\t\t\tresult[\"url\"] = \"https://github.com/nlohmann/json\";\n\t\t\tresult[\"version\"] =\n\t\t\t{\n\t\t\t\t{ \"string\", \"2.1.1\" },{ \"major\", 2 },{ \"minor\", 1 },{ \"patch\", 1 }\n\t\t\t};\n\n#ifdef _WIN32\n\t\t\tresult[\"platform\"] = \"win32\";\n#elif defined __linux__\n\t\t\tresult[\"platform\"] = \"linux\";\n#elif defined __APPLE__\n\t\t\tresult[\"platform\"] = \"apple\";\n#elif defined __unix__\n\t\t\tresult[\"platform\"] = \"unix\";\n#else\n\t\t\tresult[\"platform\"] = \"unknown\";\n#endif\n\n#if defined(__ICC) || defined(__INTEL_COMPILER)\n\t\t\tresult[\"compiler\"] = { { \"family\", \"icc\" },{ \"version\", __INTEL_COMPILER } };\n#elif defined(__clang__)\n\t\t\tresult[\"compiler\"] = { { \"family\", \"clang\" },{ \"version\", __clang_version__ } };\n#elif defined(__GNUC__) || defined(__GNUG__)\n\t\t\tresult[\"compiler\"] = { { \"family\", \"gcc\" },{ \"version\", std::to_string(__GNUC__) + \".\" + std::to_string(__GNUC_MINOR__) + \".\" + std::to_string(__GNUC_PATCHLEVEL__) } };\n#elif defined(__HP_cc) || defined(__HP_aCC)\n\t\t\tresult[\"compiler\"] = \"hp\"\n#elif defined(__IBMCPP__)\n\t\t\tresult[\"compiler\"] = { { \"family\", \"ilecpp\" },{ \"version\", __IBMCPP__ } };\n#elif defined(_MSC_VER)\n\t\t\tresult[\"compiler\"] = { { \"family\", \"msvc\" },{ \"version\", _MSC_VER } };\n#elif defined(__PGI)\n\t\t\tresult[\"compiler\"] = { { \"family\", \"pgcpp\" },{ \"version\", __PGI } };\n#elif defined(__SUNPRO_CC)\n\t\t\tresult[\"compiler\"] = { { \"family\", \"sunpro\" },{ \"version\", __SUNPRO_CC } };\n#else\n\t\t\tresult[\"compiler\"] = { { \"family\", \"unknown\" },{ \"version\", \"unknown\" } };\n#endif\n\n#ifdef __cplusplus\n\t\t\tresult[\"compiler\"][\"c++\"] = std::to_string(__cplusplus);\n#else\n\t\t\tresult[\"compiler\"][\"c++\"] = \"unknown\";\n#endif\n\t\t\treturn result;\n\t\t}\n\n\n\t\t///////////////////////////\n\t\t// JSON value data types //\n\t\t///////////////////////////\n\n\t\t/// @name JSON value data types\n\t\t/// The data types to store a JSON value. These types are derived from\n\t\t/// the template arguments passed to class @ref basic_json.\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief a type for an object\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:\n\t\t> An object is an unordered collection of zero or more name/value pairs,\n\t\t> where a name is a string and a value is a string, number, boolean, null,\n\t\t> object, or array.\n\n\t\tTo store objects in C++, a type is defined by the template parameters\n\t\tdescribed below.\n\n\t\t@tparam ObjectType  the container to store objects (e.g., `std::map` or\n\t\t`std::unordered_map`)\n\t\t@tparam StringType the type of the keys or names (e.g., `std::string`).\n\t\tThe comparison function `std::less<StringType>` is used to order elements\n\t\tinside the container.\n\t\t@tparam AllocatorType the allocator to use for objects (e.g.,\n\t\t`std::allocator`)\n\n\t\t#### Default type\n\n\t\tWith the default values for @a ObjectType (`std::map`), @a StringType\n\t\t(`std::string`), and @a AllocatorType (`std::allocator`), the default\n\t\tvalue for @a object_t is:\n\n\t\t@code {.cpp}\n\t\tstd::map<\n\t\tstd::string, // key_type\n\t\tbasic_json, // value_type\n\t\tstd::less<std::string>, // key_compare\n\t\tstd::allocator<std::pair<const std::string, basic_json>> // allocator_type\n\t\t>\n\t\t@endcode\n\n\t\t#### Behavior\n\n\t\tThe choice of @a object_t influences the behavior of the JSON class. With\n\t\tthe default type, objects have the following behavior:\n\n\t\t- When all names are unique, objects will be interoperable in the sense\n\t\tthat all software implementations receiving that object will agree on\n\t\tthe name-value mappings.\n\t\t- When the names within an object are not unique, later stored name/value\n\t\tpairs overwrite previously stored name/value pairs, leaving the used\n\t\tnames unique. For instance, `{\"key\": 1}` and `{\"key\": 2, \"key\": 1}` will\n\t\tbe treated as equal and both stored as `{\"key\": 1}`.\n\t\t- Internally, name/value pairs are stored in lexicographical order of the\n\t\tnames. Objects will also be serialized (see @ref dump) in this order.\n\t\tFor instance, `{\"b\": 1, \"a\": 2}` and `{\"a\": 2, \"b\": 1}` will be stored\n\t\tand serialized as `{\"a\": 2, \"b\": 1}`.\n\t\t- When comparing objects, the order of the name/value pairs is irrelevant.\n\t\tThis makes objects interoperable in the sense that they will not be\n\t\taffected by these differences. For instance, `{\"b\": 1, \"a\": 2}` and\n\t\t`{\"a\": 2, \"b\": 1}` will be treated as equal.\n\n\t\t#### Limits\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) specifies:\n\t\t> An implementation may set limits on the maximum depth of nesting.\n\n\t\tIn this class, the object's limit of nesting is not explicitly constrained.\n\t\tHowever, a maximum depth of nesting may be introduced by the compiler or\n\t\truntime environment. A theoretical limit can be queried by calling the\n\t\t@ref max_size function of a JSON object.\n\n\t\t#### Storage\n\n\t\tObjects are stored as pointers in a @ref basic_json type. That is, for any\n\t\taccess to object values, a pointer of type `object_t*` must be\n\t\tdereferenced.\n\n\t\t@sa @ref array_t -- type for an array value\n\n\t\t@since version 1.0.0\n\n\t\t@note The order name/value pairs are added to the object is *not*\n\t\tpreserved by the library. Therefore, iterating an object may return\n\t\tname/value pairs in a different order than they were originally stored. In\n\t\tfact, keys will be traversed in alphabetical order as `std::map` with\n\t\t`std::less` is used by default. Please note this behavior conforms to [RFC\n\t\t7159](http://rfc7159.net/rfc7159), because any order implements the\n\t\tspecified \"unordered\" nature of JSON objects.\n\t\t*/\n\n#if defined(JSON_HAS_CPP_14)\n\t\t// Use transparent comparator if possible, combined with perfect forwarding\n\t\t// on find() and count() calls prevents unnecessary string construction.\n\t\tusing object_comparator_t = std::less<>;\n#else\n\t\tusing object_comparator_t = std::less<StringType>;\n#endif\n\t\tusing object_t = ObjectType<StringType,\n\t\t\tbasic_json,\n\t\t\tobject_comparator_t,\n\t\t\tAllocatorType<std::pair<const StringType,\n\t\t\tbasic_json>>>;\n\n\t\t/*!\n\t\t@brief a type for an array\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:\n\t\t> An array is an ordered sequence of zero or more values.\n\n\t\tTo store objects in C++, a type is defined by the template parameters\n\t\texplained below.\n\n\t\t@tparam ArrayType  container type to store arrays (e.g., `std::vector` or\n\t\t`std::list`)\n\t\t@tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)\n\n\t\t#### Default type\n\n\t\tWith the default values for @a ArrayType (`std::vector`) and @a\n\t\tAllocatorType (`std::allocator`), the default value for @a array_t is:\n\n\t\t@code {.cpp}\n\t\tstd::vector<\n\t\tbasic_json, // value_type\n\t\tstd::allocator<basic_json> // allocator_type\n\t\t>\n\t\t@endcode\n\n\t\t#### Limits\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) specifies:\n\t\t> An implementation may set limits on the maximum depth of nesting.\n\n\t\tIn this class, the array's limit of nesting is not explicitly constrained.\n\t\tHowever, a maximum depth of nesting may be introduced by the compiler or\n\t\truntime environment. A theoretical limit can be queried by calling the\n\t\t@ref max_size function of a JSON array.\n\n\t\t#### Storage\n\n\t\tArrays are stored as pointers in a @ref basic_json type. That is, for any\n\t\taccess to array values, a pointer of type `array_t*` must be dereferenced.\n\n\t\t@sa @ref object_t -- type for an object value\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tusing array_t = ArrayType<basic_json, AllocatorType<basic_json>>;\n\n\t\t/*!\n\t\t@brief a type for a string\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:\n\t\t> A string is a sequence of zero or more Unicode characters.\n\n\t\tTo store objects in C++, a type is defined by the template parameter\n\t\tdescribed below. Unicode values are split by the JSON class into\n\t\tbyte-sized characters during deserialization.\n\n\t\t@tparam StringType  the container to store strings (e.g., `std::string`).\n\t\tNote this container is used for keys/names in objects, see @ref object_t.\n\n\t\t#### Default type\n\n\t\tWith the default values for @a StringType (`std::string`), the default\n\t\tvalue for @a string_t is:\n\n\t\t@code {.cpp}\n\t\tstd::string\n\t\t@endcode\n\n\t\t#### Encoding\n\n\t\tStrings are stored in UTF-8 encoding. Therefore, functions like\n\t\t`std::string::size()` or `std::string::length()` return the number of\n\t\tbytes in the string rather than the number of characters or glyphs.\n\n\t\t#### String comparison\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) states:\n\t\t> Software implementations are typically required to test names of object\n\t\t> members for equality. Implementations that transform the textual\n\t\t> representation into sequences of Unicode code units and then perform the\n\t\t> comparison numerically, code unit by code unit, are interoperable in the\n\t\t> sense that implementations will agree in all cases on equality or\n\t\t> inequality of two strings. For example, implementations that compare\n\t\t> strings with escaped characters unconverted may incorrectly find that\n\t\t> `\"a\\\\b\"` and `\"a\\u005Cb\"` are not equal.\n\n\t\tThis implementation is interoperable as it does compare strings code unit\n\t\tby code unit.\n\n\t\t#### Storage\n\n\t\tString values are stored as pointers in a @ref basic_json type. That is,\n\t\tfor any access to string values, a pointer of type `string_t*` must be\n\t\tdereferenced.\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tusing string_t = StringType;\n\n\t\t/*!\n\t\t@brief a type for a boolean\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a\n\t\ttype which differentiates the two literals `true` and `false`.\n\n\t\tTo store objects in C++, a type is defined by the template parameter @a\n\t\tBooleanType which chooses the type to use.\n\n\t\t#### Default type\n\n\t\tWith the default values for @a BooleanType (`bool`), the default value for\n\t\t@a boolean_t is:\n\n\t\t@code {.cpp}\n\t\tbool\n\t\t@endcode\n\n\t\t#### Storage\n\n\t\tBoolean values are stored directly inside a @ref basic_json type.\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tusing boolean_t = BooleanType;\n\n\t\t/*!\n\t\t@brief a type for a number (integer)\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\n\t\t> The representation of numbers is similar to that used in most\n\t\t> programming languages. A number is represented in base 10 using decimal\n\t\t> digits. It contains an integer component that may be prefixed with an\n\t\t> optional minus sign, which may be followed by a fraction part and/or an\n\t\t> exponent part. Leading zeros are not allowed. (...) Numeric values that\n\t\t> cannot be represented in the grammar below (such as Infinity and NaN)\n\t\t> are not permitted.\n\n\t\tThis description includes both integer and floating-point numbers.\n\t\tHowever, C++ allows more precise storage if it is known whether the number\n\t\tis a signed integer, an unsigned integer or a floating-point number.\n\t\tTherefore, three different types, @ref number_integer_t, @ref\n\t\tnumber_unsigned_t and @ref number_float_t are used.\n\n\t\tTo store integer numbers in C++, a type is defined by the template\n\t\tparameter @a NumberIntegerType which chooses the type to use.\n\n\t\t#### Default type\n\n\t\tWith the default values for @a NumberIntegerType (`int64_t`), the default\n\t\tvalue for @a number_integer_t is:\n\n\t\t@code {.cpp}\n\t\tint64_t\n\t\t@endcode\n\n\t\t#### Default behavior\n\n\t\t- The restrictions about leading zeros is not enforced in C++. Instead,\n\t\tleading zeros in integer literals lead to an interpretation as octal\n\t\tnumber. Internally, the value will be stored as decimal number. For\n\t\tinstance, the C++ integer literal `010` will be serialized to `8`.\n\t\tDuring deserialization, leading zeros yield an error.\n\t\t- Not-a-number (NaN) values will be serialized to `null`.\n\n\t\t#### Limits\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) specifies:\n\t\t> An implementation may set limits on the range and precision of numbers.\n\n\t\tWhen the default type is used, the maximal integer number that can be\n\t\tstored is `9223372036854775807` (INT64_MAX) and the minimal integer number\n\t\tthat can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers\n\t\tthat are out of range will yield over/underflow when used in a\n\t\tconstructor. During deserialization, too large or small integer numbers\n\t\twill be automatically be stored as @ref number_unsigned_t or @ref\n\t\tnumber_float_t.\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) further states:\n\t\t> Note that when such software is used, numbers that are integers and are\n\t\t> in the range \\f$[-2^{53}+1, 2^{53}-1]\\f$ are interoperable in the sense\n\t\t> that implementations will agree exactly on their numeric values.\n\n\t\tAs this range is a subrange of the exactly supported range [INT64_MIN,\n\t\tINT64_MAX], this class's integer type is interoperable.\n\n\t\t#### Storage\n\n\t\tInteger number values are stored directly inside a @ref basic_json type.\n\n\t\t@sa @ref number_float_t -- type for number values (floating-point)\n\n\t\t@sa @ref number_unsigned_t -- type for number values (unsigned integer)\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tusing number_integer_t = NumberIntegerType;\n\n\t\t/*!\n\t\t@brief a type for a number (unsigned)\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\n\t\t> The representation of numbers is similar to that used in most\n\t\t> programming languages. A number is represented in base 10 using decimal\n\t\t> digits. It contains an integer component that may be prefixed with an\n\t\t> optional minus sign, which may be followed by a fraction part and/or an\n\t\t> exponent part. Leading zeros are not allowed. (...) Numeric values that\n\t\t> cannot be represented in the grammar below (such as Infinity and NaN)\n\t\t> are not permitted.\n\n\t\tThis description includes both integer and floating-point numbers.\n\t\tHowever, C++ allows more precise storage if it is known whether the number\n\t\tis a signed integer, an unsigned integer or a floating-point number.\n\t\tTherefore, three different types, @ref number_integer_t, @ref\n\t\tnumber_unsigned_t and @ref number_float_t are used.\n\n\t\tTo store unsigned integer numbers in C++, a type is defined by the\n\t\ttemplate parameter @a NumberUnsignedType which chooses the type to use.\n\n\t\t#### Default type\n\n\t\tWith the default values for @a NumberUnsignedType (`uint64_t`), the\n\t\tdefault value for @a number_unsigned_t is:\n\n\t\t@code {.cpp}\n\t\tuint64_t\n\t\t@endcode\n\n\t\t#### Default behavior\n\n\t\t- The restrictions about leading zeros is not enforced in C++. Instead,\n\t\tleading zeros in integer literals lead to an interpretation as octal\n\t\tnumber. Internally, the value will be stored as decimal number. For\n\t\tinstance, the C++ integer literal `010` will be serialized to `8`.\n\t\tDuring deserialization, leading zeros yield an error.\n\t\t- Not-a-number (NaN) values will be serialized to `null`.\n\n\t\t#### Limits\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) specifies:\n\t\t> An implementation may set limits on the range and precision of numbers.\n\n\t\tWhen the default type is used, the maximal integer number that can be\n\t\tstored is `18446744073709551615` (UINT64_MAX) and the minimal integer\n\t\tnumber that can be stored is `0`. Integer numbers that are out of range\n\t\twill yield over/underflow when used in a constructor. During\n\t\tdeserialization, too large or small integer numbers will be automatically\n\t\tbe stored as @ref number_integer_t or @ref number_float_t.\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) further states:\n\t\t> Note that when such software is used, numbers that are integers and are\n\t\t> in the range \\f$[-2^{53}+1, 2^{53}-1]\\f$ are interoperable in the sense\n\t\t> that implementations will agree exactly on their numeric values.\n\n\t\tAs this range is a subrange (when considered in conjunction with the\n\t\tnumber_integer_t type) of the exactly supported range [0, UINT64_MAX],\n\t\tthis class's integer type is interoperable.\n\n\t\t#### Storage\n\n\t\tInteger number values are stored directly inside a @ref basic_json type.\n\n\t\t@sa @ref number_float_t -- type for number values (floating-point)\n\t\t@sa @ref number_integer_t -- type for number values (integer)\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\tusing number_unsigned_t = NumberUnsignedType;\n\n\t\t/*!\n\t\t@brief a type for a number (floating-point)\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\n\t\t> The representation of numbers is similar to that used in most\n\t\t> programming languages. A number is represented in base 10 using decimal\n\t\t> digits. It contains an integer component that may be prefixed with an\n\t\t> optional minus sign, which may be followed by a fraction part and/or an\n\t\t> exponent part. Leading zeros are not allowed. (...) Numeric values that\n\t\t> cannot be represented in the grammar below (such as Infinity and NaN)\n\t\t> are not permitted.\n\n\t\tThis description includes both integer and floating-point numbers.\n\t\tHowever, C++ allows more precise storage if it is known whether the number\n\t\tis a signed integer, an unsigned integer or a floating-point number.\n\t\tTherefore, three different types, @ref number_integer_t, @ref\n\t\tnumber_unsigned_t and @ref number_float_t are used.\n\n\t\tTo store floating-point numbers in C++, a type is defined by the template\n\t\tparameter @a NumberFloatType which chooses the type to use.\n\n\t\t#### Default type\n\n\t\tWith the default values for @a NumberFloatType (`double`), the default\n\t\tvalue for @a number_float_t is:\n\n\t\t@code {.cpp}\n\t\tdouble\n\t\t@endcode\n\n\t\t#### Default behavior\n\n\t\t- The restrictions about leading zeros is not enforced in C++. Instead,\n\t\tleading zeros in floating-point literals will be ignored. Internally,\n\t\tthe value will be stored as decimal number. For instance, the C++\n\t\tfloating-point literal `01.2` will be serialized to `1.2`. During\n\t\tdeserialization, leading zeros yield an error.\n\t\t- Not-a-number (NaN) values will be serialized to `null`.\n\n\t\t#### Limits\n\n\t\t[RFC 7159](http://rfc7159.net/rfc7159) states:\n\t\t> This specification allows implementations to set limits on the range and\n\t\t> precision of numbers accepted. Since software that implements IEEE\n\t\t> 754-2008 binary64 (double precision) numbers is generally available and\n\t\t> widely used, good interoperability can be achieved by implementations\n\t\t> that expect no more precision or range than these provide, in the sense\n\t\t> that implementations will approximate JSON numbers within the expected\n\t\t> precision.\n\n\t\tThis implementation does exactly follow this approach, as it uses double\n\t\tprecision floating-point numbers. Note values smaller than\n\t\t`-1.79769313486232e+308` and values greater than `1.79769313486232e+308`\n\t\twill be stored as NaN internally and be serialized to `null`.\n\n\t\t#### Storage\n\n\t\tFloating-point number values are stored directly inside a @ref basic_json\n\t\ttype.\n\n\t\t@sa @ref number_integer_t -- type for number values (integer)\n\n\t\t@sa @ref number_unsigned_t -- type for number values (unsigned integer)\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tusing number_float_t = NumberFloatType;\n\n\t\t/// @}\n\n\tprivate:\n\n\t\t/// helper for exception-safe object creation\n\t\ttemplate<typename T, typename... Args>\n\t\tstatic T* create(Args&& ... args)\n\t\t{\n\t\t\tAllocatorType<T> alloc;\n\t\t\tauto deleter = [&](T * object)\n\t\t\t{\n\t\t\t\talloc.deallocate(object, 1);\n\t\t\t};\n\t\t\tstd::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);\n\t\t\talloc.construct(object.get(), std::forward<Args>(args)...);\n\t\t\tassert(object != nullptr);\n\t\t\treturn object.release();\n\t\t}\n\n\t\t////////////////////////\n\t\t// JSON value storage //\n\t\t////////////////////////\n\n\t\t/*!\n\t\t@brief a JSON value\n\n\t\tThe actual storage for a JSON value of the @ref basic_json class. This\n\t\tunion combines the different storage types for the JSON value types\n\t\tdefined in @ref value_t.\n\n\t\tJSON type | value_t type    | used type\n\t\t--------- | --------------- | ------------------------\n\t\tobject    | object          | pointer to @ref object_t\n\t\tarray     | array           | pointer to @ref array_t\n\t\tstring    | string          | pointer to @ref string_t\n\t\tboolean   | boolean         | @ref boolean_t\n\t\tnumber    | number_integer  | @ref number_integer_t\n\t\tnumber    | number_unsigned | @ref number_unsigned_t\n\t\tnumber    | number_float    | @ref number_float_t\n\t\tnull      | null            | *no value is stored*\n\n\t\t@note Variable-length types (objects, arrays, and strings) are stored as\n\t\tpointers. The size of the union should not exceed 64 bits if the default\n\t\tvalue types are used.\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tunion json_value\n\t\t{\n\t\t\t/// object (stored with pointer to save storage)\n\t\t\tobject_t* object;\n\t\t\t/// array (stored with pointer to save storage)\n\t\t\tarray_t* array;\n\t\t\t/// string (stored with pointer to save storage)\n\t\t\tstring_t* string;\n\t\t\t/// boolean\n\t\t\tboolean_t boolean;\n\t\t\t/// number (integer)\n\t\t\tnumber_integer_t number_integer;\n\t\t\t/// number (unsigned integer)\n\t\t\tnumber_unsigned_t number_unsigned;\n\t\t\t/// number (floating-point)\n\t\t\tnumber_float_t number_float;\n\n\t\t\t/// default constructor (for null values)\n\t\t\tjson_value() = default;\n\t\t\t/// constructor for booleans\n\t\t\tjson_value(boolean_t v) noexcept : boolean(v) {}\n\t\t\t/// constructor for numbers (integer)\n\t\t\tjson_value(number_integer_t v) noexcept : number_integer(v) {}\n\t\t\t/// constructor for numbers (unsigned)\n\t\t\tjson_value(number_unsigned_t v) noexcept : number_unsigned(v) {}\n\t\t\t/// constructor for numbers (floating-point)\n\t\t\tjson_value(number_float_t v) noexcept : number_float(v) {}\n\t\t\t/// constructor for empty values of a given type\n\t\t\tjson_value(value_t t)\n\t\t\t{\n\t\t\t\tswitch (t)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tobject = create<object_t>();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tarray = create<array_t>();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::string:\n\t\t\t\t{\n\t\t\t\t\tstring = create<string_t>(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::boolean:\n\t\t\t\t{\n\t\t\t\t\tboolean = boolean_t(false);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_integer:\n\t\t\t\t{\n\t\t\t\t\tnumber_integer = number_integer_t(0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_unsigned:\n\t\t\t\t{\n\t\t\t\t\tnumber_unsigned = number_unsigned_t(0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::number_float:\n\t\t\t\t{\n\t\t\t\t\tnumber_float = number_float_t(0.0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::null:\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tif (JSON_UNLIKELY(t == value_t::null))\n\t\t\t\t\t{\n\t\t\t\t\t\tJSON_THROW(other_error::create(500, \"961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1\")); // LCOV_EXCL_LINE\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/// constructor for strings\n\t\t\tjson_value(const string_t& value)\n\t\t\t{\n\t\t\t\tstring = create<string_t>(value);\n\t\t\t}\n\n\t\t\t/// constructor for rvalue strings\n\t\t\tjson_value(string_t&& value)\n\t\t\t{\n\t\t\t\tstring = create<string_t>(std::move(value));\n\t\t\t}\n\n\t\t\t/// constructor for objects\n\t\t\tjson_value(const object_t& value)\n\t\t\t{\n\t\t\t\tobject = create<object_t>(value);\n\t\t\t}\n\n\t\t\t/// constructor for rvalue objects\n\t\t\tjson_value(object_t&& value)\n\t\t\t{\n\t\t\t\tobject = create<object_t>(std::move(value));\n\t\t\t}\n\n\t\t\t/// constructor for arrays\n\t\t\tjson_value(const array_t& value)\n\t\t\t{\n\t\t\t\tarray = create<array_t>(value);\n\t\t\t}\n\n\t\t\t/// constructor for rvalue arrays\n\t\t\tjson_value(array_t&& value)\n\t\t\t{\n\t\t\t\tarray = create<array_t>(std::move(value));\n\t\t\t}\n\n\t\t\tvoid destroy(value_t t)\n\t\t\t{\n\t\t\t\tswitch (t)\n\t\t\t\t{\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\tAllocatorType<object_t> alloc;\n\t\t\t\t\talloc.destroy(object);\n\t\t\t\t\talloc.deallocate(object, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\tAllocatorType<array_t> alloc;\n\t\t\t\t\talloc.destroy(array);\n\t\t\t\t\talloc.deallocate(array, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::string:\n\t\t\t\t{\n\t\t\t\t\tAllocatorType<string_t> alloc;\n\t\t\t\t\talloc.destroy(string);\n\t\t\t\t\talloc.deallocate(string, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t/*!\n\t\t@brief checks the class invariants\n\n\t\tThis function asserts the class invariants. It needs to be called at the\n\t\tend of every constructor to make sure that created objects respect the\n\t\tinvariant. Furthermore, it has to be called each time the type of a JSON\n\t\tvalue is changed, because the invariant expresses a relationship between\n\t\t@a m_type and @a m_value.\n\t\t*/\n\t\tvoid assert_invariant() const\n\t\t{\n\t\t\tassert(m_type != value_t::object or m_value.object != nullptr);\n\t\t\tassert(m_type != value_t::array or m_value.array != nullptr);\n\t\t\tassert(m_type != value_t::string or m_value.string != nullptr);\n\t\t}\n\n\tpublic:\n\t\t//////////////////////////\n\t\t// JSON parser callback //\n\t\t//////////////////////////\n\n\t\tusing parse_event_t = typename parser::parse_event_t;\n\n\t\t/*!\n\t\t@brief per-element parser callback type\n\n\t\tWith a parser callback function, the result of parsing a JSON text can be\n\t\tinfluenced. When passed to @ref parse, it is called on certain events\n\t\t(passed as @ref parse_event_t via parameter @a event) with a set recursion\n\t\tdepth @a depth and context JSON value @a parsed. The return value of the\n\t\tcallback function is a boolean indicating whether the element that emitted\n\t\tthe callback shall be kept or not.\n\n\t\tWe distinguish six scenarios (determined by the event type) in which the\n\t\tcallback function can be called. The following table describes the values\n\t\tof the parameters @a depth, @a event, and @a parsed.\n\n\t\tparameter @a event | description | parameter @a depth | parameter @a parsed\n\t\t------------------ | ----------- | ------------------ | -------------------\n\t\tparse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded\n\t\tparse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key\n\t\tparse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object\n\t\tparse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded\n\t\tparse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array\n\t\tparse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value\n\n\t\t@image html callback_events.png \"Example when certain parse events are triggered\"\n\n\t\tDiscarding a value (i.e., returning `false`) has different effects\n\t\tdepending on the context in which function was called:\n\n\t\t- Discarded values in structured types are skipped. That is, the parser\n\t\twill behave as if the discarded value was never read.\n\t\t- In case a value outside a structured type is skipped, it is replaced\n\t\twith `null`. This case happens if the top-level element is skipped.\n\n\t\t@param[in] depth  the depth of the recursion during parsing\n\n\t\t@param[in] event  an event of type parse_event_t indicating the context in\n\t\tthe callback function has been called\n\n\t\t@param[in,out] parsed  the current intermediate parse result; note that\n\t\twriting to this value has no effect for parse_event_t::key events\n\n\t\t@return Whether the JSON value which called the function during parsing\n\t\tshould be kept (`true`) or not (`false`). In the latter case, it is either\n\t\tskipped completely or replaced by an empty discarded object.\n\n\t\t@sa @ref parse for examples\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tusing parser_callback_t = typename parser::parser_callback_t;\n\n\n\t\t//////////////////\n\t\t// constructors //\n\t\t//////////////////\n\n\t\t/// @name constructors and destructors\n\t\t/// Constructors of class @ref basic_json, copy/move constructor, copy\n\t\t/// assignment, static functions creating objects, and the destructor.\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief create an empty value with a given type\n\n\t\tCreate an empty JSON value with a given type. The value will be default\n\t\tinitialized with an empty value which depends on the type:\n\n\t\tValue type  | initial value\n\t\t----------- | -------------\n\t\tnull        | `null`\n\t\tboolean     | `false`\n\t\tstring      | `\"\"`\n\t\tnumber      | `0`\n\t\tobject      | `{}`\n\t\tarray       | `[]`\n\n\t\t@param[in] v  the type of the value to create\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges to any JSON value.\n\n\t\t@liveexample{The following code shows the constructor for different @ref\n\t\tvalue_t values,basic_json__value_t}\n\n\t\t@sa @ref clear() -- restores the postcondition of this constructor\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tbasic_json(const value_t v)\n\t\t\t: m_type(v), m_value(v)\n\t\t{\n\t\t\tassert_invariant();\n\t\t}\n\n\t\t/*!\n\t\t@brief create a null object\n\n\t\tCreate a `null` JSON value. It either takes a null pointer as parameter\n\t\t(explicitly creating `null`) or no parameter (implicitly creating `null`).\n\t\tThe passed null pointer itself is not read -- it is only used to choose\n\t\tthe right constructor.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this constructor never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code shows the constructor with and without a\n\t\tnull pointer parameter.,basic_json__nullptr_t}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tbasic_json(std::nullptr_t = nullptr) noexcept\n\t\t\t: basic_json(value_t::null)\n\t\t{\n\t\t\tassert_invariant();\n\t\t}\n\n\t\t/*!\n\t\t@brief create a JSON value\n\n\t\tThis is a \"catch all\" constructor for all compatible JSON types; that is,\n\t\ttypes for which a `to_json()` method exsits. The constructor forwards the\n\t\tparameter @a val to that method (to `json_serializer<U>::to_json` method\n\t\twith `U = uncvref_t<CompatibleType>`, to be exact).\n\n\t\tTemplate type @a CompatibleType includes, but is not limited to, the\n\t\tfollowing types:\n\t\t- **arrays**: @ref array_t and all kinds of compatible containers such as\n\t\t`std::vector`, `std::deque`, `std::list`, `std::forward_list`,\n\t\t`std::array`, `std::valarray`, `std::set`, `std::unordered_set`,\n\t\t`std::multiset`, and `std::unordered_multiset` with a `value_type` from\n\t\twhich a @ref basic_json value can be constructed.\n\t\t- **objects**: @ref object_t and all kinds of compatible associative\n\t\tcontainers such as `std::map`, `std::unordered_map`, `std::multimap`,\n\t\tand `std::unordered_multimap` with a `key_type` compatible to\n\t\t@ref string_t and a `value_type` from which a @ref basic_json value can\n\t\tbe constructed.\n\t\t- **strings**: @ref string_t, string literals, and all compatible string\n\t\tcontainers can be used.\n\t\t- **numbers**: @ref number_integer_t, @ref number_unsigned_t,\n\t\t@ref number_float_t, and all convertible number types such as `int`,\n\t\t`size_t`, `int64_t`, `float` or `double` can be used.\n\t\t- **boolean**: @ref boolean_t / `bool` can be used.\n\n\t\tSee the examples below.\n\n\t\t@tparam CompatibleType a type such that:\n\t\t- @a CompatibleType is not derived from `std::istream`,\n\t\t- @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move\n\t\tconstructors),\n\t\t- @a CompatibleType is not a @ref basic_json nested type (e.g.,\n\t\t@ref json_pointer, @ref iterator, etc ...)\n\t\t- @ref @ref json_serializer<U> has a\n\t\t`to_json(basic_json_t&, CompatibleType&&)` method\n\n\t\t@tparam U = `uncvref_t<CompatibleType>`\n\n\t\t@param[in] val the value to be forwarded to the respective constructor\n\n\t\t@complexity Usually linear in the size of the passed @a val, also\n\t\tdepending on the implementation of the called `to_json()`\n\t\tmethod.\n\n\t\t@exceptionsafety Depends on the called constructor. For types directly\n\t\tsupported by the library (i.e., all types for which no `to_json()` function\n\t\twas provided), strong guarantee holds: if an exception is thrown, there are\n\t\tno changes to any JSON value.\n\n\t\t@liveexample{The following code shows the constructor with several\n\t\tcompatible types.,basic_json__CompatibleType}\n\n\t\t@since version 2.1.0\n\t\t*/\n\t\ttemplate<typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,\n\t\t\tdetail::enable_if_t<not std::is_base_of<std::istream, U>::value and\n\t\t\tnot std::is_same<U, basic_json_t>::value and\n\t\t\tnot detail::is_basic_json_nested_type<\n\t\t\tbasic_json_t, U>::value and\n\t\t\tdetail::has_to_json<basic_json, U>::value,\n\t\t\tint> = 0>\n\t\t\tbasic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer<U>::to_json(\n\t\t\t\tstd::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))\n\t\t{\n\t\t\tJSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));\n\t\t\tassert_invariant();\n\t\t}\n\n\t\t/*!\n\t\t@brief create a container (array or object) from an initializer list\n\n\t\tCreates a JSON value of type array or object from the passed initializer\n\t\tlist @a init. In case @a type_deduction is `true` (default), the type of\n\t\tthe JSON value to be created is deducted from the initializer list @a init\n\t\taccording to the following rules:\n\n\t\t1. If the list is empty, an empty JSON object value `{}` is created.\n\t\t2. If the list consists of pairs whose first element is a string, a JSON\n\t\tobject value is created where the first elements of the pairs are\n\t\ttreated as keys and the second elements are as values.\n\t\t3. In all other cases, an array is created.\n\n\t\tThe rules aim to create the best fit between a C++ initializer list and\n\t\tJSON values. The rationale is as follows:\n\n\t\t1. The empty initializer list is written as `{}` which is exactly an empty\n\t\tJSON object.\n\t\t2. C++ has no way of describing mapped types other than to list a list of\n\t\tpairs. As JSON requires that keys must be of type string, rule 2 is the\n\t\tweakest constraint one can pose on initializer lists to interpret them\n\t\tas an object.\n\t\t3. In all other cases, the initializer list could not be interpreted as\n\t\tJSON object type, so interpreting it as JSON array type is safe.\n\n\t\tWith the rules described above, the following JSON values cannot be\n\t\texpressed by an initializer list:\n\n\t\t- the empty array (`[]`): use @ref array(initializer_list_t)\n\t\twith an empty initializer list in this case\n\t\t- arrays whose elements satisfy rule 2: use @ref\n\t\tarray(initializer_list_t) with the same initializer list\n\t\tin this case\n\n\t\t@note When used without parentheses around an empty initializer list, @ref\n\t\tbasic_json() is called instead of this function, yielding the JSON null\n\t\tvalue.\n\n\t\t@param[in] init  initializer list with JSON values\n\n\t\t@param[in] type_deduction internal parameter; when set to `true`, the type\n\t\tof the JSON value is deducted from the initializer list @a init; when set\n\t\tto `false`, the type provided via @a manual_type is forced. This mode is\n\t\tused by the functions @ref array(initializer_list_t) and\n\t\t@ref object(initializer_list_t).\n\n\t\t@param[in] manual_type internal parameter; when @a type_deduction is set\n\t\tto `false`, the created JSON value will use the provided type (only @ref\n\t\tvalue_t::array and @ref value_t::object are valid); when @a type_deduction\n\t\tis set to `true`, this parameter has no effect\n\n\t\t@throw type_error.301 if @a type_deduction is `false`, @a manual_type is\n\t\t`value_t::object`, but @a init contains an element which is not a pair\n\t\twhose first element is a string. In this case, the constructor could not\n\t\tcreate an object. If @a type_deduction would have be `true`, an array\n\t\twould have been created. See @ref object(initializer_list_t)\n\t\tfor an example.\n\n\t\t@complexity Linear in the size of the initializer list @a init.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges to any JSON value.\n\n\t\t@liveexample{The example below shows how JSON values are created from\n\t\tinitializer lists.,basic_json__list_init_t}\n\n\t\t@sa @ref array(initializer_list_t) -- create a JSON array\n\t\tvalue from an initializer list\n\t\t@sa @ref object(initializer_list_t) -- create a JSON object\n\t\tvalue from an initializer list\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tbasic_json(initializer_list_t init,\n\t\t\tbool type_deduction = true,\n\t\t\tvalue_t manual_type = value_t::array)\n\t\t{\n\t\t\t// check if each element is an array with two elements whose first\n\t\t\t// element is a string\n\t\t\tbool is_an_object = std::all_of(init.begin(), init.end(),\n\t\t\t\t[](const detail::json_ref<basic_json>& element_ref)\n\t\t\t{\n\t\t\t\treturn (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());\n\t\t\t});\n\n\t\t\t// adjust type if type deduction is not wanted\n\t\t\tif (not type_deduction)\n\t\t\t{\n\t\t\t\t// if array is wanted, do not create an object though possible\n\t\t\t\tif (manual_type == value_t::array)\n\t\t\t\t{\n\t\t\t\t\tis_an_object = false;\n\t\t\t\t}\n\n\t\t\t\t// if object is wanted but impossible, throw an exception\n\t\t\t\tif (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(type_error::create(301, \"cannot create object from initializer list\"));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (is_an_object)\n\t\t\t{\n\t\t\t\t// the initializer list is a list of pairs -> create object\n\t\t\t\tm_type = value_t::object;\n\t\t\t\tm_value = value_t::object;\n\n\t\t\t\tstd::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)\n\t\t\t\t{\n\t\t\t\t\tauto element = element_ref.moved_or_copied();\n\t\t\t\t\tm_value.object->emplace(\n\t\t\t\t\t\tstd::move(*((*element.m_value.array)[0].m_value.string)),\n\t\t\t\t\t\tstd::move((*element.m_value.array)[1]));\n\t\t\t\t});\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// the initializer list describes an array -> create array\n\t\t\t\tm_type = value_t::array;\n\t\t\t\tm_value.array = create<array_t>(init.begin(), init.end());\n\t\t\t}\n\n\t\t\tassert_invariant();\n\t\t}\n\n\t\t/*!\n\t\t@brief explicitly create an array from an initializer list\n\n\t\tCreates a JSON array value from a given initializer list. That is, given a\n\t\tlist of values `a, b, c`, creates the JSON value `[a, b, c]`. If the\n\t\tinitializer list is empty, the empty array `[]` is created.\n\n\t\t@note This function is only needed to express two edge cases that cannot\n\t\tbe realized with the initializer list constructor (@ref\n\t\tbasic_json(initializer_list_t, bool, value_t)). These cases\n\t\tare:\n\t\t1. creating an array whose elements are all pairs whose first element is a\n\t\tstring -- in this case, the initializer list constructor would create an\n\t\tobject, taking the first elements as keys\n\t\t2. creating an empty array -- passing the empty initializer list to the\n\t\tinitializer list constructor yields an empty object\n\n\t\t@param[in] init  initializer list with JSON values to create an array from\n\t\t(optional)\n\n\t\t@return JSON array value\n\n\t\t@complexity Linear in the size of @a init.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges to any JSON value.\n\n\t\t@liveexample{The following code shows an example for the `array`\n\t\tfunction.,array}\n\n\t\t@sa @ref basic_json(initializer_list_t, bool, value_t) --\n\t\tcreate a JSON value from an initializer list\n\t\t@sa @ref object(initializer_list_t) -- create a JSON object\n\t\tvalue from an initializer list\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tstatic basic_json array(initializer_list_t init = {})\n\t\t{\n\t\t\treturn basic_json(init, false, value_t::array);\n\t\t}\n\n\t\t/*!\n\t\t@brief explicitly create an object from an initializer list\n\n\t\tCreates a JSON object value from a given initializer list. The initializer\n\t\tlists elements must be pairs, and their first elements must be strings. If\n\t\tthe initializer list is empty, the empty object `{}` is created.\n\n\t\t@note This function is only added for symmetry reasons. In contrast to the\n\t\trelated function @ref array(initializer_list_t), there are\n\t\tno cases which can only be expressed by this function. That is, any\n\t\tinitializer list @a init can also be passed to the initializer list\n\t\tconstructor @ref basic_json(initializer_list_t, bool, value_t).\n\n\t\t@param[in] init  initializer list to create an object from (optional)\n\n\t\t@return JSON object value\n\n\t\t@throw type_error.301 if @a init is not a list of pairs whose first\n\t\telements are strings. In this case, no object can be created. When such a\n\t\tvalue is passed to @ref basic_json(initializer_list_t, bool, value_t),\n\t\tan array would have been created from the passed initializer list @a init.\n\t\tSee example below.\n\n\t\t@complexity Linear in the size of @a init.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges to any JSON value.\n\n\t\t@liveexample{The following code shows an example for the `object`\n\t\tfunction.,object}\n\n\t\t@sa @ref basic_json(initializer_list_t, bool, value_t) --\n\t\tcreate a JSON value from an initializer list\n\t\t@sa @ref array(initializer_list_t) -- create a JSON array\n\t\tvalue from an initializer list\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tstatic basic_json object(initializer_list_t init = {})\n\t\t{\n\t\t\treturn basic_json(init, false, value_t::object);\n\t\t}\n\n\t\t/*!\n\t\t@brief construct an array with count copies of given value\n\n\t\tConstructs a JSON array value by creating @a cnt copies of a passed value.\n\t\tIn case @a cnt is `0`, an empty array is created.\n\n\t\t@param[in] cnt  the number of JSON copies of @a val to create\n\t\t@param[in] val  the JSON value to copy\n\n\t\t@post `std::distance(begin(),end()) == cnt` holds.\n\n\t\t@complexity Linear in @a cnt.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges to any JSON value.\n\n\t\t@liveexample{The following code shows examples for the @ref\n\t\tbasic_json(size_type\\, const basic_json&)\n\t\tconstructor.,basic_json__size_type_basic_json}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tbasic_json(size_type cnt, const basic_json& val)\n\t\t\t: m_type(value_t::array)\n\t\t{\n\t\t\tm_value.array = create<array_t>(cnt, val);\n\t\t\tassert_invariant();\n\t\t}\n\n\t\t/*!\n\t\t@brief construct a JSON container given an iterator range\n\n\t\tConstructs the JSON value with the contents of the range `[first, last)`.\n\t\tThe semantics depends on the different types a JSON value can have:\n\t\t- In case of a null type, invalid_iterator.206 is thrown.\n\t\t- In case of other primitive types (number, boolean, or string), @a first\n\t\tmust be `begin()` and @a last must be `end()`. In this case, the value is\n\t\tcopied. Otherwise, invalid_iterator.204 is thrown.\n\t\t- In case of structured types (array, object), the constructor behaves as\n\t\tsimilar versions for `std::vector` or `std::map`; that is, a JSON array\n\t\tor object is constructed from the values in the range.\n\n\t\t@tparam InputIT an input iterator type (@ref iterator or @ref\n\t\tconst_iterator)\n\n\t\t@param[in] first begin of the range to copy from (included)\n\t\t@param[in] last end of the range to copy from (excluded)\n\n\t\t@pre Iterators @a first and @a last must be initialized. **This\n\t\tprecondition is enforced with an assertion (see warning).** If\n\t\tassertions are switched off, a violation of this precondition yields\n\t\tundefined behavior.\n\n\t\t@pre Range `[first, last)` is valid. Usually, this precondition cannot be\n\t\tchecked efficiently. Only certain edge cases are detected; see the\n\t\tdescription of the exceptions below. A violation of this precondition\n\t\tyields undefined behavior.\n\n\t\t@warning A precondition is enforced with a runtime assertion that will\n\t\tresult in calling `std::abort` if this precondition is not met.\n\t\tAssertions can be disabled by defining `NDEBUG` at compile time.\n\t\tSee http://en.cppreference.com/w/cpp/error/assert for more\n\t\tinformation.\n\n\t\t@throw invalid_iterator.201 if iterators @a first and @a last are not\n\t\tcompatible (i.e., do not belong to the same JSON value). In this case,\n\t\tthe range `[first, last)` is undefined.\n\t\t@throw invalid_iterator.204 if iterators @a first and @a last belong to a\n\t\tprimitive type (number, boolean, or string), but @a first does not point\n\t\tto the first element any more. In this case, the range `[first, last)` is\n\t\tundefined. See example code below.\n\t\t@throw invalid_iterator.206 if iterators @a first and @a last belong to a\n\t\tnull value. In this case, the range `[first, last)` is undefined.\n\n\t\t@complexity Linear in distance between @a first and @a last.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges to any JSON value.\n\n\t\t@liveexample{The example below shows several ways to create JSON values by\n\t\tspecifying a subrange with iterators.,basic_json__InputIt_InputIt}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate<class InputIT, typename std::enable_if<\n\t\t\tstd::is_same<InputIT, typename basic_json_t::iterator>::value or\n\t\t\tstd::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>\n\t\t\tbasic_json(InputIT first, InputIT last)\n\t\t{\n\t\t\tassert(first.m_object != nullptr);\n\t\t\tassert(last.m_object != nullptr);\n\n\t\t\t// make sure iterator fits the current value\n\t\t\tif (JSON_UNLIKELY(first.m_object != last.m_object))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(201, \"iterators are not compatible\"));\n\t\t\t}\n\n\t\t\t// copy type from first iterator\n\t\t\tm_type = first.m_object->m_type;\n\n\t\t\t// check if iterator range is complete for primitive values\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase value_t::boolean:\n\t\t\tcase value_t::number_float:\n\t\t\tcase value_t::number_integer:\n\t\t\tcase value_t::number_unsigned:\n\t\t\tcase value_t::string:\n\t\t\t{\n\t\t\t\tif (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()\n\t\t\t\t\tor not last.m_it.primitive_iterator.is_end()))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(204, \"iterators out of range\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase value_t::number_integer:\n\t\t\t{\n\t\t\t\tm_value.number_integer = first.m_object->m_value.number_integer;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::number_unsigned:\n\t\t\t{\n\t\t\t\tm_value.number_unsigned = first.m_object->m_value.number_unsigned;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::number_float:\n\t\t\t{\n\t\t\t\tm_value.number_float = first.m_object->m_value.number_float;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::boolean:\n\t\t\t{\n\t\t\t\tm_value.boolean = first.m_object->m_value.boolean;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::string:\n\t\t\t{\n\t\t\t\tm_value = *first.m_object->m_value.string;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::object:\n\t\t\t{\n\t\t\t\tm_value.object = create<object_t>(first.m_it.object_iterator,\n\t\t\t\t\tlast.m_it.object_iterator);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::array:\n\t\t\t{\n\t\t\t\tm_value.array = create<array_t>(first.m_it.array_iterator,\n\t\t\t\t\tlast.m_it.array_iterator);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(invalid_iterator::create(206, \"cannot construct with iterators from \" +\n\t\t\t\t\tstd::string(first.m_object->type_name())));\n\t\t\t}\n\n\t\t\tassert_invariant();\n\t\t}\n\n\n\t\t///////////////////////////////////////\n\t\t// other constructors and destructor //\n\t\t///////////////////////////////////////\n\n\t\t/// @private\n\t\tbasic_json(const detail::json_ref<basic_json>& ref)\n\t\t\t: basic_json(ref.moved_or_copied())\n\t\t{}\n\n\t\t/*!\n\t\t@brief copy constructor\n\n\t\tCreates a copy of a given JSON value.\n\n\t\t@param[in] other  the JSON value to copy\n\n\t\t@post `*this == other`\n\n\t\t@complexity Linear in the size of @a other.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges to any JSON value.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is linear.\n\t\t- As postcondition, it holds: `other == basic_json(other)`.\n\n\t\t@liveexample{The following code shows an example for the copy\n\t\tconstructor.,basic_json__basic_json}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tbasic_json(const basic_json& other)\n\t\t\t: m_type(other.m_type)\n\t\t{\n\t\t\t// check of passed value is valid\n\t\t\tother.assert_invariant();\n\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase value_t::object:\n\t\t\t{\n\t\t\t\tm_value = *other.m_value.object;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::array:\n\t\t\t{\n\t\t\t\tm_value = *other.m_value.array;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::string:\n\t\t\t{\n\t\t\t\tm_value = *other.m_value.string;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::boolean:\n\t\t\t{\n\t\t\t\tm_value = other.m_value.boolean;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::number_integer:\n\t\t\t{\n\t\t\t\tm_value = other.m_value.number_integer;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::number_unsigned:\n\t\t\t{\n\t\t\t\tm_value = other.m_value.number_unsigned;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::number_float:\n\t\t\t{\n\t\t\t\tm_value = other.m_value.number_float;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tassert_invariant();\n\t\t}\n\n\t\t/*!\n\t\t@brief move constructor\n\n\t\tMove constructor. Constructs a JSON value with the contents of the given\n\t\tvalue @a other using move semantics. It \"steals\" the resources from @a\n\t\tother and leaves it as JSON null value.\n\n\t\t@param[in,out] other  value to move to this object\n\n\t\t@post `*this` has the same value as @a other before the call.\n\t\t@post @a other is a JSON null value.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this constructor never throws\n\t\texceptions.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible)\n\t\trequirements.\n\n\t\t@liveexample{The code below shows the move constructor explicitly called\n\t\tvia std::move.,basic_json__moveconstructor}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tbasic_json(basic_json&& other) noexcept\n\t\t\t: m_type(std::move(other.m_type)),\n\t\t\tm_value(std::move(other.m_value))\n\t\t{\n\t\t\t// check that passed value is valid\n\t\t\tother.assert_invariant();\n\n\t\t\t// invalidate payload\n\t\t\tother.m_type = value_t::null;\n\t\t\tother.m_value = {};\n\n\t\t\tassert_invariant();\n\t\t}\n\n\t\t/*!\n\t\t@brief copy assignment\n\n\t\tCopy assignment operator. Copies a JSON value via the \"copy and swap\"\n\t\tstrategy: It is expressed in terms of the copy constructor, destructor,\n\t\tand the `swap()` member function.\n\n\t\t@param[in] other  value to copy from\n\n\t\t@complexity Linear.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is linear.\n\n\t\t@liveexample{The code below shows and example for the copy assignment. It\n\t\tcreates a copy of value `a` which is then swapped with `b`. Finally\\, the\n\t\tcopy of `a` (which is the null value after the swap) is\n\t\tdestroyed.,basic_json__copyassignment}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\treference& operator=(basic_json other) noexcept (\n\t\t\tstd::is_nothrow_move_constructible<value_t>::value and\n\t\t\tstd::is_nothrow_move_assignable<value_t>::value and\n\t\t\tstd::is_nothrow_move_constructible<json_value>::value and\n\t\t\tstd::is_nothrow_move_assignable<json_value>::value\n\t\t\t)\n\t\t{\n\t\t\t// check that passed value is valid\n\t\t\tother.assert_invariant();\n\n\t\t\tusing std::swap;\n\t\t\tswap(m_type, other.m_type);\n\t\t\tswap(m_value, other.m_value);\n\n\t\t\tassert_invariant();\n\t\t\treturn *this;\n\t\t}\n\n\t\t/*!\n\t\t@brief destructor\n\n\t\tDestroys the JSON value and frees all allocated memory.\n\n\t\t@complexity Linear.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is linear.\n\t\t- All stored elements are destroyed and all memory is freed.\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\t~basic_json()\n\t\t{\n\t\t\tassert_invariant();\n\t\t\tm_value.destroy(m_type);\n\t\t}\n\n\t\t/// @}\n\n\tpublic:\n\t\t///////////////////////\n\t\t// object inspection //\n\t\t///////////////////////\n\n\t\t/// @name object inspection\n\t\t/// Functions to inspect the type of a JSON value.\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief serialization\n\n\t\tSerialization function for JSON values. The function tries to mimic\n\t\tPython's `json.dumps()` function, and currently supports its @a indent\n\t\tand @a ensure_ascii parameters.\n\n\t\t@param[in] indent If indent is nonnegative, then array elements and object\n\t\tmembers will be pretty-printed with that indent level. An indent level of\n\t\t`0` will only insert newlines. `-1` (the default) selects the most compact\n\t\trepresentation.\n\t\t@param[in] indent_char The character to use for indentation if @a indent is\n\t\tgreater than `0`. The default is ` ` (space).\n\t\t@param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters\n\t\tin the output are escaped with \\uXXXX sequences, and the result consists\n\t\tof ASCII characters only.\n\n\t\t@return string containing the serialization of the JSON value\n\n\t\t@complexity Linear.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges in the JSON value.\n\n\t\t@liveexample{The following example shows the effect of different @a indent\\,\n\t\t@a indent_char\\, and @a ensure_ascii parameters to the result of the\n\t\tserialization.,dump}\n\n\t\t@see https://docs.python.org/2/library/json.html#json.dump\n\n\t\t@since version 1.0.0; indentation character @a indent_char and option\n\t\t@a ensure_ascii added in version 3.0.0\n\t\t*/\n\t\tstring_t dump(const int indent = -1, const char indent_char = ' ',\n\t\t\tconst bool ensure_ascii = false) const\n\t\t{\n\t\t\tstring_t result;\n\t\t\tserializer s(detail::output_adapter<char>(result), indent_char);\n\n\t\t\tif (indent >= 0)\n\t\t\t{\n\t\t\t\ts.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ts.dump(*this, false, ensure_ascii, 0);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief return the type of the JSON value (explicit)\n\n\t\tReturn the type of the JSON value as a value from the @ref value_t\n\t\tenumeration.\n\n\t\t@return the type of the JSON value\n\t\tValue type                | return value\n\t\t------------------------- | -------------------------\n\t\tnull                      | value_t::null\n\t\tboolean                   | value_t::boolean\n\t\tstring                    | value_t::string\n\t\tnumber (integer)          | value_t::number_integer\n\t\tnumber (unsigned integer) | value_t::number_unsigned\n\t\tnumber (foating-point)    | value_t::number_float\n\t\tobject                    | value_t::object\n\t\tarray                     | value_t::array\n\t\tdiscarded                 | value_t::discarded\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `type()` for all JSON\n\t\ttypes.,type}\n\n\t\t@sa @ref operator value_t() -- return the type of the JSON value (implicit)\n\t\t@sa @ref type_name() -- return the type as string\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr value_t type() const noexcept\n\t\t{\n\t\t\treturn m_type;\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether type is primitive\n\n\t\tThis function returns true if and only if the JSON type is primitive\n\t\t(string, number, boolean, or null).\n\n\t\t@return `true` if type is primitive (string, number, boolean, or null),\n\t\t`false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_primitive()` for all JSON\n\t\ttypes.,is_primitive}\n\n\t\t@sa @ref is_structured() -- returns whether JSON value is structured\n\t\t@sa @ref is_null() -- returns whether JSON value is `null`\n\t\t@sa @ref is_string() -- returns whether JSON value is a string\n\t\t@sa @ref is_boolean() -- returns whether JSON value is a boolean\n\t\t@sa @ref is_number() -- returns whether JSON value is a number\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_primitive() const noexcept\n\t\t{\n\t\t\treturn is_null() or is_string() or is_boolean() or is_number();\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether type is structured\n\n\t\tThis function returns true if and only if the JSON type is structured\n\t\t(array or object).\n\n\t\t@return `true` if type is structured (array or object), `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_structured()` for all JSON\n\t\ttypes.,is_structured}\n\n\t\t@sa @ref is_primitive() -- returns whether value is primitive\n\t\t@sa @ref is_array() -- returns whether value is an array\n\t\t@sa @ref is_object() -- returns whether value is an object\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_structured() const noexcept\n\t\t{\n\t\t\treturn is_array() or is_object();\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is null\n\n\t\tThis function returns true if and only if the JSON value is null.\n\n\t\t@return `true` if type is null, `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_null()` for all JSON\n\t\ttypes.,is_null}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_null() const noexcept\n\t\t{\n\t\t\treturn (m_type == value_t::null);\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is a boolean\n\n\t\tThis function returns true if and only if the JSON value is a boolean.\n\n\t\t@return `true` if type is boolean, `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_boolean()` for all JSON\n\t\ttypes.,is_boolean}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_boolean() const noexcept\n\t\t{\n\t\t\treturn (m_type == value_t::boolean);\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is a number\n\n\t\tThis function returns true if and only if the JSON value is a number. This\n\t\tincludes both integer (signed and unsigned) and floating-point values.\n\n\t\t@return `true` if type is number (regardless whether integer, unsigned\n\t\tinteger or floating-type), `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_number()` for all JSON\n\t\ttypes.,is_number}\n\n\t\t@sa @ref is_number_integer() -- check if value is an integer or unsigned\n\t\tinteger number\n\t\t@sa @ref is_number_unsigned() -- check if value is an unsigned integer\n\t\tnumber\n\t\t@sa @ref is_number_float() -- check if value is a floating-point number\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_number() const noexcept\n\t\t{\n\t\t\treturn is_number_integer() or is_number_float();\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is an integer number\n\n\t\tThis function returns true if and only if the JSON value is a signed or\n\t\tunsigned integer number. This excludes floating-point values.\n\n\t\t@return `true` if type is an integer or unsigned integer number, `false`\n\t\totherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_number_integer()` for all\n\t\tJSON types.,is_number_integer}\n\n\t\t@sa @ref is_number() -- check if value is a number\n\t\t@sa @ref is_number_unsigned() -- check if value is an unsigned integer\n\t\tnumber\n\t\t@sa @ref is_number_float() -- check if value is a floating-point number\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_number_integer() const noexcept\n\t\t{\n\t\t\treturn (m_type == value_t::number_integer or m_type == value_t::number_unsigned);\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is an unsigned integer number\n\n\t\tThis function returns true if and only if the JSON value is an unsigned\n\t\tinteger number. This excludes floating-point and signed integer values.\n\n\t\t@return `true` if type is an unsigned integer number, `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_number_unsigned()` for all\n\t\tJSON types.,is_number_unsigned}\n\n\t\t@sa @ref is_number() -- check if value is a number\n\t\t@sa @ref is_number_integer() -- check if value is an integer or unsigned\n\t\tinteger number\n\t\t@sa @ref is_number_float() -- check if value is a floating-point number\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\tconstexpr bool is_number_unsigned() const noexcept\n\t\t{\n\t\t\treturn (m_type == value_t::number_unsigned);\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is a floating-point number\n\n\t\tThis function returns true if and only if the JSON value is a\n\t\tfloating-point number. This excludes signed and unsigned integer values.\n\n\t\t@return `true` if type is a floating-point number, `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_number_float()` for all\n\t\tJSON types.,is_number_float}\n\n\t\t@sa @ref is_number() -- check if value is number\n\t\t@sa @ref is_number_integer() -- check if value is an integer number\n\t\t@sa @ref is_number_unsigned() -- check if value is an unsigned integer\n\t\tnumber\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_number_float() const noexcept\n\t\t{\n\t\t\treturn (m_type == value_t::number_float);\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is an object\n\n\t\tThis function returns true if and only if the JSON value is an object.\n\n\t\t@return `true` if type is object, `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_object()` for all JSON\n\t\ttypes.,is_object}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_object() const noexcept\n\t\t{\n\t\t\treturn (m_type == value_t::object);\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is an array\n\n\t\tThis function returns true if and only if the JSON value is an array.\n\n\t\t@return `true` if type is array, `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_array()` for all JSON\n\t\ttypes.,is_array}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_array() const noexcept\n\t\t{\n\t\t\treturn (m_type == value_t::array);\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is a string\n\n\t\tThis function returns true if and only if the JSON value is a string.\n\n\t\t@return `true` if type is string, `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_string()` for all JSON\n\t\ttypes.,is_string}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_string() const noexcept\n\t\t{\n\t\t\treturn (m_type == value_t::string);\n\t\t}\n\n\t\t/*!\n\t\t@brief return whether value is discarded\n\n\t\tThis function returns true if and only if the JSON value was discarded\n\t\tduring parsing with a callback function (see @ref parser_callback_t).\n\n\t\t@note This function will always be `false` for JSON values after parsing.\n\t\tThat is, discarded values can only occur during parsing, but will be\n\t\tremoved when inside a structured value or replaced by null in other cases.\n\n\t\t@return `true` if type is discarded, `false` otherwise.\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies `is_discarded()` for all JSON\n\t\ttypes.,is_discarded}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr bool is_discarded() const noexcept\n\t\t{\n\t\t\treturn (m_type == value_t::discarded);\n\t\t}\n\n\t\t/*!\n\t\t@brief return the type of the JSON value (implicit)\n\n\t\tImplicitly return the type of the JSON value as a value from the @ref\n\t\tvalue_t enumeration.\n\n\t\t@return the type of the JSON value\n\n\t\t@complexity Constant.\n\n\t\t@exceptionsafety No-throw guarantee: this member function never throws\n\t\texceptions.\n\n\t\t@liveexample{The following code exemplifies the @ref value_t operator for\n\t\tall JSON types.,operator__value_t}\n\n\t\t@sa @ref type() -- return the type of the JSON value (explicit)\n\t\t@sa @ref type_name() -- return the type as string\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconstexpr operator value_t() const noexcept\n\t\t{\n\t\t\treturn m_type;\n\t\t}\n\n\t\t/// @}\n\n\tprivate:\n\t\t//////////////////\n\t\t// value access //\n\t\t//////////////////\n\n\t\t/// get a boolean (explicit)\n\t\tboolean_t get_impl(boolean_t* /*unused*/) const\n\t\t{\n\t\t\tif (JSON_LIKELY(is_boolean()))\n\t\t\t{\n\t\t\t\treturn m_value.boolean;\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(302, \"type must be boolean, but is \" + std::string(type_name())));\n\t\t}\n\n\t\t/// get a pointer to the value (object)\n\t\tobject_t* get_impl_ptr(object_t* /*unused*/) noexcept\n\t\t{\n\t\t\treturn is_object() ? m_value.object : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (object)\n\t\tconstexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept\n\t\t{\n\t\t\treturn is_object() ? m_value.object : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (array)\n\t\tarray_t* get_impl_ptr(array_t* /*unused*/) noexcept\n\t\t{\n\t\t\treturn is_array() ? m_value.array : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (array)\n\t\tconstexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept\n\t\t{\n\t\t\treturn is_array() ? m_value.array : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (string)\n\t\tstring_t* get_impl_ptr(string_t* /*unused*/) noexcept\n\t\t{\n\t\t\treturn is_string() ? m_value.string : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (string)\n\t\tconstexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept\n\t\t{\n\t\t\treturn is_string() ? m_value.string : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (boolean)\n\t\tboolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept\n\t\t{\n\t\t\treturn is_boolean() ? &m_value.boolean : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (boolean)\n\t\tconstexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept\n\t\t{\n\t\t\treturn is_boolean() ? &m_value.boolean : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (integer number)\n\t\tnumber_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept\n\t\t{\n\t\t\treturn is_number_integer() ? &m_value.number_integer : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (integer number)\n\t\tconstexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept\n\t\t{\n\t\t\treturn is_number_integer() ? &m_value.number_integer : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (unsigned number)\n\t\tnumber_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept\n\t\t{\n\t\t\treturn is_number_unsigned() ? &m_value.number_unsigned : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (unsigned number)\n\t\tconstexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept\n\t\t{\n\t\t\treturn is_number_unsigned() ? &m_value.number_unsigned : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (floating-point number)\n\t\tnumber_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept\n\t\t{\n\t\t\treturn is_number_float() ? &m_value.number_float : nullptr;\n\t\t}\n\n\t\t/// get a pointer to the value (floating-point number)\n\t\tconstexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept\n\t\t{\n\t\t\treturn is_number_float() ? &m_value.number_float : nullptr;\n\t\t}\n\n\t\t/*!\n\t\t@brief helper function to implement get_ref()\n\n\t\tThis function helps to implement get_ref() without code duplication for\n\t\tconst and non-const overloads\n\n\t\t@tparam ThisType will be deduced as `basic_json` or `const basic_json`\n\n\t\t@throw type_error.303 if ReferenceType does not match underlying value\n\t\ttype of the current JSON\n\t\t*/\n\t\ttemplate<typename ReferenceType, typename ThisType>\n\t\tstatic ReferenceType get_ref_impl(ThisType& obj)\n\t\t{\n\t\t\t// delegate the call to get_ptr<>()\n\t\t\tauto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();\n\n\t\t\tif (JSON_LIKELY(ptr != nullptr))\n\t\t\t{\n\t\t\t\treturn *ptr;\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(303, \"incompatible ReferenceType for get_ref, actual type is \" + std::string(obj.type_name())));\n\t\t}\n\n\tpublic:\n\t\t/// @name value access\n\t\t/// Direct access to the stored value of a JSON value.\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief get special-case overload\n\n\t\tThis overloads avoids a lot of template boilerplate, it can be seen as the\n\t\tidentity method\n\n\t\t@tparam BasicJsonType == @ref basic_json\n\n\t\t@return a copy of *this\n\n\t\t@complexity Constant.\n\n\t\t@since version 2.1.0\n\t\t*/\n\t\ttemplate <\n\t\t\ttypename BasicJsonType,\n\t\t\tdetail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type,\n\t\t\tbasic_json_t>::value,\n\t\t\tint> = 0 >\n\t\t\tbasic_json get() const\n\t\t{\n\t\t\treturn *this;\n\t\t}\n\n\t\t/*!\n\t\t@brief get a value (explicit)\n\n\t\tExplicit type conversion between the JSON value and a compatible value\n\t\twhich is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)\n\t\tand [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).\n\t\tThe value is converted by calling the @ref json_serializer<ValueType>\n\t\t`from_json()` method.\n\n\t\tThe function is equivalent to executing\n\t\t@code {.cpp}\n\t\tValueType ret;\n\t\tJSONSerializer<ValueType>::from_json(*this, ret);\n\t\treturn ret;\n\t\t@endcode\n\n\t\tThis overloads is chosen if:\n\t\t- @a ValueType is not @ref basic_json,\n\t\t- @ref json_serializer<ValueType> has a `from_json()` method of the form\n\t\t`void from_json(const basic_json&, ValueType&)`, and\n\t\t- @ref json_serializer<ValueType> does not have a `from_json()` method of\n\t\tthe form `ValueType from_json(const basic_json&)`\n\n\t\t@tparam ValueTypeCV the provided value type\n\t\t@tparam ValueType the returned value type\n\n\t\t@return copy of the JSON value, converted to @a ValueType\n\n\t\t@throw what @ref json_serializer<ValueType> `from_json()` method throws\n\n\t\t@liveexample{The example below shows several conversions from JSON values\n\t\tto other types. There a few things to note: (1) Floating-point numbers can\n\t\tbe converted to integers\\, (2) A JSON array can be converted to a standard\n\t\t`std::vector<short>`\\, (3) A JSON object can be converted to C++\n\t\tassociative containers such as `std::unordered_map<std::string\\,\n\t\tjson>`.,get__ValueType_const}\n\n\t\t@since version 2.1.0\n\t\t*/\n\t\ttemplate <\n\t\t\ttypename ValueTypeCV,\n\t\t\ttypename ValueType = detail::uncvref_t<ValueTypeCV>,\n\t\t\tdetail::enable_if_t <\n\t\t\tnot std::is_same<basic_json_t, ValueType>::value and\n\t\t\tdetail::has_from_json<basic_json_t, ValueType>::value and\n\t\t\tnot detail::has_non_default_from_json<basic_json_t, ValueType>::value,\n\t\t\tint > = 0 >\n\t\t\tValueType get() const noexcept(noexcept(\n\t\t\t\tJSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))\n\t\t{\n\t\t\t// we cannot static_assert on ValueTypeCV being non-const, because\n\t\t\t// there is support for get<const basic_json_t>(), which is why we\n\t\t\t// still need the uncvref\n\t\t\tstatic_assert(not std::is_reference<ValueTypeCV>::value,\n\t\t\t\t\"get() cannot be used with reference types, you might want to use get_ref()\");\n\t\t\tstatic_assert(std::is_default_constructible<ValueType>::value,\n\t\t\t\t\"types must be DefaultConstructible when used with get()\");\n\n\t\t\tValueType ret;\n\t\t\tJSONSerializer<ValueType>::from_json(*this, ret);\n\t\t\treturn ret;\n\t\t}\n\n\t\t/*!\n\t\t@brief get a value (explicit); special case\n\n\t\tExplicit type conversion between the JSON value and a compatible value\n\t\twhich is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)\n\t\tand **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).\n\t\tThe value is converted by calling the @ref json_serializer<ValueType>\n\t\t`from_json()` method.\n\n\t\tThe function is equivalent to executing\n\t\t@code {.cpp}\n\t\treturn JSONSerializer<ValueTypeCV>::from_json(*this);\n\t\t@endcode\n\n\t\tThis overloads is chosen if:\n\t\t- @a ValueType is not @ref basic_json and\n\t\t- @ref json_serializer<ValueType> has a `from_json()` method of the form\n\t\t`ValueType from_json(const basic_json&)`\n\n\t\t@note If @ref json_serializer<ValueType> has both overloads of\n\t\t`from_json()`, this one is chosen.\n\n\t\t@tparam ValueTypeCV the provided value type\n\t\t@tparam ValueType the returned value type\n\n\t\t@return copy of the JSON value, converted to @a ValueType\n\n\t\t@throw what @ref json_serializer<ValueType> `from_json()` method throws\n\n\t\t@since version 2.1.0\n\t\t*/\n\t\ttemplate <\n\t\t\ttypename ValueTypeCV,\n\t\t\ttypename ValueType = detail::uncvref_t<ValueTypeCV>,\n\t\t\tdetail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and\n\t\t\tdetail::has_non_default_from_json<basic_json_t,\n\t\t\tValueType>::value, int> = 0 >\n\t\t\tValueType get() const noexcept(noexcept(\n\t\t\t\tJSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))\n\t\t{\n\t\t\tstatic_assert(not std::is_reference<ValueTypeCV>::value,\n\t\t\t\t\"get() cannot be used with reference types, you might want to use get_ref()\");\n\t\t\treturn JSONSerializer<ValueTypeCV>::from_json(*this);\n\t\t}\n\n\t\t/*!\n\t\t@brief get a pointer value (explicit)\n\n\t\tExplicit pointer access to the internally stored JSON value. No copies are\n\t\tmade.\n\n\t\t@warning The pointer becomes invalid if the underlying JSON object\n\t\tchanges.\n\n\t\t@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref\n\t\tobject_t, @ref string_t, @ref boolean_t, @ref number_integer_t,\n\t\t@ref number_unsigned_t, or @ref number_float_t.\n\n\t\t@return pointer to the internally stored JSON value if the requested\n\t\tpointer type @a PointerType fits to the JSON value; `nullptr` otherwise\n\n\t\t@complexity Constant.\n\n\t\t@liveexample{The example below shows how pointers to internal values of a\n\t\tJSON value can be requested. Note that no type conversions are made and a\n\t\t`nullptr` is returned if the value and the requested pointer type does not\n\t\tmatch.,get__PointerType}\n\n\t\t@sa @ref get_ptr() for explicit pointer-member access\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate<typename PointerType, typename std::enable_if<\n\t\t\tstd::is_pointer<PointerType>::value, int>::type = 0>\n\t\t\tPointerType get() noexcept\n\t\t{\n\t\t\t// delegate the call to get_ptr\n\t\t\treturn get_ptr<PointerType>();\n\t\t}\n\n\t\t/*!\n\t\t@brief get a pointer value (explicit)\n\t\t@copydoc get()\n\t\t*/\n\t\ttemplate<typename PointerType, typename std::enable_if<\n\t\t\tstd::is_pointer<PointerType>::value, int>::type = 0>\n\t\t\tconstexpr const PointerType get() const noexcept\n\t\t{\n\t\t\t// delegate the call to get_ptr\n\t\t\treturn get_ptr<PointerType>();\n\t\t}\n\n\t\t/*!\n\t\t@brief get a pointer value (implicit)\n\n\t\tImplicit pointer access to the internally stored JSON value. No copies are\n\t\tmade.\n\n\t\t@warning Writing data to the pointee of the result yields an undefined\n\t\tstate.\n\n\t\t@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref\n\t\tobject_t, @ref string_t, @ref boolean_t, @ref number_integer_t,\n\t\t@ref number_unsigned_t, or @ref number_float_t. Enforced by a static\n\t\tassertion.\n\n\t\t@return pointer to the internally stored JSON value if the requested\n\t\tpointer type @a PointerType fits to the JSON value; `nullptr` otherwise\n\n\t\t@complexity Constant.\n\n\t\t@liveexample{The example below shows how pointers to internal values of a\n\t\tJSON value can be requested. Note that no type conversions are made and a\n\t\t`nullptr` is returned if the value and the requested pointer type does not\n\t\tmatch.,get_ptr}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate<typename PointerType, typename std::enable_if<\n\t\t\tstd::is_pointer<PointerType>::value, int>::type = 0>\n\t\t\tPointerType get_ptr() noexcept\n\t\t{\n\t\t\t// get the type of the PointerType (remove pointer and const)\n\t\t\tusing pointee_t = typename std::remove_const<typename\n\t\t\t\tstd::remove_pointer<typename\n\t\t\t\tstd::remove_const<PointerType>::type>::type>::type;\n\t\t\t// make sure the type matches the allowed types\n\t\t\tstatic_assert(\n\t\t\t\tstd::is_same<object_t, pointee_t>::value\n\t\t\t\tor std::is_same<array_t, pointee_t>::value\n\t\t\t\tor std::is_same<string_t, pointee_t>::value\n\t\t\t\tor std::is_same<boolean_t, pointee_t>::value\n\t\t\t\tor std::is_same<number_integer_t, pointee_t>::value\n\t\t\t\tor std::is_same<number_unsigned_t, pointee_t>::value\n\t\t\t\tor std::is_same<number_float_t, pointee_t>::value\n\t\t\t\t, \"incompatible pointer type\");\n\n\t\t\t// delegate the call to get_impl_ptr<>()\n\t\t\treturn get_impl_ptr(static_cast<PointerType>(nullptr));\n\t\t}\n\n\t\t/*!\n\t\t@brief get a pointer value (implicit)\n\t\t@copydoc get_ptr()\n\t\t*/\n\t\ttemplate<typename PointerType, typename std::enable_if<\n\t\t\tstd::is_pointer<PointerType>::value and\n\t\t\tstd::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>\n\t\t\tconstexpr const PointerType get_ptr() const noexcept\n\t\t{\n\t\t\t// get the type of the PointerType (remove pointer and const)\n\t\t\tusing pointee_t = typename std::remove_const<typename\n\t\t\t\tstd::remove_pointer<typename\n\t\t\t\tstd::remove_const<PointerType>::type>::type>::type;\n\t\t\t// make sure the type matches the allowed types\n\t\t\tstatic_assert(\n\t\t\t\tstd::is_same<object_t, pointee_t>::value\n\t\t\t\tor std::is_same<array_t, pointee_t>::value\n\t\t\t\tor std::is_same<string_t, pointee_t>::value\n\t\t\t\tor std::is_same<boolean_t, pointee_t>::value\n\t\t\t\tor std::is_same<number_integer_t, pointee_t>::value\n\t\t\t\tor std::is_same<number_unsigned_t, pointee_t>::value\n\t\t\t\tor std::is_same<number_float_t, pointee_t>::value\n\t\t\t\t, \"incompatible pointer type\");\n\n\t\t\t// delegate the call to get_impl_ptr<>() const\n\t\t\treturn get_impl_ptr(static_cast<PointerType>(nullptr));\n\t\t}\n\n\t\t/*!\n\t\t@brief get a reference value (implicit)\n\n\t\tImplicit reference access to the internally stored JSON value. No copies\n\t\tare made.\n\n\t\t@warning Writing data to the referee of the result yields an undefined\n\t\tstate.\n\n\t\t@tparam ReferenceType reference type; must be a reference to @ref array_t,\n\t\t@ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or\n\t\t@ref number_float_t. Enforced by static assertion.\n\n\t\t@return reference to the internally stored JSON value if the requested\n\t\treference type @a ReferenceType fits to the JSON value; throws\n\t\ttype_error.303 otherwise\n\n\t\t@throw type_error.303 in case passed type @a ReferenceType is incompatible\n\t\twith the stored JSON value; see example below\n\n\t\t@complexity Constant.\n\n\t\t@liveexample{The example shows several calls to `get_ref()`.,get_ref}\n\n\t\t@since version 1.1.0\n\t\t*/\n\t\ttemplate<typename ReferenceType, typename std::enable_if<\n\t\t\tstd::is_reference<ReferenceType>::value, int>::type = 0>\n\t\t\tReferenceType get_ref()\n\t\t{\n\t\t\t// delegate call to get_ref_impl\n\t\t\treturn get_ref_impl<ReferenceType>(*this);\n\t\t}\n\n\t\t/*!\n\t\t@brief get a reference value (implicit)\n\t\t@copydoc get_ref()\n\t\t*/\n\t\ttemplate<typename ReferenceType, typename std::enable_if<\n\t\t\tstd::is_reference<ReferenceType>::value and\n\t\t\tstd::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>\n\t\t\tReferenceType get_ref() const\n\t\t{\n\t\t\t// delegate call to get_ref_impl\n\t\t\treturn get_ref_impl<ReferenceType>(*this);\n\t\t}\n\n\t\t/*!\n\t\t@brief get a value (implicit)\n\n\t\tImplicit type conversion between the JSON value and a compatible value.\n\t\tThe call is realized by calling @ref get() const.\n\n\t\t@tparam ValueType non-pointer type compatible to the JSON value, for\n\t\tinstance `int` for JSON integer numbers, `bool` for JSON booleans, or\n\t\t`std::vector` types for JSON arrays. The character type of @ref string_t\n\t\tas well as an initializer list of this type is excluded to avoid\n\t\tambiguities as these types implicitly convert to `std::string`.\n\n\t\t@return copy of the JSON value, converted to type @a ValueType\n\n\t\t@throw type_error.302 in case passed type @a ValueType is incompatible\n\t\tto the JSON value type (e.g., the JSON value is of type boolean, but a\n\t\tstring is requested); see example below\n\n\t\t@complexity Linear in the size of the JSON value.\n\n\t\t@liveexample{The example below shows several conversions from JSON values\n\t\tto other types. There a few things to note: (1) Floating-point numbers can\n\t\tbe converted to integers\\, (2) A JSON array can be converted to a standard\n\t\t`std::vector<short>`\\, (3) A JSON object can be converted to C++\n\t\tassociative containers such as `std::unordered_map<std::string\\,\n\t\tjson>`.,operator__ValueType}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate < typename ValueType, typename std::enable_if <\n\t\t\tnot std::is_pointer<ValueType>::value and\n\t\t\tnot std::is_same<ValueType, detail::json_ref<basic_json>>::value and\n\t\t\tnot std::is_same<ValueType, typename string_t::value_type>::value\n#ifndef _MSC_VER  // fix for issue #167 operator<< ambiguity under VS2015\n\t\t\tand not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value\n#endif\n#if defined(JSON_HAS_CPP_17)\n\t\t\tand not std::is_same<ValueType, typename std::string_view>::value\n#endif\n\t\t\t, int >::type = 0 >\n\t\t\toperator ValueType() const\n\t\t{\n\t\t\t// delegate the call to get<>() const\n\t\t\treturn get<ValueType>();\n\t\t}\n\n\t\t/// @}\n\n\n\t\t////////////////////\n\t\t// element access //\n\t\t////////////////////\n\n\t\t/// @name element access\n\t\t/// Access to the JSON value.\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief access specified array element with bounds checking\n\n\t\tReturns a reference to the element at specified location @a idx, with\n\t\tbounds checking.\n\n\t\t@param[in] idx  index of the element to access\n\n\t\t@return reference to the element at index @a idx\n\n\t\t@throw type_error.304 if the JSON value is not an array; in this case,\n\t\tcalling `at` with an index makes no sense. See example below.\n\t\t@throw out_of_range.401 if the index @a idx is out of range of the array;\n\t\tthat is, `idx >= size()`. See example below.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges in the JSON value.\n\n\t\t@complexity Constant.\n\n\t\t@since version 1.0.0\n\n\t\t@liveexample{The example below shows how array elements can be read and\n\t\twritten using `at()`. It also demonstrates the different exceptions that\n\t\tcan be thrown.,at__size_type}\n\t\t*/\n\t\treference at(size_type idx)\n\t\t{\n\t\t\t// at only works for arrays\n\t\t\tif (JSON_LIKELY(is_array()))\n\t\t\t{\n\t\t\t\tJSON_TRY\n\t\t\t\t{\n\t\t\t\t\treturn m_value.array->at(idx);\n\t\t\t\t}\n\t\t\t\t\tJSON_CATCH(std::out_of_range&)\n\t\t\t\t{\n\t\t\t\t\t// create better exception explanation\n\t\t\t\t\tJSON_THROW(out_of_range::create(401, \"array index \" + std::to_string(idx) + \" is out of range\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(304, \"cannot use at() with \" + std::string(type_name())));\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified array element with bounds checking\n\n\t\tReturns a const reference to the element at specified location @a idx,\n\t\twith bounds checking.\n\n\t\t@param[in] idx  index of the element to access\n\n\t\t@return const reference to the element at index @a idx\n\n\t\t@throw type_error.304 if the JSON value is not an array; in this case,\n\t\tcalling `at` with an index makes no sense. See example below.\n\t\t@throw out_of_range.401 if the index @a idx is out of range of the array;\n\t\tthat is, `idx >= size()`. See example below.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges in the JSON value.\n\n\t\t@complexity Constant.\n\n\t\t@since version 1.0.0\n\n\t\t@liveexample{The example below shows how array elements can be read using\n\t\t`at()`. It also demonstrates the different exceptions that can be thrown.,\n\t\tat__size_type_const}\n\t\t*/\n\t\tconst_reference at(size_type idx) const\n\t\t{\n\t\t\t// at only works for arrays\n\t\t\tif (JSON_LIKELY(is_array()))\n\t\t\t{\n\t\t\t\tJSON_TRY\n\t\t\t\t{\n\t\t\t\t\treturn m_value.array->at(idx);\n\t\t\t\t}\n\t\t\t\t\tJSON_CATCH(std::out_of_range&)\n\t\t\t\t{\n\t\t\t\t\t// create better exception explanation\n\t\t\t\t\tJSON_THROW(out_of_range::create(401, \"array index \" + std::to_string(idx) + \" is out of range\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(304, \"cannot use at() with \" + std::string(type_name())));\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified object element with bounds checking\n\n\t\tReturns a reference to the element at with specified key @a key, with\n\t\tbounds checking.\n\n\t\t@param[in] key  key of the element to access\n\n\t\t@return reference to the element at key @a key\n\n\t\t@throw type_error.304 if the JSON value is not an object; in this case,\n\t\tcalling `at` with a key makes no sense. See example below.\n\t\t@throw out_of_range.403 if the key @a key is is not stored in the object;\n\t\tthat is, `find(key) == end()`. See example below.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges in the JSON value.\n\n\t\t@complexity Logarithmic in the size of the container.\n\n\t\t@sa @ref operator[](const typename object_t::key_type&) for unchecked\n\t\taccess by reference\n\t\t@sa @ref value() for access by value with a default value\n\n\t\t@since version 1.0.0\n\n\t\t@liveexample{The example below shows how object elements can be read and\n\t\twritten using `at()`. It also demonstrates the different exceptions that\n\t\tcan be thrown.,at__object_t_key_type}\n\t\t*/\n\t\treference at(const typename object_t::key_type& key)\n\t\t{\n\t\t\t// at only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\tJSON_TRY\n\t\t\t\t{\n\t\t\t\t\treturn m_value.object->at(key);\n\t\t\t\t}\n\t\t\t\t\tJSON_CATCH(std::out_of_range&)\n\t\t\t\t{\n\t\t\t\t\t// create better exception explanation\n\t\t\t\t\tJSON_THROW(out_of_range::create(403, \"key '\" + key + \"' not found\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(304, \"cannot use at() with \" + std::string(type_name())));\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified object element with bounds checking\n\n\t\tReturns a const reference to the element at with specified key @a key,\n\t\twith bounds checking.\n\n\t\t@param[in] key  key of the element to access\n\n\t\t@return const reference to the element at key @a key\n\n\t\t@throw type_error.304 if the JSON value is not an object; in this case,\n\t\tcalling `at` with a key makes no sense. See example below.\n\t\t@throw out_of_range.403 if the key @a key is is not stored in the object;\n\t\tthat is, `find(key) == end()`. See example below.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges in the JSON value.\n\n\t\t@complexity Logarithmic in the size of the container.\n\n\t\t@sa @ref operator[](const typename object_t::key_type&) for unchecked\n\t\taccess by reference\n\t\t@sa @ref value() for access by value with a default value\n\n\t\t@since version 1.0.0\n\n\t\t@liveexample{The example below shows how object elements can be read using\n\t\t`at()`. It also demonstrates the different exceptions that can be thrown.,\n\t\tat__object_t_key_type_const}\n\t\t*/\n\t\tconst_reference at(const typename object_t::key_type& key) const\n\t\t{\n\t\t\t// at only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\tJSON_TRY\n\t\t\t\t{\n\t\t\t\t\treturn m_value.object->at(key);\n\t\t\t\t}\n\t\t\t\t\tJSON_CATCH(std::out_of_range&)\n\t\t\t\t{\n\t\t\t\t\t// create better exception explanation\n\t\t\t\t\tJSON_THROW(out_of_range::create(403, \"key '\" + key + \"' not found\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(304, \"cannot use at() with \" + std::string(type_name())));\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified array element\n\n\t\tReturns a reference to the element at specified location @a idx.\n\n\t\t@note If @a idx is beyond the range of the array (i.e., `idx >= size()`),\n\t\tthen the array is silently filled up with `null` values to make `idx` a\n\t\tvalid reference to the last stored element.\n\n\t\t@param[in] idx  index of the element to access\n\n\t\t@return reference to the element at index @a idx\n\n\t\t@throw type_error.305 if the JSON value is not an array or null; in that\n\t\tcases, using the [] operator with an index makes no sense.\n\n\t\t@complexity Constant if @a idx is in the range of the array. Otherwise\n\t\tlinear in `idx - size()`.\n\n\t\t@liveexample{The example below shows how array elements can be read and\n\t\twritten using `[]` operator. Note the addition of `null`\n\t\tvalues.,operatorarray__size_type}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\treference operator[](size_type idx)\n\t\t{\n\t\t\t// implicitly convert null value to an empty array\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::array;\n\t\t\t\tm_value.array = create<array_t>();\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\t// operator[] only works for arrays\n\t\t\tif (JSON_LIKELY(is_array()))\n\t\t\t{\n\t\t\t\t// fill up array with null values if given idx is outside range\n\t\t\t\tif (idx >= m_value.array->size())\n\t\t\t\t{\n\t\t\t\t\tm_value.array->insert(m_value.array->end(),\n\t\t\t\t\t\tidx - m_value.array->size() + 1,\n\t\t\t\t\t\tbasic_json());\n\t\t\t\t}\n\n\t\t\t\treturn m_value.array->operator[](idx);\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(305, \"cannot use operator[] with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified array element\n\n\t\tReturns a const reference to the element at specified location @a idx.\n\n\t\t@param[in] idx  index of the element to access\n\n\t\t@return const reference to the element at index @a idx\n\n\t\t@throw type_error.305 if the JSON value is not an array; in that cases,\n\t\tusing the [] operator with an index makes no sense.\n\n\t\t@complexity Constant.\n\n\t\t@liveexample{The example below shows how array elements can be read using\n\t\tthe `[]` operator.,operatorarray__size_type_const}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconst_reference operator[](size_type idx) const\n\t\t{\n\t\t\t// const operator[] only works for arrays\n\t\t\tif (JSON_LIKELY(is_array()))\n\t\t\t{\n\t\t\t\treturn m_value.array->operator[](idx);\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(305, \"cannot use operator[] with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified object element\n\n\t\tReturns a reference to the element at with specified key @a key.\n\n\t\t@note If @a key is not found in the object, then it is silently added to\n\t\tthe object and filled with a `null` value to make `key` a valid reference.\n\t\tIn case the value was `null` before, it is converted to an object.\n\n\t\t@param[in] key  key of the element to access\n\n\t\t@return reference to the element at key @a key\n\n\t\t@throw type_error.305 if the JSON value is not an object or null; in that\n\t\tcases, using the [] operator with a key makes no sense.\n\n\t\t@complexity Logarithmic in the size of the container.\n\n\t\t@liveexample{The example below shows how object elements can be read and\n\t\twritten using the `[]` operator.,operatorarray__key_type}\n\n\t\t@sa @ref at(const typename object_t::key_type&) for access by reference\n\t\twith range checking\n\t\t@sa @ref value() for access by value with a default value\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\treference operator[](const typename object_t::key_type& key)\n\t\t{\n\t\t\t// implicitly convert null value to an empty object\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::object;\n\t\t\t\tm_value.object = create<object_t>();\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\t// operator[] only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\treturn m_value.object->operator[](key);\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(305, \"cannot use operator[] with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief read-only access specified object element\n\n\t\tReturns a const reference to the element at with specified key @a key. No\n\t\tbounds checking is performed.\n\n\t\t@warning If the element with key @a key does not exist, the behavior is\n\t\tundefined.\n\n\t\t@param[in] key  key of the element to access\n\n\t\t@return const reference to the element at key @a key\n\n\t\t@pre The element with key @a key must exist. **This precondition is\n\t\tenforced with an assertion.**\n\n\t\t@throw type_error.305 if the JSON value is not an object; in that cases,\n\t\tusing the [] operator with a key makes no sense.\n\n\t\t@complexity Logarithmic in the size of the container.\n\n\t\t@liveexample{The example below shows how object elements can be read using\n\t\tthe `[]` operator.,operatorarray__key_type_const}\n\n\t\t@sa @ref at(const typename object_t::key_type&) for access by reference\n\t\twith range checking\n\t\t@sa @ref value() for access by value with a default value\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconst_reference operator[](const typename object_t::key_type& key) const\n\t\t{\n\t\t\t// const operator[] only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\tassert(m_value.object->find(key) != m_value.object->end());\n\t\t\t\treturn m_value.object->find(key)->second;\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(305, \"cannot use operator[] with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified object element\n\n\t\tReturns a reference to the element at with specified key @a key.\n\n\t\t@note If @a key is not found in the object, then it is silently added to\n\t\tthe object and filled with a `null` value to make `key` a valid reference.\n\t\tIn case the value was `null` before, it is converted to an object.\n\n\t\t@param[in] key  key of the element to access\n\n\t\t@return reference to the element at key @a key\n\n\t\t@throw type_error.305 if the JSON value is not an object or null; in that\n\t\tcases, using the [] operator with a key makes no sense.\n\n\t\t@complexity Logarithmic in the size of the container.\n\n\t\t@liveexample{The example below shows how object elements can be read and\n\t\twritten using the `[]` operator.,operatorarray__key_type}\n\n\t\t@sa @ref at(const typename object_t::key_type&) for access by reference\n\t\twith range checking\n\t\t@sa @ref value() for access by value with a default value\n\n\t\t@since version 1.1.0\n\t\t*/\n\t\ttemplate<typename T>\n\t\treference operator[](T* key)\n\t\t{\n\t\t\t// implicitly convert null to object\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::object;\n\t\t\t\tm_value = value_t::object;\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\t// at only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\treturn m_value.object->operator[](key);\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(305, \"cannot use operator[] with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief read-only access specified object element\n\n\t\tReturns a const reference to the element at with specified key @a key. No\n\t\tbounds checking is performed.\n\n\t\t@warning If the element with key @a key does not exist, the behavior is\n\t\tundefined.\n\n\t\t@param[in] key  key of the element to access\n\n\t\t@return const reference to the element at key @a key\n\n\t\t@pre The element with key @a key must exist. **This precondition is\n\t\tenforced with an assertion.**\n\n\t\t@throw type_error.305 if the JSON value is not an object; in that cases,\n\t\tusing the [] operator with a key makes no sense.\n\n\t\t@complexity Logarithmic in the size of the container.\n\n\t\t@liveexample{The example below shows how object elements can be read using\n\t\tthe `[]` operator.,operatorarray__key_type_const}\n\n\t\t@sa @ref at(const typename object_t::key_type&) for access by reference\n\t\twith range checking\n\t\t@sa @ref value() for access by value with a default value\n\n\t\t@since version 1.1.0\n\t\t*/\n\t\ttemplate<typename T>\n\t\tconst_reference operator[](T* key) const\n\t\t{\n\t\t\t// at only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\tassert(m_value.object->find(key) != m_value.object->end());\n\t\t\t\treturn m_value.object->find(key)->second;\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(305, \"cannot use operator[] with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified object element with default value\n\n\t\tReturns either a copy of an object's element at the specified key @a key\n\t\tor a given default value if no element with key @a key exists.\n\n\t\tThe function is basically equivalent to executing\n\t\t@code {.cpp}\n\t\ttry {\n\t\treturn at(key);\n\t\t} catch(out_of_range) {\n\t\treturn default_value;\n\t\t}\n\t\t@endcode\n\n\t\t@note Unlike @ref at(const typename object_t::key_type&), this function\n\t\tdoes not throw if the given key @a key was not found.\n\n\t\t@note Unlike @ref operator[](const typename object_t::key_type& key), this\n\t\tfunction does not implicitly add an element to the position defined by @a\n\t\tkey. This function is furthermore also applicable to const objects.\n\n\t\t@param[in] key  key of the element to access\n\t\t@param[in] default_value  the value to return if @a key is not found\n\n\t\t@tparam ValueType type compatible to JSON values, for instance `int` for\n\t\tJSON integer numbers, `bool` for JSON booleans, or `std::vector` types for\n\t\tJSON arrays. Note the type of the expected value at @a key and the default\n\t\tvalue @a default_value must be compatible.\n\n\t\t@return copy of the element at key @a key or @a default_value if @a key\n\t\tis not found\n\n\t\t@throw type_error.306 if the JSON value is not an objec; in that cases,\n\t\tusing `value()` with a key makes no sense.\n\n\t\t@complexity Logarithmic in the size of the container.\n\n\t\t@liveexample{The example below shows how object elements can be queried\n\t\twith a default value.,basic_json__value}\n\n\t\t@sa @ref at(const typename object_t::key_type&) for access by reference\n\t\twith range checking\n\t\t@sa @ref operator[](const typename object_t::key_type&) for unchecked\n\t\taccess by reference\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate<class ValueType, typename std::enable_if<\n\t\t\tstd::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>\n\t\t\tValueType value(const typename object_t::key_type& key, const ValueType& default_value) const\n\t\t{\n\t\t\t// at only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\t// if key is found, return value and given default value otherwise\n\t\t\t\tconst auto it = find(key);\n\t\t\t\tif (it != end())\n\t\t\t\t{\n\t\t\t\t\treturn *it;\n\t\t\t\t}\n\n\t\t\t\treturn default_value;\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(306, \"cannot use value() with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief overload for a default value of type const char*\n\t\t@copydoc basic_json::value(const typename object_t::key_type&, ValueType) const\n\t\t*/\n\t\tstring_t value(const typename object_t::key_type& key, const char* default_value) const\n\t\t{\n\t\t\treturn value(key, string_t(default_value));\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified object element via JSON Pointer with default value\n\n\t\tReturns either a copy of an object's element at the specified key @a key\n\t\tor a given default value if no element with key @a key exists.\n\n\t\tThe function is basically equivalent to executing\n\t\t@code {.cpp}\n\t\ttry {\n\t\treturn at(ptr);\n\t\t} catch(out_of_range) {\n\t\treturn default_value;\n\t\t}\n\t\t@endcode\n\n\t\t@note Unlike @ref at(const json_pointer&), this function does not throw\n\t\tif the given key @a key was not found.\n\n\t\t@param[in] ptr  a JSON pointer to the element to access\n\t\t@param[in] default_value  the value to return if @a ptr found no value\n\n\t\t@tparam ValueType type compatible to JSON values, for instance `int` for\n\t\tJSON integer numbers, `bool` for JSON booleans, or `std::vector` types for\n\t\tJSON arrays. Note the type of the expected value at @a key and the default\n\t\tvalue @a default_value must be compatible.\n\n\t\t@return copy of the element at key @a key or @a default_value if @a key\n\t\tis not found\n\n\t\t@throw type_error.306 if the JSON value is not an objec; in that cases,\n\t\tusing `value()` with a key makes no sense.\n\n\t\t@complexity Logarithmic in the size of the container.\n\n\t\t@liveexample{The example below shows how object elements can be queried\n\t\twith a default value.,basic_json__value_ptr}\n\n\t\t@sa @ref operator[](const json_pointer&) for unchecked access by reference\n\n\t\t@since version 2.0.2\n\t\t*/\n\t\ttemplate<class ValueType, typename std::enable_if<\n\t\t\tstd::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>\n\t\t\tValueType value(const json_pointer& ptr, const ValueType& default_value) const\n\t\t{\n\t\t\t// at only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\t// if pointer resolves a value, return it or use default value\n\t\t\t\tJSON_TRY\n\t\t\t\t{\n\t\t\t\t\treturn ptr.get_checked(this);\n\t\t\t\t}\n\t\t\t\t\tJSON_CATCH(out_of_range&)\n\t\t\t\t{\n\t\t\t\t\treturn default_value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(306, \"cannot use value() with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief overload for a default value of type const char*\n\t\t@copydoc basic_json::value(const json_pointer&, ValueType) const\n\t\t*/\n\t\tstring_t value(const json_pointer& ptr, const char* default_value) const\n\t\t{\n\t\t\treturn value(ptr, string_t(default_value));\n\t\t}\n\n\t\t/*!\n\t\t@brief access the first element\n\n\t\tReturns a reference to the first element in the container. For a JSON\n\t\tcontainer `c`, the expression `c.front()` is equivalent to `*c.begin()`.\n\n\t\t@return In case of a structured type (array or object), a reference to the\n\t\tfirst element is returned. In case of number, string, or boolean values, a\n\t\treference to the value is returned.\n\n\t\t@complexity Constant.\n\n\t\t@pre The JSON value must not be `null` (would throw `std::out_of_range`)\n\t\tor an empty array or object (undefined behavior, **guarded by\n\t\tassertions**).\n\t\t@post The JSON value remains unchanged.\n\n\t\t@throw invalid_iterator.214 when called on `null` value\n\n\t\t@liveexample{The following code shows an example for `front()`.,front}\n\n\t\t@sa @ref back() -- access the last element\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\treference front()\n\t\t{\n\t\t\treturn *begin();\n\t\t}\n\n\t\t/*!\n\t\t@copydoc basic_json::front()\n\t\t*/\n\t\tconst_reference front() const\n\t\t{\n\t\t\treturn *cbegin();\n\t\t}\n\n\t\t/*!\n\t\t@brief access the last element\n\n\t\tReturns a reference to the last element in the container. For a JSON\n\t\tcontainer `c`, the expression `c.back()` is equivalent to\n\t\t@code {.cpp}\n\t\tauto tmp = c.end();\n\t\t--tmp;\n\t\treturn *tmp;\n\t\t@endcode\n\n\t\t@return In case of a structured type (array or object), a reference to the\n\t\tlast element is returned. In case of number, string, or boolean values, a\n\t\treference to the value is returned.\n\n\t\t@complexity Constant.\n\n\t\t@pre The JSON value must not be `null` (would throw `std::out_of_range`)\n\t\tor an empty array or object (undefined behavior, **guarded by\n\t\tassertions**).\n\t\t@post The JSON value remains unchanged.\n\n\t\t@throw invalid_iterator.214 when called on a `null` value. See example\n\t\tbelow.\n\n\t\t@liveexample{The following code shows an example for `back()`.,back}\n\n\t\t@sa @ref front() -- access the first element\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\treference back()\n\t\t{\n\t\t\tauto tmp = end();\n\t\t\t--tmp;\n\t\t\treturn *tmp;\n\t\t}\n\n\t\t/*!\n\t\t@copydoc basic_json::back()\n\t\t*/\n\t\tconst_reference back() const\n\t\t{\n\t\t\tauto tmp = cend();\n\t\t\t--tmp;\n\t\t\treturn *tmp;\n\t\t}\n\n\t\t/*!\n\t\t@brief remove element given an iterator\n\n\t\tRemoves the element specified by iterator @a pos. The iterator @a pos must\n\t\tbe valid and dereferenceable. Thus the `end()` iterator (which is valid,\n\t\tbut is not dereferenceable) cannot be used as a value for @a pos.\n\n\t\tIf called on a primitive type other than `null`, the resulting JSON value\n\t\twill be `null`.\n\n\t\t@param[in] pos iterator to the element to remove\n\t\t@return Iterator following the last removed element. If the iterator @a\n\t\tpos refers to the last element, the `end()` iterator is returned.\n\n\t\t@tparam IteratorType an @ref iterator or @ref const_iterator\n\n\t\t@post Invalidates iterators and references at or after the point of the\n\t\terase, including the `end()` iterator.\n\n\t\t@throw type_error.307 if called on a `null` value; example: `\"cannot use\n\t\terase() with null\"`\n\t\t@throw invalid_iterator.202 if called on an iterator which does not belong\n\t\tto the current JSON value; example: `\"iterator does not fit current\n\t\tvalue\"`\n\t\t@throw invalid_iterator.205 if called on a primitive type with invalid\n\t\titerator (i.e., any iterator which is not `begin()`); example: `\"iterator\n\t\tout of range\"`\n\n\t\t@complexity The complexity depends on the type:\n\t\t- objects: amortized constant\n\t\t- arrays: linear in distance between @a pos and the end of the container\n\t\t- strings: linear in the length of the string\n\t\t- other types: constant\n\n\t\t@liveexample{The example shows the result of `erase()` for different JSON\n\t\ttypes.,erase__IteratorType}\n\n\t\t@sa @ref erase(IteratorType, IteratorType) -- removes the elements in\n\t\tthe given range\n\t\t@sa @ref erase(const typename object_t::key_type&) -- removes the element\n\t\tfrom an object at the given key\n\t\t@sa @ref erase(const size_type) -- removes the element from an array at\n\t\tthe given index\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate<class IteratorType, typename std::enable_if<\n\t\t\tstd::is_same<IteratorType, typename basic_json_t::iterator>::value or\n\t\t\tstd::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type\n\t\t\t= 0>\n\t\t\tIteratorType erase(IteratorType pos)\n\t\t{\n\t\t\t// make sure iterator fits the current value\n\t\t\tif (JSON_UNLIKELY(this != pos.m_object))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n\t\t\t}\n\n\t\t\tIteratorType result = end();\n\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase value_t::boolean:\n\t\t\tcase value_t::number_float:\n\t\t\tcase value_t::number_integer:\n\t\t\tcase value_t::number_unsigned:\n\t\t\tcase value_t::string:\n\t\t\t{\n\t\t\t\tif (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(205, \"iterator out of range\"));\n\t\t\t\t}\n\n\t\t\t\tif (is_string())\n\t\t\t\t{\n\t\t\t\t\tAllocatorType<string_t> alloc;\n\t\t\t\t\talloc.destroy(m_value.string);\n\t\t\t\t\talloc.deallocate(m_value.string, 1);\n\t\t\t\t\tm_value.string = nullptr;\n\t\t\t\t}\n\n\t\t\t\tm_type = value_t::null;\n\t\t\t\tassert_invariant();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::object:\n\t\t\t{\n\t\t\t\tresult.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::array:\n\t\t\t{\n\t\t\t\tresult.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(type_error::create(307, \"cannot use erase() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief remove elements given an iterator range\n\n\t\tRemoves the element specified by the range `[first; last)`. The iterator\n\t\t@a first does not need to be dereferenceable if `first == last`: erasing\n\t\tan empty range is a no-op.\n\n\t\tIf called on a primitive type other than `null`, the resulting JSON value\n\t\twill be `null`.\n\n\t\t@param[in] first iterator to the beginning of the range to remove\n\t\t@param[in] last iterator past the end of the range to remove\n\t\t@return Iterator following the last removed element. If the iterator @a\n\t\tsecond refers to the last element, the `end()` iterator is returned.\n\n\t\t@tparam IteratorType an @ref iterator or @ref const_iterator\n\n\t\t@post Invalidates iterators and references at or after the point of the\n\t\terase, including the `end()` iterator.\n\n\t\t@throw type_error.307 if called on a `null` value; example: `\"cannot use\n\t\terase() with null\"`\n\t\t@throw invalid_iterator.203 if called on iterators which does not belong\n\t\tto the current JSON value; example: `\"iterators do not fit current value\"`\n\t\t@throw invalid_iterator.204 if called on a primitive type with invalid\n\t\titerators (i.e., if `first != begin()` and `last != end()`); example:\n\t\t`\"iterators out of range\"`\n\n\t\t@complexity The complexity depends on the type:\n\t\t- objects: `log(size()) + std::distance(first, last)`\n\t\t- arrays: linear in the distance between @a first and @a last, plus linear\n\t\tin the distance between @a last and end of the container\n\t\t- strings: linear in the length of the string\n\t\t- other types: constant\n\n\t\t@liveexample{The example shows the result of `erase()` for different JSON\n\t\ttypes.,erase__IteratorType_IteratorType}\n\n\t\t@sa @ref erase(IteratorType) -- removes the element at a given position\n\t\t@sa @ref erase(const typename object_t::key_type&) -- removes the element\n\t\tfrom an object at the given key\n\t\t@sa @ref erase(const size_type) -- removes the element from an array at\n\t\tthe given index\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate<class IteratorType, typename std::enable_if<\n\t\t\tstd::is_same<IteratorType, typename basic_json_t::iterator>::value or\n\t\t\tstd::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type\n\t\t\t= 0>\n\t\t\tIteratorType erase(IteratorType first, IteratorType last)\n\t\t{\n\t\t\t// make sure iterator fits the current value\n\t\t\tif (JSON_UNLIKELY(this != first.m_object or this != last.m_object))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(203, \"iterators do not fit current value\"));\n\t\t\t}\n\n\t\t\tIteratorType result = end();\n\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase value_t::boolean:\n\t\t\tcase value_t::number_float:\n\t\t\tcase value_t::number_integer:\n\t\t\tcase value_t::number_unsigned:\n\t\t\tcase value_t::string:\n\t\t\t{\n\t\t\t\tif (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()\n\t\t\t\t\tor not last.m_it.primitive_iterator.is_end()))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(204, \"iterators out of range\"));\n\t\t\t\t}\n\n\t\t\t\tif (is_string())\n\t\t\t\t{\n\t\t\t\t\tAllocatorType<string_t> alloc;\n\t\t\t\t\talloc.destroy(m_value.string);\n\t\t\t\t\talloc.deallocate(m_value.string, 1);\n\t\t\t\t\tm_value.string = nullptr;\n\t\t\t\t}\n\n\t\t\t\tm_type = value_t::null;\n\t\t\t\tassert_invariant();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::object:\n\t\t\t{\n\t\t\t\tresult.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,\n\t\t\t\t\tlast.m_it.object_iterator);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::array:\n\t\t\t{\n\t\t\t\tresult.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,\n\t\t\t\t\tlast.m_it.array_iterator);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(type_error::create(307, \"cannot use erase() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief remove element from a JSON object given a key\n\n\t\tRemoves elements from a JSON object with the key value @a key.\n\n\t\t@param[in] key value of the elements to remove\n\n\t\t@return Number of elements removed. If @a ObjectType is the default\n\t\t`std::map` type, the return value will always be `0` (@a key was not\n\t\tfound) or `1` (@a key was found).\n\n\t\t@post References and iterators to the erased elements are invalidated.\n\t\tOther references and iterators are not affected.\n\n\t\t@throw type_error.307 when called on a type other than JSON object;\n\t\texample: `\"cannot use erase() with null\"`\n\n\t\t@complexity `log(size()) + count(key)`\n\n\t\t@liveexample{The example shows the effect of `erase()`.,erase__key_type}\n\n\t\t@sa @ref erase(IteratorType) -- removes the element at a given position\n\t\t@sa @ref erase(IteratorType, IteratorType) -- removes the elements in\n\t\tthe given range\n\t\t@sa @ref erase(const size_type) -- removes the element from an array at\n\t\tthe given index\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tsize_type erase(const typename object_t::key_type& key)\n\t\t{\n\t\t\t// this erase only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\treturn m_value.object->erase(key);\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(307, \"cannot use erase() with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief remove element from a JSON array given an index\n\n\t\tRemoves element from a JSON array at the index @a idx.\n\n\t\t@param[in] idx index of the element to remove\n\n\t\t@throw type_error.307 when called on a type other than JSON object;\n\t\texample: `\"cannot use erase() with null\"`\n\t\t@throw out_of_range.401 when `idx >= size()`; example: `\"array index 17\n\t\tis out of range\"`\n\n\t\t@complexity Linear in distance between @a idx and the end of the container.\n\n\t\t@liveexample{The example shows the effect of `erase()`.,erase__size_type}\n\n\t\t@sa @ref erase(IteratorType) -- removes the element at a given position\n\t\t@sa @ref erase(IteratorType, IteratorType) -- removes the elements in\n\t\tthe given range\n\t\t@sa @ref erase(const typename object_t::key_type&) -- removes the element\n\t\tfrom an object at the given key\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tvoid erase(const size_type idx)\n\t\t{\n\t\t\t// this erase only works for arrays\n\t\t\tif (JSON_LIKELY(is_array()))\n\t\t\t{\n\t\t\t\tif (JSON_UNLIKELY(idx >= size()))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(out_of_range::create(401, \"array index \" + std::to_string(idx) + \" is out of range\"));\n\t\t\t\t}\n\n\t\t\t\tm_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(307, \"cannot use erase() with \" + std::string(type_name())));\n\t\t\t}\n\t\t}\n\n\t\t/// @}\n\n\n\t\t////////////\n\t\t// lookup //\n\t\t////////////\n\n\t\t/// @name lookup\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief find an element in a JSON object\n\n\t\tFinds an element in a JSON object with key equivalent to @a key. If the\n\t\telement is not found or the JSON value is not an object, end() is\n\t\treturned.\n\n\t\t@note This method always returns @ref end() when executed on a JSON type\n\t\tthat is not an object.\n\n\t\t@param[in] key key value of the element to search for.\n\n\t\t@return Iterator to an element with key equivalent to @a key. If no such\n\t\telement is found or the JSON value is not an object, past-the-end (see\n\t\t@ref end()) iterator is returned.\n\n\t\t@complexity Logarithmic in the size of the JSON object.\n\n\t\t@liveexample{The example shows how `find()` is used.,find__key_type}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate<typename KeyT>\n\t\titerator find(KeyT&& key)\n\t\t{\n\t\t\tauto result = end();\n\n\t\t\tif (is_object())\n\t\t\t{\n\t\t\t\tresult.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief find an element in a JSON object\n\t\t@copydoc find(KeyT&&)\n\t\t*/\n\t\ttemplate<typename KeyT>\n\t\tconst_iterator find(KeyT&& key) const\n\t\t{\n\t\t\tauto result = cend();\n\n\t\t\tif (is_object())\n\t\t\t{\n\t\t\t\tresult.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief returns the number of occurrences of a key in a JSON object\n\n\t\tReturns the number of elements with key @a key. If ObjectType is the\n\t\tdefault `std::map` type, the return value will always be `0` (@a key was\n\t\tnot found) or `1` (@a key was found).\n\n\t\t@note This method always returns `0` when executed on a JSON type that is\n\t\tnot an object.\n\n\t\t@param[in] key key value of the element to count\n\n\t\t@return Number of elements with key @a key. If the JSON value is not an\n\t\tobject, the return value will be `0`.\n\n\t\t@complexity Logarithmic in the size of the JSON object.\n\n\t\t@liveexample{The example shows how `count()` is used.,count}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\ttemplate<typename KeyT>\n\t\tsize_type count(KeyT&& key) const\n\t\t{\n\t\t\t// return 0 for all nonobject types\n\t\t\treturn is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;\n\t\t}\n\n\t\t/// @}\n\n\n\t\t///////////////\n\t\t// iterators //\n\t\t///////////////\n\n\t\t/// @name iterators\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief returns an iterator to the first element\n\n\t\tReturns an iterator to the first element.\n\n\t\t@image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n\t\t@return iterator to the first element\n\n\t\t@complexity Constant.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is constant.\n\n\t\t@liveexample{The following code shows an example for `begin()`.,begin}\n\n\t\t@sa @ref cbegin() -- returns a const iterator to the beginning\n\t\t@sa @ref end() -- returns an iterator to the end\n\t\t@sa @ref cend() -- returns a const iterator to the end\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\titerator begin() noexcept\n\t\t{\n\t\t\titerator result(this);\n\t\t\tresult.set_begin();\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@copydoc basic_json::cbegin()\n\t\t*/\n\t\tconst_iterator begin() const noexcept\n\t\t{\n\t\t\treturn cbegin();\n\t\t}\n\n\t\t/*!\n\t\t@brief returns a const iterator to the first element\n\n\t\tReturns a const iterator to the first element.\n\n\t\t@image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n\t\t@return const iterator to the first element\n\n\t\t@complexity Constant.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is constant.\n\t\t- Has the semantics of `const_cast<const basic_json&>(*this).begin()`.\n\n\t\t@liveexample{The following code shows an example for `cbegin()`.,cbegin}\n\n\t\t@sa @ref begin() -- returns an iterator to the beginning\n\t\t@sa @ref end() -- returns an iterator to the end\n\t\t@sa @ref cend() -- returns a const iterator to the end\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconst_iterator cbegin() const noexcept\n\t\t{\n\t\t\tconst_iterator result(this);\n\t\t\tresult.set_begin();\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief returns an iterator to one past the last element\n\n\t\tReturns an iterator to one past the last element.\n\n\t\t@image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n\t\t@return iterator one past the last element\n\n\t\t@complexity Constant.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is constant.\n\n\t\t@liveexample{The following code shows an example for `end()`.,end}\n\n\t\t@sa @ref cend() -- returns a const iterator to the end\n\t\t@sa @ref begin() -- returns an iterator to the beginning\n\t\t@sa @ref cbegin() -- returns a const iterator to the beginning\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\titerator end() noexcept\n\t\t{\n\t\t\titerator result(this);\n\t\t\tresult.set_end();\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@copydoc basic_json::cend()\n\t\t*/\n\t\tconst_iterator end() const noexcept\n\t\t{\n\t\t\treturn cend();\n\t\t}\n\n\t\t/*!\n\t\t@brief returns a const iterator to one past the last element\n\n\t\tReturns a const iterator to one past the last element.\n\n\t\t@image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n\t\t@return const iterator one past the last element\n\n\t\t@complexity Constant.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is constant.\n\t\t- Has the semantics of `const_cast<const basic_json&>(*this).end()`.\n\n\t\t@liveexample{The following code shows an example for `cend()`.,cend}\n\n\t\t@sa @ref end() -- returns an iterator to the end\n\t\t@sa @ref begin() -- returns an iterator to the beginning\n\t\t@sa @ref cbegin() -- returns a const iterator to the beginning\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconst_iterator cend() const noexcept\n\t\t{\n\t\t\tconst_iterator result(this);\n\t\t\tresult.set_end();\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief returns an iterator to the reverse-beginning\n\n\t\tReturns an iterator to the reverse-beginning; that is, the last element.\n\n\t\t@image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n\t\t@complexity Constant.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\n\t\trequirements:\n\t\t- The complexity is constant.\n\t\t- Has the semantics of `reverse_iterator(end())`.\n\n\t\t@liveexample{The following code shows an example for `rbegin()`.,rbegin}\n\n\t\t@sa @ref crbegin() -- returns a const reverse iterator to the beginning\n\t\t@sa @ref rend() -- returns a reverse iterator to the end\n\t\t@sa @ref crend() -- returns a const reverse iterator to the end\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\treverse_iterator rbegin() noexcept\n\t\t{\n\t\t\treturn reverse_iterator(end());\n\t\t}\n\n\t\t/*!\n\t\t@copydoc basic_json::crbegin()\n\t\t*/\n\t\tconst_reverse_iterator rbegin() const noexcept\n\t\t{\n\t\t\treturn crbegin();\n\t\t}\n\n\t\t/*!\n\t\t@brief returns an iterator to the reverse-end\n\n\t\tReturns an iterator to the reverse-end; that is, one before the first\n\t\telement.\n\n\t\t@image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n\t\t@complexity Constant.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\n\t\trequirements:\n\t\t- The complexity is constant.\n\t\t- Has the semantics of `reverse_iterator(begin())`.\n\n\t\t@liveexample{The following code shows an example for `rend()`.,rend}\n\n\t\t@sa @ref crend() -- returns a const reverse iterator to the end\n\t\t@sa @ref rbegin() -- returns a reverse iterator to the beginning\n\t\t@sa @ref crbegin() -- returns a const reverse iterator to the beginning\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\treverse_iterator rend() noexcept\n\t\t{\n\t\t\treturn reverse_iterator(begin());\n\t\t}\n\n\t\t/*!\n\t\t@copydoc basic_json::crend()\n\t\t*/\n\t\tconst_reverse_iterator rend() const noexcept\n\t\t{\n\t\t\treturn crend();\n\t\t}\n\n\t\t/*!\n\t\t@brief returns a const reverse iterator to the last element\n\n\t\tReturns a const iterator to the reverse-beginning; that is, the last\n\t\telement.\n\n\t\t@image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n\t\t@complexity Constant.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\n\t\trequirements:\n\t\t- The complexity is constant.\n\t\t- Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.\n\n\t\t@liveexample{The following code shows an example for `crbegin()`.,crbegin}\n\n\t\t@sa @ref rbegin() -- returns a reverse iterator to the beginning\n\t\t@sa @ref rend() -- returns a reverse iterator to the end\n\t\t@sa @ref crend() -- returns a const reverse iterator to the end\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconst_reverse_iterator crbegin() const noexcept\n\t\t{\n\t\t\treturn const_reverse_iterator(cend());\n\t\t}\n\n\t\t/*!\n\t\t@brief returns a const reverse iterator to one before the first\n\n\t\tReturns a const reverse iterator to the reverse-end; that is, one before\n\t\tthe first element.\n\n\t\t@image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n\t\t@complexity Constant.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\n\t\trequirements:\n\t\t- The complexity is constant.\n\t\t- Has the semantics of `const_cast<const basic_json&>(*this).rend()`.\n\n\t\t@liveexample{The following code shows an example for `crend()`.,crend}\n\n\t\t@sa @ref rend() -- returns a reverse iterator to the end\n\t\t@sa @ref rbegin() -- returns a reverse iterator to the beginning\n\t\t@sa @ref crbegin() -- returns a const reverse iterator to the beginning\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tconst_reverse_iterator crend() const noexcept\n\t\t{\n\t\t\treturn const_reverse_iterator(cbegin());\n\t\t}\n\n\tpublic:\n\t\t/*!\n\t\t@brief wrapper to access iterator member functions in range-based for\n\n\t\tThis function allows to access @ref iterator::key() and @ref\n\t\titerator::value() during range-based for loops. In these loops, a\n\t\treference to the JSON values is returned, so there is no access to the\n\t\tunderlying iterator.\n\n\t\t@liveexample{The following code shows how the wrapper is used,iterator_wrapper}\n\n\t\t@note The name of this function is not yet final and may change in the\n\t\tfuture.\n\t\t*/\n\t\tstatic iteration_proxy<iterator> iterator_wrapper(reference cont)\n\t\t{\n\t\t\treturn iteration_proxy<iterator>(cont);\n\t\t}\n\n\t\t/*!\n\t\t@copydoc iterator_wrapper(reference)\n\t\t*/\n\t\tstatic iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)\n\t\t{\n\t\t\treturn iteration_proxy<const_iterator>(cont);\n\t\t}\n\n\t\t/// @}\n\n\n\t\t//////////////\n\t\t// capacity //\n\t\t//////////////\n\n\t\t/// @name capacity\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief checks whether the container is empty.\n\n\t\tChecks if a JSON value has no elements (i.e. whether its @ref size is `0`).\n\n\t\t@return The return value depends on the different types and is\n\t\tdefined as follows:\n\t\tValue type  | return value\n\t\t----------- | -------------\n\t\tnull        | `true`\n\t\tboolean     | `false`\n\t\tstring      | `false`\n\t\tnumber      | `false`\n\t\tobject      | result of function `object_t::empty()`\n\t\tarray       | result of function `array_t::empty()`\n\n\t\t@liveexample{The following code uses `empty()` to check if a JSON\n\t\tobject contains any elements.,empty}\n\n\t\t@complexity Constant, as long as @ref array_t and @ref object_t satisfy\n\t\tthe Container concept; that is, their `empty()` functions have constant\n\t\tcomplexity.\n\n\t\t@iterators No changes.\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@note This function does not return whether a string stored as JSON value\n\t\tis empty - it returns whether the JSON container itself is empty which is\n\t\tfalse in the case of a string.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is constant.\n\t\t- Has the semantics of `begin() == end()`.\n\n\t\t@sa @ref size() -- returns the number of elements\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tbool empty() const noexcept\n\t\t{\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase value_t::null:\n\t\t\t{\n\t\t\t\t// null values are empty\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tcase value_t::array:\n\t\t\t{\n\t\t\t\t// delegate call to array_t::empty()\n\t\t\t\treturn m_value.array->empty();\n\t\t\t}\n\n\t\t\tcase value_t::object:\n\t\t\t{\n\t\t\t\t// delegate call to object_t::empty()\n\t\t\t\treturn m_value.object->empty();\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t{\n\t\t\t\t// all other types are nonempty\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief returns the number of elements\n\n\t\tReturns the number of elements in a JSON value.\n\n\t\t@return The return value depends on the different types and is\n\t\tdefined as follows:\n\t\tValue type  | return value\n\t\t----------- | -------------\n\t\tnull        | `0`\n\t\tboolean     | `1`\n\t\tstring      | `1`\n\t\tnumber      | `1`\n\t\tobject      | result of function object_t::size()\n\t\tarray       | result of function array_t::size()\n\n\t\t@liveexample{The following code calls `size()` on the different value\n\t\ttypes.,size}\n\n\t\t@complexity Constant, as long as @ref array_t and @ref object_t satisfy\n\t\tthe Container concept; that is, their size() functions have constant\n\t\tcomplexity.\n\n\t\t@iterators No changes.\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@note This function does not return the length of a string stored as JSON\n\t\tvalue - it returns the number of elements in the JSON value which is 1 in\n\t\tthe case of a string.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is constant.\n\t\t- Has the semantics of `std::distance(begin(), end())`.\n\n\t\t@sa @ref empty() -- checks whether the container is empty\n\t\t@sa @ref max_size() -- returns the maximal number of elements\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tsize_type size() const noexcept\n\t\t{\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase value_t::null:\n\t\t\t{\n\t\t\t\t// null values are empty\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tcase value_t::array:\n\t\t\t{\n\t\t\t\t// delegate call to array_t::size()\n\t\t\t\treturn m_value.array->size();\n\t\t\t}\n\n\t\t\tcase value_t::object:\n\t\t\t{\n\t\t\t\t// delegate call to object_t::size()\n\t\t\t\treturn m_value.object->size();\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t{\n\t\t\t\t// all other types have size 1\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief returns the maximum possible number of elements\n\n\t\tReturns the maximum number of elements a JSON value is able to hold due to\n\t\tsystem or library implementation limitations, i.e. `std::distance(begin(),\n\t\tend())` for the JSON value.\n\n\t\t@return The return value depends on the different types and is\n\t\tdefined as follows:\n\t\tValue type  | return value\n\t\t----------- | -------------\n\t\tnull        | `0` (same as `size()`)\n\t\tboolean     | `1` (same as `size()`)\n\t\tstring      | `1` (same as `size()`)\n\t\tnumber      | `1` (same as `size()`)\n\t\tobject      | result of function `object_t::max_size()`\n\t\tarray       | result of function `array_t::max_size()`\n\n\t\t@liveexample{The following code calls `max_size()` on the different value\n\t\ttypes. Note the output is implementation specific.,max_size}\n\n\t\t@complexity Constant, as long as @ref array_t and @ref object_t satisfy\n\t\tthe Container concept; that is, their `max_size()` functions have constant\n\t\tcomplexity.\n\n\t\t@iterators No changes.\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@requirement This function helps `basic_json` satisfying the\n\t\t[Container](http://en.cppreference.com/w/cpp/concept/Container)\n\t\trequirements:\n\t\t- The complexity is constant.\n\t\t- Has the semantics of returning `b.size()` where `b` is the largest\n\t\tpossible JSON value.\n\n\t\t@sa @ref size() -- returns the number of elements\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tsize_type max_size() const noexcept\n\t\t{\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase value_t::array:\n\t\t\t{\n\t\t\t\t// delegate call to array_t::max_size()\n\t\t\t\treturn m_value.array->max_size();\n\t\t\t}\n\n\t\t\tcase value_t::object:\n\t\t\t{\n\t\t\t\t// delegate call to object_t::max_size()\n\t\t\t\treturn m_value.object->max_size();\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t{\n\t\t\t\t// all other types have max_size() == size()\n\t\t\t\treturn size();\n\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/// @}\n\n\n\t\t///////////////\n\t\t// modifiers //\n\t\t///////////////\n\n\t\t/// @name modifiers\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief clears the contents\n\n\t\tClears the content of a JSON value and resets it to the default value as\n\t\tif @ref basic_json(value_t) would have been called with the current value\n\t\ttype from @ref type():\n\n\t\tValue type  | initial value\n\t\t----------- | -------------\n\t\tnull        | `null`\n\t\tboolean     | `false`\n\t\tstring      | `\"\"`\n\t\tnumber      | `0`\n\t\tobject      | `{}`\n\t\tarray       | `[]`\n\n\t\t@post Has the same effect as calling\n\t\t@code {.cpp}\n\t\t*this = basic_json(type());\n\t\t@endcode\n\n\t\t@liveexample{The example below shows the effect of `clear()` to different\n\t\tJSON types.,clear}\n\n\t\t@complexity Linear in the size of the JSON value.\n\n\t\t@iterators All iterators, pointers and references related to this container\n\t\tare invalidated.\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@sa @ref basic_json(value_t) -- constructor that creates an object with the\n\t\tsame value than calling `clear()`\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tvoid clear() noexcept\n\t\t{\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase value_t::number_integer:\n\t\t\t{\n\t\t\t\tm_value.number_integer = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::number_unsigned:\n\t\t\t{\n\t\t\t\tm_value.number_unsigned = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::number_float:\n\t\t\t{\n\t\t\t\tm_value.number_float = 0.0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::boolean:\n\t\t\t{\n\t\t\t\tm_value.boolean = false;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::string:\n\t\t\t{\n\t\t\t\tm_value.string->clear();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::array:\n\t\t\t{\n\t\t\t\tm_value.array->clear();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase value_t::object:\n\t\t\t{\n\t\t\t\tm_value.object->clear();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an array\n\n\t\tAppends the given element @a val to the end of the JSON value. If the\n\t\tfunction is called on a JSON null value, an empty array is created before\n\t\tappending @a val.\n\n\t\t@param[in] val the value to add to the JSON array\n\n\t\t@throw type_error.308 when called on a type other than JSON array or\n\t\tnull; example: `\"cannot use push_back() with number\"`\n\n\t\t@complexity Amortized constant.\n\n\t\t@liveexample{The example shows how `push_back()` and `+=` can be used to\n\t\tadd elements to a JSON array. Note how the `null` value was silently\n\t\tconverted to a JSON array.,push_back}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tvoid push_back(basic_json&& val)\n\t\t{\n\t\t\t// push_back only works for null objects or arrays\n\t\t\tif (JSON_UNLIKELY(not(is_null() or is_array())))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(308, \"cannot use push_back() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\t// transform null object into an array\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::array;\n\t\t\t\tm_value = value_t::array;\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\t// add element to array (move semantics)\n\t\t\tm_value.array->push_back(std::move(val));\n\t\t\t// invalidate object\n\t\t\tval.m_type = value_t::null;\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an array\n\t\t@copydoc push_back(basic_json&&)\n\t\t*/\n\t\treference operator+=(basic_json&& val)\n\t\t{\n\t\t\tpush_back(std::move(val));\n\t\t\treturn *this;\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an array\n\t\t@copydoc push_back(basic_json&&)\n\t\t*/\n\t\tvoid push_back(const basic_json& val)\n\t\t{\n\t\t\t// push_back only works for null objects or arrays\n\t\t\tif (JSON_UNLIKELY(not(is_null() or is_array())))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(308, \"cannot use push_back() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\t// transform null object into an array\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::array;\n\t\t\t\tm_value = value_t::array;\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\t// add element to array\n\t\t\tm_value.array->push_back(val);\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an array\n\t\t@copydoc push_back(basic_json&&)\n\t\t*/\n\t\treference operator+=(const basic_json& val)\n\t\t{\n\t\t\tpush_back(val);\n\t\t\treturn *this;\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an object\n\n\t\tInserts the given element @a val to the JSON object. If the function is\n\t\tcalled on a JSON null value, an empty object is created before inserting\n\t\t@a val.\n\n\t\t@param[in] val the value to add to the JSON object\n\n\t\t@throw type_error.308 when called on a type other than JSON object or\n\t\tnull; example: `\"cannot use push_back() with number\"`\n\n\t\t@complexity Logarithmic in the size of the container, O(log(`size()`)).\n\n\t\t@liveexample{The example shows how `push_back()` and `+=` can be used to\n\t\tadd elements to a JSON object. Note how the `null` value was silently\n\t\tconverted to a JSON object.,push_back__object_t__value}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tvoid push_back(const typename object_t::value_type& val)\n\t\t{\n\t\t\t// push_back only works for null objects or objects\n\t\t\tif (JSON_UNLIKELY(not(is_null() or is_object())))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(308, \"cannot use push_back() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\t// transform null object into an object\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::object;\n\t\t\t\tm_value = value_t::object;\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\t// add element to array\n\t\t\tm_value.object->insert(val);\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an object\n\t\t@copydoc push_back(const typename object_t::value_type&)\n\t\t*/\n\t\treference operator+=(const typename object_t::value_type& val)\n\t\t{\n\t\t\tpush_back(val);\n\t\t\treturn *this;\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an object\n\n\t\tThis function allows to use `push_back` with an initializer list. In case\n\n\t\t1. the current value is an object,\n\t\t2. the initializer list @a init contains only two elements, and\n\t\t3. the first element of @a init is a string,\n\n\t\t@a init is converted into an object element and added using\n\t\t@ref push_back(const typename object_t::value_type&). Otherwise, @a init\n\t\tis converted to a JSON value and added using @ref push_back(basic_json&&).\n\n\t\t@param[in] init  an initializer list\n\n\t\t@complexity Linear in the size of the initializer list @a init.\n\n\t\t@note This function is required to resolve an ambiguous overload error,\n\t\tbecause pairs like `{\"key\", \"value\"}` can be both interpreted as\n\t\t`object_t::value_type` or `std::initializer_list<basic_json>`, see\n\t\thttps://github.com/nlohmann/json/issues/235 for more information.\n\n\t\t@liveexample{The example shows how initializer lists are treated as\n\t\tobjects when possible.,push_back__initializer_list}\n\t\t*/\n\t\tvoid push_back(initializer_list_t init)\n\t\t{\n\t\t\tif (is_object() and init.size() == 2 and (*init.begin())->is_string())\n\t\t\t{\n\t\t\t\tbasic_json&& key = init.begin()->moved_or_copied();\n\t\t\t\tpush_back(typename object_t::value_type(\n\t\t\t\t\tstd::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpush_back(basic_json(init));\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an object\n\t\t@copydoc push_back(initializer_list_t)\n\t\t*/\n\t\treference operator+=(initializer_list_t init)\n\t\t{\n\t\t\tpush_back(init);\n\t\t\treturn *this;\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an array\n\n\t\tCreates a JSON value from the passed parameters @a args to the end of the\n\t\tJSON value. If the function is called on a JSON null value, an empty array\n\t\tis created before appending the value created from @a args.\n\n\t\t@param[in] args arguments to forward to a constructor of @ref basic_json\n\t\t@tparam Args compatible types to create a @ref basic_json object\n\n\t\t@throw type_error.311 when called on a type other than JSON array or\n\t\tnull; example: `\"cannot use emplace_back() with number\"`\n\n\t\t@complexity Amortized constant.\n\n\t\t@liveexample{The example shows how `push_back()` can be used to add\n\t\telements to a JSON array. Note how the `null` value was silently converted\n\t\tto a JSON array.,emplace_back}\n\n\t\t@since version 2.0.8\n\t\t*/\n\t\ttemplate<class... Args>\n\t\tvoid emplace_back(Args&& ... args)\n\t\t{\n\t\t\t// emplace_back only works for null objects or arrays\n\t\t\tif (JSON_UNLIKELY(not(is_null() or is_array())))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(311, \"cannot use emplace_back() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\t// transform null object into an array\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::array;\n\t\t\t\tm_value = value_t::array;\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\t// add element to array (perfect forwarding)\n\t\t\tm_value.array->emplace_back(std::forward<Args>(args)...);\n\t\t}\n\n\t\t/*!\n\t\t@brief add an object to an object if key does not exist\n\n\t\tInserts a new element into a JSON object constructed in-place with the\n\t\tgiven @a args if there is no element with the key in the container. If the\n\t\tfunction is called on a JSON null value, an empty object is created before\n\t\tappending the value created from @a args.\n\n\t\t@param[in] args arguments to forward to a constructor of @ref basic_json\n\t\t@tparam Args compatible types to create a @ref basic_json object\n\n\t\t@return a pair consisting of an iterator to the inserted element, or the\n\t\talready-existing element if no insertion happened, and a bool\n\t\tdenoting whether the insertion took place.\n\n\t\t@throw type_error.311 when called on a type other than JSON object or\n\t\tnull; example: `\"cannot use emplace() with number\"`\n\n\t\t@complexity Logarithmic in the size of the container, O(log(`size()`)).\n\n\t\t@liveexample{The example shows how `emplace()` can be used to add elements\n\t\tto a JSON object. Note how the `null` value was silently converted to a\n\t\tJSON object. Further note how no value is added if there was already one\n\t\tvalue stored with the same key.,emplace}\n\n\t\t@since version 2.0.8\n\t\t*/\n\t\ttemplate<class... Args>\n\t\tstd::pair<iterator, bool> emplace(Args&& ... args)\n\t\t{\n\t\t\t// emplace only works for null objects or arrays\n\t\t\tif (JSON_UNLIKELY(not(is_null() or is_object())))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(311, \"cannot use emplace() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\t// transform null object into an object\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::object;\n\t\t\t\tm_value = value_t::object;\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\t// add element to array (perfect forwarding)\n\t\t\tauto res = m_value.object->emplace(std::forward<Args>(args)...);\n\t\t\t// create result iterator and set iterator to the result of emplace\n\t\t\tauto it = begin();\n\t\t\tit.m_it.object_iterator = res.first;\n\n\t\t\t// return pair of iterator and boolean\n\t\t\treturn { it, res.second };\n\t\t}\n\n\t\t/*!\n\t\t@brief inserts element\n\n\t\tInserts element @a val before iterator @a pos.\n\n\t\t@param[in] pos iterator before which the content will be inserted; may be\n\t\tthe end() iterator\n\t\t@param[in] val element to insert\n\t\t@return iterator pointing to the inserted @a val.\n\n\t\t@throw type_error.309 if called on JSON values other than arrays;\n\t\texample: `\"cannot use insert() with string\"`\n\t\t@throw invalid_iterator.202 if @a pos is not an iterator of *this;\n\t\texample: `\"iterator does not fit current value\"`\n\n\t\t@complexity Constant plus linear in the distance between @a pos and end of\n\t\tthe container.\n\n\t\t@liveexample{The example shows how `insert()` is used.,insert}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\titerator insert(const_iterator pos, const basic_json& val)\n\t\t{\n\t\t\t// insert only works for arrays\n\t\t\tif (JSON_LIKELY(is_array()))\n\t\t\t{\n\t\t\t\t// check if iterator pos fits to this JSON value\n\t\t\t\tif (JSON_UNLIKELY(pos.m_object != this))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n\t\t\t\t}\n\n\t\t\t\t// insert to array and return iterator\n\t\t\t\titerator result(this);\n\t\t\t\tresult.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief inserts element\n\t\t@copydoc insert(const_iterator, const basic_json&)\n\t\t*/\n\t\titerator insert(const_iterator pos, basic_json&& val)\n\t\t{\n\t\t\treturn insert(pos, val);\n\t\t}\n\n\t\t/*!\n\t\t@brief inserts elements\n\n\t\tInserts @a cnt copies of @a val before iterator @a pos.\n\n\t\t@param[in] pos iterator before which the content will be inserted; may be\n\t\tthe end() iterator\n\t\t@param[in] cnt number of copies of @a val to insert\n\t\t@param[in] val element to insert\n\t\t@return iterator pointing to the first element inserted, or @a pos if\n\t\t`cnt==0`\n\n\t\t@throw type_error.309 if called on JSON values other than arrays; example:\n\t\t`\"cannot use insert() with string\"`\n\t\t@throw invalid_iterator.202 if @a pos is not an iterator of *this;\n\t\texample: `\"iterator does not fit current value\"`\n\n\t\t@complexity Linear in @a cnt plus linear in the distance between @a pos\n\t\tand end of the container.\n\n\t\t@liveexample{The example shows how `insert()` is used.,insert__count}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\titerator insert(const_iterator pos, size_type cnt, const basic_json& val)\n\t\t{\n\t\t\t// insert only works for arrays\n\t\t\tif (JSON_LIKELY(is_array()))\n\t\t\t{\n\t\t\t\t// check if iterator pos fits to this JSON value\n\t\t\t\tif (JSON_UNLIKELY(pos.m_object != this))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n\t\t\t\t}\n\n\t\t\t\t// insert to array and return iterator\n\t\t\t\titerator result(this);\n\t\t\t\tresult.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tJSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n\t\t}\n\n\t\t/*!\n\t\t@brief inserts elements\n\n\t\tInserts elements from range `[first, last)` before iterator @a pos.\n\n\t\t@param[in] pos iterator before which the content will be inserted; may be\n\t\tthe end() iterator\n\t\t@param[in] first begin of the range of elements to insert\n\t\t@param[in] last end of the range of elements to insert\n\n\t\t@throw type_error.309 if called on JSON values other than arrays; example:\n\t\t`\"cannot use insert() with string\"`\n\t\t@throw invalid_iterator.202 if @a pos is not an iterator of *this;\n\t\texample: `\"iterator does not fit current value\"`\n\t\t@throw invalid_iterator.210 if @a first and @a last do not belong to the\n\t\tsame JSON value; example: `\"iterators do not fit\"`\n\t\t@throw invalid_iterator.211 if @a first or @a last are iterators into\n\t\tcontainer for which insert is called; example: `\"passed iterators may not\n\t\tbelong to container\"`\n\n\t\t@return iterator pointing to the first element inserted, or @a pos if\n\t\t`first==last`\n\n\t\t@complexity Linear in `std::distance(first, last)` plus linear in the\n\t\tdistance between @a pos and end of the container.\n\n\t\t@liveexample{The example shows how `insert()` is used.,insert__range}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\titerator insert(const_iterator pos, const_iterator first, const_iterator last)\n\t\t{\n\t\t\t// insert only works for arrays\n\t\t\tif (JSON_UNLIKELY(not is_array()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\t// check if iterator pos fits to this JSON value\n\t\t\tif (JSON_UNLIKELY(pos.m_object != this))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n\t\t\t}\n\n\t\t\t// check if range iterators belong to the same JSON object\n\t\t\tif (JSON_UNLIKELY(first.m_object != last.m_object))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(210, \"iterators do not fit\"));\n\t\t\t}\n\n\t\t\tif (JSON_UNLIKELY(first.m_object == this))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(211, \"passed iterators may not belong to container\"));\n\t\t\t}\n\n\t\t\t// insert to array and return iterator\n\t\t\titerator result(this);\n\t\t\tresult.m_it.array_iterator = m_value.array->insert(\n\t\t\t\tpos.m_it.array_iterator,\n\t\t\t\tfirst.m_it.array_iterator,\n\t\t\t\tlast.m_it.array_iterator);\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief inserts elements\n\n\t\tInserts elements from initializer list @a ilist before iterator @a pos.\n\n\t\t@param[in] pos iterator before which the content will be inserted; may be\n\t\tthe end() iterator\n\t\t@param[in] ilist initializer list to insert the values from\n\n\t\t@throw type_error.309 if called on JSON values other than arrays; example:\n\t\t`\"cannot use insert() with string\"`\n\t\t@throw invalid_iterator.202 if @a pos is not an iterator of *this;\n\t\texample: `\"iterator does not fit current value\"`\n\n\t\t@return iterator pointing to the first element inserted, or @a pos if\n\t\t`ilist` is empty\n\n\t\t@complexity Linear in `ilist.size()` plus linear in the distance between\n\t\t@a pos and end of the container.\n\n\t\t@liveexample{The example shows how `insert()` is used.,insert__ilist}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\titerator insert(const_iterator pos, initializer_list_t ilist)\n\t\t{\n\t\t\t// insert only works for arrays\n\t\t\tif (JSON_UNLIKELY(not is_array()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\t// check if iterator pos fits to this JSON value\n\t\t\tif (JSON_UNLIKELY(pos.m_object != this))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n\t\t\t}\n\n\t\t\t// insert to array and return iterator\n\t\t\titerator result(this);\n\t\t\tresult.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief inserts elements\n\n\t\tInserts elements from range `[first, last)`.\n\n\t\t@param[in] first begin of the range of elements to insert\n\t\t@param[in] last end of the range of elements to insert\n\n\t\t@throw type_error.309 if called on JSON values other than objects; example:\n\t\t`\"cannot use insert() with string\"`\n\t\t@throw invalid_iterator.202 if iterator @a first or @a last does does not\n\t\tpoint to an object; example: `\"iterators first and last must point to\n\t\tobjects\"`\n\t\t@throw invalid_iterator.210 if @a first and @a last do not belong to the\n\t\tsame JSON value; example: `\"iterators do not fit\"`\n\n\t\t@complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number\n\t\tof elements to insert.\n\n\t\t@liveexample{The example shows how `insert()` is used.,insert__range_object}\n\n\t\t@since version 3.0.0\n\t\t*/\n\t\tvoid insert(const_iterator first, const_iterator last)\n\t\t{\n\t\t\t// insert only works for objects\n\t\t\tif (JSON_UNLIKELY(not is_object()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\t// check if range iterators belong to the same JSON object\n\t\t\tif (JSON_UNLIKELY(first.m_object != last.m_object))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(210, \"iterators do not fit\"));\n\t\t\t}\n\n\t\t\t// passed iterators must belong to objects\n\t\t\tif (JSON_UNLIKELY(not first.m_object->is_object()))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(202, \"iterators first and last must point to objects\"));\n\t\t\t}\n\n\t\t\tm_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);\n\t\t}\n\n\t\t/*!\n\t\t@brief updates a JSON object from another object, overwriting existing keys\n\n\t\tInserts all values from JSON object @a j and overwrites existing keys.\n\n\t\t@param[in] j  JSON object to read values from\n\n\t\t@throw type_error.312 if called on JSON values other than objects; example:\n\t\t`\"cannot use update() with string\"`\n\n\t\t@complexity O(N*log(size() + N)), where N is the number of elements to\n\t\tinsert.\n\n\t\t@liveexample{The example shows how `update()` is used.,update}\n\n\t\t@sa https://docs.python.org/3.6/library/stdtypes.html#dict.update\n\n\t\t@since version 3.0.0\n\t\t*/\n\t\tvoid update(const_reference j)\n\t\t{\n\t\t\t// implicitly convert null value to an empty object\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::object;\n\t\t\t\tm_value.object = create<object_t>();\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\tif (JSON_UNLIKELY(not is_object()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(312, \"cannot use update() with \" + std::string(type_name())));\n\t\t\t}\n\t\t\tif (JSON_UNLIKELY(not j.is_object()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(312, \"cannot use update() with \" + std::string(j.type_name())));\n\t\t\t}\n\n\t\t\tfor (auto it = j.begin(); it != j.end(); ++it)\n\t\t\t{\n\t\t\t\tm_value.object->operator[](it.key()) = it.value();\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief updates a JSON object from another object, overwriting existing keys\n\n\t\tInserts all values from from range `[first, last)` and overwrites existing\n\t\tkeys.\n\n\t\t@param[in] first begin of the range of elements to insert\n\t\t@param[in] last end of the range of elements to insert\n\n\t\t@throw type_error.312 if called on JSON values other than objects; example:\n\t\t`\"cannot use update() with string\"`\n\t\t@throw invalid_iterator.202 if iterator @a first or @a last does does not\n\t\tpoint to an object; example: `\"iterators first and last must point to\n\t\tobjects\"`\n\t\t@throw invalid_iterator.210 if @a first and @a last do not belong to the\n\t\tsame JSON value; example: `\"iterators do not fit\"`\n\n\t\t@complexity O(N*log(size() + N)), where N is the number of elements to\n\t\tinsert.\n\n\t\t@liveexample{The example shows how `update()` is used__range.,update}\n\n\t\t@sa https://docs.python.org/3.6/library/stdtypes.html#dict.update\n\n\t\t@since version 3.0.0\n\t\t*/\n\t\tvoid update(const_iterator first, const_iterator last)\n\t\t{\n\t\t\t// implicitly convert null value to an empty object\n\t\t\tif (is_null())\n\t\t\t{\n\t\t\t\tm_type = value_t::object;\n\t\t\t\tm_value.object = create<object_t>();\n\t\t\t\tassert_invariant();\n\t\t\t}\n\n\t\t\tif (JSON_UNLIKELY(not is_object()))\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(312, \"cannot use update() with \" + std::string(type_name())));\n\t\t\t}\n\n\t\t\t// check if range iterators belong to the same JSON object\n\t\t\tif (JSON_UNLIKELY(first.m_object != last.m_object))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(210, \"iterators do not fit\"));\n\t\t\t}\n\n\t\t\t// passed iterators must belong to objects\n\t\t\tif (JSON_UNLIKELY(not first.m_object->is_object()\n\t\t\t\tor not first.m_object->is_object()))\n\t\t\t{\n\t\t\t\tJSON_THROW(invalid_iterator::create(202, \"iterators first and last must point to objects\"));\n\t\t\t}\n\n\t\t\tfor (auto it = first; it != last; ++it)\n\t\t\t{\n\t\t\t\tm_value.object->operator[](it.key()) = it.value();\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief exchanges the values\n\n\t\tExchanges the contents of the JSON value with those of @a other. Does not\n\t\tinvoke any move, copy, or swap operations on individual elements. All\n\t\titerators and references remain valid. The past-the-end iterator is\n\t\tinvalidated.\n\n\t\t@param[in,out] other JSON value to exchange the contents with\n\n\t\t@complexity Constant.\n\n\t\t@liveexample{The example below shows how JSON values can be swapped with\n\t\t`swap()`.,swap__reference}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tvoid swap(reference other) noexcept (\n\t\t\tstd::is_nothrow_move_constructible<value_t>::value and\n\t\t\tstd::is_nothrow_move_assignable<value_t>::value and\n\t\t\tstd::is_nothrow_move_constructible<json_value>::value and\n\t\t\tstd::is_nothrow_move_assignable<json_value>::value\n\t\t\t)\n\t\t{\n\t\t\tstd::swap(m_type, other.m_type);\n\t\t\tstd::swap(m_value, other.m_value);\n\t\t\tassert_invariant();\n\t\t}\n\n\t\t/*!\n\t\t@brief exchanges the values\n\n\t\tExchanges the contents of a JSON array with those of @a other. Does not\n\t\tinvoke any move, copy, or swap operations on individual elements. All\n\t\titerators and references remain valid. The past-the-end iterator is\n\t\tinvalidated.\n\n\t\t@param[in,out] other array to exchange the contents with\n\n\t\t@throw type_error.310 when JSON value is not an array; example: `\"cannot\n\t\tuse swap() with string\"`\n\n\t\t@complexity Constant.\n\n\t\t@liveexample{The example below shows how arrays can be swapped with\n\t\t`swap()`.,swap__array_t}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tvoid swap(array_t& other)\n\t\t{\n\t\t\t// swap only works for arrays\n\t\t\tif (JSON_LIKELY(is_array()))\n\t\t\t{\n\t\t\t\tstd::swap(*(m_value.array), other);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(310, \"cannot use swap() with \" + std::string(type_name())));\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief exchanges the values\n\n\t\tExchanges the contents of a JSON object with those of @a other. Does not\n\t\tinvoke any move, copy, or swap operations on individual elements. All\n\t\titerators and references remain valid. The past-the-end iterator is\n\t\tinvalidated.\n\n\t\t@param[in,out] other object to exchange the contents with\n\n\t\t@throw type_error.310 when JSON value is not an object; example:\n\t\t`\"cannot use swap() with string\"`\n\n\t\t@complexity Constant.\n\n\t\t@liveexample{The example below shows how objects can be swapped with\n\t\t`swap()`.,swap__object_t}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tvoid swap(object_t& other)\n\t\t{\n\t\t\t// swap only works for objects\n\t\t\tif (JSON_LIKELY(is_object()))\n\t\t\t{\n\t\t\t\tstd::swap(*(m_value.object), other);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(310, \"cannot use swap() with \" + std::string(type_name())));\n\t\t\t}\n\t\t}\n\n\t\t/*!\n\t\t@brief exchanges the values\n\n\t\tExchanges the contents of a JSON string with those of @a other. Does not\n\t\tinvoke any move, copy, or swap operations on individual elements. All\n\t\titerators and references remain valid. The past-the-end iterator is\n\t\tinvalidated.\n\n\t\t@param[in,out] other string to exchange the contents with\n\n\t\t@throw type_error.310 when JSON value is not a string; example: `\"cannot\n\t\tuse swap() with boolean\"`\n\n\t\t@complexity Constant.\n\n\t\t@liveexample{The example below shows how strings can be swapped with\n\t\t`swap()`.,swap__string_t}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tvoid swap(string_t& other)\n\t\t{\n\t\t\t// swap only works for strings\n\t\t\tif (JSON_LIKELY(is_string()))\n\t\t\t{\n\t\t\t\tstd::swap(*(m_value.string), other);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tJSON_THROW(type_error::create(310, \"cannot use swap() with \" + std::string(type_name())));\n\t\t\t}\n\t\t}\n\n\t\t/// @}\n\n\tpublic:\n\t\t//////////////////////////////////////////\n\t\t// lexicographical comparison operators //\n\t\t//////////////////////////////////////////\n\n\t\t/// @name lexicographical comparison operators\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief comparison: equal\n\n\t\tCompares two JSON values for equality according to the following rules:\n\t\t- Two JSON values are equal if (1) they are from the same type and (2)\n\t\ttheir stored values are the same according to their respective\n\t\t`operator==`.\n\t\t- Integer and floating-point numbers are automatically converted before\n\t\tcomparison. Note than two NaN values are always treated as unequal.\n\t\t- Two JSON null values are equal.\n\n\t\t@note Floating-point inside JSON values numbers are compared with\n\t\t`json::number_float_t::operator==` which is `double::operator==` by\n\t\tdefault. To compare floating-point while respecting an epsilon, an alternative\n\t\t[comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)\n\t\tcould be used, for instance\n\t\t@code {.cpp}\n\t\ttemplate <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>\n\t\tinline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept\n\t\t{\n\t\treturn std::abs(a - b) <= epsilon;\n\t\t}\n\t\t@endcode\n\n\t\t@note NaN values never compare equal to themselves or to other NaN values.\n\n\t\t@param[in] lhs  first JSON value to consider\n\t\t@param[in] rhs  second JSON value to consider\n\t\t@return whether the values @a lhs and @a rhs are equal\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@complexity Linear.\n\n\t\t@liveexample{The example demonstrates comparing several JSON\n\t\ttypes.,operator__equal}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tfriend bool operator==(const_reference lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\tconst auto lhs_type = lhs.type();\n\t\t\tconst auto rhs_type = rhs.type();\n\n\t\t\tif (lhs_type == rhs_type)\n\t\t\t{\n\t\t\t\tswitch (lhs_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::array:\n\t\t\t\t\treturn (*lhs.m_value.array == *rhs.m_value.array);\n\n\t\t\t\tcase value_t::object:\n\t\t\t\t\treturn (*lhs.m_value.object == *rhs.m_value.object);\n\n\t\t\t\tcase value_t::null:\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase value_t::string:\n\t\t\t\t\treturn (*lhs.m_value.string == *rhs.m_value.string);\n\n\t\t\t\tcase value_t::boolean:\n\t\t\t\t\treturn (lhs.m_value.boolean == rhs.m_value.boolean);\n\n\t\t\t\tcase value_t::number_integer:\n\t\t\t\t\treturn (lhs.m_value.number_integer == rhs.m_value.number_integer);\n\n\t\t\t\tcase value_t::number_unsigned:\n\t\t\t\t\treturn (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);\n\n\t\t\t\tcase value_t::number_float:\n\t\t\t\t\treturn (lhs.m_value.number_float == rhs.m_value.number_float);\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)\n\t\t\t{\n\t\t\t\treturn (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)\n\t\t\t{\n\t\t\t\treturn (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)\n\t\t\t{\n\t\t\t\treturn (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)\n\t\t\t{\n\t\t\t\treturn (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)\n\t\t\t{\n\t\t\t\treturn (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)\n\t\t\t{\n\t\t\t\treturn (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: equal\n\t\t@copydoc operator==(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator==(const_reference lhs, const ScalarType rhs) noexcept\n\t\t{\n\t\t\treturn (lhs == basic_json(rhs));\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: equal\n\t\t@copydoc operator==(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator==(const ScalarType lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn (basic_json(lhs) == rhs);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: not equal\n\n\t\tCompares two JSON values for inequality by calculating `not (lhs == rhs)`.\n\n\t\t@param[in] lhs  first JSON value to consider\n\t\t@param[in] rhs  second JSON value to consider\n\t\t@return whether the values @a lhs and @a rhs are not equal\n\n\t\t@complexity Linear.\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@liveexample{The example demonstrates comparing several JSON\n\t\ttypes.,operator__notequal}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tfriend bool operator!=(const_reference lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn not (lhs == rhs);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: not equal\n\t\t@copydoc operator!=(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept\n\t\t{\n\t\t\treturn (lhs != basic_json(rhs));\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: not equal\n\t\t@copydoc operator!=(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn (basic_json(lhs) != rhs);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: less than\n\n\t\tCompares whether one JSON value @a lhs is less than another JSON value @a\n\t\trhs according to the following rules:\n\t\t- If @a lhs and @a rhs have the same type, the values are compared using\n\t\tthe default `<` operator.\n\t\t- Integer and floating-point numbers are automatically converted before\n\t\tcomparison\n\t\t- In case @a lhs and @a rhs have different types, the values are ignored\n\t\tand the order of the types is considered, see\n\t\t@ref operator<(const value_t, const value_t).\n\n\t\t@param[in] lhs  first JSON value to consider\n\t\t@param[in] rhs  second JSON value to consider\n\t\t@return whether @a lhs is less than @a rhs\n\n\t\t@complexity Linear.\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@liveexample{The example demonstrates comparing several JSON\n\t\ttypes.,operator__less}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tfriend bool operator<(const_reference lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\tconst auto lhs_type = lhs.type();\n\t\t\tconst auto rhs_type = rhs.type();\n\n\t\t\tif (lhs_type == rhs_type)\n\t\t\t{\n\t\t\t\tswitch (lhs_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::array:\n\t\t\t\t\treturn (*lhs.m_value.array) < (*rhs.m_value.array);\n\n\t\t\t\tcase value_t::object:\n\t\t\t\t\treturn *lhs.m_value.object < *rhs.m_value.object;\n\n\t\t\t\tcase value_t::null:\n\t\t\t\t\treturn false;\n\n\t\t\t\tcase value_t::string:\n\t\t\t\t\treturn *lhs.m_value.string < *rhs.m_value.string;\n\n\t\t\t\tcase value_t::boolean:\n\t\t\t\t\treturn lhs.m_value.boolean < rhs.m_value.boolean;\n\n\t\t\t\tcase value_t::number_integer:\n\t\t\t\t\treturn lhs.m_value.number_integer < rhs.m_value.number_integer;\n\n\t\t\t\tcase value_t::number_unsigned:\n\t\t\t\t\treturn lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;\n\n\t\t\t\tcase value_t::number_float:\n\t\t\t\t\treturn lhs.m_value.number_float < rhs.m_value.number_float;\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)\n\t\t\t{\n\t\t\t\treturn static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)\n\t\t\t{\n\t\t\t\treturn lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)\n\t\t\t{\n\t\t\t\treturn static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)\n\t\t\t{\n\t\t\t\treturn lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)\n\t\t\t{\n\t\t\t\treturn lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);\n\t\t\t}\n\t\t\telse if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)\n\t\t\t{\n\t\t\t\treturn static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;\n\t\t\t}\n\n\t\t\t// We only reach this line if we cannot compare values. In that case,\n\t\t\t// we compare types. Note we have to call the operator explicitly,\n\t\t\t// because MSVC has problems otherwise.\n\t\t\treturn operator<(lhs_type, rhs_type);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: less than\n\t\t@copydoc operator<(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator<(const_reference lhs, const ScalarType rhs) noexcept\n\t\t{\n\t\t\treturn (lhs < basic_json(rhs));\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: less than\n\t\t@copydoc operator<(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator<(const ScalarType lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn (basic_json(lhs) < rhs);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: less than or equal\n\n\t\tCompares whether one JSON value @a lhs is less than or equal to another\n\t\tJSON value by calculating `not (rhs < lhs)`.\n\n\t\t@param[in] lhs  first JSON value to consider\n\t\t@param[in] rhs  second JSON value to consider\n\t\t@return whether @a lhs is less than or equal to @a rhs\n\n\t\t@complexity Linear.\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@liveexample{The example demonstrates comparing several JSON\n\t\ttypes.,operator__greater}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tfriend bool operator<=(const_reference lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn not (rhs < lhs);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: less than or equal\n\t\t@copydoc operator<=(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept\n\t\t{\n\t\t\treturn (lhs <= basic_json(rhs));\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: less than or equal\n\t\t@copydoc operator<=(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn (basic_json(lhs) <= rhs);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: greater than\n\n\t\tCompares whether one JSON value @a lhs is greater than another\n\t\tJSON value by calculating `not (lhs <= rhs)`.\n\n\t\t@param[in] lhs  first JSON value to consider\n\t\t@param[in] rhs  second JSON value to consider\n\t\t@return whether @a lhs is greater than to @a rhs\n\n\t\t@complexity Linear.\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@liveexample{The example demonstrates comparing several JSON\n\t\ttypes.,operator__lessequal}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tfriend bool operator>(const_reference lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn not (lhs <= rhs);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: greater than\n\t\t@copydoc operator>(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator>(const_reference lhs, const ScalarType rhs) noexcept\n\t\t{\n\t\t\treturn (lhs > basic_json(rhs));\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: greater than\n\t\t@copydoc operator>(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator>(const ScalarType lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn (basic_json(lhs) > rhs);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: greater than or equal\n\n\t\tCompares whether one JSON value @a lhs is greater than or equal to another\n\t\tJSON value by calculating `not (lhs < rhs)`.\n\n\t\t@param[in] lhs  first JSON value to consider\n\t\t@param[in] rhs  second JSON value to consider\n\t\t@return whether @a lhs is greater than or equal to @a rhs\n\n\t\t@complexity Linear.\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@liveexample{The example demonstrates comparing several JSON\n\t\ttypes.,operator__greaterequal}\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tfriend bool operator>=(const_reference lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn not (lhs < rhs);\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: greater than or equal\n\t\t@copydoc operator>=(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept\n\t\t{\n\t\t\treturn (lhs >= basic_json(rhs));\n\t\t}\n\n\t\t/*!\n\t\t@brief comparison: greater than or equal\n\t\t@copydoc operator>=(const_reference, const_reference)\n\t\t*/\n\t\ttemplate<typename ScalarType, typename std::enable_if<\n\t\t\tstd::is_scalar<ScalarType>::value, int>::type = 0>\n\t\t\tfriend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept\n\t\t{\n\t\t\treturn (basic_json(lhs) >= rhs);\n\t\t}\n\n\t\t/// @}\n\n\t\t///////////////////\n\t\t// serialization //\n\t\t///////////////////\n\n\t\t/// @name serialization\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief serialize to stream\n\n\t\tSerialize the given JSON value @a j to the output stream @a o. The JSON\n\t\tvalue will be serialized using the @ref dump member function.\n\n\t\t- The indentation of the output can be controlled with the member variable\n\t\t`width` of the output stream @a o. For instance, using the manipulator\n\t\t`std::setw(4)` on @a o sets the indentation level to `4` and the\n\t\tserialization result is the same as calling `dump(4)`.\n\n\t\t- The indentation characrer can be controlled with the member variable\n\t\t`fill` of the output stream @a o. For instance, the manipulator\n\t\t`std::setfill('\\\\t')` sets indentation to use a tab character rather than\n\t\tthe default space character.\n\n\t\t@param[in,out] o  stream to serialize to\n\t\t@param[in] j  JSON value to serialize\n\n\t\t@return the stream @a o\n\n\t\t@complexity Linear.\n\n\t\t@liveexample{The example below shows the serialization with different\n\t\tparameters to `width` to adjust the indentation level.,operator_serialize}\n\n\t\t@since version 1.0.0; indentaction character added in version 3.0.0\n\t\t*/\n\t\tfriend std::ostream& operator<<(std::ostream& o, const basic_json& j)\n\t\t{\n\t\t\t// read width member and use it as indentation parameter if nonzero\n\t\t\tconst bool pretty_print = (o.width() > 0);\n\t\t\tconst auto indentation = (pretty_print ? o.width() : 0);\n\n\t\t\t// reset width to 0 for subsequent calls to this stream\n\t\t\to.width(0);\n\n\t\t\t// do the actual serialization\n\t\t\tserializer s(detail::output_adapter<char>(o), o.fill());\n\t\t\ts.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));\n\t\t\treturn o;\n\t\t}\n\n\t\t/*!\n\t\t@brief serialize to stream\n\t\t@deprecated This stream operator is deprecated and will be removed in a\n\t\tfuture version of the library. Please use\n\t\t@ref operator<<(std::ostream&, const basic_json&)\n\t\tinstead; that is, replace calls like `j >> o;` with `o << j;`.\n\t\t@since version 1.0.0; deprecated since version 3.0.0\n\t\t*/\n\t\tJSON_DEPRECATED\n\t\t\tfriend std::ostream& operator>>(const basic_json& j, std::ostream& o)\n\t\t{\n\t\t\treturn o << j;\n\t\t}\n\n\t\t/// @}\n\n\n\t\t/////////////////////\n\t\t// deserialization //\n\t\t/////////////////////\n\n\t\t/// @name deserialization\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief deserialize from a compatible input\n\n\t\tThis function reads from a compatible input. Examples are:\n\t\t- an array of 1-byte values\n\t\t- strings with character/literal type with size of 1 byte\n\t\t- input streams\n\t\t- container with contiguous storage of 1-byte values. Compatible container\n\t\ttypes include `std::vector`, `std::string`, `std::array`,\n\t\t`std::valarray`, and `std::initializer_list`. Furthermore, C-style\n\t\tarrays can be used with `std::begin()`/`std::end()`. User-defined\n\t\tcontainers can be used as long as they implement random-access iterators\n\t\tand a contiguous storage.\n\n\t\t@pre Each element of the container has a size of 1 byte. Violating this\n\t\tprecondition yields undefined behavior. **This precondition is enforced\n\t\twith a static assertion.**\n\n\t\t@pre The container storage is contiguous. Violating this precondition\n\t\tyields undefined behavior. **This precondition is enforced with an\n\t\tassertion.**\n\t\t@pre Each element of the container has a size of 1 byte. Violating this\n\t\tprecondition yields undefined behavior. **This precondition is enforced\n\t\twith a static assertion.**\n\n\t\t@warning There is no way to enforce all preconditions at compile-time. If\n\t\tthe function is called with a noncompliant container and with\n\t\tassertions switched off, the behavior is undefined and will most\n\t\tlikely yield segmentation violation.\n\n\t\t@param[in] i  input to read from\n\t\t@param[in] cb  a parser callback function of type @ref parser_callback_t\n\t\twhich is used to control the deserialization by filtering unwanted values\n\t\t(optional)\n\n\t\t@return result of the deserialization\n\n\t\t@throw parse_error.101 if a parse error occurs; example: `\"\"unexpected end\n\t\tof input; expected string literal\"\"`\n\t\t@throw parse_error.102 if to_unicode fails or surrogate error\n\t\t@throw parse_error.103 if to_unicode fails\n\n\t\t@complexity Linear in the length of the input. The parser is a predictive\n\t\tLL(1) parser. The complexity can be higher if the parser callback function\n\t\t@a cb has a super-linear complexity.\n\n\t\t@note A UTF-8 byte order mark is silently ignored.\n\n\t\t@liveexample{The example below demonstrates the `parse()` function reading\n\t\tfrom an array.,parse__array__parser_callback_t}\n\n\t\t@liveexample{The example below demonstrates the `parse()` function with\n\t\tand without callback function.,parse__string__parser_callback_t}\n\n\t\t@liveexample{The example below demonstrates the `parse()` function with\n\t\tand without callback function.,parse__istream__parser_callback_t}\n\n\t\t@liveexample{The example below demonstrates the `parse()` function reading\n\t\tfrom a contiguous container.,parse__contiguouscontainer__parser_callback_t}\n\n\t\t@since version 2.0.3 (contiguous containers)\n\t\t*/\n\t\tstatic basic_json parse(detail::input_adapter i,\n\t\t\tconst parser_callback_t cb = nullptr,\n\t\t\tconst bool allow_exceptions = true)\n\t\t{\n\t\t\tbasic_json result;\n\t\t\tparser(i, cb, allow_exceptions).parse(true, result);\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@copydoc basic_json parse(detail::input_adapter, const parser_callback_t)\n\t\t*/\n\t\tstatic basic_json parse(detail::input_adapter& i,\n\t\t\tconst parser_callback_t cb = nullptr,\n\t\t\tconst bool allow_exceptions = true)\n\t\t{\n\t\t\tbasic_json result;\n\t\t\tparser(i, cb, allow_exceptions).parse(true, result);\n\t\t\treturn result;\n\t\t}\n\n\t\tstatic bool accept(detail::input_adapter i)\n\t\t{\n\t\t\treturn parser(i).accept(true);\n\t\t}\n\n\t\tstatic bool accept(detail::input_adapter& i)\n\t\t{\n\t\t\treturn parser(i).accept(true);\n\t\t}\n\n\t\t/*!\n\t\t@brief deserialize from an iterator range with contiguous storage\n\n\t\tThis function reads from an iterator range of a container with contiguous\n\t\tstorage of 1-byte values. Compatible container types include\n\t\t`std::vector`, `std::string`, `std::array`, `std::valarray`, and\n\t\t`std::initializer_list`. Furthermore, C-style arrays can be used with\n\t\t`std::begin()`/`std::end()`. User-defined containers can be used as long\n\t\tas they implement random-access iterators and a contiguous storage.\n\n\t\t@pre The iterator range is contiguous. Violating this precondition yields\n\t\tundefined behavior. **This precondition is enforced with an assertion.**\n\t\t@pre Each element in the range has a size of 1 byte. Violating this\n\t\tprecondition yields undefined behavior. **This precondition is enforced\n\t\twith a static assertion.**\n\n\t\t@warning There is no way to enforce all preconditions at compile-time. If\n\t\tthe function is called with noncompliant iterators and with\n\t\tassertions switched off, the behavior is undefined and will most\n\t\tlikely yield segmentation violation.\n\n\t\t@tparam IteratorType iterator of container with contiguous storage\n\t\t@param[in] first  begin of the range to parse (included)\n\t\t@param[in] last  end of the range to parse (excluded)\n\t\t@param[in] cb  a parser callback function of type @ref parser_callback_t\n\t\twhich is used to control the deserialization by filtering unwanted values\n\t\t(optional)\n\t\t@param[in] allow_exceptions  whether to throw exceptions in case of a\n\t\tparse error (optional, true by default)\n\n\t\t@return result of the deserialization\n\n\t\t@throw parse_error.101 in case of an unexpected token\n\t\t@throw parse_error.102 if to_unicode fails or surrogate error\n\t\t@throw parse_error.103 if to_unicode fails\n\n\t\t@complexity Linear in the length of the input. The parser is a predictive\n\t\tLL(1) parser. The complexity can be higher if the parser callback function\n\t\t@a cb has a super-linear complexity.\n\n\t\t@note A UTF-8 byte order mark is silently ignored.\n\n\t\t@liveexample{The example below demonstrates the `parse()` function reading\n\t\tfrom an iterator range.,parse__iteratortype__parser_callback_t}\n\n\t\t@since version 2.0.3\n\t\t*/\n\t\ttemplate<class IteratorType, typename std::enable_if<\n\t\t\tstd::is_base_of<\n\t\t\tstd::random_access_iterator_tag,\n\t\t\ttypename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>\n\t\t\tstatic basic_json parse(IteratorType first, IteratorType last,\n\t\t\t\tconst parser_callback_t cb = nullptr,\n\t\t\t\tconst bool allow_exceptions = true)\n\t\t{\n\t\t\tbasic_json result;\n\t\t\tparser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);\n\t\t\treturn result;\n\t\t}\n\n\t\ttemplate<class IteratorType, typename std::enable_if<\n\t\t\tstd::is_base_of<\n\t\t\tstd::random_access_iterator_tag,\n\t\t\ttypename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>\n\t\t\tstatic bool accept(IteratorType first, IteratorType last)\n\t\t{\n\t\t\treturn parser(detail::input_adapter(first, last)).accept(true);\n\t\t}\n\n\t\t/*!\n\t\t@brief deserialize from stream\n\t\t@deprecated This stream operator is deprecated and will be removed in a\n\t\tfuture version of the library. Please use\n\t\t@ref operator>>(std::istream&, basic_json&)\n\t\tinstead; that is, replace calls like `j << i;` with `i >> j;`.\n\t\t@since version 1.0.0; deprecated since version 3.0.0\n\t\t*/\n\t\tJSON_DEPRECATED\n\t\t\tfriend std::istream& operator<<(basic_json& j, std::istream& i)\n\t\t{\n\t\t\treturn operator>>(i, j);\n\t\t}\n\n\t\t/*!\n\t\t@brief deserialize from stream\n\n\t\tDeserializes an input stream to a JSON value.\n\n\t\t@param[in,out] i  input stream to read a serialized JSON value from\n\t\t@param[in,out] j  JSON value to write the deserialized input to\n\n\t\t@throw parse_error.101 in case of an unexpected token\n\t\t@throw parse_error.102 if to_unicode fails or surrogate error\n\t\t@throw parse_error.103 if to_unicode fails\n\n\t\t@complexity Linear in the length of the input. The parser is a predictive\n\t\tLL(1) parser.\n\n\t\t@note A UTF-8 byte order mark is silently ignored.\n\n\t\t@liveexample{The example below shows how a JSON value is constructed by\n\t\treading a serialization from a stream.,operator_deserialize}\n\n\t\t@sa parse(std::istream&, const parser_callback_t) for a variant with a\n\t\tparser callback function to filter values while parsing\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tfriend std::istream& operator>>(std::istream& i, basic_json& j)\n\t\t{\n\t\t\tparser(detail::input_adapter(i)).parse(false, j);\n\t\t\treturn i;\n\t\t}\n\n\t\t/// @}\n\n\t\t///////////////////////////\n\t\t// convenience functions //\n\t\t///////////////////////////\n\n\t\t/*!\n\t\t@brief return the type as string\n\n\t\tReturns the type name as string to be used in error messages - usually to\n\t\tindicate that a function was called on a wrong JSON type.\n\n\t\t@return a string representation of a the @a m_type member:\n\t\tValue type  | return value\n\t\t----------- | -------------\n\t\tnull        | `\"null\"`\n\t\tboolean     | `\"boolean\"`\n\t\tstring      | `\"string\"`\n\t\tnumber      | `\"number\"` (for all number types)\n\t\tobject      | `\"object\"`\n\t\tarray       | `\"array\"`\n\t\tdiscarded   | `\"discarded\"`\n\n\t\t@exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n\t\t@complexity Constant.\n\n\t\t@liveexample{The following code exemplifies `type_name()` for all JSON\n\t\ttypes.,type_name}\n\n\t\t@sa @ref type() -- return the type of the JSON value\n\t\t@sa @ref operator value_t() -- return the type of the JSON value (implicit)\n\n\t\t@since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`\n\t\tsince 3.0.0\n\t\t*/\n\t\tconst char* type_name() const noexcept\n\t\t{\n\t\t\t{\n\t\t\t\tswitch (m_type)\n\t\t\t\t{\n\t\t\t\tcase value_t::null:\n\t\t\t\t\treturn \"null\";\n\t\t\t\tcase value_t::object:\n\t\t\t\t\treturn \"object\";\n\t\t\t\tcase value_t::array:\n\t\t\t\t\treturn \"array\";\n\t\t\t\tcase value_t::string:\n\t\t\t\t\treturn \"string\";\n\t\t\t\tcase value_t::boolean:\n\t\t\t\t\treturn \"boolean\";\n\t\t\t\tcase value_t::discarded:\n\t\t\t\t\treturn \"discarded\";\n\t\t\t\tdefault:\n\t\t\t\t\treturn \"number\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\tprivate:\n\t\t//////////////////////\n\t\t// member variables //\n\t\t//////////////////////\n\n\t\t/// the type of the current element\n\t\tvalue_t m_type = value_t::null;\n\n\t\t/// the value of the current element\n\t\tjson_value m_value = {};\n\n\t\t//////////////////////////////////////////\n\t\t// binary serialization/deserialization //\n\t\t//////////////////////////////////////////\n\n\t\t/// @name binary serialization/deserialization support\n\t\t/// @{\n\n\tpublic:\n\t\t/*!\n\t\t@brief create a CBOR serialization of a given JSON value\n\n\t\tSerializes a given JSON value @a j to a byte vector using the CBOR (Concise\n\t\tBinary Object Representation) serialization format. CBOR is a binary\n\t\tserialization format which aims to be more compact than JSON itself, yet\n\t\tmore efficient to parse.\n\n\t\tThe library uses the following mapping from JSON values types to\n\t\tCBOR types according to the CBOR specification (RFC 7049):\n\n\t\tJSON value type | value/range                                | CBOR type                          | first byte\n\t\t--------------- | ------------------------------------------ | ---------------------------------- | ---------------\n\t\tnull            | `null`                                     | Null                               | 0xf6\n\t\tboolean         | `true`                                     | True                               | 0xf5\n\t\tboolean         | `false`                                    | False                              | 0xf4\n\t\tnumber_integer  | -9223372036854775808..-2147483649          | Negative integer (8 bytes follow)  | 0x3b\n\t\tnumber_integer  | -2147483648..-32769                        | Negative integer (4 bytes follow)  | 0x3a\n\t\tnumber_integer  | -32768..-129                               | Negative integer (2 bytes follow)  | 0x39\n\t\tnumber_integer  | -128..-25                                  | Negative integer (1 byte follow)   | 0x38\n\t\tnumber_integer  | -24..-1                                    | Negative integer                   | 0x20..0x37\n\t\tnumber_integer  | 0..23                                      | Integer                            | 0x00..0x17\n\t\tnumber_integer  | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18\n\t\tnumber_integer  | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19\n\t\tnumber_integer  | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1a\n\t\tnumber_integer  | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1b\n\t\tnumber_unsigned | 0..23                                      | Integer                            | 0x00..0x17\n\t\tnumber_unsigned | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18\n\t\tnumber_unsigned | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19\n\t\tnumber_unsigned | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1a\n\t\tnumber_unsigned | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1b\n\t\tnumber_float    | *any value*                                | Double-Precision Float             | 0xfb\n\t\tstring          | *length*: 0..23                            | UTF-8 string                       | 0x60..0x77\n\t\tstring          | *length*: 23..255                          | UTF-8 string (1 byte follow)       | 0x78\n\t\tstring          | *length*: 256..65535                       | UTF-8 string (2 bytes follow)      | 0x79\n\t\tstring          | *length*: 65536..4294967295                | UTF-8 string (4 bytes follow)      | 0x7a\n\t\tstring          | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow)      | 0x7b\n\t\tarray           | *size*: 0..23                              | array                              | 0x80..0x97\n\t\tarray           | *size*: 23..255                            | array (1 byte follow)              | 0x98\n\t\tarray           | *size*: 256..65535                         | array (2 bytes follow)             | 0x99\n\t\tarray           | *size*: 65536..4294967295                  | array (4 bytes follow)             | 0x9a\n\t\tarray           | *size*: 4294967296..18446744073709551615   | array (8 bytes follow)             | 0x9b\n\t\tobject          | *size*: 0..23                              | map                                | 0xa0..0xb7\n\t\tobject          | *size*: 23..255                            | map (1 byte follow)                | 0xb8\n\t\tobject          | *size*: 256..65535                         | map (2 bytes follow)               | 0xb9\n\t\tobject          | *size*: 65536..4294967295                  | map (4 bytes follow)               | 0xba\n\t\tobject          | *size*: 4294967296..18446744073709551615   | map (8 bytes follow)               | 0xbb\n\n\t\t@note The mapping is **complete** in the sense that any JSON value type\n\t\tcan be converted to a CBOR value.\n\n\t\t@note If NaN or Infinity are stored inside a JSON number, they are\n\t\tserialized properly. This behavior differs from the @ref dump()\n\t\tfunction which serializes NaN or Infinity to `null`.\n\n\t\t@note The following CBOR types are not used in the conversion:\n\t\t- byte strings (0x40..0x5f)\n\t\t- UTF-8 strings terminated by \"break\" (0x7f)\n\t\t- arrays terminated by \"break\" (0x9f)\n\t\t- maps terminated by \"break\" (0xbf)\n\t\t- date/time (0xc0..0xc1)\n\t\t- bignum (0xc2..0xc3)\n\t\t- decimal fraction (0xc4)\n\t\t- bigfloat (0xc5)\n\t\t- tagged items (0xc6..0xd4, 0xd8..0xdb)\n\t\t- expected conversions (0xd5..0xd7)\n\t\t- simple values (0xe0..0xf3, 0xf8)\n\t\t- undefined (0xf7)\n\t\t- half and single-precision floats (0xf9-0xfa)\n\t\t- break (0xff)\n\n\t\t@param[in] j  JSON value to serialize\n\t\t@return MessagePack serialization as byte vector\n\n\t\t@complexity Linear in the size of the JSON value @a j.\n\n\t\t@liveexample{The example shows the serialization of a JSON value to a byte\n\t\tvector in CBOR format.,to_cbor}\n\n\t\t@sa http://cbor.io\n\t\t@sa @ref from_cbor(const std::vector<uint8_t>&, const size_t) for the\n\t\tanalogous deserialization\n\t\t@sa @ref to_msgpack(const basic_json&) for the related MessagePack format\n\n\t\t@since version 2.0.9\n\t\t*/\n\t\tstatic std::vector<uint8_t> to_cbor(const basic_json& j)\n\t\t{\n\t\t\tstd::vector<uint8_t> result;\n\t\t\tto_cbor(j, result);\n\t\t\treturn result;\n\t\t}\n\n\t\tstatic void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)\n\t\t{\n\t\t\tbinary_writer<uint8_t>(o).write_cbor(j);\n\t\t}\n\n\t\tstatic void to_cbor(const basic_json& j, detail::output_adapter<char> o)\n\t\t{\n\t\t\tbinary_writer<char>(o).write_cbor(j);\n\t\t}\n\n\t\t/*!\n\t\t@brief create a MessagePack serialization of a given JSON value\n\n\t\tSerializes a given JSON value @a j to a byte vector using the MessagePack\n\t\tserialization format. MessagePack is a binary serialization format which\n\t\taims to be more compact than JSON itself, yet more efficient to parse.\n\n\t\tThe library uses the following mapping from JSON values types to\n\t\tMessagePack types according to the MessagePack specification:\n\n\t\tJSON value type | value/range                       | MessagePack type | first byte\n\t\t--------------- | --------------------------------- | ---------------- | ----------\n\t\tnull            | `null`                            | nil              | 0xc0\n\t\tboolean         | `true`                            | true             | 0xc3\n\t\tboolean         | `false`                           | false            | 0xc2\n\t\tnumber_integer  | -9223372036854775808..-2147483649 | int64            | 0xd3\n\t\tnumber_integer  | -2147483648..-32769               | int32            | 0xd2\n\t\tnumber_integer  | -32768..-129                      | int16            | 0xd1\n\t\tnumber_integer  | -128..-33                         | int8             | 0xd0\n\t\tnumber_integer  | -32..-1                           | negative fixint  | 0xe0..0xff\n\t\tnumber_integer  | 0..127                            | positive fixint  | 0x00..0x7f\n\t\tnumber_integer  | 128..255                          | uint 8           | 0xcc\n\t\tnumber_integer  | 256..65535                        | uint 16          | 0xcd\n\t\tnumber_integer  | 65536..4294967295                 | uint 32          | 0xce\n\t\tnumber_integer  | 4294967296..18446744073709551615  | uint 64          | 0xcf\n\t\tnumber_unsigned | 0..127                            | positive fixint  | 0x00..0x7f\n\t\tnumber_unsigned | 128..255                          | uint 8           | 0xcc\n\t\tnumber_unsigned | 256..65535                        | uint 16          | 0xcd\n\t\tnumber_unsigned | 65536..4294967295                 | uint 32          | 0xce\n\t\tnumber_unsigned | 4294967296..18446744073709551615  | uint 64          | 0xcf\n\t\tnumber_float    | *any value*                       | float 64         | 0xcb\n\t\tstring          | *length*: 0..31                   | fixstr           | 0xa0..0xbf\n\t\tstring          | *length*: 32..255                 | str 8            | 0xd9\n\t\tstring          | *length*: 256..65535              | str 16           | 0xda\n\t\tstring          | *length*: 65536..4294967295       | str 32           | 0xdb\n\t\tarray           | *size*: 0..15                     | fixarray         | 0x90..0x9f\n\t\tarray           | *size*: 16..65535                 | array 16         | 0xdc\n\t\tarray           | *size*: 65536..4294967295         | array 32         | 0xdd\n\t\tobject          | *size*: 0..15                     | fix map          | 0x80..0x8f\n\t\tobject          | *size*: 16..65535                 | map 16           | 0xde\n\t\tobject          | *size*: 65536..4294967295         | map 32           | 0xdf\n\n\t\t@note The mapping is **complete** in the sense that any JSON value type\n\t\tcan be converted to a MessagePack value.\n\n\t\t@note The following values can **not** be converted to a MessagePack value:\n\t\t- strings with more than 4294967295 bytes\n\t\t- arrays with more than 4294967295 elements\n\t\t- objects with more than 4294967295 elements\n\n\t\t@note The following MessagePack types are not used in the conversion:\n\t\t- bin 8 - bin 32 (0xc4..0xc6)\n\t\t- ext 8 - ext 32 (0xc7..0xc9)\n\t\t- float 32 (0xca)\n\t\t- fixext 1 - fixext 16 (0xd4..0xd8)\n\n\t\t@note Any MessagePack output created @ref to_msgpack can be successfully\n\t\tparsed by @ref from_msgpack.\n\n\t\t@note If NaN or Infinity are stored inside a JSON number, they are\n\t\tserialized properly. This behavior differs from the @ref dump()\n\t\tfunction which serializes NaN or Infinity to `null`.\n\n\t\t@param[in] j  JSON value to serialize\n\t\t@return MessagePack serialization as byte vector\n\n\t\t@complexity Linear in the size of the JSON value @a j.\n\n\t\t@liveexample{The example shows the serialization of a JSON value to a byte\n\t\tvector in MessagePack format.,to_msgpack}\n\n\t\t@sa http://msgpack.org\n\t\t@sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the\n\t\tanalogous deserialization\n\t\t@sa @ref to_cbor(const basic_json& for the related CBOR format\n\n\t\t@since version 2.0.9\n\t\t*/\n\t\tstatic std::vector<uint8_t> to_msgpack(const basic_json& j)\n\t\t{\n\t\t\tstd::vector<uint8_t> result;\n\t\t\tto_msgpack(j, result);\n\t\t\treturn result;\n\t\t}\n\n\t\tstatic void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)\n\t\t{\n\t\t\tbinary_writer<uint8_t>(o).write_msgpack(j);\n\t\t}\n\n\t\tstatic void to_msgpack(const basic_json& j, detail::output_adapter<char> o)\n\t\t{\n\t\t\tbinary_writer<char>(o).write_msgpack(j);\n\t\t}\n\n\t\t/*!\n\t\t@brief create a JSON value from an input in CBOR format\n\n\t\tDeserializes a given input @a i to a JSON value using the CBOR (Concise\n\t\tBinary Object Representation) serialization format.\n\n\t\tThe library maps CBOR types to JSON value types as follows:\n\n\t\tCBOR type              | JSON value type | first byte\n\t\t---------------------- | --------------- | ----------\n\t\tInteger                | number_unsigned | 0x00..0x17\n\t\tUnsigned integer       | number_unsigned | 0x18\n\t\tUnsigned integer       | number_unsigned | 0x19\n\t\tUnsigned integer       | number_unsigned | 0x1a\n\t\tUnsigned integer       | number_unsigned | 0x1b\n\t\tNegative integer       | number_integer  | 0x20..0x37\n\t\tNegative integer       | number_integer  | 0x38\n\t\tNegative integer       | number_integer  | 0x39\n\t\tNegative integer       | number_integer  | 0x3a\n\t\tNegative integer       | number_integer  | 0x3b\n\t\tNegative integer       | number_integer  | 0x40..0x57\n\t\tUTF-8 string           | string          | 0x60..0x77\n\t\tUTF-8 string           | string          | 0x78\n\t\tUTF-8 string           | string          | 0x79\n\t\tUTF-8 string           | string          | 0x7a\n\t\tUTF-8 string           | string          | 0x7b\n\t\tUTF-8 string           | string          | 0x7f\n\t\tarray                  | array           | 0x80..0x97\n\t\tarray                  | array           | 0x98\n\t\tarray                  | array           | 0x99\n\t\tarray                  | array           | 0x9a\n\t\tarray                  | array           | 0x9b\n\t\tarray                  | array           | 0x9f\n\t\tmap                    | object          | 0xa0..0xb7\n\t\tmap                    | object          | 0xb8\n\t\tmap                    | object          | 0xb9\n\t\tmap                    | object          | 0xba\n\t\tmap                    | object          | 0xbb\n\t\tmap                    | object          | 0xbf\n\t\tFalse                  | `false`         | 0xf4\n\t\tTrue                   | `true`          | 0xf5\n\t\tNill                   | `null`          | 0xf6\n\t\tHalf-Precision Float   | number_float    | 0xf9\n\t\tSingle-Precision Float | number_float    | 0xfa\n\t\tDouble-Precision Float | number_float    | 0xfb\n\n\t\t@warning The mapping is **incomplete** in the sense that not all CBOR\n\t\ttypes can be converted to a JSON value. The following CBOR types\n\t\tare not supported and will yield parse errors (parse_error.112):\n\t\t- byte strings (0x40..0x5f)\n\t\t- date/time (0xc0..0xc1)\n\t\t- bignum (0xc2..0xc3)\n\t\t- decimal fraction (0xc4)\n\t\t- bigfloat (0xc5)\n\t\t- tagged items (0xc6..0xd4, 0xd8..0xdb)\n\t\t- expected conversions (0xd5..0xd7)\n\t\t- simple values (0xe0..0xf3, 0xf8)\n\t\t- undefined (0xf7)\n\n\t\t@warning CBOR allows map keys of any type, whereas JSON only allows\n\t\tstrings as keys in object values. Therefore, CBOR maps with keys\n\t\tother than UTF-8 strings are rejected (parse_error.113).\n\n\t\t@note Any CBOR output created @ref to_cbor can be successfully parsed by\n\t\t@ref from_cbor.\n\n\t\t@param[in] i  an input in CBOR format convertible to an input adapter\n\t\t@param[in] strict  whether to expect the input to be consumed until EOF\n\t\t(true by default)\n\t\t@return deserialized JSON value\n\n\t\t@throw parse_error.110 if the given input ends prematurely or the end of\n\t\tfile was not reached when @a strict was set to true\n\t\t@throw parse_error.112 if unsupported features from CBOR were\n\t\tused in the given input @a v or if the input is not valid CBOR\n\t\t@throw parse_error.113 if a string was expected as map key, but not found\n\n\t\t@complexity Linear in the size of the input @a i.\n\n\t\t@liveexample{The example shows the deserialization of a byte vector in CBOR\n\t\tformat to a JSON value.,from_cbor}\n\n\t\t@sa http://cbor.io\n\t\t@sa @ref to_cbor(const basic_json&) for the analogous serialization\n\t\t@sa @ref from_msgpack(detail::input_adapter, const bool) for the\n\t\trelated MessagePack format\n\n\t\t@since version 2.0.9; parameter @a start_index since 2.1.1; changed to\n\t\tconsume input adapters, removed start_index parameter, and added\n\t\t@a strict parameter since 3.0.0\n\t\t*/\n\t\tstatic basic_json from_cbor(detail::input_adapter i,\n\t\t\tconst bool strict = true)\n\t\t{\n\t\t\treturn binary_reader(i).parse_cbor(strict);\n\t\t}\n\n\t\t/*!\n\t\t@copydoc from_cbor(detail::input_adapter, const bool)\n\t\t*/\n\t\ttemplate<typename A1, typename A2,\n\t\t\tdetail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>\n\t\t\tstatic basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true)\n\t\t{\n\t\t\treturn binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_cbor(strict);\n\t\t}\n\n\t\t/*!\n\t\t@brief create a JSON value from an input in MessagePack format\n\n\t\tDeserializes a given input @a i to a JSON value using the MessagePack\n\t\tserialization format.\n\n\t\tThe library maps MessagePack types to JSON value types as follows:\n\n\t\tMessagePack type | JSON value type | first byte\n\t\t---------------- | --------------- | ----------\n\t\tpositive fixint  | number_unsigned | 0x00..0x7f\n\t\tfixmap           | object          | 0x80..0x8f\n\t\tfixarray         | array           | 0x90..0x9f\n\t\tfixstr           | string          | 0xa0..0xbf\n\t\tnil              | `null`          | 0xc0\n\t\tfalse            | `false`         | 0xc2\n\t\ttrue             | `true`          | 0xc3\n\t\tfloat 32         | number_float    | 0xca\n\t\tfloat 64         | number_float    | 0xcb\n\t\tuint 8           | number_unsigned | 0xcc\n\t\tuint 16          | number_unsigned | 0xcd\n\t\tuint 32          | number_unsigned | 0xce\n\t\tuint 64          | number_unsigned | 0xcf\n\t\tint 8            | number_integer  | 0xd0\n\t\tint 16           | number_integer  | 0xd1\n\t\tint 32           | number_integer  | 0xd2\n\t\tint 64           | number_integer  | 0xd3\n\t\tstr 8            | string          | 0xd9\n\t\tstr 16           | string          | 0xda\n\t\tstr 32           | string          | 0xdb\n\t\tarray 16         | array           | 0xdc\n\t\tarray 32         | array           | 0xdd\n\t\tmap 16           | object          | 0xde\n\t\tmap 32           | object          | 0xdf\n\t\tnegative fixint  | number_integer  | 0xe0-0xff\n\n\t\t@warning The mapping is **incomplete** in the sense that not all\n\t\tMessagePack types can be converted to a JSON value. The following\n\t\tMessagePack types are not supported and will yield parse errors:\n\t\t- bin 8 - bin 32 (0xc4..0xc6)\n\t\t- ext 8 - ext 32 (0xc7..0xc9)\n\t\t- fixext 1 - fixext 16 (0xd4..0xd8)\n\n\t\t@note Any MessagePack output created @ref to_msgpack can be successfully\n\t\tparsed by @ref from_msgpack.\n\n\t\t@param[in] i  an input in MessagePack format convertible to an input\n\t\tadapter\n\t\t@param[in] strict  whether to expect the input to be consumed until EOF\n\t\t(true by default)\n\n\t\t@throw parse_error.110 if the given input ends prematurely or the end of\n\t\tfile was not reached when @a strict was set to true\n\t\t@throw parse_error.112 if unsupported features from MessagePack were\n\t\tused in the given input @a i or if the input is not valid MessagePack\n\t\t@throw parse_error.113 if a string was expected as map key, but not found\n\n\t\t@complexity Linear in the size of the input @a i.\n\n\t\t@liveexample{The example shows the deserialization of a byte vector in\n\t\tMessagePack format to a JSON value.,from_msgpack}\n\n\t\t@sa http://msgpack.org\n\t\t@sa @ref to_msgpack(const basic_json&) for the analogous serialization\n\t\t@sa @ref from_cbor(detail::input_adapter, const bool) for the related CBOR\n\t\tformat\n\n\t\t@since version 2.0.9; parameter @a start_index since 2.1.1; changed to\n\t\tconsume input adapters, removed start_index parameter, and added\n\t\t@a strict parameter since 3.0.0\n\t\t*/\n\t\tstatic basic_json from_msgpack(detail::input_adapter i,\n\t\t\tconst bool strict = true)\n\t\t{\n\t\t\treturn binary_reader(i).parse_msgpack(strict);\n\t\t}\n\n\t\t/*!\n\t\t@copydoc from_msgpack(detail::input_adapter, const bool)\n\t\t*/\n\t\ttemplate<typename A1, typename A2,\n\t\t\tdetail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>\n\t\t\tstatic basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true)\n\t\t{\n\t\t\treturn binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_msgpack(strict);\n\t\t}\n\n\t\t/// @}\n\n\t\t//////////////////////////\n\t\t// JSON Pointer support //\n\t\t//////////////////////////\n\n\t\t/// @name JSON Pointer functions\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief access specified element via JSON Pointer\n\n\t\tUses a JSON pointer to retrieve a reference to the respective JSON value.\n\t\tNo bound checking is performed. Similar to @ref operator[](const typename\n\t\tobject_t::key_type&), `null` values are created in arrays and objects if\n\t\tnecessary.\n\n\t\tIn particular:\n\t\t- If the JSON pointer points to an object key that does not exist, it\n\t\tis created an filled with a `null` value before a reference to it\n\t\tis returned.\n\t\t- If the JSON pointer points to an array index that does not exist, it\n\t\tis created an filled with a `null` value before a reference to it\n\t\tis returned. All indices between the current maximum and the given\n\t\tindex are also filled with `null`.\n\t\t- The special value `-` is treated as a synonym for the index past the\n\t\tend.\n\n\t\t@param[in] ptr  a JSON pointer\n\n\t\t@return reference to the element pointed to by @a ptr\n\n\t\t@complexity Constant.\n\n\t\t@throw parse_error.106   if an array index begins with '0'\n\t\t@throw parse_error.109   if an array index was not a number\n\t\t@throw out_of_range.404  if the JSON pointer can not be resolved\n\n\t\t@liveexample{The behavior is shown in the example.,operatorjson_pointer}\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\treference operator[](const json_pointer& ptr)\n\t\t{\n\t\t\treturn ptr.get_unchecked(this);\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified element via JSON Pointer\n\n\t\tUses a JSON pointer to retrieve a reference to the respective JSON value.\n\t\tNo bound checking is performed. The function does not change the JSON\n\t\tvalue; no `null` values are created. In particular, the the special value\n\t\t`-` yields an exception.\n\n\t\t@param[in] ptr  JSON pointer to the desired element\n\n\t\t@return const reference to the element pointed to by @a ptr\n\n\t\t@complexity Constant.\n\n\t\t@throw parse_error.106   if an array index begins with '0'\n\t\t@throw parse_error.109   if an array index was not a number\n\t\t@throw out_of_range.402  if the array index '-' is used\n\t\t@throw out_of_range.404  if the JSON pointer can not be resolved\n\n\t\t@liveexample{The behavior is shown in the example.,operatorjson_pointer_const}\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\tconst_reference operator[](const json_pointer& ptr) const\n\t\t{\n\t\t\treturn ptr.get_unchecked(this);\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified element via JSON Pointer\n\n\t\tReturns a reference to the element at with specified JSON pointer @a ptr,\n\t\twith bounds checking.\n\n\t\t@param[in] ptr  JSON pointer to the desired element\n\n\t\t@return reference to the element pointed to by @a ptr\n\n\t\t@throw parse_error.106 if an array index in the passed JSON pointer @a ptr\n\t\tbegins with '0'. See example below.\n\n\t\t@throw parse_error.109 if an array index in the passed JSON pointer @a ptr\n\t\tis not a number. See example below.\n\n\t\t@throw out_of_range.401 if an array index in the passed JSON pointer @a ptr\n\t\tis out of range. See example below.\n\n\t\t@throw out_of_range.402 if the array index '-' is used in the passed JSON\n\t\tpointer @a ptr. As `at` provides checked access (and no elements are\n\t\timplicitly inserted), the index '-' is always invalid. See example below.\n\n\t\t@throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.\n\t\tSee example below.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges in the JSON value.\n\n\t\t@complexity Constant.\n\n\t\t@since version 2.0.0\n\n\t\t@liveexample{The behavior is shown in the example.,at_json_pointer}\n\t\t*/\n\t\treference at(const json_pointer& ptr)\n\t\t{\n\t\t\treturn ptr.get_checked(this);\n\t\t}\n\n\t\t/*!\n\t\t@brief access specified element via JSON Pointer\n\n\t\tReturns a const reference to the element at with specified JSON pointer @a\n\t\tptr, with bounds checking.\n\n\t\t@param[in] ptr  JSON pointer to the desired element\n\n\t\t@return reference to the element pointed to by @a ptr\n\n\t\t@throw parse_error.106 if an array index in the passed JSON pointer @a ptr\n\t\tbegins with '0'. See example below.\n\n\t\t@throw parse_error.109 if an array index in the passed JSON pointer @a ptr\n\t\tis not a number. See example below.\n\n\t\t@throw out_of_range.401 if an array index in the passed JSON pointer @a ptr\n\t\tis out of range. See example below.\n\n\t\t@throw out_of_range.402 if the array index '-' is used in the passed JSON\n\t\tpointer @a ptr. As `at` provides checked access (and no elements are\n\t\timplicitly inserted), the index '-' is always invalid. See example below.\n\n\t\t@throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.\n\t\tSee example below.\n\n\t\t@exceptionsafety Strong guarantee: if an exception is thrown, there are no\n\t\tchanges in the JSON value.\n\n\t\t@complexity Constant.\n\n\t\t@since version 2.0.0\n\n\t\t@liveexample{The behavior is shown in the example.,at_json_pointer_const}\n\t\t*/\n\t\tconst_reference at(const json_pointer& ptr) const\n\t\t{\n\t\t\treturn ptr.get_checked(this);\n\t\t}\n\n\t\t/*!\n\t\t@brief return flattened JSON value\n\n\t\tThe function creates a JSON object whose keys are JSON pointers (see [RFC\n\t\t6901](https://tools.ietf.org/html/rfc6901)) and whose values are all\n\t\tprimitive. The original JSON value can be restored using the @ref\n\t\tunflatten() function.\n\n\t\t@return an object that maps JSON pointers to primitive values\n\n\t\t@note Empty objects and arrays are flattened to `null` and will not be\n\t\treconstructed correctly by the @ref unflatten() function.\n\n\t\t@complexity Linear in the size the JSON value.\n\n\t\t@liveexample{The following code shows how a JSON object is flattened to an\n\t\tobject whose keys consist of JSON pointers.,flatten}\n\n\t\t@sa @ref unflatten() for the reverse function\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\tbasic_json flatten() const\n\t\t{\n\t\t\tbasic_json result(value_t::object);\n\t\t\tjson_pointer::flatten(\"\", *this, result);\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief unflatten a previously flattened JSON value\n\n\t\tThe function restores the arbitrary nesting of a JSON value that has been\n\t\tflattened before using the @ref flatten() function. The JSON value must\n\t\tmeet certain constraints:\n\t\t1. The value must be an object.\n\t\t2. The keys must be JSON pointers (see\n\t\t[RFC 6901](https://tools.ietf.org/html/rfc6901))\n\t\t3. The mapped values must be primitive JSON types.\n\n\t\t@return the original JSON from a flattened version\n\n\t\t@note Empty objects and arrays are flattened by @ref flatten() to `null`\n\t\tvalues and can not unflattened to their original type. Apart from\n\t\tthis example, for a JSON value `j`, the following is always true:\n\t\t`j == j.flatten().unflatten()`.\n\n\t\t@complexity Linear in the size the JSON value.\n\n\t\t@throw type_error.314  if value is not an object\n\t\t@throw type_error.315  if object values are not primitive\n\n\t\t@liveexample{The following code shows how a flattened JSON object is\n\t\tunflattened into the original nested JSON object.,unflatten}\n\n\t\t@sa @ref flatten() for the reverse function\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\tbasic_json unflatten() const\n\t\t{\n\t\t\treturn json_pointer::unflatten(*this);\n\t\t}\n\n\t\t/// @}\n\n\t\t//////////////////////////\n\t\t// JSON Patch functions //\n\t\t//////////////////////////\n\n\t\t/// @name JSON Patch functions\n\t\t/// @{\n\n\t\t/*!\n\t\t@brief applies a JSON patch\n\n\t\t[JSON Patch](http://jsonpatch.com) defines a JSON document structure for\n\t\texpressing a sequence of operations to apply to a JSON) document. With\n\t\tthis function, a JSON Patch is applied to the current JSON value by\n\t\texecuting all operations from the patch.\n\n\t\t@param[in] json_patch  JSON patch document\n\t\t@return patched document\n\n\t\t@note The application of a patch is atomic: Either all operations succeed\n\t\tand the patched document is returned or an exception is thrown. In\n\t\tany case, the original value is not changed: the patch is applied\n\t\tto a copy of the value.\n\n\t\t@throw parse_error.104 if the JSON patch does not consist of an array of\n\t\tobjects\n\n\t\t@throw parse_error.105 if the JSON patch is malformed (e.g., mandatory\n\t\tattributes are missing); example: `\"operation add must have member path\"`\n\n\t\t@throw out_of_range.401 if an array index is out of range.\n\n\t\t@throw out_of_range.403 if a JSON pointer inside the patch could not be\n\t\tresolved successfully in the current JSON value; example: `\"key baz not\n\t\tfound\"`\n\n\t\t@throw out_of_range.405 if JSON pointer has no parent (\"add\", \"remove\",\n\t\t\"move\")\n\n\t\t@throw other_error.501 if \"test\" operation was unsuccessful\n\n\t\t@complexity Linear in the size of the JSON value and the length of the\n\t\tJSON patch. As usually only a fraction of the JSON value is affected by\n\t\tthe patch, the complexity can usually be neglected.\n\n\t\t@liveexample{The following code shows how a JSON patch is applied to a\n\t\tvalue.,patch}\n\n\t\t@sa @ref diff -- create a JSON patch by comparing two JSON values\n\n\t\t@sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)\n\t\t@sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\tbasic_json patch(const basic_json& json_patch) const\n\t\t{\n\t\t\t// make a working copy to apply the patch to\n\t\t\tbasic_json result = *this;\n\n\t\t\t// the valid JSON Patch operations\n\t\t\tenum class patch_operations { add, remove, replace, move, copy, test, invalid };\n\n\t\t\tconst auto get_op = [](const std::string & op)\n\t\t\t{\n\t\t\t\tif (op == \"add\")\n\t\t\t\t{\n\t\t\t\t\treturn patch_operations::add;\n\t\t\t\t}\n\t\t\t\tif (op == \"remove\")\n\t\t\t\t{\n\t\t\t\t\treturn patch_operations::remove;\n\t\t\t\t}\n\t\t\t\tif (op == \"replace\")\n\t\t\t\t{\n\t\t\t\t\treturn patch_operations::replace;\n\t\t\t\t}\n\t\t\t\tif (op == \"move\")\n\t\t\t\t{\n\t\t\t\t\treturn patch_operations::move;\n\t\t\t\t}\n\t\t\t\tif (op == \"copy\")\n\t\t\t\t{\n\t\t\t\t\treturn patch_operations::copy;\n\t\t\t\t}\n\t\t\t\tif (op == \"test\")\n\t\t\t\t{\n\t\t\t\t\treturn patch_operations::test;\n\t\t\t\t}\n\n\t\t\t\treturn patch_operations::invalid;\n\t\t\t};\n\n\t\t\t// wrapper for \"add\" operation; add value at ptr\n\t\t\tconst auto operation_add = [&result](json_pointer & ptr, basic_json val)\n\t\t\t{\n\t\t\t\t// adding to the root of the target document means replacing it\n\t\t\t\tif (ptr.is_root())\n\t\t\t\t{\n\t\t\t\t\tresult = val;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// make sure the top element of the pointer exists\n\t\t\t\t\tjson_pointer top_pointer = ptr.top();\n\t\t\t\t\tif (top_pointer != ptr)\n\t\t\t\t\t{\n\t\t\t\t\t\tresult.at(top_pointer);\n\t\t\t\t\t}\n\n\t\t\t\t\t// get reference to parent of JSON pointer ptr\n\t\t\t\t\tconst auto last_path = ptr.pop_back();\n\t\t\t\t\tbasic_json& parent = result[ptr];\n\n\t\t\t\t\tswitch (parent.m_type)\n\t\t\t\t\t{\n\t\t\t\t\tcase value_t::null:\n\t\t\t\t\tcase value_t::object:\n\t\t\t\t\t{\n\t\t\t\t\t\t// use operator[] to add value\n\t\t\t\t\t\tparent[last_path] = val;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase value_t::array:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (last_path == \"-\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// special case: append to back\n\t\t\t\t\t\t\tparent.push_back(val);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst auto idx = std::stoi(last_path);\n\t\t\t\t\t\t\tif (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// avoid undefined behavior\n\t\t\t\t\t\t\t\tJSON_THROW(out_of_range::create(401, \"array index \" + std::to_string(idx) + \" is out of range\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// default case: insert add offset\n\t\t\t\t\t\t\t\tparent.insert(parent.begin() + static_cast<difference_type>(idx), val);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t{\n\t\t\t\t\t\t// if there exists a parent it cannot be primitive\n\t\t\t\t\t\tassert(false);  // LCOV_EXCL_LINE\n\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// wrapper for \"remove\" operation; remove value at ptr\n\t\t\tconst auto operation_remove = [&result](json_pointer & ptr)\n\t\t\t{\n\t\t\t\t// get reference to parent of JSON pointer ptr\n\t\t\t\tconst auto last_path = ptr.pop_back();\n\t\t\t\tbasic_json& parent = result.at(ptr);\n\n\t\t\t\t// remove child\n\t\t\t\tif (parent.is_object())\n\t\t\t\t{\n\t\t\t\t\t// perform range check\n\t\t\t\t\tauto it = parent.find(last_path);\n\t\t\t\t\tif (JSON_LIKELY(it != parent.end()))\n\t\t\t\t\t{\n\t\t\t\t\t\tparent.erase(it);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tJSON_THROW(out_of_range::create(403, \"key '\" + last_path + \"' not found\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (parent.is_array())\n\t\t\t\t{\n\t\t\t\t\t// note erase performs range check\n\t\t\t\t\tparent.erase(static_cast<size_type>(std::stoi(last_path)));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// type check: top level value must be an array\n\t\t\tif (JSON_UNLIKELY(not json_patch.is_array()))\n\t\t\t{\n\t\t\t\tJSON_THROW(parse_error::create(104, 0, \"JSON patch must be an array of objects\"));\n\t\t\t}\n\n\t\t\t// iterate and apply the operations\n\t\t\tfor (const auto& val : json_patch)\n\t\t\t{\n\t\t\t\t// wrapper to get a value for an operation\n\t\t\t\tconst auto get_value = [&val](const std::string & op,\n\t\t\t\t\tconst std::string & member,\n\t\t\t\t\tbool string_type) -> basic_json&\n\t\t\t\t{\n\t\t\t\t\t// find value\n\t\t\t\t\tauto it = val.m_value.object->find(member);\n\n\t\t\t\t\t// context-sensitive error message\n\t\t\t\t\tconst auto error_msg = (op == \"op\") ? \"operation\" : \"operation '\" + op + \"'\";\n\n\t\t\t\t\t// check if desired value is present\n\t\t\t\t\tif (JSON_UNLIKELY(it == val.m_value.object->end()))\n\t\t\t\t\t{\n\t\t\t\t\t\tJSON_THROW(parse_error::create(105, 0, error_msg + \" must have member '\" + member + \"'\"));\n\t\t\t\t\t}\n\n\t\t\t\t\t// check if result is of type string\n\t\t\t\t\tif (JSON_UNLIKELY(string_type and not it->second.is_string()))\n\t\t\t\t\t{\n\t\t\t\t\t\tJSON_THROW(parse_error::create(105, 0, error_msg + \" must have string member '\" + member + \"'\"));\n\t\t\t\t\t}\n\n\t\t\t\t\t// no error: return value\n\t\t\t\t\treturn it->second;\n\t\t\t\t};\n\n\t\t\t\t// type check: every element of the array must be an object\n\t\t\t\tif (JSON_UNLIKELY(not val.is_object()))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(parse_error::create(104, 0, \"JSON patch must be an array of objects\"));\n\t\t\t\t}\n\n\t\t\t\t// collect mandatory members\n\t\t\t\tconst std::string op = get_value(\"op\", \"op\", true);\n\t\t\t\tconst std::string path = get_value(op, \"path\", true);\n\t\t\t\tjson_pointer ptr(path);\n\n\t\t\t\tswitch (get_op(op))\n\t\t\t\t{\n\t\t\t\tcase patch_operations::add:\n\t\t\t\t{\n\t\t\t\t\toperation_add(ptr, get_value(\"add\", \"value\", false));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase patch_operations::remove:\n\t\t\t\t{\n\t\t\t\t\toperation_remove(ptr);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase patch_operations::replace:\n\t\t\t\t{\n\t\t\t\t\t// the \"path\" location must exist - use at()\n\t\t\t\t\tresult.at(ptr) = get_value(\"replace\", \"value\", false);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase patch_operations::move:\n\t\t\t\t{\n\t\t\t\t\tconst std::string from_path = get_value(\"move\", \"from\", true);\n\t\t\t\t\tjson_pointer from_ptr(from_path);\n\n\t\t\t\t\t// the \"from\" location must exist - use at()\n\t\t\t\t\tbasic_json v = result.at(from_ptr);\n\n\t\t\t\t\t// The move operation is functionally identical to a\n\t\t\t\t\t// \"remove\" operation on the \"from\" location, followed\n\t\t\t\t\t// immediately by an \"add\" operation at the target\n\t\t\t\t\t// location with the value that was just removed.\n\t\t\t\t\toperation_remove(from_ptr);\n\t\t\t\t\toperation_add(ptr, v);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase patch_operations::copy:\n\t\t\t\t{\n\t\t\t\t\tconst std::string from_path = get_value(\"copy\", \"from\", true);\n\t\t\t\t\tconst json_pointer from_ptr(from_path);\n\n\t\t\t\t\t// the \"from\" location must exist - use at()\n\t\t\t\t\tresult[ptr] = result.at(from_ptr);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase patch_operations::test:\n\t\t\t\t{\n\t\t\t\t\tbool success = false;\n\t\t\t\t\tJSON_TRY\n\t\t\t\t\t{\n\t\t\t\t\t\t// check if \"value\" matches the one at \"path\"\n\t\t\t\t\t\t// the \"path\" location must exist - use at()\n\t\t\t\t\t\tsuccess = (result.at(ptr) == get_value(\"test\", \"value\", false));\n\t\t\t\t\t}\n\t\t\t\t\t\tJSON_CATCH(out_of_range&)\n\t\t\t\t\t{\n\t\t\t\t\t\t// ignore out of range errors: success remains false\n\t\t\t\t\t}\n\n\t\t\t\t\t// throw an exception if test fails\n\t\t\t\t\tif (JSON_UNLIKELY(not success))\n\t\t\t\t\t{\n\t\t\t\t\t\tJSON_THROW(other_error::create(501, \"unsuccessful: \" + val.dump()));\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase patch_operations::invalid:\n\t\t\t\t{\n\t\t\t\t\t// op must be \"add\", \"remove\", \"replace\", \"move\", \"copy\", or\n\t\t\t\t\t// \"test\"\n\t\t\t\t\tJSON_THROW(parse_error::create(105, 0, \"operation value '\" + op + \"' is invalid\"));\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t/*!\n\t\t@brief creates a diff as a JSON patch\n\n\t\tCreates a [JSON Patch](http://jsonpatch.com) so that value @a source can\n\t\tbe changed into the value @a target by calling @ref patch function.\n\n\t\t@invariant For two JSON values @a source and @a target, the following code\n\t\tyields always `true`:\n\t\t@code {.cpp}\n\t\tsource.patch(diff(source, target)) == target;\n\t\t@endcode\n\n\t\t@note Currently, only `remove`, `add`, and `replace` operations are\n\t\tgenerated.\n\n\t\t@param[in] source  JSON value to compare from\n\t\t@param[in] target  JSON value to compare against\n\t\t@param[in] path    helper value to create JSON pointers\n\n\t\t@return a JSON patch to convert the @a source to @a target\n\n\t\t@complexity Linear in the lengths of @a source and @a target.\n\n\t\t@liveexample{The following code shows how a JSON patch is created as a\n\t\tdiff for two JSON values.,diff}\n\n\t\t@sa @ref patch -- apply a JSON patch\n\n\t\t@sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)\n\n\t\t@since version 2.0.0\n\t\t*/\n\t\tstatic basic_json diff(const basic_json& source, const basic_json& target,\n\t\t\tconst std::string& path = \"\")\n\t\t{\n\t\t\t// the patch\n\t\t\tbasic_json result(value_t::array);\n\n\t\t\t// if the values are the same, return empty patch\n\t\t\tif (source == target)\n\t\t\t{\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tif (source.type() != target.type())\n\t\t\t{\n\t\t\t\t// different types: replace value\n\t\t\t\tresult.push_back(\n\t\t\t\t{\n\t\t\t\t\t{ \"op\", \"replace\" },{ \"path\", path },{ \"value\", target }\n\t\t\t\t});\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tswitch (source.type())\n\t\t\t\t{\n\t\t\t\tcase value_t::array:\n\t\t\t\t{\n\t\t\t\t\t// first pass: traverse common elements\n\t\t\t\t\tstd::size_t i = 0;\n\t\t\t\t\twhile (i < source.size() and i < target.size())\n\t\t\t\t\t{\n\t\t\t\t\t\t// recursive call to compare array values at index i\n\t\t\t\t\t\tauto temp_diff = diff(source[i], target[i], path + \"/\" + std::to_string(i));\n\t\t\t\t\t\tresult.insert(result.end(), temp_diff.begin(), temp_diff.end());\n\t\t\t\t\t\t++i;\n\t\t\t\t\t}\n\n\t\t\t\t\t// i now reached the end of at least one array\n\t\t\t\t\t// in a second pass, traverse the remaining elements\n\n\t\t\t\t\t// remove my remaining elements\n\t\t\t\t\tconst auto end_index = static_cast<difference_type>(result.size());\n\t\t\t\t\twhile (i < source.size())\n\t\t\t\t\t{\n\t\t\t\t\t\t// add operations in reverse order to avoid invalid\n\t\t\t\t\t\t// indices\n\t\t\t\t\t\tresult.insert(result.begin() + end_index, object(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t{ \"op\", \"remove\" },\n\t\t\t\t\t\t\t{ \"path\", path + \"/\" + std::to_string(i) }\n\t\t\t\t\t\t}));\n\t\t\t\t\t\t++i;\n\t\t\t\t\t}\n\n\t\t\t\t\t// add other remaining elements\n\t\t\t\t\twhile (i < target.size())\n\t\t\t\t\t{\n\t\t\t\t\t\tresult.push_back(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t{ \"op\", \"add\" },\n\t\t\t\t\t\t\t{ \"path\", path + \"/\" + std::to_string(i) },\n\t\t\t\t\t\t\t{ \"value\", target[i] }\n\t\t\t\t\t\t});\n\t\t\t\t\t\t++i;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase value_t::object:\n\t\t\t\t{\n\t\t\t\t\t// first pass: traverse this object's elements\n\t\t\t\t\tfor (auto it = source.begin(); it != source.end(); ++it)\n\t\t\t\t\t{\n\t\t\t\t\t\t// escape the key name to be used in a JSON patch\n\t\t\t\t\t\tconst auto key = json_pointer::escape(it.key());\n\n\t\t\t\t\t\tif (target.find(it.key()) != target.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// recursive call to compare object values at key it\n\t\t\t\t\t\t\tauto temp_diff = diff(it.value(), target[it.key()], path + \"/\" + key);\n\t\t\t\t\t\t\tresult.insert(result.end(), temp_diff.begin(), temp_diff.end());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// found a key that is not in o -> remove it\n\t\t\t\t\t\t\tresult.push_back(object(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t{ \"op\", \"remove\" },{ \"path\", path + \"/\" + key }\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// second pass: traverse other object's elements\n\t\t\t\t\tfor (auto it = target.begin(); it != target.end(); ++it)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (source.find(it.key()) == source.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// found a key that is not in this -> add it\n\t\t\t\t\t\t\tconst auto key = json_pointer::escape(it.key());\n\t\t\t\t\t\t\tresult.push_back(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t{ \"op\", \"add\" },{ \"path\", path + \"/\" + key },\n\t\t\t\t\t\t\t\t{ \"value\", it.value() }\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\t// both primitive type: replace value\n\t\t\t\t\tresult.push_back(\n\t\t\t\t\t{\n\t\t\t\t\t\t{ \"op\", \"replace\" },{ \"path\", path },{ \"value\", target }\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\t/// @}\n\t};\n\n\t/////////////\n\t// presets //\n\t/////////////\n\n\t/*!\n\t@brief default JSON class\n\n\tThis type is the default specialization of the @ref basic_json class which\n\tuses the standard template types.\n\n\t@since version 1.0.0\n\t*/\n\tusing json = basic_json<>;\n\n\t//////////////////\n\t// json_pointer //\n\t//////////////////\n\n\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\tNLOHMANN_BASIC_JSON_TPL&\n\t\tjson_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const\n\t{\n\t\tusing size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;\n\t\tauto result = &j;\n\n\t\t// in case no reference tokens exist, return a reference to the JSON value\n\t\t// j which will be overwritten by a primitive value\n\t\tfor (const auto& reference_token : reference_tokens)\n\t\t{\n\t\t\tswitch (result->m_type)\n\t\t\t{\n\t\t\tcase detail::value_t::null:\n\t\t\t{\n\t\t\t\tif (reference_token == \"0\")\n\t\t\t\t{\n\t\t\t\t\t// start a new array if reference token is 0\n\t\t\t\t\tresult = &result->operator[](0);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// start a new object otherwise\n\t\t\t\t\tresult = &result->operator[](reference_token);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase detail::value_t::object:\n\t\t\t{\n\t\t\t\t// create an entry in the object\n\t\t\t\tresult = &result->operator[](reference_token);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase detail::value_t::array:\n\t\t\t{\n\t\t\t\t// create an entry in the array\n\t\t\t\tJSON_TRY\n\t\t\t\t{\n\t\t\t\t\tresult = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));\n\t\t\t\t}\n\t\t\t\t\tJSON_CATCH(std::invalid_argument&)\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\tThe following code is only reached if there exists a reference\n\t\t\ttoken _and_ the current value is primitive. In this case, we have\n\t\t\tan error situation, because primitive values may only occur as\n\t\t\tsingle value; that is, with an empty list of reference tokens.\n\t\t\t*/\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(detail::type_error::create(313, \"invalid value to unflatten\"));\n\t\t\t}\n\t\t}\n\n\t\treturn *result;\n\t}\n\n\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\tNLOHMANN_BASIC_JSON_TPL&\n\t\tjson_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const\n\t{\n\t\tusing size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;\n\t\tfor (const auto& reference_token : reference_tokens)\n\t\t{\n\t\t\t// convert null values to arrays or objects before continuing\n\t\t\tif (ptr->m_type == detail::value_t::null)\n\t\t\t{\n\t\t\t\t// check if reference token is a number\n\t\t\t\tconst bool nums =\n\t\t\t\t\tstd::all_of(reference_token.begin(), reference_token.end(),\n\t\t\t\t\t\t[](const char x)\n\t\t\t\t{\n\t\t\t\t\treturn (x >= '0' and x <= '9');\n\t\t\t\t});\n\n\t\t\t\t// change value to array for numbers or \"-\" or to object otherwise\n\t\t\t\t*ptr = (nums or reference_token == \"-\")\n\t\t\t\t\t? detail::value_t::array\n\t\t\t\t\t: detail::value_t::object;\n\t\t\t}\n\n\t\t\tswitch (ptr->m_type)\n\t\t\t{\n\t\t\tcase detail::value_t::object:\n\t\t\t{\n\t\t\t\t// use unchecked object access\n\t\t\t\tptr = &ptr->operator[](reference_token);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase detail::value_t::array:\n\t\t\t{\n\t\t\t\t// error condition (cf. RFC 6901, Sect. 4)\n\t\t\t\tif (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(detail::parse_error::create(106, 0,\n\t\t\t\t\t\t\"array index '\" + reference_token +\n\t\t\t\t\t\t\"' must not begin with '0'\"));\n\t\t\t\t}\n\n\t\t\t\tif (reference_token == \"-\")\n\t\t\t\t{\n\t\t\t\t\t// explicitly treat \"-\" as index beyond the end\n\t\t\t\t\tptr = &ptr->operator[](ptr->m_value.array->size());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// convert array index to number; unchecked access\n\t\t\t\t\tJSON_TRY\n\t\t\t\t\t{\n\t\t\t\t\t\tptr = &ptr->operator[](\n\t\t\t\t\t\t\tstatic_cast<size_type>(std::stoi(reference_token)));\n\t\t\t\t\t}\n\t\t\t\t\t\tJSON_CATCH(std::invalid_argument&)\n\t\t\t\t\t{\n\t\t\t\t\t\tJSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(detail::out_of_range::create(404, \"unresolved reference token '\" + reference_token + \"'\"));\n\t\t\t}\n\t\t}\n\n\t\treturn *ptr;\n\t}\n\n\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\tNLOHMANN_BASIC_JSON_TPL&\n\t\tjson_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const\n\t{\n\t\tusing size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;\n\t\tfor (const auto& reference_token : reference_tokens)\n\t\t{\n\t\t\tswitch (ptr->m_type)\n\t\t\t{\n\t\t\tcase detail::value_t::object:\n\t\t\t{\n\t\t\t\t// note: at performs range check\n\t\t\t\tptr = &ptr->at(reference_token);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase detail::value_t::array:\n\t\t\t{\n\t\t\t\tif (JSON_UNLIKELY(reference_token == \"-\"))\n\t\t\t\t{\n\t\t\t\t\t// \"-\" always fails the range check\n\t\t\t\t\tJSON_THROW(detail::out_of_range::create(402,\n\t\t\t\t\t\t\"array index '-' (\" + std::to_string(ptr->m_value.array->size()) +\n\t\t\t\t\t\t\") is out of range\"));\n\t\t\t\t}\n\n\t\t\t\t// error condition (cf. RFC 6901, Sect. 4)\n\t\t\t\tif (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(detail::parse_error::create(106, 0,\n\t\t\t\t\t\t\"array index '\" + reference_token +\n\t\t\t\t\t\t\"' must not begin with '0'\"));\n\t\t\t\t}\n\n\t\t\t\t// note: at performs range check\n\t\t\t\tJSON_TRY\n\t\t\t\t{\n\t\t\t\t\tptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));\n\t\t\t\t}\n\t\t\t\t\tJSON_CATCH(std::invalid_argument&)\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(detail::out_of_range::create(404, \"unresolved reference token '\" + reference_token + \"'\"));\n\t\t\t}\n\t\t}\n\n\t\treturn *ptr;\n\t}\n\n\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\tconst NLOHMANN_BASIC_JSON_TPL&\n\t\tjson_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const\n\t{\n\t\tusing size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;\n\t\tfor (const auto& reference_token : reference_tokens)\n\t\t{\n\t\t\tswitch (ptr->m_type)\n\t\t\t{\n\t\t\tcase detail::value_t::object:\n\t\t\t{\n\t\t\t\t// use unchecked object access\n\t\t\t\tptr = &ptr->operator[](reference_token);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase detail::value_t::array:\n\t\t\t{\n\t\t\t\tif (JSON_UNLIKELY(reference_token == \"-\"))\n\t\t\t\t{\n\t\t\t\t\t// \"-\" cannot be used for const access\n\t\t\t\t\tJSON_THROW(detail::out_of_range::create(402,\n\t\t\t\t\t\t\"array index '-' (\" + std::to_string(ptr->m_value.array->size()) +\n\t\t\t\t\t\t\") is out of range\"));\n\t\t\t\t}\n\n\t\t\t\t// error condition (cf. RFC 6901, Sect. 4)\n\t\t\t\tif (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(detail::parse_error::create(106, 0,\n\t\t\t\t\t\t\"array index '\" + reference_token +\n\t\t\t\t\t\t\"' must not begin with '0'\"));\n\t\t\t\t}\n\n\t\t\t\t// use unchecked array access\n\t\t\t\tJSON_TRY\n\t\t\t\t{\n\t\t\t\t\tptr = &ptr->operator[](\n\t\t\t\t\t\tstatic_cast<size_type>(std::stoi(reference_token)));\n\t\t\t\t}\n\t\t\t\t\tJSON_CATCH(std::invalid_argument&)\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(detail::out_of_range::create(404, \"unresolved reference token '\" + reference_token + \"'\"));\n\t\t\t}\n\t\t}\n\n\t\treturn *ptr;\n\t}\n\n\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\tconst NLOHMANN_BASIC_JSON_TPL&\n\t\tjson_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const\n\t{\n\t\tusing size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;\n\t\tfor (const auto& reference_token : reference_tokens)\n\t\t{\n\t\t\tswitch (ptr->m_type)\n\t\t\t{\n\t\t\tcase detail::value_t::object:\n\t\t\t{\n\t\t\t\t// note: at performs range check\n\t\t\t\tptr = &ptr->at(reference_token);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase detail::value_t::array:\n\t\t\t{\n\t\t\t\tif (JSON_UNLIKELY(reference_token == \"-\"))\n\t\t\t\t{\n\t\t\t\t\t// \"-\" always fails the range check\n\t\t\t\t\tJSON_THROW(detail::out_of_range::create(402,\n\t\t\t\t\t\t\"array index '-' (\" + std::to_string(ptr->m_value.array->size()) +\n\t\t\t\t\t\t\") is out of range\"));\n\t\t\t\t}\n\n\t\t\t\t// error condition (cf. RFC 6901, Sect. 4)\n\t\t\t\tif (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(detail::parse_error::create(106, 0,\n\t\t\t\t\t\t\"array index '\" + reference_token +\n\t\t\t\t\t\t\"' must not begin with '0'\"));\n\t\t\t\t}\n\n\t\t\t\t// note: at performs range check\n\t\t\t\tJSON_TRY\n\t\t\t\t{\n\t\t\t\t\tptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));\n\t\t\t\t}\n\t\t\t\t\tJSON_CATCH(std::invalid_argument&)\n\t\t\t\t{\n\t\t\t\t\tJSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tJSON_THROW(detail::out_of_range::create(404, \"unresolved reference token '\" + reference_token + \"'\"));\n\t\t\t}\n\t\t}\n\n\t\treturn *ptr;\n\t}\n\n\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\tvoid json_pointer::flatten(const std::string& reference_string,\n\t\t\tconst NLOHMANN_BASIC_JSON_TPL& value,\n\t\t\tNLOHMANN_BASIC_JSON_TPL& result)\n\t{\n\t\tswitch (value.m_type)\n\t\t{\n\t\tcase detail::value_t::array:\n\t\t{\n\t\t\tif (value.m_value.array->empty())\n\t\t\t{\n\t\t\t\t// flatten empty array as null\n\t\t\t\tresult[reference_string] = nullptr;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// iterate array and use index as reference string\n\t\t\t\tfor (std::size_t i = 0; i < value.m_value.array->size(); ++i)\n\t\t\t\t{\n\t\t\t\t\tflatten(reference_string + \"/\" + std::to_string(i),\n\t\t\t\t\t\tvalue.m_value.array->operator[](i), result);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase detail::value_t::object:\n\t\t{\n\t\t\tif (value.m_value.object->empty())\n\t\t\t{\n\t\t\t\t// flatten empty object as null\n\t\t\t\tresult[reference_string] = nullptr;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// iterate object and use keys as reference string\n\t\t\t\tfor (const auto& element : *value.m_value.object)\n\t\t\t\t{\n\t\t\t\t\tflatten(reference_string + \"/\" + escape(element.first), element.second, result);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault:\n\t\t{\n\t\t\t// add primitive value with its reference string\n\t\t\tresult[reference_string] = value;\n\t\t\tbreak;\n\t\t}\n\t\t}\n\t}\n\n\tNLOHMANN_BASIC_JSON_TPL_DECLARATION\n\t\tNLOHMANN_BASIC_JSON_TPL\n\t\tjson_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value)\n\t{\n\t\tif (JSON_UNLIKELY(not value.is_object()))\n\t\t{\n\t\t\tJSON_THROW(detail::type_error::create(314, \"only objects can be unflattened\"));\n\t\t}\n\n\t\tNLOHMANN_BASIC_JSON_TPL result;\n\n\t\t// iterate the JSON object values\n\t\tfor (const auto& element : *value.m_value.object)\n\t\t{\n\t\t\tif (JSON_UNLIKELY(not element.second.is_primitive()))\n\t\t\t{\n\t\t\t\tJSON_THROW(detail::type_error::create(315, \"values in object must be primitive\"));\n\t\t\t}\n\n\t\t\t// assign value to reference pointed to by JSON pointer; Note that if\n\t\t\t// the JSON pointer is \"\" (i.e., points to the whole value), function\n\t\t\t// get_and_create returns a reference to result itself. An assignment\n\t\t\t// will then create a primitive value.\n\t\t\tjson_pointer(element.first).get_and_create(result) = element.second;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tinline bool operator==(json_pointer const& lhs, json_pointer const& rhs) noexcept\n\t{\n\t\treturn (lhs.reference_tokens == rhs.reference_tokens);\n\t}\n\n\tinline bool operator!=(json_pointer const& lhs, json_pointer const& rhs) noexcept\n\t{\n\t\treturn not (lhs == rhs);\n\t}\n} // namespace nlohmann\n\n\n  ///////////////////////\n  // nonmember support //\n  ///////////////////////\n\n  // specialization of std::swap, and std::hash\nnamespace std\n{\n\t/*!\n\t@brief exchanges the values of two JSON objects\n\n\t@since version 1.0.0\n\t*/\n\ttemplate<>\n\tinline void swap(nlohmann::json& j1,\n\t\tnlohmann::json& j2) noexcept(\n\t\t\tis_nothrow_move_constructible<nlohmann::json>::value and\n\t\t\tis_nothrow_move_assignable<nlohmann::json>::value\n\t\t\t)\n\t{\n\t\tj1.swap(j2);\n\t}\n\n\t/// hash value for JSON objects\n\ttemplate<>\n\tstruct hash<nlohmann::json>\n\t{\n\t\t/*!\n\t\t@brief return a hash value for a JSON object\n\n\t\t@since version 1.0.0\n\t\t*/\n\t\tstd::size_t operator()(const nlohmann::json& j) const\n\t\t{\n\t\t\t// a naive hashing via the string representation\n\t\t\tconst auto& h = hash<nlohmann::json::string_t>();\n\t\t\treturn h(j.dump());\n\t\t}\n\t};\n\n\t/// specialization for std::less<value_t>\n\t/// @note: do not remove the space after '<',\n\t///        see https://github.com/nlohmann/json/pull/679\n\ttemplate<>\n\tstruct less< ::nlohmann::detail::value_t>\n\t{\n\t\t/*!\n\t\t@brief compare two value_t enum values\n\t\t@since version 3.0.0\n\t\t*/\n\t\tbool operator()(nlohmann::detail::value_t lhs,\n\t\t\tnlohmann::detail::value_t rhs) const noexcept\n\t\t{\n\t\t\treturn nlohmann::detail::operator<(lhs, rhs);\n\t\t}\n\t};\n\n} // namespace std\n\n  /*!\n  @brief user-defined string literal for JSON values\n\n  This operator implements a user-defined string literal for JSON objects. It\n  can be used by adding `\"_json\"` to a string literal and returns a JSON object\n  if no parse error occurred.\n\n  @param[in] s  a string representation of a JSON object\n  @param[in] n  the length of string @a s\n  @return a JSON object\n\n  @since version 1.0.0\n  */\ninline nlohmann::json operator \"\" _json(const char* s, std::size_t n)\n{\n\treturn nlohmann::json::parse(s, s + n);\n}\n\n/*!\n@brief user-defined string literal for JSON pointer\n\nThis operator implements a user-defined string literal for JSON Pointers. It\ncan be used by adding `\"_json_pointer\"` to a string literal and returns a JSON pointer\nobject if no parse error occurred.\n\n@param[in] s  a string representation of a JSON Pointer\n@param[in] n  the length of string @a s\n@return a JSON pointer object\n\n@since version 2.0.0\n*/\ninline nlohmann::json::json_pointer operator \"\" _json_pointer(const char* s, std::size_t n)\n{\n\treturn nlohmann::json::json_pointer(std::string(s, n));\n}\n\n// restore GCC/clang diagnostic settings\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n#pragma GCC diagnostic pop\n#endif\n#if defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n\n// clean up\n#undef JSON_CATCH\n#undef JSON_THROW\n#undef JSON_TRY\n#undef JSON_LIKELY\n#undef JSON_UNLIKELY\n#undef JSON_DEPRECATED\n#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION\n#undef NLOHMANN_BASIC_JSON_TPL\n\n#endif\n"
  },
  {
    "path": "src/gpu/algorithm/gpu_algorithm_atomic.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"Declarations.hpp\"\n#include \"gpu/gpu_shell.hpp\"\n#include \"logging/Message.hpp\"\n\nnamespace Burst\n{\n\tstruct GpuAlgorithmAtomic\n\t{\n\t\ttemplate <typename TGpu_Impl>\n\t\tstatic bool run(ScoopData* scoops, const size_t size, const GensigData& gensig, Poco::UInt64 nonceStart,\n\t\t                Poco::UInt64 baseTarget, void* stream, std::pair<Poco::UInt64, Poco::UInt64>& bestDeadline)\n\t\t{\n\t\t\tusing Shell = GpuShell<TGpu_Impl>;\n\n\t\t\tbool ok;\n\t\t\tScoopData* gpuScoops;\n\t\t\tGensigData* gpuGensig;\n\t\t\tPoco::UInt64* gpuDeadlines;\n\t\t\tstd::string errorString;\n\t\t\tconst auto nonces = size;\n\t\t\tPoco::UInt64 minDeadline;\n\t\t\tPoco::UInt64 minDeadlineIndex;\n\n\t\t\t// allocate the memory for the gpu\n\t\t\tauto allocated = Shell::allocateMemory(reinterpret_cast<void**>(&gpuScoops), MemoryType::Buffer, nonces);\n\t\t\tallocated = allocated && Shell::allocateMemory(reinterpret_cast<void**>(&gpuGensig), MemoryType::Gensig, 1);\n\t\t\tallocated = allocated && Shell::allocateMemory(reinterpret_cast<void**>(&gpuDeadlines), MemoryType::Bytes, nonces * sizeof(Poco::UInt64));\n\n\t\t\tok = allocated;\n\n\t\t\t// copy the memory from RAM to gpu\n\t\t\tok = ok && Shell::copyMemory(scoops, gpuScoops, MemoryType::Buffer, nonces, MemoryCopyDirection::ToDevice, stream);\n\t\t\tok = ok && Shell::copyMemory(&gensig, gpuGensig, MemoryType::Gensig, 1, MemoryCopyDirection::ToDevice, stream);\n\n\t\t\t// calculate the deadlines on gpu\n\t\t\tok = ok && Shell::verify(gpuGensig, gpuScoops, gpuDeadlines, nonces, nonceStart, baseTarget, stream);\n\n\t\t\t// get the best deadline on gpu\n\t\t\tok = ok && Shell::getMinDeadline(gpuDeadlines, nonces, minDeadline, minDeadlineIndex, stream);\n\n\t\t\t// fetch the last error if there is one\n\t\t\tok = !Shell::getError(errorString);\n\n\t\t\tif (ok)\n\t\t\t{\n\t\t\t\tbestDeadline.first = nonceStart + minDeadlineIndex;\n\t\t\t\tbestDeadline.second = minDeadline;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// print the error\n\t\t\t\tlog_error(MinerLogger::plotVerifier, \"Error while verifying a plot file!\\n\\tError: %s\", errorString);\n\t\t\t}\n\n\t\t\t// give the memory on gpu free\n\t\t\tok = ok && Shell::freeMemory(gpuScoops);\n\t\t\tok = ok && Shell::freeMemory(gpuGensig);\n\t\t\tok = ok && Shell::freeMemory(gpuDeadlines);\n\t\t\t\n\t\t\treturn ok;\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "src/gpu/gpu_algorithm_shell.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <memory>\n#include <Poco/Types.h>\n\nnamespace Burst\n{\n\ttemplate <typename TAlgorithm>\n\tstruct GpuAlgorithmShell\n\t{\n\t\ttemplate <typename TGpuShell, typename ...TArgs>\n\t\tstatic std::pair<Poco::UInt64, Poco::UInt64> run(TArgs&&... args)\n\t\t{\n\t\t\treturn TAlgorithm::run(std::forward<TArgs&&>(args)...);\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "src/gpu/gpu_declarations.hpp",
    "content": "#pragma once\n\n#include <Poco/Types.h>\n\nnamespace Burst\n{\n\tstruct CalculatedDeadline\n\t{\n\t\tPoco::UInt64 deadline;\n\t\tPoco::UInt64 nonce;\n\t};\n\n\tenum class MemoryType\n\t{\n\t\tBuffer,\n\t\tGensig,\n\t\tDeadlines,\n\t\tBytes\n\t};\n\n\tenum class MemoryCopyDirection\n\t{\n\t\tToHost,\n\t\tToDevice\n\t};\n}\n"
  },
  {
    "path": "src/gpu/gpu_shell.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"impl/gpu_cuda_impl.hpp\"\n#include \"impl/gpu_opencl_impl.hpp\"\n\nnamespace Burst\n{\n\t/**\n\t * \\brief A shell class, that has simple functions that operates on a GPU.\n\t * The functions are adapters that call a real implementation.\n\t * \\tparam TImpl The implementation class.\n\t */\n\ttemplate <typename TImpl>\n\tstruct GpuShell\n\t{\n\t\t/**\n\t\t * \\brief An alias for the implementation.\n\t\t */\n\t\tusing ImplT = TImpl;\n\n\t\t/**\n\t\t* \\brief Initializes a new stream (queue).\n\t\t* \\tparam Args Variadic template types.\n\t\t* \\param args The arguments to create the stream.\n\t\t* \\return true, when the stream was created, false otherwise.\n\t\t*/\n\t\ttemplate <typename ...Args>\n\t\tstatic bool initStream(Args&&... args)\n\t\t{\n\t\t\treturn TImpl::initStream(std::forward<Args&&>(args)...);\n\t\t}\n\n\t\t/**\n\t\t * \\brief Allocates memory on the GPU.\n\t\t * \\tparam Args Variadic template types.\n\t\t * \\param args The arguments to create the memory.\n\t\t * \\return true, when the memory was allocated, false otherwise.\n\t\t */\n\t\ttemplate <typename ...Args>\n\t\tstatic bool allocateMemory(Args&&... args)\n\t\t{\n\t\t\treturn TImpl::allocateMemory(std::forward<Args&&>(args)...);\n\t\t}\n\n\t\t/**\n\t\t * \\brief Copies a memory block on the GUP to another memory block on the GPU.\n\t\t * \\tparam Args Variadic template types.\n\t\t * \\param args The arguments to copy the memory.\n\t\t * \\return true, when the memory was copied, false otherwise.\n\t\t */\n\t\ttemplate <typename ...Args>\n\t\tstatic bool copyMemory(Args&&... args)\n\t\t{\n\t\t\treturn TImpl::copyMemory(std::forward<Args&&>(args)...);\n\t\t}\n\n\t\t/**\n\t\t * \\brief Frees a memory block on the GPU.\n\t\t * \\tparam Args Variadic template types.\n\t\t * \\param args The arguments to free the memory.\n\t\t * \\return true, when the memory was freed, false otherwise.\n\t\t */\n\t\ttemplate <typename ...Args>\n\t\tstatic bool freeMemory(Args&&... args)\n\t\t{\n\t\t\treturn TImpl::freeMemory(std::forward<Args&&>(args)...);\n\t\t}\n\n\t\t/**\n\t\t * \\brief Searches for the best deadline in a memory block.\n\t\t * \\tparam Args Variadic template types.\n\t\t * \\param args The arguments that are needed to verify the deadlines.\n\t\t * \\return true, when there was an error, false otherwise.\n\t\t */\n\t\ttemplate <typename ...Args>\n\t\tstatic bool verify(Args&&... args)\n\t\t{\n\t\t\treturn TImpl::verify(std::forward<Args&&>(args)...);\n\t\t}\n\n\t\t/**\n\t\t * \\brief Searches for the best deadline in an array of deadlines.\n\t\t * \\tparam Args Variadic template types. \n\t\t * \\param args The arguments that are needed to search for the best deadline.\n\t\t * \\return true, when there was no error, false otherwise.\n\t\t */\n\t\ttemplate <typename ...Args>\n\t\tstatic bool getMinDeadline(Args&&... args)\n\t\t{\n\t\t\treturn TImpl::getMinDeadline(std::forward<Args&&>(args)...);\n\t\t}\n\n\t\t/**\n\t\t * \\brief Runs an algorithm to search for the best deadline in a memory block.\n\t\t * \\tparam TAlgorithm The type of the algorithm that is used.\n\t\t * \\tparam Args Variadic template types.\n\t\t * \\param args The arguments that are needed for the search of deadlines.\n\t\t * \\return true, when there was no error, false otherwise.\n\t\t */\n\t\ttemplate <typename TAlgorithm, typename ...Args>\n\t\tstatic bool run(Args&&... args)\n\t\t{\n\t\t\treturn TAlgorithm::template run<GpuShell>(std::forward<Args&&>(args)...);\n\t\t}\n\n\t\t/**\n\t\t * \\brief Gets the last error, if any occured.\n\t\t * \\tparam Args Variadic template types.\n\t\t * \\param args The arguments that are needed the get the last error.\n\t\t * \\return true, when there was an error, false otherwise.\n\t\t */\n\t\ttemplate <typename ...Args>\n\t\tstatic bool getError(Args&&... args)\n\t\t{\n\t\t\treturn TImpl::getError(std::forward<Args&&>(args)...);\n\t\t}\n\t};\n\n\tstruct GpuHelper\n\t{\n\t\t/**\n\t\t * \\brief Calculates the byte size a structure type.\n\t\t * \\param memType The type of the structure.\n\t\t * \\param size The amount of structures.\n\t\t * \\return The size of all structures in bytes.\n\t\t */\n\t\tstatic Poco::UInt64 calcMemorySize(const MemoryType memType, Poco::UInt64 size)\n\t\t{\n\t\t\tif (memType == MemoryType::Buffer)\n\t\t\t\tsize *= sizeof(Poco::UInt8) * Settings::scoopSize;\n\t\t\telse if (memType == MemoryType::Gensig)\n\t\t\t\tsize = sizeof(Poco::UInt8) * Settings::hashSize;\n\t\t\telse if (memType == MemoryType::Deadlines)\n\t\t\t\tsize *= sizeof(CalculatedDeadline);\n\n\t\t\treturn size;\n\t\t}\n\n\t\t/**\n\t\t * \\brief Calculates the bytes for a type.\n\t\t * \\tparam T The type.\n\t\t * \\param size The amount of types.\n\t\t * \\return The size of all types in bytes.\n\t\t */\n\t\ttemplate <typename T>\n\t\tstatic Poco::UInt64 calcMemorySize(const Poco::UInt64 size)\n\t\t{\n\t\t\treturn size * sizeof(T);\n\t\t}\n\t};\n\n\tusing GpuCuda = GpuShell<GpuCudaImpl>;\n\tusing GpuOpenCl = GpuShell<GpuOpenclImpl>;\n}\n"
  },
  {
    "path": "src/gpu/impl/gpu_cuda_impl.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"gpu_cuda_impl.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include \"shabal/cuda/Shabal.hpp\"\n#include \"mining/MinerData.hpp\"\n#include \"Declarations.hpp\"\n#include \"gpu/gpu_shell.hpp\"\n#include \"mining/MinerConfig.hpp\"\n\n#define check(x) if (!x) { log_critical(MinerLogger::plotVerifier, \"Error on %s\", std::string(#x)); return false; }\n\nbool Burst::GpuCudaImpl::initStream(void** stream)\n{\n\treturn true;\n}\n\nbool Burst::GpuCudaImpl::allocateMemory(void** memory, MemoryType type, size_t size)\n{\n\tuseDevice(MinerConfig::getConfig().getGpuPlatform());\n\tsize = GpuHelper::calcMemorySize(type, size);\n\tcheck(cuda_alloc_memory(size, memory));\n\treturn true;\n}\n\nbool Burst::GpuCudaImpl::verify(const GensigData* gpuGensig, ScoopData* gpuScoops, Poco::UInt64* gpuDeadlines,\n\tsize_t nonces, Poco::UInt64 nonceStart, Poco::UInt64 baseTarget, void* stream)\n{\n\tuseDevice(MinerConfig::getConfig().getGpuPlatform());\n\tstd::string errorString;\n\tcheck(cuda_calculate_shabal_host_preallocated(gpuScoops, gpuDeadlines, nonces, gpuGensig, nonceStart, baseTarget, errorString));\n\treturn true;\n}\n\nbool Burst::GpuCudaImpl::getMinDeadline(Poco::UInt64* gpuDeadlines, size_t size, Poco::UInt64& minDeadline, Poco::UInt64& minDeadlineIndex, void* stream)\n{\n\tuseDevice(MinerConfig::getConfig().getGpuPlatform());\n\tstd::string errorString;\n\tcheck(cuda_reduce_best_deadline(gpuDeadlines, size, minDeadline, minDeadlineIndex, errorString));\n\treturn true;\n}\n\nbool Burst::GpuCudaImpl::freeMemory(void* memory)\n{\n\tuseDevice(MinerConfig::getConfig().getGpuPlatform());\n\tcheck(cuda_free_memory(memory));\n\treturn true;\n}\n\nbool Burst::GpuCudaImpl::getError(std::string& errorString)\n{\n\tuseDevice(MinerConfig::getConfig().getGpuPlatform());\n\treturn cuda_get_error(errorString);\n}\n\nbool Burst::GpuCudaImpl::listDevices()\n{\n\tstd::vector<std::string> devices;\n\t\n\tcuda_get_devices(devices);\n\n\tif (devices.empty())\n\t\treturn true;\n\n\tlog_system(MinerLogger::general, \"CUDA devices:\");\n\n\tfor (auto i = 0u; i < devices.size(); ++i)\n\t\tlog_system(MinerLogger::general, \"\\tDevice[%u]: %s\", i, devices[i]);\n\n\treturn true;\n}\n\nbool Burst::GpuCudaImpl::useDevice(unsigned device)\n{\n\treturn cuda_set_device(device);\n}\n\nbool Burst::GpuCudaImpl::copyMemory(const void* input, void* output, MemoryType type, size_t size, MemoryCopyDirection direction, void* stream)\n{\n\tuseDevice(MinerConfig::getConfig().getGpuPlatform());\n\tsize = GpuHelper::calcMemorySize(type, size);\n\tcheck(cuda_copy_memory(size, input, output, direction));\n\treturn true;\n}\n\n#ifndef USE_CUDA\nvoid cuda_calc_occupancy(int bufferSize, int& gridSize, int& blockSize)\n{\n}\n\nbool cuda_alloc_memory(Poco::UInt64 size, void** mem) { return true; }\nbool cuda_realloc_memory(Poco::UInt64 size, void** mem) { return true; }\n\nbool cuda_copy_memory(Poco::UInt64 size, const void* from, void* to,\n\tBurst::MemoryCopyDirection copyDirection) {\n\treturn true;\n}\n\nbool cuda_free_memory(void* mem) { return true; }\nPoco::UInt64 cuda_calc_memory_size(Burst::MemoryType memType, Poco::UInt64 size) { return true; }\n\nbool cuda_calculate_shabal_host_preallocated(Burst::ScoopData* buffer, Poco::UInt64* deadlines, Poco::UInt64 bufferSize,\n\tconst Burst::GensigData* gensig,\n\tPoco::UInt64 nonceStart, Poco::UInt64 baseTarget, std::string& errorString)\n{\n\treturn true;\n}\n\nbool cuda_reduce_best_deadline(Poco::UInt64* deadlines, size_t size,\n\tPoco::UInt64& minDeadline, Poco::UInt64& index, std::string& errorString)\n{\n\treturn true;\n}\n\nbool cuda_get_error(std::string& errorString) { return false; }\nbool cuda_get_devices(std::vector<std::string>& devices) { return true; }\nbool cuda_set_device(unsigned index) { return true; }\n#endif\n"
  },
  {
    "path": "src/gpu/impl/gpu_cuda_impl.hpp",
    "content": "#pragma once\n\n#include <utility>\n#include <Poco/Types.h>\n#include \"gpu/gpu_declarations.hpp\"\n#include \"mining/MinerData.hpp\"\n\nnamespace Burst\n{\n\tstruct GpuCudaImpl\n\t{\n\t\tstatic bool initStream(void** stream);\n\t\tstatic bool allocateMemory(void** memory, MemoryType type, size_t size);\n\t\tstatic bool copyMemory(const void* input, void* output, MemoryType type, size_t size, MemoryCopyDirection direction, void* stream);\n\t\tstatic bool verify(const GensigData* gpuGensig, ScoopData* gpuScoops, Poco::UInt64* gpuDeadlines, size_t nonces,\n\t\t\tPoco::UInt64 nonceStart, Poco::UInt64 baseTarget, void* stream);\n\t\tstatic bool getMinDeadline(Poco::UInt64* gpuDeadlines, size_t size, Poco::UInt64& minDeadline, Poco::UInt64& minDeadlineIndex, void* stream);\n\t\tstatic bool freeMemory(void* memory);\n\t\tstatic bool getError(std::string& errorString);\n\t\tstatic bool listDevices();\n\t\tstatic bool useDevice(unsigned device);\n\t};\n}\n"
  },
  {
    "path": "src/gpu/impl/gpu_opencl_impl.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"gpu_opencl_impl.hpp\"\n#include \"mining/MinerCL.hpp\"\n#include \"gpu/gpu_shell.hpp\"\n#include <random>\n#include \"logging/Message.hpp\"\n#include \"logging/MinerLogger.hpp\"\n\nint Burst::GpuOpenclImpl::lastError_ = 0;\n\nbool Burst::GpuOpenclImpl::initStream(void** stream)\n{\n#ifdef USE_OPENCL\n\tconst auto queue = MinerCl::getCL().createCommandQueue();\n\n\tif (queue == nullptr)\n\t\treturn false;\n\n\t*stream = queue;\n#endif\n\treturn true;\n}\n\nbool Burst::GpuOpenclImpl::allocateMemory(void** memory, MemoryType type, size_t size)\n{\n#ifdef USE_OPENCL\n\tcl_int ret;\n\n\tsize = GpuHelper::calcMemorySize(type, size);\n\n\tif (size <= 0)\n\t\treturn false;\n\n\tconst auto allocated = clCreateBuffer(MinerCl::getCL().getContext(), CL_MEM_READ_WRITE, size, nullptr, &ret);\n\n\tif (ret == CL_SUCCESS)\n\t{\n\t\t*memory = allocated;\n\t\treturn true;\n\t}\n\n\tlastError_ = ret;\n\treturn false;\n#else\n\treturn true;\n#endif\n}\n\nnamespace Burst\n{\n\tstruct Gpu_Opencl_Impl_Helper\n\t{\n\t\tstatic size_t calcOccupancy(const size_t elements, const size_t local_optimal, const size_t local_preferred_multiply)\n\t\t{\n\t\t\tif (local_preferred_multiply == 0 || local_optimal == 0)\n\t\t\t\treturn 1;\n\n\t\t\tauto local = local_optimal;\n\n\t\t\tfor (auto i = local / local_preferred_multiply; i > 0 && local == local_optimal; i--)\n\t\t\t\tif (fmod(elements, i * local_preferred_multiply) == 0.f)\n\t\t\t\t\tlocal = i * local_preferred_multiply;\n\n\t\t\tif (local == local_optimal)\n\t\t\t\tlocal = 1;\n\n\t\t\treturn local;\n\t\t}\n\t};\n}\n\nbool Burst::GpuOpenclImpl::verify(const GensigData* gpuGensig, ScoopData* gpuScoops, Poco::UInt64* gpuDeadlines,\n\tsize_t nonces, Poco::UInt64 nonceStart, Poco::UInt64 baseTarget, void* stream)\n{\n#ifdef USE_OPENCL\n\tauto ret = clSetKernelArg(MinerCl::getCL().getKernel_Calculate(), 0, sizeof(cl_mem), &gpuGensig);\n\n\tif (ret == CL_SUCCESS)\n\t\tret = clSetKernelArg(MinerCl::getCL().getKernel_Calculate(), 1, sizeof(cl_mem), &gpuScoops);\n\n\tif (ret == CL_SUCCESS)\n\t\tret = clSetKernelArg(MinerCl::getCL().getKernel_Calculate(), 2, sizeof(cl_mem), &gpuDeadlines);\n\n\tif (ret == CL_SUCCESS)\n\t\tret = clSetKernelArg(MinerCl::getCL().getKernel_Calculate(), 3, sizeof(cl_ulong), reinterpret_cast<const void*>(&nonces));\n\t\n\tif (ret == CL_SUCCESS)\n\t\tret = clSetKernelArg(MinerCl::getCL().getKernel_Calculate(), 4, sizeof(cl_ulong), reinterpret_cast<const void*>(&baseTarget));\n\n\tif (ret != CL_SUCCESS)\n\t\treturn false;\n\n\tauto local = Gpu_Opencl_Impl_Helper::calcOccupancy(nonces, MinerCl::getCL().getKernelCalculateWorkGroupSize(),\n\t                                                   MinerCl::getCL().getKernelCalculateWorkGroupSize(true));\n\n\tret = clEnqueueNDRangeKernel(static_cast<cl_command_queue>(stream), MinerCl::getCL().getKernel_Calculate(), 1, nullptr,\n\t                             &nonces, &local, 0, nullptr, nullptr);\n\n\tif (ret != CL_SUCCESS)\n\t{\n\t\tlastError_ = ret;\n\t\treturn false;\n\t}\n#endif\n\treturn true;\n}\n\nbool Burst::GpuOpenclImpl::getMinDeadline(Poco::UInt64* gpuDeadlines, size_t size, Poco::UInt64& minDeadline, Poco::UInt64& minDeadlineIndex, void* stream)\n{\n#ifdef USE_OPENCL\n\tauto errorCode = CL_SUCCESS;\n\tPoco::UInt64* gpuBestMemory;\n\n\t//auto global = size;\n\t//const auto preferred_local_size = MinerCL::getCL().getKernelFindBestWorkGroupSize(true);\n\n\t//if (global % preferred_local_size != 0)\n\t//\tglobal = (global / preferred_local_size + 1) * preferred_local_size;\n\n\t//auto local = Gpu_Opencl_Impl_Helper::calcOccupancy(size, MinerCL::getCL().getKernelFindBestWorkGroupSize(),\n\t//                                                   MinerCL::getCL().getKernelFindBestWorkGroupSize(true));\n\n\t//auto local = MinerCL::getCL().getComputeUnits() * MinerCL::getCL().getKernelFindBestWorkGroupSize(true);\n\n\t//local = MinerCL::getCL().getKernelFindBestWorkGroupSize();\n\t//global = local * 4;\n\n\tauto local = MinerCl::getCL().getKernelFindBestWorkGroupSize();\n\tauto global = local;\n\n\tconst auto reduction_groups = global / local;\n\tconst auto reduction_group_size = 2;\n\tconst auto reduction_group_bytes = reduction_group_size * sizeof(Poco::UInt64);\n\tconst auto reduction_groups_size = reduction_groups * reduction_group_size;\n\tconst auto reduction_groups_bytes = reduction_groups * reduction_group_bytes;\n\n\tif (!allocateMemory(reinterpret_cast<void**>(&gpuBestMemory), MemoryType::Bytes, reduction_groups_bytes))\n\t\treturn false;\n\n\tauto ret = true;\n\tret = ret && (errorCode = clSetKernelArg(MinerCl::getCL().getKernel_GetMin(), 0, sizeof(cl_mem), &gpuDeadlines)) == CL_SUCCESS;\n\tret = ret && (errorCode = clSetKernelArg(MinerCl::getCL().getKernel_GetMin(), 1, sizeof(cl_uint), &size)) == CL_SUCCESS;\n\tret = ret && (errorCode = clSetKernelArg(MinerCl::getCL().getKernel_GetMin(), 2, sizeof(cl_uint) * local, nullptr)) == CL_SUCCESS;\n\tret = ret && (errorCode = clSetKernelArg(MinerCl::getCL().getKernel_GetMin(), 3, sizeof(cl_ulong) * local, nullptr)) == CL_SUCCESS;\n\tret = ret && (errorCode = clSetKernelArg(MinerCl::getCL().getKernel_GetMin(), 4, sizeof(cl_mem), &gpuBestMemory)) == CL_SUCCESS;\n\n\tret = ret && (errorCode = clEnqueueNDRangeKernel(static_cast<cl_command_queue>(stream),\n\t                                                 MinerCl::getCL().getKernel_GetMin(), 1, nullptr,\n\t                                                 &global, &local, 0, nullptr, nullptr)) == CL_SUCCESS;\n\n\tret = ret && (errorCode = clEnqueueReadBuffer(static_cast<cl_command_queue>(stream), cl_mem(gpuBestMemory), CL_TRUE,\n\t                                              0, sizeof(Poco::UInt64), &minDeadlineIndex, 0,\n\t                                              nullptr, nullptr)) == CL_SUCCESS;\n\n\tret = ret && (errorCode = clEnqueueReadBuffer(static_cast<cl_command_queue>(stream), cl_mem(gpuBestMemory), CL_TRUE,\n\t                                              sizeof(Poco::UInt64), sizeof(Poco::UInt64), &minDeadline, 0,\n\t                                              nullptr, nullptr)) == CL_SUCCESS;\n\t\n\tstd::vector<Poco::UInt64> bestMemory(reduction_groups_size);\n\n\t// only needed when global == local * N; N > 1\n\t/*copyMemory(gpuBestMemory, bestMemory.data(), MemoryType::Bytes, reduction_groups_bytes, MemoryCopyDirection::ToHost, stream);\n\t\n\tfor (auto i = 0; i < reduction_groups_size; ++i)\n\t{\n\t\tif (i % 2 == 0)\n\t\t{\n\t\t\tif (minDeadline > bestMemory[i] || i == 0)\n\t\t\t{\n\t\t\t\tminDeadlineIndex = bestMemory[i + 0];\n\t\t\t\tminDeadline = bestMemory[i + 1];\n\t\t\t}\n\t\t}\n\t}*/\n\n\tif (!ret)\n\t\tlastError_ = errorCode;\n\n\tfreeMemory(gpuBestMemory);\n\n\treturn ret;\n#else\n\treturn true;\n#endif\n}\n\nbool Burst::GpuOpenclImpl::freeMemory(void* memory)\n{\n#ifdef USE_OPENCL\n\tconst auto ret = clReleaseMemObject(static_cast<cl_mem>(memory));\n\n\tif (ret == CL_SUCCESS)\n\t\treturn true;\n\n\tlastError_ = ret;\n\treturn false;\n#else\n\treturn true;\n#endif\n}\n\nbool Burst::GpuOpenclImpl::getError(std::string& errorString)\n{\n#ifdef USE_OPENCL\n\tconst auto getErrorString = [&]() {\n\t\tswitch (lastError_)\n\t\t{\n\t\tcase 0: return \"CL_SUCCESS\";\n\t\tcase -1: return \"CL_DEVICE_NOT_FOUND\";\n\t\tcase -2: return \"CL_DEVICE_NOT_AVAILABLE\";\n\t\tcase -3: return \"CL_COMPILER_NOT_AVAILABLE\";\n\t\tcase -4: return \"CL_MEM_OBJECT_ALLOCATION_FAILURE\";\n\t\tcase -5: return \"CL_OUT_OF_RESOURCES\";\n\t\tcase -6: return \"CL_OUT_OF_HOST_MEMORY\";\n\t\tcase -7: return \"CL_PROFILING_INFO_NOT_AVAILABLE\";\n\t\tcase -8: return \"CL_MEM_COPY_OVERLAP\";\n\t\tcase -9: return \"CL_IMAGE_FORMAT_MISMATCH\";\n\t\tcase -10: return \"CL_IMAGE_FORMAT_NOT_SUPPORTED\";\n\t\tcase -11: return \"CL_BUILD_PROGRAM_FAILURE\";\n\t\tcase -12: return \"CL_MAP_FAILURE\";\n\t\tcase -13: return \"CL_MISALIGNED_SUB_BUFFER_OFFSET\";\n\t\tcase -14: return \"CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST\";\n\t\tcase -15: return \"CL_COMPILE_PROGRAM_FAILURE\";\n\t\tcase -16: return \"CL_LINKER_NOT_AVAILABLE\";\n\t\tcase -17: return \"CL_LINK_PROGRAM_FAILURE\";\n\t\tcase -18: return \"CL_DEVICE_PARTITION_FAILED\";\n\t\tcase -19: return \"CL_KERNEL_ARG_INFO_NOT_AVAILABLE\";\n\t\tcase -30: return \"CL_INVALID_VALUE\";\n\t\tcase -31: return \"CL_INVALID_DEVICE_TYPE\";\n\t\tcase -32: return \"CL_INVALID_PLATFORM\";\n\t\tcase -33: return \"CL_INVALID_DEVICE\";\n\t\tcase -34: return \"CL_INVALID_CONTEXT\";\n\t\tcase -35: return \"CL_INVALID_QUEUE_PROPERTIES\";\n\t\tcase -36: return \"CL_INVALID_COMMAND_QUEUE\";\n\t\tcase -37: return \"CL_INVALID_HOST_PTR\";\n\t\tcase -38: return \"CL_INVALID_MEM_OBJECT\";\n\t\tcase -39: return \"CL_INVALID_IMAGE_FORMAT_DESCRIPTOR\";\n\t\tcase -40: return \"CL_INVALID_IMAGE_SIZE\";\n\t\tcase -41: return \"CL_INVALID_SAMPLER\";\n\t\tcase -42: return \"CL_INVALID_BINARY\";\n\t\tcase -43: return \"CL_INVALID_BUILD_OPTIONS\";\n\t\tcase -44: return \"CL_INVALID_PROGRAM\";\n\t\tcase -45: return \"CL_INVALID_PROGRAM_EXECUTABLE\";\n\t\tcase -46: return \"CL_INVALID_KERNEL_NAME\";\n\t\tcase -47: return \"CL_INVALID_KERNEL_DEFINITION\";\n\t\tcase -48: return \"CL_INVALID_KERNEL\";\n\t\tcase -49: return \"CL_INVALID_ARG_INDEX\";\n\t\tcase -50: return \"CL_INVALID_ARG_VALUE\";\n\t\tcase -51: return \"CL_INVALID_ARG_SIZE\";\n\t\tcase -52: return \"CL_INVALID_KERNEL_ARGS\";\n\t\tcase -53: return \"CL_INVALID_WORK_DIMENSION\";\n\t\tcase -54: return \"CL_INVALID_WORK_GROUP_SIZE\";\n\t\tcase -55: return \"CL_INVALID_WORK_ITEM_SIZE\";\n\t\tcase -56: return \"CL_INVALID_GLOBAL_OFFSET\";\n\t\tcase -57: return \"CL_INVALID_EVENT_WAIT_LIST\";\n\t\tcase -58: return \"CL_INVALID_EVENT\";\n\t\tcase -59: return \"CL_INVALID_OPERATION\";\n\t\tcase -60: return \"CL_INVALID_GL_OBJECT\";\n\t\tcase -61: return \"CL_INVALID_BUFFER_SIZE\";\n\t\tcase -62: return \"CL_INVALID_MIP_LEVEL\";\n\t\tcase -63: return \"CL_INVALID_GLOBAL_WORK_SIZE\";\n\t\tcase -64: return \"CL_INVALID_PROPERTY\";\n\t\tcase -65: return \"CL_INVALID_IMAGE_DESCRIPTOR\";\n\t\tcase -66: return \"CL_INVALID_COMPILER_OPTIONS\";\n\t\tcase -67: return \"CL_INVALID_LINKER_OPTIONS\";\n\t\tcase -68: return \"CL_INVALID_DEVICE_PARTITION_COUNT\";\n\t\tcase -1000: return \"CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR\";\n\t\tcase -1001: return \"CL_PLATFORM_NOT_FOUND_KHR\";\n\t\tcase -1002: return \"CL_INVALID_D3D10_DEVICE_KHR\";\n\t\tcase -1003: return \"CL_INVALID_D3D10_RESOURCE_KHR\";\n\t\tcase -1004: return \"CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR\";\n\t\tcase -1005: return \"CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR\";\n\t\tdefault: return \"Unknown OpenCL error\";\n\t\t}\n\t};\n\n\tif (lastError_ == CL_SUCCESS)\n\t\treturn false;\n\n\terrorString = getErrorString();\n\treturn true;\n#else\n\treturn false;\n#endif\n}\n\nbool Burst::GpuOpenclImpl::copyMemory(const void* input, void* output, MemoryType type, size_t size, MemoryCopyDirection direction, void* stream)\n{\n#ifdef USE_OPENCL\n\tsize = GpuHelper::calcMemorySize(type, size);\n\n\tif (direction == MemoryCopyDirection::ToDevice)\n\t{\n\t\tconst auto ret = clEnqueueWriteBuffer(static_cast<cl_command_queue>(stream), cl_mem(output), CL_TRUE, 0, size, input, 0,\n\t\t                                      nullptr, nullptr);\n\n\t\tif (ret == CL_SUCCESS)\n\t\t\treturn true;\n\n\t\tlastError_ = ret;\n\t\treturn false;\n\t}\n\n\tif (direction == MemoryCopyDirection::ToHost)\n\t{\n\t\tconst auto ret = clEnqueueReadBuffer(static_cast<cl_command_queue>(stream), cl_mem(input), CL_TRUE, 0, size, output, 0,\n\t\t                                     nullptr, nullptr);\n\n\t\tif (ret == CL_SUCCESS)\n\t\t\treturn true;\n\n\t\tlastError_ = ret;\n\t\treturn false;\n\t}\n\n\treturn false;\n#else\n\treturn true;\n#endif\n}"
  },
  {
    "path": "src/gpu/impl/gpu_opencl_impl.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <utility>\n#include <Poco/Types.h>\n#include \"gpu/gpu_declarations.hpp\"\n#include \"mining/MinerData.hpp\"\n\nnamespace Burst\n{\n\tstruct CalculatedDeadline;\n\n\tstruct GpuOpenclImpl\n\t{\n\t\tstatic bool initStream(void** stream);\n\t\tstatic bool allocateMemory(void** memory, MemoryType type, size_t size);\n\t\tstatic bool copyMemory(const void* input, void* output, MemoryType type, size_t size, MemoryCopyDirection direction, void* stream);\n\t\tstatic bool verify(const GensigData* gpuGensig, ScoopData* gpuScoops, Poco::UInt64* gpuDeadlines, size_t nonces,\n\t\t\tPoco::UInt64 nonceStart, Poco::UInt64 baseTarget, void* stream);\n\t\tstatic bool getMinDeadline(Poco::UInt64* gpuDeadlines, size_t size, Poco::UInt64& minDeadline, Poco::UInt64& minDeadlineIndex, void* stream);\n\t\tstatic bool freeMemory(void* memory);\n\t\tstatic bool getError(std::string& errorString);\n\n\tprivate:\n\t\tstatic int lastError_;\n\t};\n}\n"
  },
  {
    "path": "src/logging/Console.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n\n#include \"Console.hpp\"\n#include <iostream>\n#include \"mining/Miner.hpp\"\n#include \"MinerUtil.hpp\"\n#include \"mining/MinerConfig.hpp\"\n\n#ifdef _WIN32\n#include <wincon.h>\n#include <windows.h>\n#else\n#include <iomanip>\n#include <cmath>\n#endif\n\nconst std::string Burst::Console::yes = \"Yes\";\nconst std::string Burst::Console::no = \"No\";\n\nBurst::PrintBlock::PrintBlock(std::ostream& stream, void* handle)\n\t: handle_(handle), stream_(&stream)\n{\n}\n\nconst Burst::PrintBlock& Burst::PrintBlock::print(const std::string& text) const\n{\n#ifdef WIN32\n\tDWORD written;\n\tWriteFile(handle_, text.data(), static_cast<DWORD>(text.size()), &written, nullptr);\n\treturn *this;\n#else\n\t*stream_ << text;\n\treturn *this;\n#endif\n}\n\nconst Burst::PrintBlock& Burst::PrintBlock::operator<<(ConsoleColor color) const\n{\n\tConsole::setColor(color);\n\treturn *this;\n}\n\nconst Burst::PrintBlock& Burst::PrintBlock::operator<<(ConsoleColorPair color) const\n{\n\tConsole::setColor(color);\n\treturn *this;\n}\n\nconst Burst::PrintBlock& Burst::PrintBlock::addTime() const\n{\n\t*this << getTime();\n\treturn *this;\n}\n\nconst Burst::PrintBlock& Burst::PrintBlock::nextLine() const\n{\n\t*stream_ << std::endl;\n\treturn *this;\n}\n\nconst Burst::PrintBlock& Burst::PrintBlock::resetColor() const\n{\n\tConsole::resetColor();\n\treturn *this;\n}\n\nconst Burst::PrintBlock& Burst::PrintBlock::setColor(ConsoleColor color) const\n{\n\treturn *this << color;\n}\n\nvoid* Burst::PrintBlock::getHandle() const\n{\n\treturn handle_;\n}\n\nconst Burst::PrintBlock& Burst::PrintBlock::clearLine(bool wipe) const\n{\n\tConsole::clearLine(wipe);\n\treturn *this;\n}\n\nconst Burst::PrintBlock& Burst::PrintBlock::flush() const\n{\n\t*stream_ << std::flush;\n\treturn *this;\n}\n\nBurst::PrintBlock::~PrintBlock()\n{\n\tflush();\n\tresetColor();\n}\n\nvoid Burst::Console::setColor(ConsoleColor foreground, ConsoleColor background)\n{\n\tif (MinerConfig::getConfig().getLogOutputType() != LogOutputType::Terminal ||\n\t\t!MinerConfig::getConfig().isUsingLogColors())\n\t\treturn;\n\n#ifdef _WIN32\n\tauto hConsole = GetStdHandle(STD_OUTPUT_HANDLE);\n\tWORD color = (static_cast<int>(foreground) & 0x0F) + ((static_cast<int>(background) & 0x0F) << 4);\n\tSetConsoleTextAttribute(hConsole, color);\n#elif defined __linux__\n\tstd::cout << getUnixConsoleCode(foreground);\n#endif\n}\n\nvoid Burst::Console::setColor(ConsoleColorPair color)\n{\n\tsetColor(color.foreground, color.background);\n}\n\nvoid Burst::Console::resetColor()\n{\n\tif (MinerConfig::getConfig().getLogOutputType() != LogOutputType::Terminal ||\n\t\t!MinerConfig::getConfig().isUsingLogColors())\n\t\treturn;\n\n#ifdef _WIN32\n\tsetColor(ConsoleColor::White);\n#elif defined __linux__\n\tstd::cout << \"\\033[0m\";\n#endif\n}\n\nstd::string Burst::Console::getUnixConsoleCode(ConsoleColor color)\n{\n\tswitch (color)\n\t{\n\tcase ConsoleColor::Black: return \"\\033[30m\";\n\tcase ConsoleColor::Blue: return \"\\033[34m\";\n\tcase ConsoleColor::Green: return \"\\033[0;32m\";\n\tcase ConsoleColor::Cyan: return \"\\033[36m\";\n\tcase ConsoleColor::Red: return \"\\033[31m\";\n\tcase ConsoleColor::Magenta: return \"\\033[35m\";\n\tcase ConsoleColor::Brown:\n\tcase ConsoleColor::Yellow: return \"\\033[33;1m\";\n\tcase ConsoleColor::LightGray: return \"\\033[2;37m\";\n\tcase ConsoleColor::DarkGray: return \"\\033[30;1m\";\n\tcase ConsoleColor::LightBlue: return \"\\033[34;1m\";\n\tcase ConsoleColor::LightGreen: return \"\\033[32;1m\";\n\tcase ConsoleColor::LightCyan: return \"\\033[36;1m\";;\n\tcase ConsoleColor::LightRed: return \"\\033[31;1m\";;\n\tcase ConsoleColor::LightMagenta: return \"\\033[35;1m\";;\n\tcase ConsoleColor::White: return \"\\033[37;1m\";\n\tdefault: return \"\\033[0m\";\n\t}\n}\n\nBurst::PrintBlock Burst::Console::print()\n{\n#ifdef WIN32\n\treturn PrintBlock{std::cout, GetStdHandle(STD_OUTPUT_HANDLE)};\n#else\n\treturn PrintBlock{std::cout};\n#endif\n}\n\nvoid Burst::Console::clearLine(bool wipe)\n{\n\tif (MinerConfig::getConfig().getLogOutputType() != LogOutputType::Terminal)\n\t\treturn;\n\n\tsize_t consoleLength = 0;\n\n#ifdef WIN32\n\tCONSOLE_SCREEN_BUFFER_INFO csbi;\n\tGetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);\n\tconsoleLength = csbi.srWindow.Right - csbi.srWindow.Left;\n#else\n\twinsize size;\n\n\tif (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) > -1)\n\t\tconsoleLength = size.ws_col;\n#endif\n\n\tif (consoleLength > 0)\n\t{\n\t\tstd::cout << '\\r';\n\n\t\tif (wipe)\n\t\t\tstd::cout << std::string(consoleLength, ' ') << '\\r';\n\n\t\tstd::cout << std::flush;\n\t}\n}\n\nvoid Burst::Console::nextLine()\n{\n\tstd::cout << std::endl;\n}\n\nstd::string Burst::Console::readInput(const std::vector<std::string>& options, const std::string& header,\n\tconst std::string& defaultValue, int& index)\n{\n\tauto pb = Console::print();\n\tpb.addTime().print(\": \").setColor(ConsoleColor::LightCyan).print(\"%s\", header).resetColor().nextLine();\n\n\tfor (size_t i = 0; i < options.size(); ++i)\n\t{\n\t\tpb.addTime().print(\": [%7z]: %s\", i + 1, options[i]);\n\n\t\tif (options[i] == defaultValue)\n\t\t\tpb.setColor(ConsoleColor::LightGreen).print(\" <--\").resetColor();\n\n\t\tpb.nextLine();\n\t}\n\t\n\tpb.addTime().print(\": [  Enter]: Use the default value (\")\n\t  .setColor(ConsoleColor::Green).print(defaultValue)\n\t  .resetColor().print(')').nextLine();\n\n\tbool useDefault;\n\n\tdo\n\t{\n\t\tpb.addTime().print(\": Your choice: \");\n\t\tstd::string choice;\n\t\tstd::getline(std::cin, choice);\n\t\tuseDefault = choice.empty();\n\t\tif (Poco::NumberParser::tryParse(choice, index))\n\t\t\t--index;\n\t\telse\n\t\t\tindex = -1;\n\t}\n\twhile (!useDefault && (index < 0 || index >= static_cast<int>(options.size())));\n\n\tstd::string choiceText;\n\n\tif (useDefault)\n\t{\n\t\tchoiceText = defaultValue;\n\t\tconst auto iter = find(options.begin(), options.end(), defaultValue);\n\t\tindex = static_cast<int>(distance(options.begin(), iter));\n\t}\n\telse\n\t\tchoiceText = options[index];\n\n\treturn choiceText;\n}\n\nstd::string Burst::Console::readYesNo(const std::string& header, bool defaultValue)\n{\n\tint index;\n\treturn readInput({\"Yes\", \"No\"}, header, defaultValue ? \"Yes\" : \"No\", index);\n}\n\nbool Burst::Console::readNumber(const std::string& title, Poco::Int64 min, Poco::Int64 max, Poco::Int64 defaultValue,\n\tPoco::Int64& number)\n{\n\tauto entered = false;\n\tstd::string input;\n\tconst auto pb = Console::print();\n\n\twhile (!entered)\n\t{\n\t\ttry\n\t\t{\n\t\t\tpb.addTime().print(\": \").print(title).print(\": \");\n\t\t\tgetline(std::cin, input);\n\t\t\t\n\t\t\tif (input.empty())\n\t\t\t\tnumber = defaultValue;\n\t\t\telse if (input == \"\\n\" || input == \"\\r\") // exit\n\t\t\t\treturn false;\n\t\t\telse\n\t\t\t\tnumber = Poco::NumberParser::parse64(input);\n\n\t\t\tentered = number >= min && number <= max;\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t}\n\t}\n\n\treturn entered;\n}\n\nstd::string Burst::Console::readText(const std::string& title,\n\tstd::function<bool(const std::string&, std::string&)> validator)\n{\n\tauto validated = false;\n\tstd::string input, output;\n\n\tconst auto pb = Console::print();\n\n\twhile (!validated)\n\t{\n\t\tpb.addTime().print(\": \").setColor(ConsoleColor::LightCyan).print(title).print(\": \").resetColor();\n\t\tgetline(std::cin, input);\n\t\tvalidated = validator(input, output);\n\t}\n\n\treturn output;\n}\n"
  },
  {
    "path": "src/logging/Console.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"channels/ColoredPriorityConsoleChannel.hpp\"\n#include <mutex>\n#include <string>\n#include <functional>\n#include <Poco/Format.h>\n\nnamespace Burst\n{\n\t/**\n\t * \\brief Colors for the console.\n\t */\n\tenum class ConsoleColor\n\t{\n\t\tBlack = 0,\n\t\tBlue = 1,\n\t\tGreen = 2,\n\t\tCyan = 3,\n\t\tRed = 4,\n\t\tMagenta = 5,\n\t\tBrown = 6,\n\t\tLightGray = 7,\n\t\tDarkGray = 8,\n\t\tLightBlue = 9,\n\t\tLightGreen = 10,\n\t\tLightCyan = 11,\n\t\tLightRed = 12,\n\t\tLightMagenta = 13,\n\t\tYellow = 14,\n\t\tWhite = 15\n\t};\n\n\t/**\n\t * \\brief A pair of fore- and background.\n\t */\n\tstruct ConsoleColorPair\n\t{\n\t\tConsoleColor foreground, background;\n\t};\n\n\t/**\n\t * \\brief A print block for the console.\n\t * This class is not thread-safe and should not be used in concurrent way!\n\t */\n\tclass PrintBlock\n\t{\n\tpublic:\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * Locks the console mutex.\n\t\t * \\param stream The output stream.\n\t\t */\n\t\tPrintBlock(std::ostream& stream, void* handle = nullptr);\n\n\t\t/**\n\t\t * \\brief Destructor.\n\t\t */\n\t\t~PrintBlock();\n\n\t\tPrintBlock(PrintBlock&& rhs) noexcept = default;\n\t\tPrintBlock(const PrintBlock& rhs) = default;\n\t\tPrintBlock& operator=(const PrintBlock& rhs) = default;\n\t\tPrintBlock& operator=(PrintBlock&& rhs) noexcept = default;\n\n\t\t/**\n\t\t * \\brief Prints a value to output.\n\t\t * \\tparam T The type of the value.\n\t\t * \\param text The value.\n\t\t * \\return The print block instance.\n\t\t */\n\t\ttemplate <typename T>\n\t\tconst PrintBlock& operator<< (const T& text) const\n\t\t{\n\t\t\t*stream_ << text;\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename T>\n\t\tconst PrintBlock& print(const T& text) const\n\t\t{\n\t\t\treturn (*this << text);\n\t\t}\n\n\t\tconst PrintBlock& print(const std::string& text) const;\n\n\t\ttemplate <typename ...T>\n\t\tconst PrintBlock& print(const std::string& format, const T&... args) const\n\t\t{\n\t\t\treturn print(Poco::format(format, std::forward<const T&>(args)...));\n\t\t}\n\n\t\t/**\n\t\t * \\brief Changes the current color of the font.\n\t\t * \\param color The font color.\n\t\t * \\return The print block instance.\n\t\t */\n\t\tconst PrintBlock& operator<< (ConsoleColor color) const;\n\n\t\t/**\n\t\t * \\brief Changes he current color of the font.\n\t\t * \\param color The font color.\n\t\t * \\return The print block instance.\n\t\t */\n\t\tconst PrintBlock& operator<< (ConsoleColorPair color) const;\n\n\t\t/**\n\t\t * \\brief Prints the current local time.\n\t\t * The format will be HH:MM:SS.\n\t\t * \\return The print block instance.\n\t\t */\n\t\tconst PrintBlock& addTime() const;\n\n\t\t/**\n\t\t * \\brief Prints a line break.\n\t\t * \\return The print block instance.\n\t\t */\n\t\tconst PrintBlock& nextLine() const;\n\n\t\t/**\n\t\t * \\brief Resets the current line.\n\t\t * \\param wipe If true, the line will be erased,\n\t\t * otherwise only the cursor will be set to the beginning of the line.\n\t\t */\n\t\tconst PrintBlock& clearLine(bool wipe = true) const;\n\n\t\t/**\n\t\t * \\brief Flushes the current console buffer.\n\t\t */\n\t\tconst PrintBlock& flush() const;\n\n\t\t/**\n\t\t * \\brief Resets the font color.\n\t\t */\n\t\tconst PrintBlock& resetColor() const;\n\t\t\n\t\tconst PrintBlock& setColor(ConsoleColor color) const;\n\n\t\tvoid* getHandle() const;\n\n\tprivate:\n\t\tvoid* handle_ = nullptr;\n\t\tstd::ostream* stream_;\n\t};\n\n\t/**\n\t * \\brief A static abstraction class for the console/terminal.\n\t * These functions are not thread-safe and should not be used in concurrent way!\n\t */\n\tclass Console\n\t{\n\tpublic:\n\t\tstatic const std::string yes, no;\n\n\tpublic:\n\t\tConsole() = delete;\n\t\t~Console() = delete;\n\t\tConsole(const Console& rhs) = delete;\n\t\tConsole(Console&& rhs) = delete;\n\n\t\tConsole& operator=(const Console& rhs) = delete;\n\t\tConsole& operator=(Console&& rhs) = delete;\n\n\t\t/**\n\t\t * \\brief Changes the color of the font in the console.\n\t\t * \\param foreground The new foreground color.\n\t\t * \\param background The new background color.\n\t\t */\n\t\tstatic void setColor(ConsoleColor foreground, ConsoleColor background = ConsoleColor::Black);\n\n\t\t/**\n\t\t * \\brief Changes the color of the font in the console.\n\t\t * \\param color The new back- and foreground color.\n\t\t */\n\t\tstatic void setColor(ConsoleColorPair color);\n\n\t\t/**\n\t\t * \\brief Changes the color of the font in the console back to the default value.\n\t\t */\n\t\tstatic void resetColor();\n\n\t\t/**\n\t\t * \\brief Returns an ANSI color escape code for the terminal.\n\t\t * Only useful for Unix systems.\n\t\t * \\param color The color, for which the ANSI color escape code will be returned.\n\t\t * \\return The ANSI color escape code.\n\t\t */\n\t\tstatic std::string getUnixConsoleCode(ConsoleColor color);\n\n\t\t/**\n\t\t * \\brief Creates a print block for the console for console output.\n\t\t * \\return The shared_ptr for a newly created print block.\n\t\t */\n\t\tstatic PrintBlock print();\n\n\t\t/**\n\t\t * \\brief Resets the current line.\n\t\t * \\param wipe If true, the line will be erased,\n\t\t * otherwise only the cursor will be set to the beginning of the line.\n\t\t */\n\t\tstatic void clearLine(bool wipe = true);\n\n\t\t/**\n\t\t * \\brief Prints a line break.\n\t\t */\n\t\tstatic void nextLine();\n\n\t\t/**\n\t\t * \\brief Reads the index based user choice from a list of options.\n\t\t * \\param options The options, from whom the user can choose.\n\t\t * \\param header The text that will be printed in different color before the options are listed.\n\t\t * \\param defaultValue The default value that will be chosen if the user just presses enter.\n\t\t * \\param index The index of the chosen element.\n\t\t * \\return The chosen text.\n\t\t */\n\t\tstatic std::string readInput(const std::vector<std::string>& options, const std::string& header,\n\t\t                             const std::string& defaultValue, int& index);\n\n\t\t/**\n\t\t * \\brief Prints a question and lets the user decide between yes or no.\n\t\t * \\param header The question that will be printed before the decision.\n\t\t * \\param defaultValue The default value that will be chosen if the user just presses enter.\n\t\t * \\return The chosen the text.\n\t\t */\n\t\tstatic std::string readYesNo(const std::string& header, bool defaultValue);\n\n\t\t/**\n\t\t * \\brief Reads a number written by the user.\n\t\t * \\param title The text that will be printed before the input.\n\t\t * \\param min The minimum number that the user has to enter.\n\t\t * \\param max The maximum number that the user has to enter.\n\t\t * \\param defaultValue The default value that will be chosen if the user just presses enter.\n\t\t * \\param number The number that the user wrote.\n\t\t * \\return true, if the user gave a valid number, false otherwise\n\t\t */\n\t\tstatic bool readNumber(const std::string& title, Poco::Int64 min, Poco::Int64 max,\n\t\t                       Poco::Int64 defaultValue, Poco::Int64& number);\n\n\t\t/**\n\t\t * \\brief Reads a text written by the user.\n\t\t * \\param title The text that will be printed before the input.\n\t\t * \\param validator The validator of the written text.\n\t\t * \\return The text that the user gave.\n\t\t */\n\t\tstatic std::string readText(const std::string& title,\n\t\t                            std::function<bool(const std::string&, std::string&)> validator);\n\t};\n}\n"
  },
  {
    "path": "src/logging/Message.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"Message.hpp\"\n#include <Poco/Format.h>\n#include <sstream>\n#include <memory>\n#include \"MinerLogger.hpp\"\n#include \"mining/MinerConfig.hpp\"\n#include <memory>\n#include \"MinerUtil.hpp\"\n\nPoco::NotificationQueue Burst::Message::messageQueue_;\n\nBurst::MessageNotification::MessageNotification(Poco::Logger& logger, Poco::Message message)\n\t: message(std::move(message)), logger(&logger)\n{}\n\nvoid Burst::Message::log(Poco::Message::Priority priority, TextType type, Poco::Logger& logger, const std::string& text, const char* file, int line, bool condition)\n{\n\tcreateAndLog(priority, type, logger, text, file, line, condition);\n}\n\nvoid Burst::Message::log(Poco::Message::Priority priority, TextType type, Poco::Logger& logger, Poco::Exception& exception, const char* file, int line)\n{\n\tlog(priority, type, logger, Poco::format(\"Exception occured: %s\\n\\terror-code: %d\\n\\tclass: %s\",\n\t                                         exception.displayText(), exception.code(), std::string(exception.className())), file, line);\n}\n\nvoid Burst::Message::log(Poco::Message::Priority priority, TextType type, Poco::Logger& logger, const Poco::NestedDiagnosticContext& stackframe, const char* file, int line)\n{\n\tMessage::stackframe(priority, type, logger, stackframe, file, line);\n}\n\nvoid Burst::Message::log(Poco::Message::Priority priority, TextType type, Poco::Logger& logger, const std::string& text, const void* memory, size_t size, const char* file, int line)\n{\n\tlogger.dump(text, memory, size);\n}\n\nvoid Burst::Message::logIntoFile(Poco::Message::Priority priority, TextType type, Poco::Logger& logger, const std::string& text, const char* file, int line)\n{\n\t// if the logfile is not used, we cant log into it\n\tif (!MinerConfig::getConfig().isLogfileUsed())\n\t\treturn;\n\n\tauto fileChannel = MinerLogger::getFileFormattingChannel();\n\n\t// check if the filechannel is open and active\n\tif (fileChannel != nullptr )\n\t{\n\t\t// create the message..\n\t\tauto message = create(priority, type, logger, text, file, line);\n\t\t// ..and log it\n\t\tfileChannel->log(message);\n\t}\n}\n\nvoid Burst::Message::wakeUpAllDispatcher()\n{\n\tmessageQueue_.wakeUpAll();\n}\n\nBurst::Message::Dispatcher::Dispatcher(Poco::NotificationQueue& queue)\n\t: Poco::Task(\"Message-Dispatcher\"), queue_(&queue)\n{}\n\nvoid Burst::Message::Dispatcher::runTask()\n{\n\twhile (!isCancelled())\n\t{\n\t\t// wait for an incoming message...\n\t\tPoco::Notification::Ptr notification(queue_->waitDequeueNotification());\n\t\tMessageNotification::Ptr messageNotification;\n\n\t\tif (notification)\n\t\t\t// cast to the right notification type\n\t\t\tmessageNotification = notification.cast<MessageNotification>();\n\t\telse\n\t\t\t// wake up call (a higher instance is forcing us to terminate)\n\t\t\treturn;\n\n\t\t// finally log it\n\t\tmessageNotification->logger->log(messageNotification->message);\n\t}\n}\n\nstd::unique_ptr<Burst::Message::Dispatcher> Burst::Message::Dispatcher::create()\n{\n\treturn std::make_unique<Dispatcher>(messageQueue_);\n}\n\nPoco::Message Burst::Message::create(Poco::Message::Priority priority, TextType type, Poco::Logger& logger, const std::string& text, const char* file, int line, bool condition)\n{\n\tPoco::Message message;\n\tmessage.setText(text);\n\tmessage.setPriority(priority);\n\tmessage.set(\"type\", std::to_string(static_cast<int>(type)));\n\tmessage.set(\"condition\", std::to_string(condition));\n\tmessage.setSource(logger.name());\n\tmessage.setSourceFile(file);\n\tmessage.setSourceLine(line);\n\treturn message;\n}\n\nvoid Burst::Message::log(Poco::Logger& logger, const Poco::Message& message)\n{\n\tlogger.log(message);\n\n\t// it is possible to make this whole process async by replacing\n\t// logger.log(message) with this line of code:\n\t//messageQueue_.enqueueNotification(new MessageNotification(logger, message));\n\t// then also an instance of the Message::Dispatcher needs to be created in the main\n}\n\nvoid Burst::Message::createAndLog(Poco::Message::Priority priority, TextType type, Poco::Logger& logger, const std::string& text, const char* file, int line, bool condition)\n{\n\tlog(logger, create(priority, type, logger, text, file, line, condition));\n}\n\nvoid Burst::Message::stackframe(Poco::Message::Priority priority, TextType type, Poco::Logger& logger, const Poco::NestedDiagnosticContext& stackframe, const char* file, int line)\n{\n\tstd::stringstream ss;\n\tss << \"Stackframe\" << std::endl;\n\tstackframe.dump(ss);\n\tconst auto stackframeString = ss.str();\n\n\tlog(priority, type, logger, stackframeString.substr(0, stackframeString.size() - 1), file, line);\n}\n\nBurst::Message::Message() = default;\n"
  },
  {
    "path": "src/logging/Message.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <Poco/Message.h>\n#include <Poco/Logger.h>\n#include <Poco/NestedDiagnosticContext.h>\n#include <Poco/NotificationQueue.h>\n#include <thread>\n#include <Poco/Task.h>\n\nnamespace Burst\n{\n\tenum class TextType\n\t{\n\t\tNormal,\n\t\tError,\n\t\tInformation,\n\t\tSuccess,\n\t\tWarning,\n\t\tImportant,\n\t\tSystem,\n\t\tUnimportant,\n\t\tOk,\n\t\tDebug,\n\t\tProgress\n\t};\n\n\t/**\n\t * \\brief A Notification that holds a message to be send.\n\t */\n\tstruct MessageNotification : Poco::Notification\n\t{\n\t\t/**\n\t\t * \\brief short alias for Poco::AutoPtr<MessageNotification>\n\t\t */\n\t\tusing Ptr = Poco::AutoPtr<MessageNotification>;\n\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * \\param logger The sending logger.\n\t\t * \\param message The message to send.\n\t\t */\n\t\tMessageNotification(Poco::Logger& logger, Poco::Message message);\n\n\t\t/**\n\t\t * \\brief The message that was sent.\n\t\t */\n\t\tPoco::Message message;\n\n\t\t/**\n\t\t * \\brief The sending logger.\n\t\t */\n\t\tPoco::Logger* logger;\n\t};\n\n\tstruct Message\n\t{\n\t\t/**\n\t\t* \\brief Logging a message.\n\t\t* \\param priority The priority of the message.\n\t\t* \\param type The type of the message.\n\t\t* \\param logger The logger, that logs the message.\n\t\t* \\param text The logged message.\n\t\t* \\param file The file, in which the log was created.\n\t\t* \\param line The line in the file, in which the log was created.\n\t\t*/\n\t\tstatic void log(Poco::Message::Priority priority, TextType type,\n\t\t                Poco::Logger& logger, const std::string& text, const char* file, int line, bool condition = true);\n\n\t\t/**\n\t\t* \\brief Logging a message with placeholders.\n\t\t* \\tparam Args Variadic types of the values for the placeholders.\n\t\t* \\param priority The priority of the message.\n\t\t* \\param type The type of the message.\n\t\t* \\param logger The logger, that logs the message.\n\t\t* \\param format The logged message including spaceholders.\n\t\t* \\param file The file, in which the log was created.\n\t\t* \\param line The line in the file, in which the log was created.\n\t\t* \\param args The values for the placeholders in format.\n\t\t*/\n\t\ttemplate <typename ...Args>\n\t\tstatic void log(Poco::Message::Priority priority, TextType type,\n\t\t                Poco::Logger& logger, const std::string& format, const char* file, int line, bool condition, Args&&... args)\n\t\t{\n\t\t\tlog(priority, type, logger, Poco::format(format, args...), file, line, condition);\n\t\t}\n\n\t\t/**\n\t\t* \\brief Logging an exception.\n\t\t* \\param priority The priority of the message.\n\t\t* \\param type The type of the message.\n\t\t* \\param logger The logger, that logs the message.\n\t\t* \\param exception The exception being logged.\n\t\t* \\param file The file, in which the log was created.\n\t\t* \\param line The line in the file, in which the log was created.\n\t\t*/\n\t\tstatic void log(Poco::Message::Priority priority, TextType type,\n\t\t                Poco::Logger& logger, Poco::Exception& exception, const char* file, int line);\n\n\t\t/**\n\t\t* \\brief Logging a stackframe.\n\t\t* \\param priority The priority of the message.\n\t\t* \\param type The type of the message.\n\t\t* \\param logger The logger, that logs the message.\n\t\t* \\param stackframe The stackframe, that is being logged.\n\t\t* \\param file The file, in which the log was created.\n\t\t* \\param line The line in the file, in which the log was created.\n\t\t*/\n\t\tstatic void log(Poco::Message::Priority priority, TextType type,\n\t\t                Poco::Logger& logger, const Poco::NestedDiagnosticContext& stackframe, const char* file, int line);\n\n\t\t/**\n\t\t* \\brief Logging a message with a dump of a memory block.\n\t\t* \\param priority The priority of the message.\n\t\t* \\param type The type of the message.\n\t\t* \\param logger The logger, that logs the message.\n\t\t* \\param text The additional logged message.\n\t\t* \\param memory The dumped memory block.\n\t\t* \\param size The size of the memory to dump.\n\t\t* \\param file The file, in which the log was created.\n\t\t* \\param line The line in the file, in which the log was created.\n\t\t*/\n\t\tstatic void log(Poco::Message::Priority priority, TextType type,\n\t\t                Poco::Logger& logger, const std::string& text, const void* memory, size_t size, const char* file, int line);\n\n\t\t/**\n\t\t * \\brief Logging a message into the logfile (if active).\n\t\t * \\param priority The priority of the message.\n\t\t * \\param type The type of the message.\n\t\t * \\param logger The logger, that logs the message.\n\t\t * \\param text The logged message.\n\t\t * \\param file The file, in which the log was created.\n\t\t*  \\param line The line in the file, in which the log was created.\n\t\t */\n\t\tstatic void logIntoFile(Poco::Message::Priority priority, TextType type,\n\t\t                        Poco::Logger& logger, const std::string& text, const char* file, int line);\n\n\t\t/**\n\t\t* \\brief Logging a message into the logfile (if active) with placeholders.\n\t\t* \\tparam Args Variadic types of the values for the placeholders.\n\t\t* \\param priority The priority of the message.\n\t\t* \\param type The type of the message.\n\t\t* \\param logger The logger, that logs the message.\n\t\t* \\param format The logged message including spaceholders.\n\t\t* \\param file The file, in which the log was created.\n\t\t* \\param line The line in the file, in which the log was created.\n\t\t* \\param args The values for the placeholders in format.\n\t\t*/\n\t\ttemplate <typename ...Args>\n\t\tstatic void logIntoFile(Poco::Message::Priority priority, TextType type,\n\t\t                        Poco::Logger& logger, const std::string& format, const char* file, int line, Args&&... args)\n\t\t{\n\t\t\tlogIntoFile(priority, type, logger, Poco::format(format, args...), file, line);\n\t\t}\n\n\t\t/**\n\t\t * \\brief Wakes up all active dispatcher and forces them to terminate.\n\t\t */\n\t\tstatic void wakeUpAllDispatcher();\n\n\t\t/**\n\t\t * \\brief An asyncronous message dispatcher.\n\t\t * It logs every message, that will be pushed on a queue.\n\t\t */\n\t\tstruct Dispatcher : Poco::Task\n\t\t{\n\t\t\t/**\n\t\t\t * \\brief Constructor.\n\t\t\t * \\param queue The queue, from which the message are taken for logging.\n\t\t\t */\n\t\t\texplicit Dispatcher(Poco::NotificationQueue& queue);\n\n\t\t\t/**\n\t\t\t * \\brief Runs the dispatcher.\n\t\t\t */\n\t\t\tvoid runTask() override;\n\n\t\t\t/**\n\t\t\t * \\brief Creates a new dispatcher that access the global messages queue.\n\t\t\t * \\return A new Dispatcher.\n\t\t\t */\n\t\t\tstatic std::unique_ptr<Dispatcher> create();\n\n\t\tprivate:\n\t\t\t// The message queue, from which the dispatcher takes messages for logging.\n\t\t\tPoco::NotificationQueue* queue_;\n\t\t};\n\n\tprivate:\n\t\t/**\n\t\t * \\brief Creates a message object.\n\t\t * \\param priority The priority of the message.\n\t\t * \\param type The type of the message.\n\t\t * \\param logger The logger, that created the message.\n\t\t * \\param text The content of the message.\n\t\t * \\param file The file, that created the message.\n\t\t * \\param line The line in the file, in that the message was created.\n\t\t * \\param condition Indicates, wether the message should be displayed or not.\n\t\t * \\return A Poco::Message object.\n\t\t */\n\t\tstatic Poco::Message create(Poco::Message::Priority priority, TextType type,\n\t\t                            Poco::Logger& logger, const std::string& text, const char* file, int line, bool condition = true);\n\n\t\t/**\n\t\t * \\brief Logs a message on all connected and available channels.\n\t\t * \\param logger The logger, that will log the message.\n\t\t * \\param message The message that is logged.\n\t\t */\n\t\tstatic void log(Poco::Logger& logger, const Poco::Message& message);\n\n\t\t/**\n\t\t * \\brief Creates and logs a message.\n\t\t * \\param priority The priority of the message.\n\t\t * \\param type The type of the message.\n\t\t * \\param logger The logger, that created the message.\n\t\t * \\param text The content of the message.\n\t\t * \\param file The file, that created the message.\n\t\t * \\param line The line in the file, in that the message was created.\n\t\t * \\param condition Indicates, wether the message should be displayed or not.\n\t\t */\n\t\tstatic void createAndLog(Poco::Message::Priority priority, TextType type,\n\t\t                         Poco::Logger& logger, const std::string& text, const char* file, int line, bool condition = true);\n\n\t\t/**\n\t\t * \\brief Creates a messages with a stackframe as the content and logs it.\n\t\t * \\param priority The priority of the message.\n\t\t * \\param type The type of the message.\n\t\t * \\param logger The logger, that created the message.\n\t\t * \\param stackframe The stackframe to log.\n\t\t * \\param file The file, that created the message.\n\t\t * \\param line The line in the file, in that the message was created.\n\t\t */\n\t\tstatic void stackframe(Poco::Message::Priority priority, TextType type,\n\t\t                       Poco::Logger& logger, const Poco::NestedDiagnosticContext& stackframe, const char* file, int line);\n\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * Should not be called.\n\t\t */\n\t\tMessage();\n\n\t\t// queue for all messages to log\n\t\tstatic Poco::NotificationQueue messageQueue_;\n\t};\n}\n\n#define log_fatal(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_FATAL, Burst::TextType::Error, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_critical(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_CRITICAL, Burst::TextType::Error, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_error(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_ERROR, Burst::TextType::Error, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_warning(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_WARNING, Burst::TextType::Error, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_notice(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_NOTICE, Burst::TextType::Information, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_information(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::Normal, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_information_if(logger, cond, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::Normal, *logger, text, __FILE__, __LINE__, cond, ##__VA_ARGS__)\n#define log_debug(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_DEBUG, Burst::TextType::Debug, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_trace(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_TRACE, Burst::TextType::Debug, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_exception(logger, exception) Burst::Message::log(Poco::Message::Priority::PRIO_ERROR, Burst::TextType::Error, *logger, exception, __FILE__, __LINE__)\n#define log_memory(logger, text, memory, size) Burst::Message::log(Poco::Message::Priority::PRIO_TRACE, Burst::TextType::Debug, *logger, text, memory, size, __FILE__, __LINE__)\n#define log_stackframe(logger, stackframe) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::Unimportant, *logger, stackframe, __FILE__, __LINE__)\n#define log_current_stackframe(logger) log_stackframe(logger, Poco::NestedDiagnosticContext::current())\n\n#define log_ok(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::Ok, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_ok_if(logger, cond, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::Ok, *logger, text, __FILE__, __LINE__, cond, ##__VA_ARGS__)\n#define log_unimportant(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::Unimportant, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_unimportant_if(logger, cond, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::Unimportant, *logger, text, __FILE__, __LINE__, cond, ##__VA_ARGS__)\n#define log_success(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::Success, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_success_if(logger, cond, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::Success, *logger, text, __FILE__, __LINE__, cond, ##__VA_ARGS__)\n\n#define log_system(logger, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::System, *logger, text, __FILE__, __LINE__, true, ##__VA_ARGS__)\n#define log_system_if(logger, cond, text, ...) Burst::Message::log(Poco::Message::Priority::PRIO_INFORMATION, Burst::TextType::System, *logger, text, __FILE__, __LINE__, cond, ##__VA_ARGS__)\n\n#define log_file_only(logger, priority, type, text, ...) Burst::Message::logIntoFile(priority, type, *logger, text, __FILE__, __LINE__, ##__VA_ARGS__)\n"
  },
  {
    "path": "src/logging/MinerLogger.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"MinerLogger.hpp\"\n#include <mutex>\n#include \"mining/MinerConfig.hpp\"\n#include <Poco/NestedDiagnosticContext.h>\n#include \"MinerUtil.hpp\"\n#include <sstream>\n\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <iomanip>\n#include <cmath>\n#endif\n\n#include <Poco/Logger.h>\n#include <Poco/FileChannel.h>\n#include <Poco/PatternFormatter.h>\n#include <Poco/FormattingChannel.h>\n#include <Poco/SplitterChannel.h>\n#include <Poco/File.h>\n#include \"Output.hpp\"\n#include <fstream>\n#include <Poco/FileStream.h>\n#include \"mining/MinerData.hpp\"\n#include \"Console.hpp\"\n#include \"channels/MinerDataChannel.hpp\"\n#include \"ProgressPrinter.hpp\"\n#include <Poco/StringTokenizer.h>\n\nPoco::Mutex Burst::MinerLogger::mutex_;\nBurst::TextType Burst::MinerLogger::currentTextType_ = Burst::TextType::Normal;\nbool Burst::MinerLogger::progressFlag_ = false;\nBurst::Progress Burst::MinerLogger::lastProgress_;\nsize_t Burst::MinerLogger::lastProgressDoneRead_ = 0;\nsize_t Burst::MinerLogger::lastProgressDoneVerify_ = 0;\nsize_t Burst::MinerLogger::lastPipeCount_ = 0u;\nBurst::ProgressPrinter Burst::MinerLogger::progressPrinter_;\n\nPoco::Logger* Burst::MinerLogger::miner;\nPoco::Logger* Burst::MinerLogger::config;\nPoco::Logger* Burst::MinerLogger::server;\nPoco::Logger* Burst::MinerLogger::socket;\nPoco::Logger* Burst::MinerLogger::session;\nPoco::Logger* Burst::MinerLogger::nonceSubmitter;\nPoco::Logger* Burst::MinerLogger::plotReader;\nPoco::Logger* Burst::MinerLogger::plotVerifier;\nPoco::Logger* Burst::MinerLogger::wallet;\nPoco::Logger* Burst::MinerLogger::general;\n\nBurst::OutputFlags Burst::MinerLogger::output_ = []()\n{\n\tauto output_flags = OutputHelper::createFlags(true);\n\toutput_flags[PlotDone] = false;\n\toutput_flags[NonceFoundTooHigh] = false;\n\treturn output_flags;\n}();\n\nconst std::vector<Burst::MinerLogger::ChannelDefinition> Burst::MinerLogger::channelDefinitions =\n{\n\t{ \"miner\", Poco::Message::Priority::PRIO_INFORMATION },\n\t{ \"config\", Poco::Message::Priority::PRIO_INFORMATION },\n\t{ \"server\", Poco::Message::Priority::PRIO_FATAL },\n\t{ \"socket\", static_cast<Poco::Message::Priority>(0) },\n\t{ \"session\", Poco::Message::Priority::PRIO_ERROR },\n\t{ \"nonceSubmitter\", Poco::Message::Priority::PRIO_INFORMATION },\n\t{ \"plotReader\", Poco::Message::Priority::PRIO_INFORMATION },\n\t{ \"plotVerifier\", Poco::Message::Priority::PRIO_INFORMATION },\n\t{ \"wallet\", Poco::Message::Priority::PRIO_FATAL },\n\t{ \"general\", Poco::Message::Priority::PRIO_INFORMATION },\n};\n\nconst std::unordered_map<std::string, Burst::ColoredPriorityConsoleChannel*> Burst::MinerLogger::channels = []()\n{\n\tstd::unordered_map<std::string, ColoredPriorityConsoleChannel*> channels_;\n\n\tfor (auto& channel : channelDefinitions)\n\t\tchannels_.insert({channel.name , new ColoredPriorityConsoleChannel{channel.default_priority}});\n\n\treturn channels_;\n}();\n\nconst std::unordered_map<std::string, Burst::MinerDataChannel*> Burst::MinerLogger::websocketChannels = []()\n{\n\tstd::unordered_map<std::string, MinerDataChannel*> channels_;\n\n\tfor (auto& channel : channelDefinitions)\n\t\tchannels_.insert({channel.name , new MinerDataChannel{nullptr}});\n\n\treturn channels_;\n}();\n\nPoco::Channel* Burst::MinerLogger::fileChannel_ = new Poco::FileChannel;\nPoco::FormattingChannel* Burst::MinerLogger::fileFormatter_ = nullptr;\nstd::string Burst::MinerLogger::logFileName_ = \"creepMiner.log\";\n\nstd::map<Burst::TextType, Burst::ConsoleColorPair> Burst::MinerLogger::typeColors_ =\n\t{\n\t\t\t{ TextType::Normal, { ConsoleColor::White, ConsoleColor::Black } },\n\t\t\t{ TextType::Error, { ConsoleColor::LightRed, ConsoleColor::Black } },\n\t\t\t{ TextType::Information, { ConsoleColor::LightCyan, ConsoleColor::Black } },\n\t\t\t{ TextType::Success, { ConsoleColor::LightGreen, ConsoleColor::Black } },\n\t\t\t{ TextType::Warning, { ConsoleColor::Brown, ConsoleColor::Black } },\n\t\t\t{ TextType::Important, { ConsoleColor::Black, ConsoleColor::White } },\n\t\t\t{ TextType::System, { ConsoleColor::Yellow, ConsoleColor::Black } },\n#ifdef _WIN32\n\t\t\t{ TextType::Unimportant, { ConsoleColor::DarkGray, ConsoleColor::Black } },\n#else\n\t\t\t{ TextType::Unimportant, { ConsoleColor::LightGray, ConsoleColor::Black } },\n#endif\n\t\t\t{ TextType::Ok, { ConsoleColor::Green, ConsoleColor::Black } },\n\t\t\t{ TextType::Debug, { ConsoleColor::LightMagenta, ConsoleColor::Black } },\n\t\t\t{ TextType::Progress, { ConsoleColor::DarkGray, ConsoleColor::Black } },\n\t};\n\nBurst::MinerLogger::ChannelDefinition::ChannelDefinition(std::string name, Poco::Message::Priority default_priority)\n\t: name{std::move(name)},\n\t  default_priority{default_priority} {}\n\nconst Burst::OutputFlags& Burst::MinerLogger::getOutput()\n{\n\treturn output_;\n}\n\nbool Burst::MinerLogger::setChannelPriority(const std::string& channel, Poco::Message::Priority priority)\n{\n\tauto iter = channels.find(channel);\n\n\tif (iter != channels.end())\n\t{\n\t\titer->second->setPriority(priority);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nbool Burst::MinerLogger::setChannelPriority(const std::string& channel, const std::string& priority)\n{\n\tauto iter = channels.find(channel);\n\n\tif (iter != channels.end())\n\t{\n\t\titer->second->setPriority(getStringToPriority(priority));\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nstd::string Burst::MinerLogger::getChannelPriority(const std::string& channel)\n{\n\tconst auto iter = channels.find(channel);\n\n\tif (iter != channels.end())\n\t\treturn getPriorityToString(iter->second->getPriority());\n\n\treturn \"\";\n}\n\nPoco::Message::Priority Burst::MinerLogger::getStringToPriority(const std::string& priority)\n{\n\tif (priority == \"fatal\")\n\t\treturn Poco::Message::PRIO_FATAL;\n\tif (priority == \"critical\")\n\t\treturn Poco::Message::PRIO_CRITICAL;\n\tif (priority == \"error\")\n\t\treturn Poco::Message::PRIO_ERROR;\n\tif (priority == \"warning\")\n\t\treturn Poco::Message::PRIO_WARNING;\n\tif (priority == \"notice\")\n\t\treturn Poco::Message::PRIO_NOTICE;\n\tif (priority == \"information\")\n\t\treturn Poco::Message::PRIO_INFORMATION;\n\tif (priority == \"debug\")\n\t\treturn Poco::Message::PRIO_DEBUG;\n\tif (priority == \"trace\")\n\t\treturn Poco::Message::PRIO_TRACE;\n\tif (priority == \"off\")\n\t\treturn static_cast<Poco::Message::Priority>(0);\n\tif (priority == \"all\")\n\t\treturn Poco::Message::PRIO_TRACE;\n\t\n\treturn static_cast<Poco::Message::Priority>(0);\n}\n\nstd::string Burst::MinerLogger::getPriorityToString(Poco::Message::Priority priority)\n{\n\tif (static_cast<int>(priority) == 0)\n\t\treturn \"off\";\n\n\tif (static_cast<int>(priority) > static_cast<int>(Poco::Message::Priority::PRIO_TRACE))\n\t\treturn \"all\";\n\n\tswitch (priority)\n\t{\n\tcase Poco::Message::PRIO_FATAL:\n\t\treturn \"fatal\";\n\tcase Poco::Message::PRIO_CRITICAL:\n\t\treturn \"critical\";\n\tcase Poco::Message::PRIO_ERROR:\n\t\treturn \"error\";\n\tcase Poco::Message::PRIO_WARNING:\n\t\treturn \"warning\";\n\tcase Poco::Message::PRIO_NOTICE:\n\t\treturn \"notice\";\n\tcase Poco::Message::PRIO_INFORMATION:\n\t\treturn \"information\";\n\tcase Poco::Message::PRIO_DEBUG:\n\t\treturn \"debug\";\n\tcase Poco::Message::PRIO_TRACE:\n\t\treturn \"trace\";\n\tdefault:\n\t\treturn \"\";\n\t}\n}\n\nstd::map<std::string, std::string> Burst::MinerLogger::getChannelPriorities()\n{\n\tstd::map<std::string, std::string> channel_priorities;\n\n\tfor (auto& channel : channels)\n\t\tchannel_priorities.emplace(channel.first, getChannelPriority(channel.first));\n\n\treturn channel_priorities;\n}\n\nstd::string Burst::MinerLogger::setLogDir(const std::string& dir)\n{\n\ttry\n\t{\n\t\tPoco::ScopedLock<Poco::Mutex> lock(mutex_);\n\n\t\tPoco::Path fullPath;\n\t\tfullPath.parseDirectory(dir);\n\n\t\tif (!fullPath.toString().empty())\n\t\t{\n\t\t\tPoco::File file{ fullPath };\n\n\t\t\tif (!file.exists())\n\t\t\t\tfile.createDirectories();\n\t\t}\n\t\t\n\t\tfullPath.append(logFileName_);\n\t\tauto logPath = fullPath.toString();\n\n\t\tfileChannel_->close();\n\n\t\tauto oldLogfilePath = fileChannel_->getProperty(\"path\");\n\n\t\tif (!oldLogfilePath.empty())\n\t\t{\n\t\t\tstd::ifstream oldLogfile{ oldLogfilePath, std::ios::in | std::ios::binary | std::ios::ate };\n\n\t\t\tif (oldLogfile)\n\t\t\t{\n\t\t\t\tconst auto fileSize = oldLogfile.tellg();\n\t\t\t\toldLogfile.seekg(0, std::ios::beg);\n\n\t\t\t\tstd::vector<char> bytes(fileSize);\n\t\t\t\toldLogfile.read(&bytes[0], fileSize);\n\n\t\t\t\tconst std::string oldContent{&bytes[0], static_cast<size_t>(fileSize)};\n\n\t\t\t\toldLogfile.close();\n\n\t\t\t\tPoco::File oldLogfileObj{ oldLogfilePath };\n\t\t\t\toldLogfileObj.remove();\n\n\t\t\t\tstd::ofstream newLogfile{ logPath, std::ios::out | std::ios::binary };\n\t\t\t\tnewLogfile << oldContent;\n\t\t\t\tnewLogfile.close();\n\t\t\t}\n\t\t}\n\n\t\tfileChannel_->setProperty(\"path\", logPath);\n\t\tfileChannel_->open();\n\n\t\treturn logPath;\n\t}\n\tcatch (...)\n\t{\n\t\tthrow;\n\t}\n}\n\nvoid Burst::MinerLogger::setChannelMinerData(MinerData* minerData)\n{\n\tfor (auto& channel : websocketChannels)\n\t\tchannel.second->setMinerData(minerData);\n}\n\nPoco::FormattingChannel* Burst::MinerLogger::getFileFormattingChannel()\n{\n\treturn fileFormatter_;\n}\n\nvoid Burst::MinerLogger::setOutput(Burst::Output id, bool set)\n{\n\toutput_[id] = set;\n}\n\nbool Burst::MinerLogger::hasOutput(Burst::Output id)\n{\n\tconst auto iter = output_.find(id);\n\n\tif (iter != output_.end())\n\t\treturn iter->second;\n\n\treturn false;\n}\n\nvoid Burst::MinerLogger::write(const std::string& text, TextType type)\n{\n\tPoco::ScopedLock<Poco::Mutex> lock(mutex_);\n\n\tauto block = Console::print();\n\n\tconst auto wasProgress = progressFlag_ && MinerConfig::getConfig().isSteadyProgressBar();\n\n\tif (wasProgress)\n\t\tblock.clearLine();\n\n\tprogressFlag_ = type == TextType::Progress && MinerConfig::getConfig().isSteadyProgressBar();\n\t\n\tPoco::StringTokenizer tokenizer(text, \"\\n\");\n\t\n\tfor (auto i = 0u; i < tokenizer.count(); ++i)\n\t{\n\t\tblock << getTextTypeColor(TextType::Unimportant) << getTime() << \": \"\n\t\t\t<< getTextTypeColor(type);\n\t\t\n#ifdef _WIN32\n\t\tstd::wstring utext;\n\t\tPoco::UnicodeConverter::toUTF16(tokenizer[i], utext);\n\t\tDWORD written;\n\t\tWriteConsoleW(block.getHandle(), utext.data(), static_cast<DWORD>(utext.size()), &written, nullptr);\n#else\n\t\tblock << tokenizer[i];\n#endif\n\n\t\tif (i != tokenizer.count() - 1)\n\t\t\tblock.nextLine();\n\n\t\tblock.resetColor();\n\t}\n\n\tif (!progressFlag_)\n\t\tblock.nextLine();\n\n\tif (wasProgress && (lastProgress_.read < 100.f || lastProgress_.verify < 100.f))\n\t{\n\t\tprogressPrinter_.print(lastProgress_);\n\t\tprogressFlag_ = true;\n\t}\n}\n\nvoid Burst::MinerLogger::writeProgress(const Progress& progress)\n{\n\tPoco::ScopedLock<Poco::Mutex> lock(mutex_);\n\n\tsize_t doneSizeRead, notDoneSize, doneSizeVerified;\n\n\tProgressPrinter::calculateProgressProportions(progress.read, progress.verify,\n\t\tprogressPrinter_.totalSize, doneSizeRead, doneSizeVerified, notDoneSize);\n\n\tif (MinerConfig::getConfig().isFancyProgressBar())\n\t{\n\t\tif (static_cast<size_t>(lastProgress_.read) == static_cast<size_t>(doneSizeRead) &&\n\t\t\tstatic_cast<size_t>(lastProgress_.verify) == static_cast<size_t>(doneSizeVerified))\n\t\t\treturn;\n\t}\n\telse\n\t{\n\t\tif (static_cast<size_t>(progress.read) == static_cast<size_t>(lastProgress_.read) &&\n\t\t\tstatic_cast<size_t>(progress.verify) == static_cast<size_t>(lastProgress_.verify))\n\t\t\treturn;\n\t}\n\n\tif (progressFlag_)\n\t\tConsole::clearLine(false);\n\n\tlastProgress_ = progress;\n\tlastProgressDoneRead_ = doneSizeRead;\n\tlastProgressDoneVerify_ = doneSizeVerified;\n\tprogressFlag_ = MinerConfig::getConfig().isSteadyProgressBar();\n\n\tprogressPrinter_.print(progress);\n\n\tif (!MinerConfig::getConfig().isSteadyProgressBar())\n\t\tConsole::nextLine();\n}\n\nvoid Burst::MinerLogger::setTextTypeColor(TextType type, ConsoleColorPair color)\n{\n\tPoco::ScopedLock<Poco::Mutex> lock(mutex_);\n\ttypeColors_[type] = color;\n}\n\nvoid Burst::MinerLogger::setup()\n{\n\tminer = &Poco::Logger::get(\"miner\");\n\tconfig = &Poco::Logger::get(\"config\");\n\tserver = &Poco::Logger::get(\"server\");\n\tsocket = &Poco::Logger::get(\"socket\");\n\tsession = &Poco::Logger::get(\"session\");\n\tnonceSubmitter = &Poco::Logger::get(\"nonceSubmitter\");\n\tplotReader = &Poco::Logger::get(\"plotReader\");\n\tplotVerifier = &Poco::Logger::get(\"plotVerifier\");\n\twallet = &Poco::Logger::get(\"wallet\");\n\tgeneral = &Poco::Logger::get(\"general\");\n\n\t// create (not open yet) FileChannel\n\t{\n\t\tfileChannel_ = new Poco::FileChannel;\n\n\t\t// rotate every 10 MB\n\t\tfileChannel_->setProperty(\"rotation\", \"10 M\");\n\t\t// purge old logs\n\t\t//fileChannel_->setProperty(\"purgeAge\", \"1 days\");\n\t\tfileChannel_->setProperty(\"purgeCount\", \"10\");\n\t\t// use local times\n\t\tfileChannel_->setProperty(\"times\", \"local\");\n\t\t// archive old logfiles\n\t\tfileChannel_->setProperty(\"compress\", \"true\");\n\n\t\tauto filePattern = new Poco::PatternFormatter{ \"%d.%m.%Y %H:%M:%S (%I, %U, %u, %p): %t\" };\n\t\tfilePattern->setProperty(\"times\", \"local\");\n\t\tfileFormatter_ = new Poco::FormattingChannel{ filePattern, fileChannel_ };\n\t}\n\n\trefreshChannels();\n}\n\nvoid Burst::MinerLogger::refreshChannels()\n{\n\t// close the filechannel if not used\n\tif (!MinerConfig::getConfig().isLogfileUsed() &&\n\t\tfileChannel_ != nullptr)\n\t\tfileChannel_->close();\n\n\t// create all logger channels\n\tfor (auto& channel : channelDefinitions)\n\t{\n\t\tauto& logger = Poco::Logger::get(channel.name);\n\t\t// set the logger to fetch all messages\n\t\tlogger.setLevel(Poco::Message::Priority::PRIO_TRACE);\n\n\t\tauto splitter = new Poco::SplitterChannel;\n\t\tauto& consoleChannel = channels.at(channel.name);\n\t\tauto& websocketChannel = websocketChannels.at(channel.name);\n\n\t\tsplitter->addChannel(consoleChannel);\n\n\t\tif (MinerConfig::getConfig().getStartServer())\n\t\t\tsplitter->addChannel(websocketChannel);\n\n\t\tif (MinerConfig::getConfig().isLogfileUsed())\n\t\t\tsplitter->addChannel(fileFormatter_);\n\n\t\tPoco::Logger::get(channel.name).setChannel(splitter);\n\t}\n}\n\nBurst::ConsoleColorPair Burst::MinerLogger::getTextTypeColor(TextType type)\n{\n\tconst auto iter = typeColors_.find(type);\n\n\tif (iter == typeColors_.end())\n\t\treturn getTextTypeColor(TextType::Normal);\n\n\treturn (*iter).second;\n}\n\nvoid Burst::MinerLogger::writeStackframe(const std::string& additionalText)\n{\n\tstd::stringstream sstream;\n\n\tsstream << additionalText << std::endl\n\t\t<< \"Stackframe\" << std::endl << std::endl;\n\n\tPoco::NDC::current().dump(sstream);\n\t\t\n\twrite(sstream.str(), TextType::Error);\n}\n"
  },
  {
    "path": "src/logging/MinerLogger.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <string>\n#include <mutex>\n#include <map>\n#include <vector>\n#include <Poco/Channel.h>\n#include <Poco/Message.h>\n#include <unordered_map>\n#include <Poco/Logger.h>\n#include <Poco/FormattingChannel.h>\n#include <functional>\n#include \"Output.hpp\"\n#include \"Message.hpp\"\n#include \"Console.hpp\"\n#include \"ProgressPrinter.hpp\"\n\nnamespace Burst\n{\n\tclass ColoredPriorityConsoleChannel;\n\tclass MinerDataChannel;\n\tclass BlockData;\n\tclass MinerData;\n\n\tclass MinerLogger\n\t{\n\tpublic:\n\t\t/**\n\t\t * \\brief Initializes the logger.\n\t\t * When called more then once, the old context will be overwritten,\n\t\t * so be careful!\n\t\t */\n\t\tstatic void setup();\n\n\t\tstruct ChannelDefinition\n\t\t{\n\t\t\tChannelDefinition(std::string name, Poco::Message::Priority default_priority);\n\t\t\tstd::string name;\n\t\t\tPoco::Message::Priority default_priority;\n\t\t};\n\n\t\t/**\n\t\t * \\brief Definitions of all logger.\n\t\t */\n\t\tstatic const std::vector<ChannelDefinition> channelDefinitions;\n\n\t\tstatic ConsoleColorPair getTextTypeColor(TextType type);\n\t\tstatic void setTextTypeColor(TextType type, ConsoleColorPair color);\n\n\t\t/**\n\t\t * \\brief Writes a simple progress bar into stdcout.\n\t\t * \\param progress The progress.\n\t\t */\n\t\tstatic void writeProgress(const Progress& progress);\n\n\t\t/**\n\t\t * \\brief Writes a text of a specifig type and a timestamp into stdout.\n\t\t * The type can be splitted by \\n.\n\t\t * \\param text The text to write.\n\t\t * \\param type The type of the text.\n\t\t */\n\t\tstatic void write(const std::string& text, TextType type = TextType::Normal);\n\n\t\t/**\n\t\t * \\brief Writes a stack frame into stdout.\n\t\t * \\param additionalText An additional text, that will be displayed before the stack frame.\n\t\t * Use it to explain, when and where the error happened.\n\t\t */\n\t\tstatic void writeStackframe(const std::string& additionalText);\n\n\t\t/**\n\t\t * \\brief Refreshes all logging channels.\n\t\t * Not used channels will be removed.\n\t\t */\n\t\tstatic void refreshChannels();\n\n\t\tstatic bool setChannelPriority(const std::string& channel, Poco::Message::Priority priority);\n\t\tstatic bool setChannelPriority(const std::string& channel, const std::string& priority);\n\t\tstatic std::string getChannelPriority(const std::string& channel);\n\t\tstatic Poco::Message::Priority getStringToPriority(const std::string& priority);\n\t\tstatic std::string getPriorityToString(Poco::Message::Priority priority);\n\t\tstatic std::map<std::string, std::string> getChannelPriorities();\n\t\tstatic std::string setLogDir(const std::string& dir);\n\t\tstatic void setChannelMinerData(MinerData* minerData);\n\t\tstatic Poco::FormattingChannel* getFileFormattingChannel();\n\n\t\tstatic Poco::Logger* miner;\n\t\tstatic Poco::Logger* config;\n\t\tstatic Poco::Logger* server;\n\t\tstatic Poco::Logger* socket;\n\t\tstatic Poco::Logger* session;\n\t\tstatic Poco::Logger* nonceSubmitter;\n\t\tstatic Poco::Logger* plotReader;\n\t\tstatic Poco::Logger* plotVerifier;\n\t\tstatic Poco::Logger* wallet;\n\t\tstatic Poco::Logger* general;\n\t\t\n\t\t/**\n\t\t * \\brief Sets the flag for a specific output.\n\t\t * \\param id The id of the output.\n\t\t * \\param set The flag for the output, that indicates, if the output should\n\t\t * be visible or not.\n\t\t */\n\t\tstatic void setOutput(Output id, bool set);\n\n\t\t/**\n\t\t * \\brief Returns the flag for a specifig output.\n\t\t * \\param id The id of the output.\n\t\t * \\return If true, the output should be shown, otherwise not.\n\t\t */\n\t\tstatic bool hasOutput(Output id);\n\n\t\t/**\n\t\t * \\brief Returns the flags for all outputs.\n\t\t * \\return A flag-map for all outputs.\n\t\t */\n\t\tstatic const OutputFlags& getOutput();\n\n\tprivate:\t\t\n\t\tstatic Poco::Mutex mutex_;\n\t\tstatic TextType currentTextType_;\n\t\tstatic std::map<TextType, ConsoleColorPair> typeColors_;\n\t\tstatic bool progressFlag_;\n\t\tstatic Progress lastProgress_;\n\t\tstatic size_t lastProgressDoneRead_, lastProgressDoneVerify_;\n\t\tstatic size_t lastPipeCount_;\n\n\t\tstatic const std::unordered_map<std::string, ColoredPriorityConsoleChannel*> channels;\n\t\tstatic const std::unordered_map<std::string, MinerDataChannel*> websocketChannels;\n\t\tstatic OutputFlags output_;\n\t\tstatic Poco::Channel* fileChannel_;\n\t\tstatic Poco::FormattingChannel* fileFormatter_;\n\t\tstatic std::string logFileName_;\n\t\tstatic ProgressPrinter progressPrinter_;\n\t};\n}\n"
  },
  {
    "path": "src/logging/Output.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"Output.hpp\"\n#include <algorithm>\n\nconst std::map<Burst::Output, std::string> Burst::OutputHelper::outputNames = []()\n{\n\treturn std::map<Burst::Output, std::string> {\n\t\t{LastWinner, \"lastWinner\"},\n\t\t{NonceFound, \"nonceFound\"},\n\t\t{NonceFoundTooHigh, \"nonceFoundTooHigh\"},\n\t\t{NonceSent, \"nonceSent\"},\n\t\t{NonceConfirmed, \"nonceConfirmed\"},\n\t\t{PlotDone, \"plotDone\"},\n\t\t{DirDone, \"dirDone\"}\n\t};\n}();\n\nusing Output_Map_Pair_t = decltype(Burst::OutputHelper::outputNames)::value_type;\n\nstd::string Burst::OutputHelper::outputToString(Output output)\n{\n\tauto iter = std::find_if(outputNames.begin(), outputNames.end(), [&](const Output_Map_Pair_t& output_pair)\n\t{\n\t\treturn output_pair.first == output;\n\t});\n\n\treturn iter == outputNames.end() ? \"\" : iter->second;\n}\n\nBurst::Output Burst::OutputHelper::stringToOutput(const std::string& output)\n{\n\tauto iter = std::find_if(outputNames.begin(), outputNames.end(), [&](const Output_Map_Pair_t& output_pair)\n\t{\n\t\treturn output_pair.second == output;\n\t});\n\n\treturn iter == outputNames.end() ? Output() : iter->first;\n}\n\nBurst::OutputFlags Burst::OutputHelper::createFlags(bool default_flag)\n{\n\treturn {\n\t\t{LastWinner, default_flag},\n\t\t{NonceFound, default_flag},\n\t\t{NonceFoundTooHigh, default_flag},\n\t\t{NonceSent, default_flag},\n\t\t{NonceConfirmed, default_flag},\n\t\t{PlotDone, default_flag},\n\t\t{DirDone, default_flag}\n\t};\n}\n"
  },
  {
    "path": "src/logging/Output.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <Poco/Types.h>\n#include <map>\n\nnamespace Burst\n{\n\t/**\n\t * \\brief The output ids.\n\t * They all represent a specific event in the application.\n\t */\n\tenum Output : Poco::UInt32\n\t{\n\t\tLastWinner,\n\t\tNonceFound,\n\t\tNonceFoundTooHigh,\n\t\tNonceSent,\n\t\tNonceConfirmed,\n\t\tPlotDone,\n\t\tDirDone\n\t};\n\n\t/**\n\t * \\brief Alias for std::map<Output, T>.\n\t * \\tparam T The value type.\n\t */\n\ttemplate <typename T>\n\tusing OutputMap = std::map<Output, T>;\n\n\t/**\n\t * \\brief Alias for std::map<Output, bool>.\n\t */\n\tusing OutputFlags = OutputMap<bool>;\n\n\t/**\n\t * \\brief Helper class for \\enum Output.\n\t */\n\tstruct OutputHelper\n\t{\n\t\t/**\n\t\t * \\brief A map with canonical names for all values in \\enum Output.\n\t\t */\n\t\tstatic const OutputMap<std::string> outputNames;\n\n\t\t/**\n\t\t * \\brief Gets the canonical name for a output.\n\t\t * \\param output The output id.\n\t\t * \\return The canonical name of the output, if it exists. An empty string otherwise.\n\t\t */\n\t\tstatic std::string outputToString(Output output);\n\n\t\t/**\n\t\t * \\brief Gets the matching \\enum Output for his canonical name.\n\t\t * \\param output The canonical name of the output.\n\t\t * \\return The \\enum Output, if it exists.\n\t\t * Otherwise the default value of \\enum Output (undefined).\n\t\t */\n\t\tstatic Output stringToOutput(const std::string& output);\n\n\t\t/**\n\t\t * \\brief Creates a flag map for all values inside \\enum Output.\n\t\t * \\param defaultFlag The value of the flags.\n\t\t * \\return The flag map.\n\t\t */\n\t\tstatic OutputFlags createFlags(bool defaultFlag = true);\n\t};\t\n}\n"
  },
  {
    "path": "src/logging/ProgressPrinter.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"ProgressPrinter.hpp\"\n#include \"Console.hpp\"\n#include \"MinerLogger.hpp\"\n#include \"MinerUtil.hpp\"\n#include \"mining/MinerConfig.hpp\"\n\nBurst::ProgressPrinter::ProgressPrinter()\n{\n#ifdef POCO_COMPILER_MSVC\n\tdelimiterFront = { \"\\xBA\", TextType::Unimportant };\n\treadDoneChar = { \"\\xB1\", TextType::Normal };\n\tverifiedDoneChar = { \"\\xB2\", TextType::Success };\n\treadNotDoneChar = { \"\\xB0\", TextType::Unimportant };\n\tdelimiterEnd = { \"\\xBA\", TextType::Unimportant };\n#else\n\tdelimiterFront = { \"\\u2590\", TextType::Unimportant };\n\treadDoneChar = { \"\\u2592\", TextType::Success };\n\tverifiedDoneChar = { \"\\u2593\", TextType::Ok };\n\treadNotDoneChar = { \"\\u2591\", TextType::Unimportant };\n\tdelimiterEnd = { \"\\u258C\", TextType::Unimportant };\n#endif\n\ttotalSize = 48;\n}\n\nnamespace Burst\n{\n\tstd::ostream& toPercentage(std::ostream& stream)\n\t{\n\t\tstream << std::right << std::fixed << std::setw(6) << std::setfill(' ') << std::setprecision(2);\n\t\treturn stream;\n\t}\n\n\tstd::string repeat(size_t times, const std::string&token)\n\t{\n\t\tstd::stringstream sstream;\n\n\t\tfor (auto i = 0u; i < times; ++i)\n\t\t\tsstream << token;\n\n\t\treturn sstream.str();\n\t}\n}\n\nvoid Burst::ProgressPrinter::print(const Progress& progress) const\n{\n\tif (MinerConfig::getConfig().getLogOutputType() != LogOutputType::Terminal)\n\t\treturn;\n\n\tif (MinerConfig::getConfig().isFancyProgressBar())\n\t{\n\t\t// calculate the progress bar proportions\n\t\tsize_t doneSizeRead, notDoneSize, doneSizeVerified;\n\n\t\tcalculateProgressProportions(progress.read, progress.verify, totalSize, doneSizeRead, doneSizeVerified, notDoneSize);\n\n\t\tauto block = Console::print();\n\t\t\n\t\tblock << MinerLogger::getTextTypeColor(TextType::Unimportant) << getTime() << \": \"\n\t\t\t<< MinerLogger::getTextTypeColor(delimiterFront.textType) << delimiterFront.character\n\t\t\t<< MinerLogger::getTextTypeColor(verifiedDoneChar.textType) << repeat(doneSizeVerified, verifiedDoneChar.character)\n\t\t\t<< MinerLogger::getTextTypeColor(readDoneChar.textType) << repeat(doneSizeRead, readDoneChar.character)\n\t\t\t<< MinerLogger::getTextTypeColor(readNotDoneChar.textType) << repeat(notDoneSize, readNotDoneChar.character)\n\t\t\t<< MinerLogger::getTextTypeColor(delimiterEnd.textType) << delimiterEnd.character\n\t\t\t<< ' ' << toPercentage << (progress.read + progress.verify) / 2 << \" % \"\n\t\t\t<< MinerLogger::getTextTypeColor(delimiterEnd.textType) << delimiterEnd.character\n\t\t\t<< ' ' << memToString(static_cast<Poco::UInt64>(progress.bytesPerSecondRead), 2) << \"/s\";\n\n\t\tblock.flush();\n\t}\n\telse\n\t\tConsole::print()\n\t\t\t<< MinerLogger::getTextTypeColor(TextType::Unimportant) << getTime() << \": \"\n\t\t\t<< \"Read:  \" << toPercentage << progress.read << \"% (\"\n\t\t\t<< memToString(static_cast<Poco::UInt64>(progress.bytesPerSecondRead), 2) << \"/s)   \"\n\t\t\t<< \"Verified:  \" << toPercentage << progress.verify << \"% (\"\n\t\t\t<< memToString(static_cast<Poco::UInt64>(progress.bytesPerSecondVerify), 2) << \"/s)\";\n}\n\nvoid Burst::ProgressPrinter::calculateProgressProportions(double progressRead, double progressVerified,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  size_t totalSize, size_t& readSize, size_t& verifiedSize, size_t& notDoneSize)\n{\n\treadSize = static_cast<size_t>(totalSize * (progressRead / 100));\n\tverifiedSize = static_cast<size_t>(totalSize * (progressVerified / 100));\n\n\tauto notReadSize = totalSize - readSize;\n\tauto notVerifiedSize = totalSize - verifiedSize;\n\n\tif (readSize > verifiedSize)\n\t\treadSize = readSize - verifiedSize;\n\telse\n\t\treadSize = 0;\n\n\tnotDoneSize = std::min(notReadSize, notVerifiedSize);\n}\n"
  },
  {
    "path": "src/logging/ProgressPrinter.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"Message.hpp\"\n\nnamespace Burst\n{\n\tstruct ProgressToken\n\t{\n\t\tstd::string character;\n\t\tTextType textType;\n\t};\n\n\tstruct Progress\n\t{\n\t\tdouble read;\n\t\tdouble verify;\n\t\tdouble bytesPerSecondRead;\n\t\tdouble bytesPerSecondVerify;\n\t\tdouble bytesPerSecondCombined;\n\t};\n\n\tstruct ProgressPrinter\n\t{\n\t\t/**\n\t\t* \\brief The front delimiter.\n\t\t*/\n\t\tProgressToken delimiterFront;\n\n\t\t/**\n\t\t* \\brief A char that represents the filled part of the progress bar for reading.\n\t\t*/\n\t\tProgressToken readDoneChar;\n\n\t\t/**\n\t\t* \\brief A char that represents the filled part of the progress bar for reading.\n\t\t*/\n\t\tProgressToken verifiedDoneChar;\n\n\t\t/**\n\t\t* \\brief A char that represents the not filled  part of the progress bar for reading.\n\t\t*/\n\t\tProgressToken readNotDoneChar;\n\n\t\t/**\n\t\t* \\brief The end delimiter.\n\t\t*/\n\t\tProgressToken delimiterEnd;\n\n\t\t/**\n\t\t * \\brief The size of the filled and not filled part of the progressbar combined.\n\t\t */\n\t\tsize_t totalSize;\n\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t */\n\t\tProgressPrinter();\n\n\t\t/**\n\t\t * \\brief Prints the progress bar.\n\t\t */\n\t\tvoid print(const Progress& progress) const;\n\n\t\t/**\n\t\t* \\brief Calculates the proportion of the filled and not filled part of a progress bar.\n\t\t* \\param progressRead The read progress, where 0 <= progress <= 100.\n\t\t* \\param progressVerified The verification progress, where 0 <= progress <= 100.\n\t\t* \\param totalSize The whole size of the progress bar.\n\t\t* It will be split it by done and not done (doneSize + notDoneSize = totalSize).\n\t\t* \\param readSize The proportion of the filled part that was read.\n\t\t* \\param verifiedSize The proportion of the filled part that was verified.\n\t\t* \\param notDoneSize The proportion of the not filled part.\n\t\t*/\n\t\tstatic void calculateProgressProportions(double progressRead, double progressVerified, size_t totalSize,\n\t\t\t\t\t\t\t\t\t\t\t\t size_t& readSize, size_t& verifiedSize, size_t& notDoneSize);\n\t};\n}\n"
  },
  {
    "path": "src/logging/channels/ColoredPriorityConsoleChannel.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"ColoredPriorityConsoleChannel.hpp\"\n#include <Poco/NumberParser.h>\n#include <Poco/StringTokenizer.h>\n#include \"logging/Message.hpp\"\n#include \"logging/MinerLogger.hpp\"\n\nPoco::Mutex Burst::ColoredPriorityConsoleChannel::mutex_;\n\nBurst::ColoredPriorityConsoleChannel::ColoredPriorityConsoleChannel()\n\t: ColoredPriorityConsoleChannel{Poco::Message::Priority::PRIO_INFORMATION}\n{\n}\n\nBurst::ColoredPriorityConsoleChannel::ColoredPriorityConsoleChannel(Poco::Message::Priority priority)\n\t: priority_{priority}\n{\n}\n\nvoid Burst::ColoredPriorityConsoleChannel::log(const Poco::Message& msg)\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\tif (priority_ >= msg.getPriority())\n\t{\n\t\tPoco::StringTokenizer tokenizer{msg.getText(), \"\\n\"};\n\t\tauto type = TextType::Normal;\n\n\t\tif (msg.has(\"type\"))\n\t\t\ttype = static_cast<TextType>(Poco::NumberParser::parse(msg.get(\"type\")));\n\n\t\tauto condition = true;\n\n\t\tif (msg.has(\"condition\"))\n\t\t\tcondition = Poco::NumberParser::parseBool(msg.get(\"condition\"));\n\n\t\tif (condition)\n\t\t\tMinerLogger::write(msg.getText(), type);\n\t}\n}\n\nvoid Burst::ColoredPriorityConsoleChannel::setPriority(Poco::Message::Priority priority)\n{\n\tpriority_ = priority;\n}\n\nPoco::Message::Priority Burst::ColoredPriorityConsoleChannel::getPriority() const\n{\n\treturn priority_;\n}\n"
  },
  {
    "path": "src/logging/channels/ColoredPriorityConsoleChannel.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <Poco/Message.h>\n#include <Poco/Mutex.h>\n#include <Poco/Channel.h>\n\nnamespace Burst\n{\n\t/**\n\t * \\brief A logging channel that logs messages into the \\class Console\n\t */\n\tclass ColoredPriorityConsoleChannel : public Poco::Channel\n\t{\n\tpublic:\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * The default priority INFORMATION is set.\n\t\t */\n\t\tColoredPriorityConsoleChannel();\n\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * \\param priority The priority of the channel.\n\t\t */\n\t\texplicit ColoredPriorityConsoleChannel(Poco::Message::Priority priority);\n\n\t\t/**\n\t\t * \\brief Destructor.\n\t\t */\n\t\t~ColoredPriorityConsoleChannel() override = default;\n\n\t\t/**\n\t\t * \\brief Logs a messages.\n\t\t * \\param msg The message.\n\t\t */\n\t\tvoid log(const Poco::Message& msg) override;\n\n\t\t/**\n\t\t * \\brief Sets the priority of the channel.\n\t\t * \\param priority The new priority.\n\t\t */\n\t\tvoid setPriority(Poco::Message::Priority priority);\n\n\t\t/**\n\t\t * \\brief Returns the priority of the channel.\n\t\t * \\return The priority.\n\t\t */\n\t\tPoco::Message::Priority getPriority() const;\n\n\tprivate:\n\t\tstatic Poco::Mutex mutex_;\n\t\tPoco::Message::Priority priority_;\n\t};\n}\n"
  },
  {
    "path": "src/logging/channels/MinerDataChannel.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"MinerDataChannel.hpp\"\n#include <Poco/Message.h>\n#include \"mining/MinerData.hpp\"\n\nBurst::MinerDataChannel::MinerDataChannel()\n\t: minerData_{ nullptr }\n{}\n\nBurst::MinerDataChannel::MinerDataChannel(MinerData* minerData)\n\t: minerData_{ minerData }\n{}\n\nvoid Burst::MinerDataChannel::log(const Poco::Message& msg)\n{\n\tif (minerData_ == nullptr)\n\t\treturn;\n\n\t// we dont send informations and notices, because for them are build custom JSON objects\n\t// so that the webserver can react appropriate\n\tif (msg.getPriority() == Poco::Message::PRIO_INFORMATION ||\n\t\tmsg.getPriority() == Poco::Message::PRIO_NOTICE)\n\t\treturn;\n\n\tminerData_->addMessage(msg);\n}\n\nvoid Burst::MinerDataChannel::setMinerData(MinerData* minerData)\n{\n\tminerData_ = minerData;\n}\n\nBurst::MinerData* Burst::MinerDataChannel::getMinerData() const\n{\n\treturn minerData_;\n}\n"
  },
  {
    "path": "src/logging/channels/MinerDataChannel.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <Poco/Channel.h>\n\nnamespace Burst\n{\n\tclass MinerData;\n\n\t/**\n\t * \\brief A logging channel that logs messages into the \\class MinerData\n\t */\n\tclass MinerDataChannel : public Poco::Channel\n\t{\n\tpublic:\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * The miner data is not defined, therefore no messages will be logged.\n\t\t */\n\t\tMinerDataChannel();\n\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * \\param minerData The miner data, in which the channel will log messages.\n\t\t */\n\t\texplicit MinerDataChannel(MinerData* minerData);\n\n\t\t/**\n\t\t * \\brief Destructor.\n\t\t */\n\t\t~MinerDataChannel() override = default;\n\n\t\t/**\n\t\t * \\brief Logs a messages.\n\t\t * When no miner data is defined, the message is discarded.\n\t\t * \\param msg The message.\n\t\t */\n\t\tvoid log(const Poco::Message& msg) override;\n\n\t\t/**\n\t\t * \\brief Sets the destination miner data, in which the channel will log the messages.\n\t\t * \\param minerData The miner data.\n\t\t */\n\t\tvoid setMinerData(MinerData* minerData);\n\n\t\t/**\n\t\t * \\brief Returns the miner data, in which the channel logs messages.\n\t\t * \\return The miner data.\n\t\t */\n\t\tMinerData* getMinerData() const;\n\n\tprivate:\n\t\tMinerData* minerData_;\n\t};\n}\n"
  },
  {
    "path": "src/main.cpp",
    "content": "// ==========================================================================\n//\n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n//\n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n//\n// ==========================================================================\n\n#define CUDA_API_PER_THREAD_DEFAULT_STREAM\n\n#include \"mining/Miner.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include \"mining/MinerConfig.hpp\"\n#include <Poco/Net/SSLManager.h>\n#include \"Poco/Net/ConsoleCertificateHandler.h\"\n#include \"Poco/Net/HTTPSStreamFactory.h\"\n#include \"Poco/Net/AcceptCertificateHandler.h\"\n#include <Poco/Net/HTTPSSessionInstantiator.h>\n// ReSharper disable CppUnusedIncludeDirective\n#include <Poco/Net/PrivateKeyPassphraseHandler.h>\n// ReSharper restore CppUnusedIncludeDirective\n#include <Poco/NestedDiagnosticContext.h>\n#include \"webserver/MinerServer.hpp\"\n#include <Poco/Logger.h>\n#include \"mining/MinerCL.hpp\"\n#include \"gpu/impl/gpu_cuda_impl.hpp\"\n#include <Poco/Util/OptionSet.h>\n#include <Poco/Util/OptionProcessor.h>\n#include <Poco/Util/HelpFormatter.h>\n#include <Poco/Util/Validator.h>\n#include <Poco/FileStream.h>\n#include <Poco/File.h>\n#include <regex>\n#include <Poco/Data/SQLite/Connector.h>\n#include \"MinerUtil.hpp\"\n\nclass SslInitializer\n{\npublic:\n\tSslInitializer();\n\t~SslInitializer();\n};\n\nclass KeyConfigHandler: public Poco::Net::PrivateKeyPassphraseHandler\n{\npublic:\n\texplicit KeyConfigHandler(bool server);\n\t~KeyConfigHandler() override;\n\tvoid onPrivateKeyRequested(const void*, std::string& privateKey) override;\n};\n\nstruct Arguments\n{\n\tArguments();\n\tbool process(int argc, const char* argv[]);\n\n\tbool helpRequested = false;\n\tstd::string confPath = \"mining.conf\";\n\nprivate:\n\tvoid displayHelp(const std::string& name, const std::string& value);\n\tvoid setConfPath(const std::string& name, const std::string& value);\n\nprivate:\n\tPoco::Util::OptionSet options_;\n};\n\nint main(const int argc, const char* argv[])\n{\n\tpoco_ndc(main);\n\n\tArguments arguments;\n\n\tif (!arguments.process(argc, argv))\n\t\treturn EXIT_FAILURE;\n\n\tif (arguments.helpRequested)\n\t\treturn EXIT_SUCCESS;\n\n\tBurst::MinerLogger::setup();\n\n\t// create a message dispatcher..\n\t//auto messageDispatcher = Burst::Message::Dispatcher::create();\n\t// ..and start it in its own thread\n\t//Poco::ThreadPool::defaultPool().start(*messageDispatcher);\n\n\tconst auto general = &Poco::Logger::get(\"general\");\n\n#ifdef NDEBUG\n\tstd::string mode = \"Release\";\n#else\n\tstd::string mode = \"Debug\";\n#endif\n\n\tusing namespace Burst::Settings;\n\n\tlog_information(general, Burst::Settings::project.nameAndVersionVerbose);\n\tlog_information(general, \"%s mode%s\", mode, Burst::createBuildFeatures());\n\tlog_information(general, \"----------------------------------------------\");\n\tlog_information(general, \"Github:   https://github.com/Creepsky/creepMiner\");\n\tlog_information(general, \"Author:   Creepsky [creepsky@gmail.com]\");\n\tlog_information(general, \"Burst :   BURST-JBKL-ZUAV-UXMB-2G795\");\n\tlog_information(general, \"----------------------------------------------\");\n\n\ttry\n\t{\n\t\tusing namespace Poco;\n\t\tusing namespace Net;\n\n\t\tSslInitializer sslInitializer;\n\t\tHTTPSStreamFactory::registerFactory();\n\n\t\tconst SharedPtr<InvalidCertificateHandler> ptrCert(new AcceptCertificateHandler(false));\n\t\tconst Context::Ptr clientContext(new Context(Context::CLIENT_USE, \"\"));\n\t\tSSLManager::instance().initializeClient(nullptr, ptrCert, clientContext);\n\n\t\tHTTPSessionInstantiator::registerInstantiator();\n\t\tHTTPSSessionInstantiator::registerInstantiator();\n\n\t\t// start versionChecker timer thread , checking online version every 30 minutes\n\t\tTimer checkVersionTimer(100, 1800000);\n\t\tcheckVersionTimer.start(Poco::TimerCallback<Burst::ProjectData>(project, &Burst::ProjectData::refreshAndCheckOnlineVersion));\n\n\t\tauto running = true;\n\t\t\n\t\tData::SQLite::Connector::registerConnector();\n\n\t\twhile (running)\n\t\t{\n\t\t\t// load the config\n\t\t\tauto& config = Burst::MinerConfig::getConfig();\n\t\t\tauto configLoaded = config.readConfigFile(arguments.confPath);\n\t\t\t\n\t\t\t// the config could not be loaded, look for a config in the creepMiner home dir\n\t\t\tif (configLoaded == Burst::ReadConfigFileResult::NotFound)\n\t\t\t{\n\t\t\t\tlog_information(general, \"Could not load config %s\", arguments.confPath);\n\n\t\t\t\t// create the home directory\n\t\t\t\tconst auto minerHomePath = Burst::getMinerHomeDir();\n\n\t\t\t\tauto homeConfigPath(minerHomePath);\n\t\t\t\thomeConfigPath.append(\"mining.conf\");\n\t\t\t\tconst auto homeConfig = homeConfigPath.toString();\n\n\t\t\t\tlog_information(general, \"Trying to load config %s\", homeConfig);\n\t\t\t\tconfigLoaded = config.readConfigFile(homeConfig);\n\n\t\t\t\t// if there is also no config in the home dir, create one in the home dir\n\t\t\t\tif (configLoaded == Burst::ReadConfigFileResult::NotFound)\n\t\t\t\t{\n\t\t\t\t\tconst auto createConfig = [&config](const auto& rootPath)\n\t\t\t\t\t{\n\t\t\t\t\t\tPath logDir{rootPath};\n\n\t\t\t\t\t\tPath configPath{rootPath};\n\t\t\t\t\t\tconfigPath.append(\"mining.conf\");\n\n\t\t\t\t\t\tPath databasePath{rootPath};\n\t\t\t\t\t\tdatabasePath.setFileName(\"data.db\");\n\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlogDir.makeDirectory();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// save settings to the config\n\t\t\t\t\t\t\tconfig.setLogDir(logDir.toString());\n\t\t\t\t\t\t\tconfig.useLogfile(true);\n\t\t\t\t\t\t\tconfig.setDatabasePath(databasePath.toString());\n\n\t\t\t\t\t\t\tif (!config.save(configPath.toString()))\n\t\t\t\t\t\t\t\tlog_error(Burst::MinerLogger::general, \"Could not save current settings!\");\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (const Exception& e)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlog_warning(Burst::MinerLogger::config, \"Could not create the config at %s: %s\", rootPath, e.displayText());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn config.readConfigFile(configPath.toString());\n\t\t\t\t\t};\n\n\t\t\t\t\tconfigLoaded = createConfig(Path::current());\n\n\t\t\t\t\tif (configLoaded != Burst::ReadConfigFileResult::Ok)\n\t\t\t\t\t\tconfigLoaded = createConfig(minerHomePath);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (configLoaded == Burst::ReadConfigFileResult::Ok)\n\t\t\t{\n\t\t\t\tlog_information(general, \"Config loaded: %s\", Burst::MinerConfig::getConfig().getPath());\n\n\t\t\t\tif (!config.getServerCertificatePath().empty())\n\t\t\t\t{\n#ifdef _WIN32\n\t\t\t\t\tconst Context::Ptr serverContext(new Context(Context::SERVER_USE,\n\t\t\t\t\t\tconfig.getServerCertificatePath(),\n\t\t\t\t\t\tContext::VERIFY_RELAXED, Context::OPT_LOAD_CERT_FROM_FILE | Context::OPT_USE_STRONG_CRYPTO));\n#elif defined __linux__ || defined __APPLE__\n\t\t\t\t\tPoco::Path pathCertificate{config.getServerCertificatePath()};\n\t\t\t\t\tPoco::Path pathKey{pathCertificate};\n\t\t\t\t\tpathKey.setExtension(\"key\");\n\t\t\t\t\tconst Context::Ptr serverContext(new Context(Context::SERVER_USE,\n\t\t\t\t\t\tpathKey.toString(),\n\t\t\t\t\t\tpathCertificate.toString(),\n\t\t\t\t\t\t\"\"));\n#endif\n\n\t\t\t\t\tconst SharedPtr<PrivateKeyPassphraseHandler> privateKeyPassphraseHandler(new KeyConfigHandler(true));\n\t\t\t\t\tSSLManager::instance().initializeServer(privateKeyPassphraseHandler, ptrCert, serverContext);\n\t\t\t\t}\n\n\t\t\t\tif (config.getProcessorType() == \"OPENCL\" &&\n\t\t\t\t\t!Burst::MinerCl::getCL().initialized())\n\t\t\t\t\tBurst::MinerCl::getCL().create(Burst::MinerConfig::getConfig().getGpuPlatform(),\n\t\t\t\t\t\tconfig.getGpuDevice());\n\t\t\t\telse if (config.getProcessorType() == \"CUDA\")\n\t\t\t\t{\n\t\t\t\t\tBurst::GpuCudaImpl::listDevices();\n\t\t\t\t\tBurst::GpuCudaImpl::useDevice(config.getGpuDevice());\n\t\t\t\t}\n\n\t\t\t\tBurst::Miner miner;\n\t\t\t\tBurst::MinerServer server{miner};\n\n\t\t\t\tif (config.getStartServer())\n\t\t\t\t{\n\t\t\t\t\tserver.connectToMinerData(miner.getData());\n\t\t\t\t\tserver.run(config.getServerUrl().getPort());\n\t\t\t\t}\n\n\t\t\t\tBurst::MinerLogger::setChannelMinerData(&miner.getData());\n\t\t\t\tconfig.checkPlotOverlaps();\n\n\t\t\t\tif (!config.getProxyFullUrl().empty())\n\t\t\t\t\tHTTPClientSession::setGlobalProxyConfig(config.getProxyConfig());\n\n\t\t\t\tminer.run();\n\t\t\t\tserver.stop();\n\n\t\t\t\trunning = miner.wantRestart();\n\t\t\t\tBurst::MinerLogger::setChannelMinerData(nullptr);\n\n\t\t\t\tif (running)\n\t\t\t\t\tlog_system(Burst::MinerLogger::miner, \"Restarting the miner...\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_error(general, \"Aborting program due to invalid configuration\");\n\t\t\t\trunning = false;\n\t\t\t}\n\t\t}\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_fatal(general, \"Aborting program due to exceptional state: %s\", exc.displayText());\n\t\tlog_exception(general, exc);\n\t}\n\tcatch (std::exception& exc)\n\t{\n\t\tlog_fatal(general, \"Aborting program due to exceptional state: %s\", std::string(exc.what()));\n\t}\n\n\t// wake up all message dispatcher\n\t//Burst::Message::wakeUpAllDispatcher();\n\n\t// stop all running background-tasks\n\tPoco::ThreadPool::defaultPool().stopAll();\n\tPoco::ThreadPool::defaultPool().joinAll();\n\n\treturn 0;\n}\n\nSslInitializer::SslInitializer()\n{\n\tPoco::Net::initializeSSL();\n}\n\nSslInitializer::~SslInitializer()\n{\n\tPoco::Net::uninitializeSSL();\n}\n\nArguments::Arguments()\n{\n\tusing Poco::Util::Option;\n\n\toptions_.addOption(Option(\"help\", \"h\", \"Display this help information\")\n\t\t.required(false)\n\t\t.repeatable(false)\n\t\t.callback(Poco::Util::OptionCallback<Arguments>(this, &Arguments::displayHelp)));\n\n\toptions_.addOption(Option(\"config\", \"c\", \"Path to miner config file\\n\"\n        \"e.g. Windows -c d:\\\\creepMiner\\\\miner.config\\n\"\n        \"     or      --config=c:\\\\creepMiner\\\\miner.config\\n\"\n        \"e.g. linux   -c /path/miner.config\")\n\t\t.required(false)\n\t\t.repeatable(false)\n\t\t.argument(\"path\")\n\t\t.callback(Poco::Util::OptionCallback<Arguments>(this, &Arguments::setConfPath)));\n}\n\nbool Arguments::process(const int argc, const char* argv[])\n{\n\tPoco::Util::OptionProcessor optionProcessor(options_);\n\toptionProcessor.setUnixStyle(std::string(Burst::Settings::osFamily) != \"Windows\");\n\n\ttry\n\t{\n\t\tfor (auto i = 1; i < argc; ++i)\n\t\t{\n\t\t\tstd::string name;\n\t\t\tstd::string value;\n\n\t\t\tif (optionProcessor.process(argv[i], name, value))\n\t\t\t{\n\t\t\t\tif (!name.empty())\n\t\t\t\t{\n\t\t\t\t\tconst auto& option = options_.getOption(name);\n\n\t\t\t\t\tif (option.validator())\n\t\t\t\t\t\toption.validator()->validate(option, value);\n\n\t\t\t\t\tif (option.callback())\n\t\t\t\t\t\toption.callback()->invoke(name, value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\toptionProcessor.checkRequired();\n\t\treturn true;\n\t}\n\tcatch (...)\n\t{\n\t\tdisplayHelp(\"\", \"\");\n\t\treturn false;\n\t}\n}\n\nvoid Arguments::displayHelp(const std::string& name, const std::string& value)\n{\n\tPoco::Util::HelpFormatter helpFormatter(options_);\n\thelpFormatter.setUnixStyle(std::string(Burst::Settings::osFamily) != \"Windows\");\n\thelpFormatter.setCommand(\"creepMiner\");\n\thelpFormatter.setUsage(\"<options>\");\n\thelpFormatter.setHeader(\"Burstcoin Proof-of-Capacity CPU and GPU miner.\");\n\thelpFormatter.setFooter(\"Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\");\n\thelpFormatter.setAutoIndent();\n\thelpFormatter.format(std::cout);\n\n\thelpRequested = true;\n}\n\nvoid Arguments::setConfPath(const std::string& name, const std::string& value)\n{\n\tconfPath = value;\n}\n\nKeyConfigHandler::KeyConfigHandler(bool server)\n\t: PrivateKeyPassphraseHandler{server}\n{}\n\nKeyConfigHandler::~KeyConfigHandler() = default;\n\nvoid KeyConfigHandler::onPrivateKeyRequested(const void*, std::string& privateKey)\n{\n\tprivateKey = Burst::MinerConfig::getConfig().getServerCertificatePass();\n}\n"
  },
  {
    "path": "src/mining/Deadline.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"Deadline.hpp\"\n#include \"MinerUtil.hpp\"\n#include <algorithm>\n#include <utility>\n#include \"nxt/nxt_address.h\"\n#include \"wallet/Account.hpp\"\n#include \"MinerData.hpp\"\n#include \"plots/PlotSizes.hpp\"\n#include \"MinerConfig.hpp\"\n\nBurst::Deadline::Deadline(Deadline&& other) noexcept\n\t: account_{std::move(other.account_)}, block_{other.block_}, nonce_{other.nonce_},\n\t  deadline_{other.deadline_}, plotFile_{std::move(other.plotFile_)}, onTheWay_{other.onTheWay_.load()},\n\t  sent_{other.sent_.load()},\n\t  confirmed_{other.confirmed_.load()}, minerName_{std::move(other.minerName_)},\n\t  workerName_{std::move(other.workerName_)}, plotsize_{other.plotsize_}, ip_{std::move(other.ip_)},\n\t  parent_{other.parent_}\n{\n}\n\nBurst::Deadline& Burst::Deadline::operator=(Deadline&& other) noexcept\n{\n\tif (this == &other)\n\t\treturn *this;\n\taccount_ = std::move(other.account_);\n\tblock_ = other.block_;\n\tnonce_ = other.nonce_;\n\tdeadline_ = other.deadline_;\n\tplotFile_ = std::move(other.plotFile_);\n\tonTheWay_ = other.onTheWay_.load();\n\tsent_ = other.sent_.load();\n\tconfirmed_ = other.confirmed_.load();\n\tminerName_ = std::move(other.minerName_);\n\tworkerName_ = std::move(other.workerName_);\n\tplotsize_ = other.plotsize_;\n\tip_ = std::move(other.ip_);\n\tparent_ = other.parent_;\n\treturn *this;\n}\n\nBurst::Deadline::Deadline(const Poco::UInt64 nonce, const Poco::UInt64 deadline, std::shared_ptr<Account> account,\n                          const Poco::UInt64 block, std::string plotFile, Deadlines* parent)\n\t: account_(std::move(account)),\n\t  block_(block),\n\t  nonce_(nonce),\n\t  deadline_(deadline),\n\t  plotFile_(std::move(plotFile)),\n\t  onTheWay_{false},\n\t  sent_{false},\n\t  confirmed_{false},\n\t  parent_{parent}\n{}\n\nPoco::UInt64 Burst::Deadline::getNonce() const\n{\n\treturn nonce_;\n}\n\nPoco::UInt64 Burst::Deadline::getDeadline() const\n{\n\treturn deadline_;\n}\n\nBurst::AccountId Burst::Deadline::getAccountId() const\n{\n\treturn account_->getId();\n}\n\nstd::string Burst::Deadline::getAccountName() const\n{\n\tauto name = account_->getName();\n\n\tif (name.empty())\n\t\treturn NxtAddress(getAccountId()).to_string();\n\n\treturn name;\n}\n\nPoco::UInt64 Burst::Deadline::getBlock() const\n{\n\treturn block_;\n}\n\nbool Burst::Deadline::isOnTheWay() const\n{\n\treturn onTheWay_.load();\n}\n\nbool Burst::Deadline::isSent() const\n{\n\treturn sent_.load();\n}\n\nbool Burst::Deadline::isConfirmed() const\n{\n\treturn confirmed_.load();\n}\n\nconst std::string& Burst::Deadline::getPlotFile() const\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{ mutex_ };\n\treturn plotFile_;\n}\n\nstd::string Burst::Deadline::getMiner() const\n{\n\treturn minerName_.empty() ? Settings::project.nameAndVersionVerbose : minerName_;\n}\n\nconst std::string& Burst::Deadline::getWorker() const\n{\n\treturn workerName_;\n}\n\nPoco::UInt64 Burst::Deadline::getTotalPlotsize() const\n{\n\treturn plotsize_ == 0 ? PlotSizes::getTotal(PlotSizes::Type::Combined) : plotsize_;\n}\n\nconst Poco::Net::IPAddress& Burst::Deadline::getIp() const\n{\n\treturn ip_;\n}\n\nstd::string Burst::Deadline::toActionString(const std::string& action) const\n{\n\tif (MinerConfig::getConfig().isVerboseLogging())\n\t\treturn Poco::format(\"%s: %s (%s)\\n\"\n\t\t                    \"\\tnonce: %s\\n\"\n\t\t                    \"\\tin:    %s\\n\"\n\t\t                    \"\\tfrom:  %s\",\n\t\t                    getAccountName(), action, deadlineToReadableString(), numberToString(getNonce()), getPlotFile(),\n\t\t                    getWorker().empty() ? getIp().toString() : Poco::format(\"%s (%s)\", getWorker(), getIp().toString()));\n\n\treturn Poco::format(\"%s: %s (%s)\", getAccountName(), action, deadlineToReadableString(), numberToString(getNonce()));\n}\n\nstd::string Burst::Deadline::toActionString(const std::string& action,\n\tconst std::vector<std::pair<std::string, std::string>>& additionalData) const\n{\n\tsize_t longestKey = 0;\n\n\tfor (const auto& pair : additionalData)\n\t\tif (pair.first.size() > longestKey)\n\t\t\tlongestKey = pair.first.size();\n\n\tlongestKey = std::max(longestKey, size_t{5});\n\t\n\tstd::stringstream sstream;\n\tsstream << Poco::format(\"%s: %s (%s)\", getAccountName(), action, deadlineToReadableString()) << std::endl;\n\tsstream << '\\t' << Poco::format(\"nonce:%s%s\", std::string(longestKey + 3 - 5, ' '), numberToString(getNonce())) << std::endl;\n\tsstream << '\\t' << Poco::format(\"in:%s%s\", std::string(longestKey + 3 - 2, ' '), getPlotFile()) << std::endl;\n\tsstream << '\\t' << Poco::format(\"from:%s%s\",\n\t                                std::string(longestKey + 3 - 4, ' '),\n\t                                getWorker().empty()\n\t\t                                ? getIp().toString()\n\t\t                                : Poco::format(\"%s (%s)\", getWorker(), getIp().toString())) << std::endl;\n\n\tfor (size_t i = 0; i < additionalData.size(); ++i)\n\t{\n\t\tconst auto& pair = additionalData[i];\n\n\t\tsstream << '\\t' << Poco::format(\"%s:%s%s\", pair.first, std::string(longestKey + 3 - pair.first.size(), ' '),\n\t\t                                pair.second);\n\n\t\tif (i + 1 < additionalData.size())\n\t\t\tsstream << std::endl;\t\t\n\t}\n\n\treturn sstream.str();\n}\n\nvoid Burst::Deadline::setDeadline(Poco::UInt64 deadline)\n{\n\tdeadline_ = deadline;\n\n\tif (parent_ != nullptr)\n\t\tparent_->resort();\n}\n\nvoid Burst::Deadline::setMiner(const std::string& miner)\n{\n\tminerName_ = miner;\n}\n\nvoid Burst::Deadline::setWorker(const std::string& worker)\n{\n\tworkerName_ = worker;\n}\n\nvoid Burst::Deadline::setTotalPlotsize(const Poco::UInt64 plotsize)\n{\n\tplotsize_ = plotsize;\n}\n\nvoid Burst::Deadline::setIp(const Poco::Net::IPAddress& ip)\n{\n\tip_ = ip;\n}\n\nvoid Burst::Deadline::setParent(Deadlines* parent)\n{\n\tparent_ = parent;\n}\n\nbool Burst::Deadline::operator<(const Burst::Deadline& rhs) const\n{\n\treturn getDeadline() < rhs.getDeadline();\n}\n\nBurst::Deadline::~Deadline() = default;\n\nvoid Burst::Deadline::found(const bool tooHigh)\n{\n\tif (parent_ != nullptr)\n\t\tparent_->deadlineEvent(this->shared_from_this(), std::string(\"nonce found\") + (tooHigh ? \" (too high)\" : + \"\"));\n}\n\nvoid Burst::Deadline::onTheWay()\n{\n\tonTheWay_ = true;\n\n\tif (parent_ != nullptr)\n\t\tparent_->deadlineEvent(this->shared_from_this(), \"nonce found\");\n}\n\nvoid Burst::Deadline::send()\n{\t\n\tsent_ = true;\n\n\tif (parent_ != nullptr)\n\t\tparent_->deadlineEvent(this->shared_from_this(), \"nonce submitted\");\n}\n\nvoid Burst::Deadline::confirm()\n{\t\n\tconfirmed_ = true;\n\n\tif (parent_ != nullptr)\n\t\tparent_->deadlineConfirmed(this->shared_from_this());\n}\n\nstd::string Burst::Deadline::deadlineToReadableString() const\n{\n\treturn deadlineFormat(deadline_);\n}\n\nbool Burst::Deadline::operator()(const Deadline& lhs, const Deadline& rhs) const\n{\n\treturn lhs.deadline_ < rhs.deadline_;\n}\n\nBurst::Deadlines::Deadlines(BlockData* parent)\n\t: parent_{parent}\n{}\n\nstd::shared_ptr<Burst::Deadline> Burst::Deadlines::add(Poco::UInt64 nonce, Poco::UInt64 deadline, std::shared_ptr<Account> account, Poco::UInt64 block, std::string plotFile)\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{mutex_};\n\tauto deadlinePtr = std::make_shared<Deadline>(nonce, deadline, account, block, std::move(plotFile), this);\n\tdeadlines_.insert(deadlinePtr);\n\treturn deadlinePtr;\n}\n\nvoid Burst::Deadlines::add(std::shared_ptr<Deadline> deadline)\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{mutex_};\n\tdeadline->setParent(this);\n\tdeadlines_.emplace(std::move(deadline));\n}\n\nvoid Burst::Deadlines::clear()\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{ mutex_ };\n\tdeadlines_.clear();\n}\n\nbool Burst::Deadlines::confirm(Nonce nonce)\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{ mutex_ };\n\n\tconst auto iter = std::find_if(deadlines_.begin(), deadlines_.end(), [nonce](std::shared_ptr<Deadline> dl)\n\t{\n\t\treturn dl->getNonce() == nonce;\n\t});\n\n\tif (iter == deadlines_.end())\n\t\treturn false;\n\n\t(*iter)->confirm();\n\n\treturn true;\n}\n\nbool Burst::Deadlines::confirm(Nonce nonce, AccountId accountId, Poco::UInt64 block)\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{ mutex_ };\n\n\tconst auto iter = std::find_if(deadlines_.begin(), deadlines_.end(),\n\t                               [nonce, accountId, block](std::shared_ptr<Deadline> dl)\n\t                               {\n\t\t                               return dl->getNonce() == nonce && dl->getAccountId() == accountId && dl->getBlock() ==\n\t\t\t                               block;\n\t                               });\n\n\tif (iter == deadlines_.end())\n\t\treturn false;\n\n\t(*iter)->confirm();\n\treturn true;\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::Deadlines::getBest() const\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{ mutex_ };\n\n\tif (deadlines_.empty())\n\t\treturn nullptr;\n\n\treturn *deadlines_.begin();\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::Deadlines::getBestConfirmed() const\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{ mutex_ };\n\n\tfor (auto& deadline : deadlines_)\n\t\tif (deadline->isConfirmed())\n\t\t\treturn deadline;\n\n\treturn nullptr;\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::Deadlines::getBestFound() const\n{\n\treturn getBest();\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::Deadlines::getBestSent() const\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{ mutex_ };\n\n\tfor (auto& deadline : deadlines_)\n\t\tif (deadline->isSent())\n\t\t\treturn deadline;\n\n\treturn nullptr;\n}\n\nstd::vector<std::shared_ptr<Burst::Deadline>> Burst::Deadlines::getDeadlines() const\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{mutex_};\n\tstd::vector<std::shared_ptr<Deadline>> deadlines;\n\n\tfor (auto& deadline : deadlines_)\n\t\tdeadlines.emplace_back(deadline);\n\n\treturn deadlines;\n}\n\nvoid Burst::Deadlines::deadlineEvent(const std::shared_ptr<Deadline>& deadline, const std::string& type) const\n{\n\tif (parent_ != nullptr)\n\t\tparent_->addBlockEntry(createJsonDeadline(*deadline, type));\n}\n\nvoid Burst::Deadlines::deadlineConfirmed(const std::shared_ptr<Deadline>& deadline) const\n{\n\tif (parent_ != nullptr)\n\t\tparent_->confirmedDeadlineEvent(deadline);\n}\n\nvoid Burst::Deadlines::resort()\n{\n\tPoco::ScopedLock<Poco::FastMutex> lock{ mutex_ };\n\tdeadlines_ = { deadlines_.begin(), deadlines_.end() };\n}\n"
  },
  {
    "path": "src/mining/Deadline.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <memory>\n#include \"Declarations.hpp\"\n#include <Poco/Mutex.h>\n#include <atomic>\n#include <set>\n#include <vector>\n#include <Poco/Net/IPAddress.h>\n\nnamespace Burst\n{\n\tclass Deadlines;\n\tclass Account;\n\tclass BlockData;\n\n\tclass Deadline : public std::enable_shared_from_this<Deadline>\n\t{\n\tpublic:\n\n\t\tDeadline(Poco::UInt64 nonce, Poco::UInt64 deadline, std::shared_ptr<Account> account, Poco::UInt64 block, std::string plotFile,\n\t\t\tDeadlines* parent = nullptr);\n\t\tDeadline(const Deadline& other) = delete;\n\t\tDeadline(Deadline&& other) noexcept;\n\t\tDeadline& operator=(const Deadline& other) = delete;\n\t\tDeadline& operator=(Deadline&& other) noexcept;\n\t\t~Deadline();\n\n\t\tvoid found(bool tooHigh = false);\n\t\tvoid onTheWay();\n\t\tvoid send();\n\t\tvoid confirm();\n\n\t\tstd::string deadlineToReadableString() const;\n\t\tPoco::UInt64 getNonce() const;\n\t\tPoco::UInt64 getDeadline() const;\n\t\tAccountId getAccountId() const;\n\t\tstd::string getAccountName() const;\n\t\tPoco::UInt64 getBlock() const;\n\t\tconst std::string& getPlotFile() const;\n\t\tstd::string getMiner() const;\n\t\tconst std::string& getWorker() const;\n\t\tPoco::UInt64 getTotalPlotsize() const;\n\t\tconst Poco::Net::IPAddress& getIp() const;\n\t\tstd::string toActionString(const std::string& action) const;\n\t\tstd::string toActionString(const std::string& action,\n\t\t\tconst std::vector<std::pair<std::string, std::string>>& additionalData) const;\n\n\t\tbool isOnTheWay() const;\n\t\tbool isSent() const;\n\t\tbool isConfirmed() const;\n\n\t\tvoid setDeadline(Poco::UInt64 deadline);\n\t\tvoid setMiner(const std::string& miner);\n\t\tvoid setWorker(const std::string& worker);\n\t\tvoid setTotalPlotsize(Poco::UInt64 plotsize);\n\t\tvoid setIp(const Poco::Net::IPAddress& ip);\n\t\tvoid setParent(Deadlines* parent);\n\n\t\tbool operator<(const Deadline& rhs) const;\n\t\tbool operator()(const Deadline& lhs, const Deadline& rhs) const;\n\n\tprivate:\n\t\tstd::shared_ptr<Account> account_;\n\t\tPoco::UInt64 block_;\n\t\tPoco::UInt64 nonce_;\n\t\tPoco::UInt64 deadline_;\n\t\tstd::string plotFile_ = \"\";\n\t\tstd::atomic<bool> onTheWay_;\n\t\tstd::atomic<bool> sent_;\n\t\tstd::atomic<bool> confirmed_;\n\t\tstd::string minerName_ = \"\";\n\t\tstd::string workerName_ = \"\";\n\t\tPoco::UInt64 plotsize_ = 0;\n\t\tPoco::Net::IPAddress ip_{\"127.0.0.1\"};\n\t\tDeadlines* parent_;\n\t\tmutable Poco::FastMutex mutex_;\n\t};\n\n\tclass Deadlines\n\t{\n\tpublic:\n\t\texplicit Deadlines(BlockData* parent = nullptr);\n\t\t//Deadlines(const Deadlines& rhs);\n\t\t//Deadlines& operator=(const Deadlines& rhs);\n\n\t\tstd::shared_ptr<Deadline> add(Poco::UInt64 nonce, Poco::UInt64 deadline, std::shared_ptr<Account> account, Poco::UInt64 block, std::string plotFile);\n\t\tvoid add(std::shared_ptr<Deadline> deadline);\n\t\tvoid clear();\n\t\tbool confirm(Nonce nonce);\n\t\tbool confirm(Nonce nonce, AccountId accountId, Poco::UInt64 block);\n\n\t\tstd::shared_ptr<Deadline> getBest() const;\n\t\tstd::shared_ptr<Deadline> getBestConfirmed() const;\n\t\tstd::shared_ptr<Deadline> getBestFound() const;\n\t\tstd::shared_ptr<Deadline> getBestSent() const;\n\n\t\tstd::vector<std::shared_ptr<Deadline>> getDeadlines() const;\n\n\tprivate:\n\t\tvoid deadlineEvent(const std::shared_ptr<Deadline>& deadline, const std::string& type) const;\n\t\tvoid deadlineConfirmed(const std::shared_ptr<Deadline>& deadline) const;\n\t\tvoid resort();\n\n\t\tstruct LessThan : std::binary_function<std::shared_ptr<Deadline>, std::shared_ptr<Deadline>, bool>\n\t\t{\n\t\t\tbool operator()(const std::shared_ptr<Deadline>& lhs, const std::shared_ptr<Deadline>& rhs) const\n\t\t\t{\n\t\t\t\treturn !(lhs == rhs) && (*lhs < *rhs);\n\t\t\t}\n\t\t};\n\n\t\tstd::set<std::shared_ptr<Deadline>, LessThan> deadlines_;\n\t\tBlockData* parent_;\n\t\tmutable Poco::FastMutex mutex_;\n\n\t\tfriend class Deadline;\n\t};\n}\n"
  },
  {
    "path": "src/mining/Miner.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"Miner.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include \"MinerConfig.hpp\"\n#include \"plots/PlotReader.hpp\"\n#include \"MinerUtil.hpp\"\n#include \"network/Request.hpp\"\n#include <Poco/Net/HTTPRequest.h>\n#include \"network/NonceSubmitter.hpp\"\n#include <Poco/JSON/Parser.h>\n#include \"plots/PlotSizes.hpp\"\n#include <Poco/FileStream.h>\n#include <fstream>\n#include <Poco/File.h>\n#include <Poco/Delegate.h>\n#include \"plots/PlotVerifier.hpp\"\n\nnamespace Burst\n{\n\tnamespace MinerHelper\n\t{\n\t\ttemplate <typename T>\n\t\tvoid createWorkerDefault(std::unique_ptr<Poco::ThreadPool>& thread_pool, std::unique_ptr<Poco::TaskManager>& task_manager,\n\t\t\tconst size_t size, Miner& miner, Poco::NotificationQueue& queue)\n\t\t{\n\t\t\tthread_pool = std::make_unique<Poco::ThreadPool>(1, static_cast<int>(size));\n\t\t\ttask_manager = std::make_unique<Poco::TaskManager>(*thread_pool);\n\n\t\t\tauto submitFunction = [&miner](Poco::UInt64 nonce, Poco::UInt64 accountId, Poco::UInt64 deadline,\n\t\t\t                               Poco::UInt64 blockheight, const std::string& plotFile,\n\t\t\t                               bool ownAccount)\n\t\t\t{\n\t\t\t\tDeadline deadlineToAdd{nonce, deadline, miner.getAccount(accountId, ownAccount), blockheight, plotFile};\n\t\t\t\tdeadlineToAdd.setWorker(MinerConfig::getConfig().getWorkerName());\n\t\t\t\tNonceConfirmation _;\n\t\t\t\tconst auto addedDeadline = miner.addDeadline(std::move(deadlineToAdd), _);\n\t\t\t\tif (addedDeadline != nullptr)\n\t\t\t\t{\n\t\t\t\t\tstd::thread thread{[=, &miner]()\n\t\t\t\t\t{\n\t\t\t\t\t\tminer.submitDeadline(addedDeadline);\n\t\t\t\t\t}};\n\n\t\t\t\t\tthread.detach();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor (size_t i = 0; i < size; ++i)\n\t\t\t\ttask_manager->start(new T(miner.getData(), queue, submitFunction));\n\t\t}\n\n\t\ttemplate <typename T, typename ...Args>\n\t\tvoid createWorker(std::unique_ptr<Poco::ThreadPool>& thread_pool, std::unique_ptr<Poco::TaskManager>& task_manager,\n\t\t\tconst size_t size, Args&&... args)\n\t\t{\n\t\t\tthread_pool = std::make_unique<Poco::ThreadPool>(1, static_cast<int>(size));\n\t\t\ttask_manager = std::make_unique<Poco::TaskManager>(*thread_pool);\n\n\t\t\tfor (size_t i = 0; i < size; ++i)\n\t\t\t\ttask_manager->start(new T(std::forward<Args>(args)...));\n\t\t}\n\t}\n}\n\nBurst::Miner::Miner()\n{}\n\nBurst::Miner::~Miner() = default;\n\nvoid Burst::Miner::run()\n{\n\tpoco_ndc(Miner::run);\n\trunning_ = true;\n\tprogressRead_ = std::make_shared<PlotReadProgress>();\n\tprogressVerify_ = std::make_shared<PlotReadProgress>();\n\n\tprogressRead_->progressChanged.add(Poco::delegate(this, &Miner::progressChanged));\n\tprogressVerify_->progressChanged.add(Poco::delegate(this, &Miner::progressChanged));\n\n\tauto& config = MinerConfig::getConfig();\n\tauto errors = 0u;\n\n\tif (config.getPoolUrl().empty() &&\n\t\tconfig.getMiningInfoUrl().empty() &&\n\t\tconfig.getWalletUrl().empty())\n\t{\n\t\tlog_critical(MinerLogger::miner, \"One of the URLs are all empty! Therfore the miner is shutting down!\");\n\t\treturn;\n\t}\n\n\tPoco::ThreadPool::defaultPool().addCapacity(128);\n\n\tMinerConfig::getConfig().printConsole();\n\n\t// only create the thread pools and manager for mining if there is work to do (plot files)\n\tif (!config.getPlotFiles().empty())\n\t{\n\t\t// manager\n\t\tnonceSubmitterManager_ = std::make_unique<Poco::TaskManager>();\n\n\t\t// create the plot readers\n\t\tMinerHelper::createWorker<PlotReader>(plotReaderPool_, plotReader_, MinerConfig::getConfig().getMaxPlotReaders(),\n\t\t\tdata_, progressRead_, progressVerify_, verificationQueue_, plotReadQueue_);\n\n\t\t// create the plot verifiers\n\t\tcreatePlotVerifiers();\n\n#ifndef USE_CUDA\n\t\tif (config.getProcessorType() == \"CUDA\")\n\t\t\tlog_error(MinerLogger::miner, \"You are mining with your CUDA GPU, but the miner is compiled without the CUDA SDK!\\n\"\n\t\t\t\t\"You will not see any deadline coming from this miner!\");\n#endif\n\t}\n\n\twallet_ = MinerConfig::getConfig().getWalletUrl();\n\n\tconst auto wakeUpTime = static_cast<long>(config.getWakeUpTime());\n\n\tif (wakeUpTime > 0)\n\t{\n\t\tconst Poco::TimerCallback<Miner> callback(*this, &Miner::onWakeUp);\n\n\t\twakeUpTimer_.setPeriodicInterval(wakeUpTime * 1000);\n\t\twakeUpTimer_.start(callback);\n\t}\n\t\n\trunning_ = true;\n\n\tminingInfoSession_ = MinerConfig::getConfig().createSession(HostType::MiningInfo);\n\tminingInfoSession_->setKeepAlive(true);\n\n\t// TODO REWORK\n\t//wallet_.getLastBlock(currentBlockHeight_);\n\n\tlog_information(MinerLogger::miner, \"Fetching getMiningInfo from pool\");\n\tsize_t currentMiningInfoIndex = 0;\n\tstd::string currentUrl;\n\n\twhile (running_)\n\t{\n\t\ttry\n\t\t{\n\t\t\tconst auto& altMiningInfoUrls = MinerConfig::getConfig().getMiningInfoUrlAlt();\n\t\t\t\n\t\t\tstd::vector<Url> miningInfoUrls;\n\t\t\tminingInfoUrls.reserve(altMiningInfoUrls.size() + 1);\n\t\t\tminingInfoUrls.emplace_back(MinerConfig::getConfig().getMiningInfoUrl());\n\t\t\tminingInfoUrls.insert(miningInfoUrls.end(), altMiningInfoUrls.begin(), altMiningInfoUrls.end());\n\n\t\t\tif (currentMiningInfoIndex >= miningInfoUrls.size())\n\t\t\t\tcurrentMiningInfoIndex = 0;\n\n\t\t\tconst auto& miningInfoUrl = miningInfoUrls[currentMiningInfoIndex];\n\n\t\t\tif (miningInfoUrl.getCanonical(true) != currentUrl)\n\t\t\t{\n\t\t\t\tcurrentUrl = miningInfoUrl.getCanonical(true);\n\t\t\t\tlog_debug(MinerLogger::miner, \"Switched getMiningInfo source to %s\", currentUrl);\n\t\t\t}\n\t\t\t\n\t\t\tif (getMiningInfo(miningInfoUrl))\n\t\t\t\terrors = 0;\n\t\t\telse\n\t\t\t{\n\t\t\t\t++errors;\n\t\t\t\tlog_debug(MinerLogger::miner, \"Could not fetch getMiningInfo %s (%u/5 times total)...\",\n\t\t\t\t\tminingInfoUrl.getCanonical(), errors);\n\t\t\t\t++currentMiningInfoIndex;\n\t\t\t\tminingInfoSession_.reset();\n\t\t\t}\n\n\t\t\t// we have a tollerance of 5 times of not being able to fetch mining infos, before its a real error\n\t\t\tif (errors >= 5)\n\t\t\t{\n\t\t\t\t// reset error-counter and show error-message in console\n\t\t\t\tlog_error(MinerLogger::miner, \"Could not fetch getMiningInfo!\");\n\t\t\t\terrors = 0;\n\t\t\t}\n\t\t}\n\t\tcatch (const Poco::Exception& e)\n\t\t{\n\t\t\tlog_error(MinerLogger::miner, \"Could not fetch getMiningInfo: %s\", e.displayText());\n\t\t\tlog_current_stackframe(MinerLogger::miner);\n\t\t}\n\n\t\tstd::this_thread::sleep_for(std::chrono::seconds(MinerConfig::getConfig().getMiningInfoInterval()));\n\t}\n\n\tif (wakeUpTime > 0)\n\t\twakeUpTimer_.stop();\n\n\trunning_ = false;\n}\n\nvoid Burst::Miner::stop()\n{\n\tpoco_ndc(Miner::stop);\n\n\t// stop plot reader\n\tif (plotReader_ != nullptr)\n\t\tshutDownWorker(*plotReaderPool_, *plotReader_, plotReadQueue_);\n\n\t// stop verifier\n\tif (verifier_ != nullptr)\n\t\tshutDownWorker(*verifierPool_, *verifier_, verificationQueue_);\n\t\n\trunning_ = false;\n}\n\nvoid Burst::Miner::restart()\n{\n\trestart_ = true;\n\tstop();\n}\n\nvoid Burst::Miner::addPlotReadNotifications(bool wakeUpCall)\n{\n\tconst auto initPlotReadNotification = [this, wakeUpCall](PlotDir& plotDir)\n\t{\n\t\tauto notification = new PlotReadNotification;\n\t\tnotification->dir = plotDir.getPath();\n\t\tnotification->gensig = getGensig();\n\t\tnotification->scoopNum = getScoopNum();\n\t\tnotification->blockheight = getBlockheight();\n\t\tnotification->baseTarget = getBaseTarget();\n\t\tnotification->type = plotDir.getType();\n\t\tnotification->wakeUpCall = wakeUpCall;\n\n\t\tfor (const auto& plotFile : plotDir.getPlotfiles(true))\n\t\t\taccounts_.getAccount(plotFile->getAccountId(), wallet_, true);\n\n\t\treturn notification;\n\t};\n\n\tconst auto addParallel = [this, &initPlotReadNotification](PlotDir& plotDir, std::shared_ptr<PlotFile> plotFile)\n\t{\n\t\tauto plotRead = initPlotReadNotification(plotDir);\n\t\tplotRead->plotList.emplace_back(plotFile);\n\t\tplotReadQueue_.enqueueNotification(plotRead);\n\t};\n\n\tMinerConfig::getConfig().forPlotDirs([this, &addParallel, &initPlotReadNotification](PlotDir& plotDir)\n\t{\n\t\tif (plotDir.getType() == PlotDir::Type::Parallel)\n\t\t{\n\t\t\tfor (const auto& plotFile : plotDir.getPlotfiles())\n\t\t\t\taddParallel(plotDir, plotFile);\n\n\t\t\tfor (const auto& relatedPlotDir : plotDir.getRelatedDirs())\n\t\t\t\tfor (const auto& plotFile : relatedPlotDir->getPlotfiles())\n\t\t\t\t\taddParallel(plotDir, plotFile);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto plotRead = initPlotReadNotification(plotDir);\n\t\t\tplotRead->plotList = plotDir.getPlotfiles();\n\n\t\t\tfor (const auto& relatedPlotDir : plotDir.getRelatedDirs())\n\t\t\t\tplotRead->relatedPlotLists.emplace_back(relatedPlotDir->getPath(), relatedPlotDir->getPlotfiles());\n\n\t\t\tplotReadQueue_.enqueueNotification(plotRead);\n\t\t}\n\n\t\treturn true;\n\t});\n}\n\nbool Burst::Miner::wantRestart() const\n{\n\treturn restart_;\n}\n\nvoid Burst::Miner::updateGensig(const std::string& gensigStr, Poco::UInt64 blockHeight, Poco::UInt64 baseTarget)\n{\n\tpoco_ndc(Miner::updateGensig);\n\n\ttry\n\t{\n\t\t// stop all reading processes if any\n\t\tif (!MinerConfig::getConfig().getPlotFiles().empty())\n\t\t{\n\t\t\tlog_debug(MinerLogger::miner, \"Plot-read-queue: %d (%d reader), verification-queue: %d (%d verifier)\",\n\t\t\t\tplotReadQueue_.size(), plotReader_->count(), verificationQueue_.size(), verifier_->count());\n\t\t\tlog_debug(MinerLogger::miner, \"Allocated memory: %s\", memToString(PlotReader::globalBufferSize.getSize(), 1));\n\t\t\n\t\t\tPlotReader::globalBufferSize.setMax(MinerConfig::getConfig().getMaxBufferSize());\n\t\t}\n\t\t\n\t\t// clear the plot read queue\n\t\tplotReadQueue_.clear();\n\n\t\t// Set dynamic targetDL for this round if a submitProbability is given\n\t\tif (MinerConfig::getConfig().getSubmitProbability() > 0.)\n\t\t{\n\t\t\tconst auto difficultyFl = 18325193796.0 / static_cast<float>(baseTarget);\n\t\t\tconst auto tarDlFac = MinerConfig::getConfig().getTargetDLFactor();\n\t\t\tconst auto totAccPlotsize = static_cast<double>(PlotSizes::getTotalBytes(PlotSizes::Type::Combined)) / 1024.f / 1024.f / 1024.f / 1024.f;\n\n\t\t\tauto blockTargetDeadline = MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Local);\n\t\t\tif (totAccPlotsize > 0 && MinerConfig::getConfig().getSubmitProbability() > 0.)\n\t\t\t\tblockTargetDeadline = static_cast<Poco::UInt64>(tarDlFac * difficultyFl / totAccPlotsize);\n\t\t\tconst auto poolDeadline = MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Pool);\n\n\t\t\tif (blockTargetDeadline < poolDeadline || poolDeadline == 0)\n\t\t\t\tMinerConfig::getConfig().setTargetDeadline(blockTargetDeadline, TargetDeadlineType::Local);\n\t\t\telse\n\t\t\t\tMinerConfig::getConfig().setTargetDeadline(poolDeadline, TargetDeadlineType::Local);\n\t\t}\n\n\t\t// Set total run time of previous block\n\t\tif (startPoint_.time_since_epoch().count() > 0)\n\t\t{\n\t\t\tconst auto timeDiff = std::chrono::high_resolution_clock::now() - startPoint_;\n\t\t\tconst auto timeDiffSeconds = std::chrono::duration_cast<std::chrono::seconds>(timeDiff);\n\t\t\tlog_unimportant(MinerLogger::miner, \"Block %s ended in %s\", numberToString(blockHeight - 1),\n\t\t\t\tdeadlineFormat(timeDiffSeconds.count()));\n\t\t\tdata_.getBlockData()->setBlockTime(timeDiffSeconds.count());\n\t\t}\n\n\t\t// setup new block-data\n\t\tauto block = data_.startNewBlock(blockHeight, baseTarget, gensigStr, MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Local));\n\t\tsetIsProcessing(true);\n\n\t\t// printing block info and transfer it to local server\n\t\t{\n\t\t\tconst auto difficulty = block->getDifficulty();\n\t\t\tconst auto difficultyDifference = data_.getDifficultyDifference();\n\t\t\tstd::string diffiultyDifferenceToString;\n\n\t\t\tif (difficultyDifference < 0)\n\t\t\t\tdiffiultyDifferenceToString = numberToString(difficultyDifference);\n\t\t\telse if (difficultyDifference == 0)\n\t\t\t\tdiffiultyDifferenceToString = \"no change\";\n\t\t\telse\n\t\t\t\tdiffiultyDifferenceToString = '+' + numberToString(difficultyDifference);\n\n\t\t\tlog_notice(MinerLogger::miner, std::string(50, '-') + \"\\n\"\n\t\t\t\t\"block#     \\t%s\\n\"\n\t\t\t\t\"scoop#     \\t%Lu\\n\"\n\t\t\t\t\"baseTarget#\\t%s\\n\"\n\t\t\t\t\"gensig     \\t%s\\n\"\n\t\t\t\t\"difficulty \\t%s (%s)\\n\"\n\t\t\t\t\"targetDL   \\t%s\\n\" +\n\t\t\t\tstd::string(50, '-'),\n\t\t\t\tnumberToString(blockHeight), block->getScoop(), numberToString(baseTarget), createTruncatedString(getGensigStr(), 14, 32),\n\t\t\t\tnumberToString(difficulty),\n\t\t\t\tdiffiultyDifferenceToString,\n\t\t\t\tdeadlineFormat(MinerConfig::getConfig().getTargetDeadline())\n\t\t\t);\n\n\t\t\tdata_.getBlockData()->refreshBlockEntry();\n\t\t}\n\n\t\tif (MinerConfig::getConfig().isRescanningEveryBlock())\n\t\t\tMinerConfig::getConfig().rescanPlotfiles();\n\n\t\tprogressRead_->reset(blockHeight, MinerConfig::getConfig().getTotalPlotsize());\n\t\tprogressVerify_->reset(blockHeight, MinerConfig::getConfig().getTotalPlotsize());\n\n\t\tPlotSizes::nextRound();\n\t\tPlotSizes::refresh(Poco::Net::IPAddress{\"127.0.0.1\"});\n\t\tstartPoint_ = std::chrono::high_resolution_clock::now();\n\n\t\taddPlotReadNotifications();\n\n\t\tdata_.getWonBlocksAsync(wallet_, accounts_);\n\n\t\t// why we start a new thread to gather the last winner:\n\t\t// it could be slow and is not necessary for the whole process\n\t\t// so show it when it's done\n\t\tif (blockHeight > 0 && wallet_.isActive())\n\t\t\tblock->getLastWinnerAsync(wallet_, accounts_);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not update the gensig: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t}\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::Miner::addDeadline(Deadline deadline, NonceConfirmation& confirmation)\n{\n\tpoco_ndc(Miner::addNewDeadline);\n\n\ttry\n\t{\n\t\tconst auto currentHeight = getBlockheight();\n\n\t\tif (deadline.getBlock() != currentHeight)\n\t\t{\n\t\t\tlog_debug(MinerLogger::miner, deadline.toActionString(\"nonce discarded - wrong block\"));\n\t\t\tconfirmation = NonceConfirmation::createWrongBlock(deadline.getBlock(), currentHeight, deadline.getNonce(),\n\t\t\t                                                   deadline.getDeadline());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst auto targetDeadline = MinerConfig::getConfig().getTargetDeadline();\n\t\t\tconst auto tooHigh = targetDeadline > 0 && deadline.getDeadline() > targetDeadline;\n\n\t\t\tauto block = data_.getBlockData();\n\n\t\t\tif (block == nullptr)\n\t\t\t{\n\t\t\t\tlog_debug(MinerLogger::miner, deadline.toActionString(\"nonce discarded - no block data\"));\n\t\t\t\tconfirmation = NonceConfirmation::createError(deadline.getNonce(), deadline.getDeadline(), \"No block data\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto addedDeadline = block->addDeadlineIfBest(std::move(deadline));\n\n\t\t\t\tif (addedDeadline != nullptr)\n\t\t\t\t{\n\t\t\t\t\taddedDeadline->found(tooHigh);\n\n\t\t\t\t\tauto output = MinerLogger::hasOutput(NonceFound) || (tooHigh && MinerLogger::hasOutput(NonceFoundTooHigh));\n\n\t\t\t\t\tif (tooHigh)\n\t\t\t\t\t\toutput = MinerLogger::hasOutput(NonceFoundTooHigh);\n\n\t\t\t\t\tlog_unimportant_if(MinerLogger::miner, output, addedDeadline->toActionString(\"nonce found\"));\n\t\t\t\t\t\t\n\t\t\t\t\tif (tooHigh)\n\t\t\t\t\t{\n\t\t\t\t\t\tlog_debug(MinerLogger::miner, addedDeadline->toActionString(\"nonce discarded - deadline too high\"));\n\t\t\t\t\t\tconfirmation = NonceConfirmation::createTooHigh(addedDeadline->getNonce(), addedDeadline->getDeadline(), targetDeadline);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn addedDeadline;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t//else\n\t\t\t//{\n\t\t\t//\tlog_debug(MinerLogger::miner, deadline->toActionString(\"nonce discarded - not best\"));\n\t\t\t//\tconst auto best = block->getBestDeadline();\n\t\t\t//\tPoco::UInt64 bestDeadline = 0;\n\t\t\t//\tif (best != nullptr)\n\t\t\t//\t\tbestDeadline = best->getDeadline();\n\t\t\t//\tnonceConfirmation = NonceConfirmation::createNotBest(deadline->getNonce(), deadline->getDeadline(), bestDeadline);\n\t\t\t//}\n\t\t}\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, deadline.toActionString(\"nonce discarded - error occured\") + Poco::format(\"\\n\\tReason: %s\", e.displayText()));\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\tconfirmation = NonceConfirmation::createError(deadline.getNonce(), deadline.getDeadline(), e.displayText());\n\t}\n\n\treturn nullptr;\n}\n\nBurst::NonceConfirmation Burst::Miner::submitDeadline(std::shared_ptr<Deadline> deadline)\n{\n\treturn NonceSubmitter{*this, deadline}.submit();\n}\n\nconst Burst::GensigData& Burst::Miner::getGensig() const\n{\n\tconst auto blockData = data_.getBlockData();\n\n\tif (blockData == nullptr)\n\t{\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\tthrow Poco::NullPointerException{\"Tried to access the gensig from a nullptr!\"};\n\t}\n\n\treturn blockData->getGensig();\n}\n\nconst std::string& Burst::Miner::getGensigStr() const\n{\n\tconst auto blockData = data_.getBlockData();\n\n\tif (blockData == nullptr)\n\t{\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\tthrow Poco::NullPointerException{\"Tried to access the gensig from a nullptr!\"};\n\t}\n\n\treturn blockData->getGensigStr();\n}\n\nPoco::UInt64 Burst::Miner::getBaseTarget() const\n{\n\treturn data_.getCurrentBasetarget();\n}\n\nPoco::UInt64 Burst::Miner::getBlockheight() const\n{\n\treturn data_.getCurrentBlockheight();\n}\n\nbool Burst::Miner::hasBlockData() const\n{\n\treturn data_.getBlockData() != nullptr;\n}\n\nPoco::UInt64 Burst::Miner::getScoopNum() const\n{\n\treturn data_.getCurrentScoopNum();\n}\n\nbool Burst::Miner::isProcessing() const\n{\n\treturn isProcessing_;\n}\n\nbool Burst::Miner::getMiningInfo(const Url& url)\n{\n\tusing namespace Poco::Net;\n\tpoco_ndc(Miner::getMiningInfo);\n\n\ttry\n\t{\n\t\tif (miningInfoSession_ == nullptr && !url.empty())\n\t\t\tminingInfoSession_ = MinerConfig::getConfig().createSession(url);\n\n\t\tRequest request(std::move(miningInfoSession_));\n\n\t\tHTTPRequest requestData { HTTPRequest::HTTP_GET, \"/burst?requestType=getMiningInfo\", HTTPRequest::HTTP_1_1 };\n\t\trequestData.setKeepAlive(true);\n\n\t\tauto response = request.send(requestData);\n\t\tstd::string responseData;\n\t\t\n\t\tif (response.receive(responseData))\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tif (responseData.empty())\n\t\t\t\t\treturn false;\n\n\t\t\t\tHttpResponse httpResponse(responseData);\n\t\t\t\tPoco::JSON::Parser parser;\n\t\t\t\tPoco::JSON::Object::Ptr root;\n\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\troot = parser.parse(httpResponse.getMessage()).extract<Poco::JSON::Object::Ptr>();\n\t\t\t\t}\n\t\t\t\tcatch (...)\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tstd::string gensig;\n\n\t\t\t\tif (root->has(\"generationSignature\"))\n\t\t\t\t{\n\t\t\t\t\tgensig = root->get(\"generationSignature\").convert<std::string>();\n\n\t\t\t\t\tif ((data_.getBlockData() == nullptr || gensig != data_.getBlockData()->getGensigStr()) &&\n\t\t\t\t\t\troot->has(\"height\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string baseTargetStr;\n\n\t\t\t\t\t\tconst std::string newBlockHeightStr = root->get(\"height\");\n\t\t\t\t\t\tconst auto newBlockHeight = std::stoull(newBlockHeightStr);\n\n\t\t\t\t\t\tif (root->has(\"baseTarget\"))\n\t\t\t\t\t\t\tbaseTargetStr = root->get(\"baseTarget\").convert<std::string>();\n\n\t\t\t\t\t\tif (root->has(\"targetDeadline\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// remember the current pool target deadline\n\t\t\t\t\t\t\tconst auto targetDeadlinePoolBefore = MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Pool);\n\n\t\t\t\t\t\t\t// get the target deadline from pool\n\t\t\t\t\t\t\tauto targetDeadlinePoolJson = root->get(\"targetDeadline\");\n\t\t\t\t\t\t\tPoco::UInt64 targetDeadlinePool = 0;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// update the new pool target deadline\n\t\t\t\t\t\t\tif (!targetDeadlinePoolJson.isEmpty())\n\t\t\t\t\t\t\t\ttargetDeadlinePool = targetDeadlinePoolJson.convert<Poco::UInt64>();\n\n\t\t\t\t\t\t\tMinerConfig::getConfig().setTargetDeadline(targetDeadlinePool, TargetDeadlineType::Pool);\n\n\t\t\t\t\t\t\t// if its changed, print it\n\t\t\t\t\t\t\tif (MinerConfig::getConfig().getSubmitProbability() == 0.)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (targetDeadlinePoolBefore != MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Pool))\n\t\t\t\t\t\t\t\t\tlog_system(MinerLogger::config, std::string(50, '-') + \"\\n\" +\n\t\t\t\t\t\t\t\t\t\t\"got new target deadline from pool\\n\"\n\t\t\t\t\t\t\t\t\t\t\"old pool target deadline:    \\t%s\\n\"\n\t\t\t\t\t\t\t\t\t\t\"new pool target deadline:    \\t%s\\n\"\n\t\t\t\t\t\t\t\t\t\t\"target deadline from config: \\t%s\\n\"\n\t\t\t\t\t\t\t\t\t\t\"lowest target deadline:      \\t%s\\n\" +\n\t\t\t\t\t\t\t\t\t\tstd::string(50, '-'),\n\t\t\t\t\t\t\t\t\t\tdeadlineFormat(targetDeadlinePoolBefore),\n\t\t\t\t\t\t\t\t\t\tdeadlineFormat(MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Pool)),\n\t\t\t\t\t\t\t\t\t\tdeadlineFormat(MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Local)),\n\t\t\t\t\t\t\t\t\t\tdeadlineFormat(MinerConfig::getConfig().getTargetDeadline()));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (targetDeadlinePoolBefore != MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Pool))\n\t\t\t\t\t\t\t\t\tlog_system(MinerLogger::config, std::string(50, '-') + \"\\n\" +\n\t\t\t\t\t\t\t\t\t\t\"got new target deadline from pool\\n\"\n\t\t\t\t\t\t\t\t\t\t\"old pool target deadline:    \\t%s\\n\"\n\t\t\t\t\t\t\t\t\t\t\"new pool target deadline:    \\t%s\\n\" +\n\t\t\t\t\t\t\t\t\t\tstd::string(50, '-'),\n\t\t\t\t\t\t\t\t\t\tdeadlineFormat(targetDeadlinePoolBefore),\n\t\t\t\t\t\t\t\t\t\tdeadlineFormat(MinerConfig::getConfig().getTargetDeadline(TargetDeadlineType::Pool)));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tupdateGensig(gensig, newBlockHeight, std::stoull(baseTargetStr));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttransferSession(response, miningInfoSession_);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcatch (Poco::Exception& exc)\n\t\t\t{\n\t\t\t\tlog_error(MinerLogger::miner, \"Error on getting new block information!\\n\\t%s\", exc.displayText());\n\t\t\t\t// because the full response may be too long, we only log the it in the logfile\n\t\t\t\tlog_file_only(MinerLogger::miner, Poco::Message::PRIO_ERROR, TextType::Error, \"Block information full response:\\n%s\", responseData);\n\t\t\t\tlog_current_stackframe(MinerLogger::miner);\n\t\t\t}\n\t\t}\n\n\t\ttransferSession(request, miningInfoSession_);\n\t\ttransferSession(response, miningInfoSession_);\n\n\t\treturn false;\n\t}\n\tcatch (const Poco::NotFoundException& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get the mining information: %s\", e.displayText());\n\t\treturn false;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get the mining information: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn false;\n\t}\n}\n\nvoid Burst::Miner::shutDownWorker(Poco::ThreadPool& threadPool, Poco::TaskManager& taskManager, Poco::NotificationQueue& queue) const\n{\n\tPoco::Mutex::ScopedLock lock(workerMutex_);\n\tqueue.wakeUpAll();\n\ttaskManager.cancelAll();\n\tthreadPool.stopAll();\n\tthreadPool.joinAll();\n}\n\nnamespace Burst\n{\n\tstd::mutex progressMutex;\n\tProgress progress;\n\n\tvoid showProgress(PlotReadProgress& progressRead, PlotReadProgress& progressVerify, MinerData& data, Poco::UInt64 blockheight,\n\t\tstd::chrono::high_resolution_clock::time_point& startPoint,\n\t\tconst std::function<void(Poco::UInt64, double)>& blockProcessed)\n\t{\n\t\tstd::lock_guard<std::mutex> lock(progressMutex);\n\n\t\tconst auto readProgressPercent = progressRead.getProgress();\n\t\tconst auto verifyProgressPercent = progressVerify.getProgress();\n\t\tconst auto readProgressValue = progressRead.getValue();\n\t\tconst auto verifyProgressValue = progressVerify.getValue();\n\n\t\tconst auto timeDiff = std::chrono::high_resolution_clock::now() - startPoint;\n\t\tconst auto timeDiffSeconds = std::chrono::duration<double>(timeDiff);\n\n\t\tconst auto readProgressChanged = progress.read != readProgressPercent;\n\t\tconst auto verifyProgressChanged = progress.verify != readProgressPercent;\n\n\t\tif (readProgressChanged || verifyProgressChanged)\n\t\t{\n\t\t\tprogress.read = readProgressPercent;\n\t\t\tprogress.verify = verifyProgressPercent;\n\t\t\tprogress.bytesPerSecondRead = readProgressValue / 4096. / timeDiffSeconds.count();\n\t\t\tprogress.bytesPerSecondVerify = verifyProgressValue / 4096. / timeDiffSeconds.count();\n\t\t\tprogress.bytesPerSecondCombined = (readProgressValue + verifyProgressValue) / 4096. / timeDiffSeconds.\n\t\t\t\tcount();\n\t\t\t\n\t\t\tMinerLogger::writeProgress(progress);\n\t\t\tdata.getBlockData()->setProgress(readProgressPercent, verifyProgressPercent, blockheight);\n\t\t\t\n\t\t\tif (readProgressPercent == 100.f && verifyProgressPercent == 100.f && blockProcessed != nullptr)\n\t\t\t{\n\t\t\t\tblockProcessed(blockheight, timeDiffSeconds.count());\n\t\t\t\tprogress.read = 0.f;\n\t\t\t\tprogress.verify = 0.f;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Burst::Miner::progressChanged(float &progress)\n{\n\tshowProgress(*progressRead_, *progressVerify_, getData(), getBlockheight(), startPoint_,\n\t             [this](Poco::UInt64 blockHeight, double roundTime) { onRoundProcessed(blockHeight, roundTime); });\n}\n\nvoid Burst::Miner::onWakeUp(Poco::Timer& timer)\n{\n\taddPlotReadNotifications(true);\n}\n\nvoid Burst::Miner::onRoundProcessed(Poco::UInt64 blockHeight, double roundTime)\n{\n\tpoco_ndc(Miner::onRoundProcessed);\n\n\ttry\n\t{\n\t\tconst auto block = data_.getBlockData();\n\t\tsetIsProcessing(false);\n\n\t\tif (block == nullptr || block->getBlockheight() != blockHeight)\n\t\t\treturn;\n\n\t\tblock->setRoundTime(roundTime);\n\t\tconst auto bestDeadline = block->getBestDeadline(BlockData::DeadlineSearchType::Found);\n\n\t\tlog_information(MinerLogger::miner, std::string(50, '-') + \"\\n\"\n\t\t\t\"processed block \\t%s\\n\"\n\t\t\t\"round time      \\t%ss\\n\"\n\t\t\t\"best deadline   \\t%s\\n\" +\n\t\t\tstd::string(50, '-'),\n\t\t\tnumberToString(block->getBlockheight()),\n\t\t\tPoco::NumberFormatter::format(roundTime, 3),\n\t\t\tbestDeadline == nullptr ? \"none\" : deadlineFormat(bestDeadline->getDeadline()));\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not processes the round end: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t}\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::Miner::getBestSent(Poco::UInt64 accountId, Poco::UInt64 blockHeight) const\n{\n\tpoco_ndc(Miner::getBestSent);\n\n\tconst auto block = data_.getBlockData();\n\n\tif (block == nullptr ||\n\t\tblockHeight != block->getBlockheight())\n\t\treturn nullptr;\n\n\treturn block->getBestDeadline(accountId, BlockData::DeadlineSearchType::Sent);\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::Miner::getBestConfirmed(Poco::UInt64 accountId, Poco::UInt64 blockHeight) const\n{\n\tpoco_ndc(Miner::getBestConfirmed);\n\n\tconst auto block = data_.getBlockData();\n\n\tif (block == nullptr ||\n\t\tblockHeight != block->getBlockheight())\n\t\treturn nullptr;\n\n\treturn block->getBestDeadline(accountId, BlockData::DeadlineSearchType::Confirmed);\n}\n\nBurst::MinerData& Burst::Miner::getData()\n{\n\treturn data_;\n}\n\nstd::shared_ptr<Burst::Account> Burst::Miner::getAccount(AccountId id, bool persistent)\n{\n\treturn accounts_.getAccount(id, wallet_, persistent);\n}\n\nvoid Burst::Miner::createPlotVerifiers()\n{\n\tconst auto& processorType = MinerConfig::getConfig().getProcessorType();\n\tauto cpuInstructionSet = MinerConfig::getConfig().getCpuInstructionSet();\n\tauto forceCpu = false, fallback = false;\n\tconst auto createWorker = [this](std::function<void(std::unique_ptr<Poco::ThreadPool>&,\n\t                                                    std::unique_ptr<Poco::TaskManager>&,\n\t                                                    size_t, Miner&, Poco::NotificationQueue&)> function)\n\t{\n\t\tfunction(verifierPool_, verifier_, MinerConfig::getConfig().getMiningIntensity(), *this, verificationQueue_);\n\t};\n\n\tif (processorType == \"CUDA\")\n\t{\n\t\tif (Settings::cuda)\n\t\t\tcreateWorker(MinerHelper::createWorkerDefault<PlotVerifierCuda>);\n\t\telse\n\t\t\tforceCpu = true;\n\t}\n\telse if (processorType == \"OPENCL\")\n\t{\n\t\tif (Settings::openCl)\n\t\t\tcreateWorker(MinerHelper::createWorkerDefault<PlotVerifierOpencl>);\n\t\telse\n\t\t\tforceCpu = true;\n\t}\n\n\tif (processorType == \"CPU\" || forceCpu)\n\t{\n\t\tif (cpuInstructionSet == \"SSE4\" && Settings::sse4)\n\t\t\tcreateWorker(MinerHelper::createWorkerDefault<PlotVerifierSse4>);\n\t\telse if (cpuInstructionSet == \"AVX\" && Settings::avx)\n\t\t\tcreateWorker(MinerHelper::createWorkerDefault<PlotVerifierAvx>);\n\t\telse if (cpuInstructionSet == \"AVX2\" && Settings::avx2)\n\t\t\tcreateWorker(MinerHelper::createWorkerDefault<PlotVerifierAvx2>);\n\t\telse if (cpuInstructionSet == \"SSE2\")\n\t\t\tcreateWorker(MinerHelper::createWorkerDefault<PlotVerifierSse2>);\n\t\telse\n\t\t\tfallback = true;\n\t}\n\n\tif (fallback)\n\t\tcpuInstructionSet = \"SSE2\";\n\n\tif (forceCpu)\n\t{\n\t\tlog_warning(MinerLogger::miner, \"You are using the processor type %s with the instruction set %s,\\n\"\n\t\t\t\"but your miner is compiled without that feature!\\n\"\n\t\t\t\"As a fallback solution your CPU with the instruction set %s is used.\", processorType, MinerConfig::getConfig().\n\t\t\tgetCpuInstructionSet(), cpuInstructionSet);\n\t\t\n\t\tcreateWorker(MinerHelper::createWorkerDefault<PlotVerifierSse2>);\n\t}\n}\n\nvoid Burst::Miner::setMiningIntensity(unsigned intensity)\n{\n\tPoco::Mutex::ScopedLock lock(workerMutex_);\n\n\t// dont change it if its the same intensity\n\t// changing it is a heavy task\n\tif (MinerConfig::getConfig().getMiningIntensity() == intensity)\n\t\treturn;\n\n\tshutDownWorker(*verifierPool_, *verifier_, verificationQueue_);\n\tMinerConfig::getConfig().setMininigIntensity(intensity);\n\tcreatePlotVerifiers();\n}\n\nvoid Burst::Miner::setMaxPlotReader(unsigned max_reader)\n{\n\tPoco::Mutex::ScopedLock lock(workerMutex_);\n\n\t// dont change it if its the same reader count\n\t// changing it is a heavy task\n\tif (MinerConfig::getConfig().getMaxPlotReaders() == max_reader)\n\t\treturn;\n\n\tshutDownWorker(*plotReaderPool_, *plotReader_, plotReadQueue_);\n\tMinerConfig::getConfig().setMaxPlotReaders(max_reader);\n\tMinerHelper::createWorker<PlotReader>(plotReaderPool_, plotReader_, MinerConfig::getConfig().getMaxPlotReaders(),\n\t\tdata_, progressRead_, progressVerify_, verificationQueue_, plotReadQueue_);\n}\n\nvoid Burst::Miner::setMaxBufferSize(Poco::UInt64 size)\n{\n\tMinerConfig::getConfig().setBufferSize(size);\n\tPlotReader::globalBufferSize.setMax(size);\n}\n\nvoid Burst::Miner::rescanPlotfiles()\n{\n\t// rescan the plot files...\n\tif (MinerConfig::getConfig().rescanPlotfiles())\n\t{\n\t\t// we send the new settings (size could be changed)\n\t\tdata_.getBlockData()->refreshConfig();\n\n\t\t// then we send all plot dirs and files\n\t\tdata_.getBlockData()->refreshPlotDirs();\n\t}\n\telse\n\t{\n\t\tlog_success(MinerLogger::config, \"No plot dir changes\");\n\t}\n}\n\nvoid Burst::Miner::setIsProcessing(bool isProc)\n{\n\tPoco::Mutex::ScopedLock lock(workerMutex_);\n\n\tisProcessing_ = isProc;\n}\n\nbool Burst::Miner::isPoC2() const\n{\n\tconst auto block = data_.getBlockData();\n\tpoco_check_ptr(block);\n\treturn block->getBlockheight() >= MinerConfig::getConfig().getPoc2StartBlock();\n}\n"
  },
  {
    "path": "src/mining/Miner.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"Declarations.hpp\"\n#include \"Deadline.hpp\"\n#include <memory>\n#include \"wallet/Account.hpp\"\n#include \"wallet/Wallet.hpp\"\n#include <Poco/TaskManager.h>\n#include \"MinerData.hpp\"\n#include <Poco/NotificationQueue.h>\n#include \"WorkerList.hpp\"\n#include \"network/Response.hpp\"\n#include <Poco/Timer.h>\n\nnamespace Poco\n{\n\tnamespace Net\n\t{\n\t\tclass HTTPClientSession;\n\t}\n}\n\nnamespace Burst\n{\n\tclass MinerConfig;\n\tclass PlotReadProgress;\n\tclass Deadline;\n\n\tclass Miner\n\t{\n\tpublic:\n\t\tMiner();\n\t\t~Miner();\n\n\t\tvoid run();\n\t\tvoid stop();\n\t\tvoid restart();\n\t\tvoid addPlotReadNotifications(bool wakeUpCall = false);\n\t\tbool wantRestart() const;\n\n\t\tbool hasBlockData() const;\n\t\tbool isProcessing() const;\n\t\tPoco::UInt64 getScoopNum() const;\n\t\tPoco::UInt64 getBaseTarget() const;\n\t\tPoco::UInt64 getBlockheight() const;\n\t\tconst GensigData& getGensig() const;\n\t\tconst std::string& getGensigStr() const;\n\t\tvoid updateGensig(const std::string& gensigStr, Poco::UInt64 blockHeight, Poco::UInt64 baseTarget);\n\n\t\tstd::shared_ptr<Deadline> addDeadline(Deadline deadline, NonceConfirmation& confirmation);\n\t\tNonceConfirmation submitDeadline(std::shared_ptr<Deadline> deadline);\n\n\t\tstd::shared_ptr<Deadline> getBestSent(Poco::UInt64 accountId, Poco::UInt64 blockHeight) const;\n\t\tstd::shared_ptr<Deadline> getBestConfirmed(Poco::UInt64 accountId, Poco::UInt64 blockHeight) const;\n\t\tMinerData& getData();\n\t\tstd::shared_ptr<Account> getAccount(AccountId id, bool persistent = false);\n\t\tvoid createPlotVerifiers();\n\n\t\tvoid setMiningIntensity(unsigned intensity);\n\t\tvoid setMaxPlotReader(unsigned max_reader);\n\t\tstatic void setMaxBufferSize(Poco::UInt64 size);\n\t\tvoid rescanPlotfiles();\n\t\tvoid setIsProcessing(bool isProc);\n\n\t\tbool isPoC2() const;\n\n\tprivate:\n\t\tbool getMiningInfo(const Url& url);\n\t\tvoid shutDownWorker(Poco::ThreadPool& threadPool, Poco::TaskManager& taskManager,\n\t\t                    Poco::NotificationQueue& queue) const;\n\t\tvoid progressChanged(float& progress);\n\t\tvoid onWakeUp(Poco::Timer& timer);\n\t\tvoid onRoundProcessed(Poco::UInt64 blockHeight, double roundTime);\n\n\t\tbool running_ = false, restart_ = false, isProcessing_ = false;\n\t\tMinerData data_;\n\t\tstd::shared_ptr<PlotReadProgress> progressRead_, progressVerify_;\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> miningInfoSession_;\n\t\tAccounts accounts_;\n\t\tWallet wallet_;\n\t\tstd::unique_ptr<Poco::TaskManager> nonceSubmitterManager_, plotReader_, verifier_;\n\t\tPoco::NotificationQueue plotReadQueue_;\n\t\tPoco::NotificationQueue verificationQueue_;\n\t\tstd::unique_ptr<Poco::ThreadPool> verifierPool_, plotReaderPool_;\n\t\tPoco::Timer wakeUpTimer_;\n\t\tmutable Poco::Mutex workerMutex_;\n\t\tstd::chrono::high_resolution_clock::time_point startPoint_;\n\t};\n}\n"
  },
  {
    "path": "src/mining/MinerCL.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"MinerCL.hpp\"\n\n#ifdef USE_OPENCL\n#include \"logging/MinerLogger.hpp\"\n#include <fstream>\n#include \"gpu/impl/gpu_opencl_impl.hpp\"\n#endif\n\nnamespace Burst\n{\n#ifdef USE_OPENCL\n\tstruct MinerCLHelper\n\t{\n\t\ttemplate <typename TSubject, typename TInfoFunc, typename TArg>\n\t\tstatic auto infoHelperFunc(const TSubject& subject, std::string& info, TInfoFunc infoFunc, TArg arg, int& ret)\n\t\t{\n\t\t\tinfo = std::string(255, '\\0');\n\t\t\tsize_t size = 0;\n\n\t\t\tret = infoFunc(subject, arg, info.size(), &info[0], &size);\n\n\t\t\tif (ret != CL_SUCCESS)\n\t\t\t\treturn false;\n\n\t\t\t// cut away the \\0\n\t\t\tif (size > 0)\n\t\t\t\t--size;\n\n\t\t\tinfo.resize(size);\n\t\t\treturn true;\n\t\t};\n\t};\n#endif\n}\n\nstd::vector<cl_device_id> Burst::ClPlatform::getDeviceIds() const\n{\n\tstd::vector<cl_device_id> deviceIds;\n\tdeviceIds.reserve(devices.size());\n\n\tfor (const auto& device : devices)\n\t\tdeviceIds.emplace_back(device.id);\n\n\treturn deviceIds;\n}\n\nbool Burst::ClPlatform::getPlatforms(std::vector<ClPlatform>& platforms, std::string& error)\n{\n#ifdef USE_OPENCL\n\tplatforms.clear();\n\n\tstd::vector<cl_platform_id> platform_ids;\n\n\t// get the platforms and print infos \n\tcl_uint sizePlatforms;\n\n\tauto ret = clGetPlatformIDs(0, nullptr, &sizePlatforms);\n\n\t// get the number of valid opencl platforms \n\tif (ret != CL_SUCCESS)\n\t{\n\t\terror = Poco::format(\"Could not detect the number of valid OpenCL platforms!\\n\\tError-code:\\t%d\", ret);\n\t\treturn false;\n\t}\n\n\tif (sizePlatforms == 0)\n\t{\n\t\terror = \"No valid OpenCL platforms detected!\";\n\t\treturn false;\n\t}\n\n\t// get all valid opencl platforms \n\tplatform_ids.resize(sizePlatforms);\n\tplatforms.resize(sizePlatforms);\n\n\tret = clGetPlatformIDs(sizePlatforms, platform_ids.data(), nullptr);\n\n\tif (ret != CL_SUCCESS)\n\t{\n\t\terror = Poco::format(\"Could not get a list of valid OpenCL platforms!\\n\\tError-code:\\t%d\", ret);\n\t\treturn false;\n\t}\n\n\t// print platform infos\n\tfor (size_t i = 0; i < platform_ids.size(); ++i)\n\t{\n\t\tcl_int ret_platform, ret_version;\n\n\t\tconst auto& platform_id = platform_ids[i];\n\t\tauto& platform = platforms[i];\n\n\t\tplatform.id = platform_id;\n\t\tMinerCLHelper::infoHelperFunc(platform_id, platform.name, clGetPlatformInfo, CL_PLATFORM_NAME, ret_platform);\n\t\tMinerCLHelper::infoHelperFunc(platform_id, platform.version, clGetPlatformInfo, CL_PLATFORM_VERSION, ret_version);\n\n\t\t// get the devices of the desired platform \n\t\tcl_uint sizeDevices = 0;\n\n\t\tret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, 0, nullptr, &sizeDevices);\n\n\t\tif (ret != CL_SUCCESS)\n\t\t\treturn ret;\n\n\t\tstd::vector<cl_device_id> device_ids;\n\n\t\tdevice_ids.resize(sizeDevices);\n\t\tplatform.devices.resize(sizeDevices);\n\n\t\tret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, sizeDevices, device_ids.data(), nullptr);\n\n\t\tif (ret != CL_SUCCESS)\n\t\t{\n\t\t\terror = Poco::format(\"Could not detect the number of valid OpenCL devices!\\n\\tError-code:\\t%d\", ret);\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// print platform infos\n\t\tfor (size_t j = 0; j < device_ids.size(); ++j)\n\t\t{\n\t\t\tstd::string deviceName;\n\n\t\t\tconst auto& device_id = device_ids[j];\n\t\t\tauto& device = platform.devices[j];\n\n\t\t\tcl_int ret_device_name;\n\n\t\t\tdevice.id = device_id;\n\t\t\tMinerCLHelper::infoHelperFunc(device_id, device.name, clGetDeviceInfo, CL_DEVICE_NAME, ret_device_name);\n\t\t}\n\t}\n#endif\n\treturn true;\n}\n\nBurst::MinerCl::MinerCl()\n{\n\tstd::string error;\n\tClPlatform::getPlatforms(platforms_, error);\n}\n\n#ifdef USE_OPENCL\nBurst::MinerCl::~MinerCl()\n{\n\tfor (auto command_queue : commandQueues_)\n\t{\n\t\tif (command_queue != nullptr)\n\t\t{\n\t\t\tclFlush(command_queue);\n\t\t\tclFinish(command_queue);\n\t\t}\n\t}\n\n\tif (kernelCalculateDeadlines_ != nullptr)\n\t\tclReleaseKernel(kernelCalculateDeadlines_);\n\n\tif (program_ != nullptr)\n\t\tclReleaseProgram(program_);\n\n\tfor (auto command_queue : commandQueues_)\n\t\tif (command_queue != nullptr)\n\t\t\tclReleaseCommandQueue(command_queue);\n\n\tif (context_ != nullptr)\n\t\tclReleaseContext(context_);\n\n\tinitialized_ = false;\n}\n#else\nBurst::MinerCl::~MinerCl() = default;\n#endif\n\nbool Burst::MinerCl::create(unsigned platformIdx, unsigned deviceIdx)\n{\n\tdeviceIdx_ = deviceIdx;\n\tplatformIdx_ = platformIdx;\n\n#ifdef USE_OPENCL\n\t// try open the kernel file..\n\tstd::ifstream stream(\"mining.cl\");\n\tstd::string miningKernel(std::istreambuf_iterator<char>(stream), {});\n\n\tif (miningKernel.empty())\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not initialize OpenCL - the kernel file is missing!\");\n\t\treturn false;\n\t}\n\n\t// first, delete the old context \n\tif (context_ != nullptr)\n\t{\n\t\tclReleaseContext(context_);\n\t\tcontext_ = nullptr;\n\t}\n\n\t// get the platforms and print infos \n\t{\t\t\n\t\tlog_system(MinerLogger::miner, \"Available OpenCL platforms:\");\n\n\t\t// print platform infos\n\t\tfor (auto i = 0u; i < platforms_.size(); ++i)\n\t\t{\n\t\t\tconst auto& platform = platforms_[i];\n\t\t\tlog_system(MinerLogger::miner, \"Platform[%u]: %s, Version: %s\", i, platform.name, platform.version);\n\t\t}\n\t}\n\n\t// get the devices of the desired platform \n\t{\n\t\tif (platformIdx < platforms_.size())\n\t\t{\n\t\t\tlog_system(MinerLogger::miner, \"Using platform[%u]\", platformIdx);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_fatal(MinerLogger::miner, \"Platform index is out of bounds (%u, max: %z)\",\n\t\t\t\tplatformIdx, platforms_.size() - 1);\n\t\t\treturn false;\n\t\t}\n\n\t\tconst auto platform = platforms_[platformIdx];\n\n\t\tlog_system(MinerLogger::miner, \"Available OpenCL devices on platform[%u]:\", platformIdx);\n\t\t\n\t\t// print platform infos\n\t\tfor (size_t i = 0; i < platform.devices.size(); ++i)\n\t\t{\n\t\t\tconst auto& device = platform.devices[i];\n\t\t\tlog_system(MinerLogger::miner, \"Device[%z]: %s\", i, device.name);\n\t\t}\n\n\t\tif (deviceIdx < platform.devices.size())\n\t\t{\n\t\t\tlog_system(MinerLogger::miner, \"Using device[%u]\", deviceIdx);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_fatal(MinerLogger::miner, \"Device index is out of bounds (%u, max: %z)\",\n\t\t\t\tdeviceIdx, platform.devices.size() - 1);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// create the context \n\t{\n\t\tauto err = 0;\n\n\t\tcontext_ = clCreateContext(nullptr, static_cast<cl_uint>(getPlatform()->devices.size()),\n\t\t                           getPlatform()->getDeviceIds().data(), nullptr, nullptr, &err);\n\n\t\tif (err != CL_SUCCESS)\n\t\t{\n\t\t\tlog_fatal(MinerLogger::miner, \"Could not create an OpenCL context!\\n\\tError-code:\\t%d\", err);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// create program\n\t{\n\t\tcl_int retCreate;\n\t\tauto size = miningKernel.size();\n\t\tauto miningKernel_Cstr = miningKernel.c_str();\n\n\t\tprogram_ = clCreateProgramWithSource(context_, 1, reinterpret_cast<const char**>(&miningKernel_Cstr),\n\t\t                                     reinterpret_cast<const size_t*>(&size), &retCreate);\n\n\t\tconst auto retBuild = clBuildProgram(program_, 1, getDeviceId(), nullptr, nullptr, nullptr);\n\n\t\tif (retCreate != CL_SUCCESS || retBuild != CL_SUCCESS)\n\t\t{\n\t\t\tsize_t logSize;\n\t\t\tclGetProgramBuildInfo(program_, *getDeviceId(), CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);\n\t\t\t\n\t\t\tstd::string log;\n\t\t\tlog.resize(logSize);\n\n\t\t\tclGetProgramBuildInfo(program_, *getDeviceId(), CL_PROGRAM_BUILD_LOG, logSize, &log[0], nullptr);\n\n\t\t\tlog_fatal(MinerLogger::miner, \"Could not create the OpenCL program (mining.cl)!\\n%s\", log);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// create kernel\n\t{\n\t\tcl_int ret;\n\t\tkernelCalculateDeadlines_ = clCreateKernel(program_, \"calculate_deadlines\", &ret);\n\n\t\tif (ret != CL_SUCCESS)\n\t\t{\n\t\t\tlog_fatal(MinerLogger::miner, \"Could not create the OpenCL kernel 'calculate_deadlines'!\\n\\tError-code:\\t%d\", ret);\n\t\t\treturn false;\n\t\t}\n\n\t\tkernelBestDeadline_ = clCreateKernel(program_, \"reduce_best\", &ret);\n\n\t\tif (ret != CL_SUCCESS)\n\t\t{\n\t\t\tlog_fatal(MinerLogger::miner, \"Could not create the OpenCL kernel 'reduce_best'!\\n\\tError-code:\\t%d\", ret);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// get work group size\n\t{\n\t\tauto ret = clGetKernelWorkGroupInfo(kernelCalculateDeadlines_, *getDeviceId(),\n\t\t                                    CL_KERNEL_WORK_GROUP_SIZE,\n\t\t                                    sizeof(kernelCalculateWorkGroupSize_), &kernelCalculateWorkGroupSize_,\n\t\t                                    nullptr);\n\n\t\tif (ret == CL_SUCCESS)\n\t\t\tret = clGetKernelWorkGroupInfo(kernelCalculateDeadlines_, *getDeviceId(),\n\t\t\t                               CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE,\n\t\t\t                               sizeof(kernelCalculatePrefferedWorkGroupSize_), &kernelCalculatePrefferedWorkGroupSize_,\n\t\t\t                               nullptr);\n\n\t\tif (ret != CL_SUCCESS)\n\t\t{\n\t\t\tlog_fatal(MinerLogger::miner, \"Could not get the maximum work group size for the kernel calculate deadlines!\");\n\t\t\treturn false;\n\t\t}\n\n\t\tret = clGetKernelWorkGroupInfo(kernelBestDeadline_, *getDeviceId(),\n\t\t                               CL_KERNEL_WORK_GROUP_SIZE,\n\t\t                               sizeof(kernelFindBestWorkGroupSize_), &kernelFindBestWorkGroupSize_,\n\t\t                               nullptr);\n\n\t\tif (ret == CL_SUCCESS)\n\t\t\tret = clGetKernelWorkGroupInfo(kernelBestDeadline_, *getDeviceId(),\n\t\t\t                               CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE,\n\t\t\t                               sizeof(kernelFindBestPrefferedWorkGroupSize_), &kernelFindBestPrefferedWorkGroupSize_,\n\t\t\t                               nullptr);\n\n\t\tif (ret != CL_SUCCESS)\n\t\t{\n\t\t\tlog_fatal(MinerLogger::miner, \"Could not get the maximum work group size for the kernel find best deadline!\");\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// compute units\n\t{\n\t\tconst auto ret = clGetDeviceInfo(*getDeviceId(), CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(size_t), &computeUnits_, nullptr);\n\n\t\tif (ret != CL_SUCCESS)\n\t\t{\n\t\t\tlog_fatal(MinerLogger::miner, \"Could not get the maximum compute units for the device!\");\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tlog_system(MinerLogger::miner, \"Successfully initialized OpenCL!\");\n#endif\n\n\tinitialized_ = true;\n\n\treturn true;\n}\n\ncl_command_queue Burst::MinerCl::createCommandQueue()\n{\n#ifdef USE_OPENCL\n\tauto ret = 0;\n\tauto command_queue = clCreateCommandQueue(context_, getDevice()->id, 0, &ret);\n\n\tif (ret != CL_SUCCESS)\n\t{\n\t\tlog_fatal(MinerLogger::miner, \"Could not create an OpenCL command queue!\\n\\tError-code:\\t%d\", ret);\n\t\treturn nullptr;\n\t}\n\n\tcommandQueues_.emplace_back(command_queue);\n\treturn command_queue;\n#else\n\treturn nullptr;\n#endif\n}\n\ncl_context Burst::MinerCl::getContext() const\n{\n\treturn context_;\n}\n\ncl_kernel Burst::MinerCl::getKernel_Calculate() const\n{\n\treturn kernelCalculateDeadlines_;\n}\n\ncl_kernel Burst::MinerCl::getKernel_GetMin() const\n{\n\treturn kernelBestDeadline_;\n}\n\nsize_t Burst::MinerCl::getKernelCalculateWorkGroupSize(const bool preferred) const\n{\n\treturn preferred ? kernelCalculatePrefferedWorkGroupSize_ : kernelCalculateWorkGroupSize_;\n}\n\nsize_t Burst::MinerCl::getKernelFindBestWorkGroupSize(const bool preferred) const\n{\n\treturn preferred ? kernelFindBestPrefferedWorkGroupSize_ : kernelFindBestWorkGroupSize_;\n}\n\nsize_t Burst::MinerCl::getComputeUnits() const\n{\n\treturn computeUnits_;\n}\n\nconst Burst::ClPlatform* Burst::MinerCl::getPlatform() const\n{\n\tif (platformIdx_ >= platforms_.size())\n\t\treturn nullptr;\n\n\treturn &platforms_[platformIdx_];\n}\n\nconst cl_device_id* Burst::MinerCl::getDeviceId() const\n{\n\tconst auto device = getDevice();\n\n\tif (device == nullptr)\n\t\treturn nullptr;\n\n\treturn &device->id;\n}\n\nconst Burst::ClDevice* Burst::MinerCl::getDevice() const\n{\n\tif (platformIdx_ >= platforms_.size())\n\t\treturn nullptr;\n\n\tconst auto& platform = platforms_[platformIdx_];\n\n\tif (deviceIdx_ >= platform.devices.size())\n\t\treturn nullptr;\n\n\treturn &platform.devices[platformIdx_];\n}\n\nconst std::vector<Burst::ClPlatform>& Burst::MinerCl::getPlatforms() const\n{\n\treturn platforms_;\n}\n\nbool Burst::MinerCl::initialized() const\n{\n\treturn initialized_;\n}\n\nBurst::MinerCl& Burst::MinerCl::getCL()\n{\n\tstatic MinerCl minerCL;\n\treturn minerCL;\n}\n\ncl_program Burst::MinerCl::getProgram() const\n{\n\treturn program_;\n}\n"
  },
  {
    "path": "src/mining/MinerCL.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n/*\n * OpenCL relevant classes and functions.\n */\n#include <vector>\n#include <cstdio>\n#include <string>\n\n#ifdef USE_OPENCL\n#ifdef __APPLE__\n#include <OpenCL/cl.h>\n#else\n#include <CL/cl.h>\n#endif\n#else\nusing cl_context = int*;\nusing cl_command_queue = int*;\nusing cl_kernel = int*;\nusing cl_program = int*;\nusing cl_platform_id = int*;\nusing cl_device_id = int*;\n#endif\n\nnamespace Burst\n{\n\tstruct ClDevice\n\t{\n\t\tcl_device_id id;\n\t\tstd::string name;\n\t};\n\n\tstruct ClPlatform\n\t{\n\t\tcl_platform_id id;\n\t\tstd::string name;\n\t\tstd::string version;\n\t\tstd::vector<ClDevice> devices;\n\t\tstd::vector<cl_device_id> getDeviceIds() const;\n\n\t\tstatic bool getPlatforms(std::vector<ClPlatform>& platforms, std::string& error);\n\t};\n\n\t/**\n\t * \\brief A OpenCL context.\n\t */\n\tclass MinerCl\n\t{\n\tpublic:\n\t\tMinerCl();\n\t\t~MinerCl();\n\n\t\tbool create(unsigned platformIdx = 0, unsigned deviceIdx = 0);\n\t\tcl_command_queue createCommandQueue();\n\n\t\tcl_context getContext() const;\n\t\tcl_program getProgram() const;\n\t\tcl_kernel getKernel_Calculate() const;\n\t\tcl_kernel getKernel_GetMin() const;\n\t\tsize_t getKernelCalculateWorkGroupSize(bool preferred = false) const;\n\t\tsize_t getKernelFindBestWorkGroupSize(bool preferred = false) const;\n\t\tsize_t getComputeUnits() const;\n\t\tconst ClPlatform* getPlatform() const;\n\t\tconst cl_device_id* getDeviceId() const;\n\t\tconst ClDevice* getDevice() const;\n\t\tconst std::vector<ClPlatform>& getPlatforms() const;\n\n\t\tbool initialized() const;\n\n\t\tstatic MinerCl& getCL();\n\n\tprivate:\n\t\tcl_context context_ = nullptr;\n\t\tcl_program program_ = nullptr;\n\t\tstd::vector<cl_command_queue> commandQueues_;\n\t\tcl_kernel kernelCalculateDeadlines_ = nullptr,\n\t\t\tkernelBestDeadline_ = nullptr;\n\t\tbool initialized_ = false;\n\t\tstd::vector<ClPlatform> platforms_;\n\t\tunsigned platformIdx_ = 0, deviceIdx_ = 0;\n\t\tsize_t kernelCalculateWorkGroupSize_ = 0;\n\t\tsize_t kernelFindBestWorkGroupSize_ = 0;\n\t\tsize_t kernelCalculatePrefferedWorkGroupSize_ = 0;\n\t\tsize_t kernelFindBestPrefferedWorkGroupSize_ = 0;\n\t\tsize_t computeUnits_ = 0;\n\t};\n}\n"
  },
  {
    "path": "src/mining/MinerConfig.cpp",
    "content": "// ==========================================================================\n//\n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n//\n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n//\n// ==========================================================================\n\n#include \"MinerConfig.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include \"MinerUtil.hpp\"\n#include <fstream>\n#include <memory>\n#include <Poco/File.h>\n#include <Poco/Path.h>\n#include <Poco/JSON/Parser.h>\n#include <Poco/JSON/Array.h>\n#include <Poco/NestedDiagnosticContext.h>\n#include <Poco/SHA1Engine.h>\n#include <Poco/DigestStream.h>\n#include \"plots/PlotSizes.hpp\"\n#include <Poco/Logger.h>\n#include <Poco/SplitterChannel.h>\n#include \"logging/Output.hpp\"\n#include \"plots/PlotReader.hpp\"\n#include \"plots/Plot.hpp\"\n#include <Poco/FileStream.h>\n#include <Poco/JSON/PrintHandler.h>\n#include <Poco/StringTokenizer.h>\n#include \"extlibs/json.hpp\"\n#include <regex>\n#include <Poco/Random.h>\n#include <Poco/Crypto/CipherFactory.h>\n#include <Poco/Crypto/CipherKey.h>\n#include <Poco/Crypto/Cipher.h>\n\nconst std::string Burst::Passphrase::delimiter = \"::::\";\n\nvoid Burst::MinerConfig::rescan()\n{\n\treadConfigFile(configPath_);\n}\n\nbool Burst::MinerConfig::rescanPlotfiles()\n{\n\tlog_system(MinerLogger::config, \"Rescanning plot-dirs...\");\n\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tfor (auto& plotDir : plotDirs_)\n\t\tplotDir->rescan();\n\n\tconst auto oldPlotsHash = plotsHash_;\n\trecalculatePlotsHash();\n\n\tif (oldPlotsHash != plotsHash_)\n\t{\n\t\tprintConsolePlots();\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nvoid Burst::MinerConfig::checkPlotOverlaps() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tPoco::UInt64 totalOverlaps = 0;\n\n\tconst auto plotFiles = getPlotFiles();\n\tconst auto numPlots = plotFiles.size();\n\n\tif (numPlots == 0)\n\t\treturn;\n\n\tlog_system(MinerLogger::config, \"Checking local plots for overlaps...\");\n\n\tfor (auto iterOne = plotFiles.begin(); iterOne != plotFiles.end(); ++iterOne)\n\t{\n\t\tconst auto& fileOne = **iterOne;\n\n\t\tfor (auto iterTwo = iterOne + 1; iterTwo != plotFiles.end(); ++iterTwo)\n\t\t{\n\t\t\tconst auto& fileTwo = **iterTwo;\n\n\t\t\tif (fileOne.getPath() != fileTwo.getPath() && fileOne.getAccountId() == fileTwo.getAccountId())\n\t\t\t{\n\t\t\t\tif (fileTwo.getNonceStart() >= fileOne.getNonceStart() && fileTwo.getNonceStart() < fileOne.getNonceStart() + fileOne.getNonces())\n\t\t\t\t{\n\t\t\t\t\tauto overlap = fileOne.getNonceStart() + fileOne.getNonces() - fileTwo.getNonceStart();\n\t\t\t\t\tif (fileTwo.getNonces() < overlap)\n\t\t\t\t\t\toverlap = fileTwo.getNonces();\n\t\t\t\t\tlog_error(MinerLogger::miner, \"%s and %s overlap by %s nonces.\", fileOne.getPath(), fileTwo.getPath(), std::to_string(overlap));\n\t\t\t\t\t++totalOverlaps;\n\t\t\t\t}\n\t\t\t\telse if (fileOne.getNonceStart() >= fileTwo.getNonceStart() && fileOne.getNonceStart() < fileTwo.getNonceStart() + fileTwo.getNonces())\n\t\t\t\t{\n\t\t\t\t\tauto overlap = fileTwo.getNonceStart() + fileTwo.getNonces() - fileOne.getNonceStart();\n\t\t\t\t\tif (fileOne.getNonces() < overlap)\n\t\t\t\t\t\toverlap = fileOne.getNonces();\n\t\t\t\t\tlog_error(MinerLogger::miner, \"%s and %s overlap by %s nonces.\", fileTwo.getPath(), fileOne.getPath(), std::to_string(overlap));\n\t\t\t\t\t++totalOverlaps;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (totalOverlaps > 0)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Total overlaps found: \" + std::to_string(totalOverlaps));\n\t}\n\telse\n\t\tlog_system(MinerLogger::config, \"No overlaps found.\");\n}\n\nvoid Burst::MinerConfig::printConsole() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tlog_system(MinerLogger::config, \"Version : %s%s\", Settings::project.getVersion().literal,\n\t\tSettings::project.getVersion().revision > 0\n\t\t\t? Poco::format(\" (DEV. %u)\", Settings::project.getVersion().revision)\n\t\t\t: std::string{});\n\n#ifdef NDEBUG\n\tstd::string mode = \"Release\";\n#else\n\tstd::string mode = \"Debug\";\n#endif\n\n\tlog_system(MinerLogger::config, \"Mode : %s\", mode);\n\tlog_system(MinerLogger::config, \"Build features :%s\", createBuildFeatures());\n\n\tif (!getWorkerName().empty())\n\t\tlog_system(MinerLogger::config, \"Worker : %s\", getWorkerName());\n\n\tlog_system(MinerLogger::config, \"Submission Max Retry : %s\",\n\t\tgetSubmissionMaxRetry() == 0u ? \"unlimited\" : std::to_string(getSubmissionMaxRetry()) + \" seconds\");\n\n\tprintBufferSize();\n\tprintBufferChunks();\n\n\tprintUrl(HostType::Pool);\n\tprintUrl(HostType::MiningInfo);\n\tprintUrl(HostType::Wallet);\n\tprintUrl(HostType::Server);\n\n\tif (!getProxyFullUrl().empty())\n\t{\n\t\tauto proxyConfig = getProxyConfig();\n\t\tlog_system(MinerLogger::config, \"Proxy URL : %s:%hu\", proxyConfig.host, proxyConfig.port);\n\t}\n\n\tif (getConfig().getSubmitProbability() > 0.)\n\t\tprintSubmitProbability();\n\telse\n\t\tprintTargetDeadline();\n\n\tif (isLogfileUsed())\n\t\tlog_system(MinerLogger::config, \"Log path : %s\", getConfig().getPathLogfile().toString());\n\n\tlog_system(MinerLogger::config, \"Database path : %s\", getConfig().getDatabasePath());\n\n\tprintConsolePlots();\n\n\tlog_system(MinerLogger::config, \"Get mining info interval : %u seconds\", getConfig().getMiningInfoInterval());\n\n\tlog_system(MinerLogger::config, \"Processor type : %s\", getConfig().getProcessorType());\n\n\tif (getConfig().getProcessorType() == \"CPU\")\n\t\tlog_system(MinerLogger::config, \"CPU instruction set : %s\", getConfig().getCpuInstructionSet());\n}\n\nvoid Burst::MinerConfig::printConsolePlots() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tlog_system(MinerLogger::config, \"Total plots size: %s\", memToString(getConfig().getTotalPlotsize(), 2));\n\tlog_system(MinerLogger::config, \"Mining intensity : %u\", getMiningIntensity());\n\tlog_system(MinerLogger::config, \"Max plot readers : %u\", getMaxPlotReaders());\n}\n\nvoid Burst::MinerConfig::printUrl(HostType type) const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tswitch (type)\n\t{\n\tcase HostType::MiningInfo: return printUrl(urlMiningInfo_, \"Mininginfo URL\");\n\tcase HostType::MiningInfoAlts:\n\t\t{\n\t\t\tfor (size_t i = 0; i < urlMiningInfoAlt_.size(); ++i)\n\t\t\t\tprintUrl(urlMiningInfoAlt_[i], Poco::format(\"Alt. Mininginfo URL %z\", i));\n\t\t}\n\tcase HostType::Pool: return printUrl(urlPool_, \"Submission URL\");\n\tcase HostType::Wallet: return printUrl(urlWallet_, \"Wallet URL\");\n\tcase HostType::Server: return printUrl(urlServer_, \"Server URL\");\n\t}\n}\n\nvoid Burst::MinerConfig::printUrl(const Url& url, const std::string& url_name)\n{\n\tif (!url.empty())\n\t\tlog_system(MinerLogger::config, \"%s : %s:%hu\",\n\t\t\turl_name ,url.getCanonical(true), url.getPort());\n}\n\nvoid Burst::MinerConfig::printBufferSize() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tlog_system(MinerLogger::config, \"Buffer Size : %s\",\n\t\tstd::to_string(getMaxBufferSizeRaw()) + \" (\" + memToString(getMaxBufferSize(), 0) + \")\");\n}\n\nvoid Burst::MinerConfig::printBufferChunks() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tlog_system(MinerLogger::config, \"Buffer Chunks : %s (%s each)\", std::to_string(getBufferChunkCount()),\n\t\tmemToString(getMaxBufferSize() / getBufferChunkCount(), 0));\n}\n\ntemplate <typename T>\nT getOrAdd(Poco::JSON::Object::Ptr object, const std::string& key, T defaultValue)\n{\n\tauto json = object->get(key);\n\n\tif (json.isEmpty())\n\t{\n\t\tobject->set(key, defaultValue);\n\t\treturn defaultValue;\n\t}\n\n\treturn json.convert<T>();\n}\n\ntemplate <typename T>\nT getOrAddExtract(Poco::JSON::Object::Ptr object, const std::string& key, T defaultValue)\n{\n\tauto json = object->get(key);\n\n\tif (json.isEmpty())\n\t{\n\t\tobject->set(key, defaultValue);\n\t\treturn defaultValue;\n\t}\n\n\treturn json.extract<T>();\n}\n\nvoid Burst::MinerConfig::recalculatePlotsHash()\n{\n\tPoco::SHA1Engine sha;\n\tPoco::DigestOutputStream shaStream{sha};\n\n\tfor (const auto& plotFile : getPlotFiles())\n\t\tshaStream << plotFile->getPath();\n\n\tshaStream << std::flush;\n\tplotsHash_ = Poco::SHA1Engine::digestToHex(sha.digest());\n\n\t// we remember our total plot size\n\tPlotSizes::set(Poco::Net::IPAddress{\"127.0.0.1\"}, getTotalPlotsize(), true);\n}\n\nBurst::ReadConfigFileResult Burst::MinerConfig::readConfigFile(const std::string& configPath)\n{\n\tpoco_ndc(readConfigFile);\n\tstd::ifstream inputFileStream;\n\n\t// first we open the config file\n\ttry\n\t{\n\t\tinputFileStream.open(configPath);\n\t}\n\tcatch (...)\n\t{\n\t\tlog_critical(MinerLogger::config, \"Unable to open config %s\", configPath);\n\t\treturn ReadConfigFileResult::Error;\n\t}\n\n\tif (!inputFileStream.is_open())\n\t\treturn ReadConfigFileResult::NotFound;\n\n\tconfigPath_ = configPath;\n\tplotDirs_.clear();\n\n\tPoco::JSON::Parser parser;\n\tPoco::JSON::Object::Ptr config;\n\tstd::stringstream jsonValidationStream;\n\n\tparser.setAllowComments(true);\n\n\tconst std::string jsonStr((std::istreambuf_iterator<char>(inputFileStream)),\n\t\tstd::istreambuf_iterator<char>());\n\n\tinputFileStream.close();\n\n\ttry\n\t{\n\t\t// validate the syntax\n\t\tnlohmann::json::parse(jsonStr);\n\n\t\t// parse the config\n\t\tconfig = parser.parse(jsonStr).extract<Poco::JSON::Object::Ptr>();\n\t}\n\tcatch (nlohmann::json::parse_error& exc)\n\t{\n\t\tconst auto slice = 256;\n\t\tauto startByte = std::max(0, static_cast<int>(exc.byte) - slice);\n\t\tauto endByte = std::min(exc.byte + slice, jsonStr.size());\n\n\t\tif (startByte < 5)\n\t\t\tstartByte = 0;\n\n\t\tif (endByte > jsonStr.size() - 5)\n\t\t\tendByte = jsonStr.size();\n\n\t\tconst auto errorColor = MinerLogger::getTextTypeColor(TextType::Error);\n\n\t\tauto printBlock = Console::print();\n\t\tprintBlock.addTime() << \": \" << errorColor << \"There is an error in the config file!\";\n\t\tprintBlock.nextLine();\n\t\tprintBlock.resetColor();\n\n\t\tif (startByte > 0)\n\t\t\tprintBlock << \"...\";\n\n\t\tprintBlock << jsonStr.substr(startByte, exc.byte - startByte)\n\t\t\t<< errorColor << \" <-- error somewhere here\";\n\t\tprintBlock.resetColor() << jsonStr.substr(exc.byte, endByte - exc.byte);\n\n\t\tif (endByte < jsonStr.size())\n\t\t\tprintBlock << \"...\";\n\n\t\tprintBlock.nextLine();\n\t\treturn ReadConfigFileResult::Invalid;\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_error(MinerLogger::config,\n\t\t\t\"There is an error in the config file!\\n\"\n\t\t\t\"%s\",\n\t\t\texc.displayText()\n\t\t);\n\n\t\tlog_current_stackframe(MinerLogger::config);\n\n\t\t// dont forget to close the file\n\t\tif (inputFileStream.is_open())\n\t\t\tinputFileStream.close();\n\n\t\treturn ReadConfigFileResult::Invalid;\n\t}\n\n\tconst auto checkCreateUrlFunc = [](Poco::JSON::Object::Ptr urlsObj, const std::string& name, Url& url,\n\t\tconst std::string& defaultScheme, unsigned short defaultPort, const std::string& createUrl, bool forceInsert = false)\n\t{\n\t\tauto var = getOrAdd(urlsObj, name, createUrl);\n\n\t\tif (var.empty() && forceInsert)\n\t\t{\n\t\t\turl = { createUrl };\n\t\t\turlsObj->set(name, url.getUri().toString());\n\t\t}\n\t\telse if (!var.empty())\n\t\t{\n\t\t\turl = { var, defaultScheme, defaultPort };\n\t\t\turlsObj->set(name, url.getUri().toString());\n\t\t}\n\t\telse\n\t\t{\n\t\t\turl = { \"\" };\n\t\t}\n\t};\n\n\t// logging\n\t{\n\t\tPoco::JSON::Object::Ptr loggingObj = nullptr;\n\n\t\tif (config->has(\"logging\"))\n\t\t\tloggingObj = config->get(\"logging\").extract<Poco::JSON::Object::Ptr>();\n\n\t\tif (!loggingObj.isNull())\n\t\t{\n\t\t\t// do we need to create a logfile\n\t\t\tlogfile_ = getOrAdd(loggingObj, \"logfile\", true);\n\n\t\t\tconst auto logOutput = getOrAdd(loggingObj, \"outputType\", std::string(\"terminal\"));\n\n\t\t\tif (logOutput == \"terminal\")\n\t\t\t\tlogOutputType_ = LogOutputType::Terminal;\n\t\t\telse if (logOutput == \"service\")\n\t\t\t\tlogOutputType_ = LogOutputType::Service;\n\t\t\telse\n\t\t\t\tlogOutputType_ = LogOutputType::Terminal;\n\n\t\t\tlogUseColors_ = getOrAdd(loggingObj, \"useColors\", true);\n\t\t\tverboseLogging_ = getOrAdd(loggingObj, \"verbose\", true);\n\n\t\t\tPoco::JSON::Object::Ptr progressBarObj = nullptr;\n\n\t\t\tif (loggingObj->has(\"progressBar\"))\n\t\t\t\tprogressBarObj = loggingObj->get(\"progressBar\").extract<Poco::JSON::Object::Ptr>();\n\n\t\t\tif (progressBarObj.isNull())\n\t\t\t{\n\t\t\t\tprogressBarObj.assign(new Poco::JSON::Object);\n\t\t\t\tprogressBarObj->set(\"steady\", true);\n\t\t\t\tprogressBarObj->set(\"fancy\", true);\n\t\t\t\tloggingObj->set(\"progressBar\", progressBarObj);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsteadyProgressBar_ = getOrAdd(progressBarObj, \"steady\", true);\n\t\t\t\tfancyProgressBar_ = getOrAdd(progressBarObj, \"fancy\", true);\n\t\t\t}\n\n\t\t\ttry\n\t\t\t{\n\t\t\t\tconst auto dirLogFile = getOrAdd(loggingObj, \"path\", std::string(\"\"));\n\t\t\t\tsetLogDir(dirLogFile);\n\t\t\t}\n\t\t\tcatch (Poco::Exception& exc)\n\t\t\t{\n\t\t\t\tlog_fatal(MinerLogger::config, \"Could not set path for log-file!\\n%s\", exc.displayText());\n\t\t\t}\n\n\t\t\t// setup logger\n\t\t\tfor (auto& channel : MinerLogger::channelDefinitions)\n\t\t\t{\n\t\t\t\tif (loggingObj->has(channel.name))\n\t\t\t\t\tMinerLogger::setChannelPriority(channel.name, loggingObj->get(channel.name).extract<std::string>());\n\t\t\t\telse\n\t\t\t\t\tloggingObj->set(channel.name, MinerLogger::getChannelPriority(channel.name));\n\t\t\t}\n\t\t}\n\t\t// if it dont exist, we create it!\n\t\telse\n\t\t{\n\t\t\tloggingObj = new Poco::JSON::Object;\n\t\t\tloggingObj->set(\"path\", \"\");\n\t\t\tloggingObj->set(\"logfile\", false);\n\t\t\tloggingObj->set(\"outputType\", std::string(\"terminal\"));\n\n\t\t\tloggingObj->set(\"useColors\", true);\n\n\t\t\t// progress bar\n\t\t\t{\n\t\t\t\tPoco::JSON::Object progressBarJson;\n\t\t\t\tprogressBarJson.set(\"steady\", true);\n\t\t\t\tprogressBarJson.set(\"fancy\", true);\n\t\t\t\tloggingObj->set(\"progressBar\", progressBarJson);\n\t\t\t}\n\n\t\t\tfor (auto& channel : MinerLogger::channelDefinitions)\n\t\t\t\tloggingObj->set(channel.name, MinerLogger::getChannelPriority(channel.name));\n\n\t\t\tconfig->set(\"logging\", loggingObj);\n\t\t}\n\n\t\t// output\n\t\t{\n\t\t\tPoco::JSON::Object::Ptr outputObj;\n\n\t\t\tauto outputLoggingObj = readOutput(loggingObj->getObject(\"output\"));\n\n\t\t\tif (!outputLoggingObj.isNull())\n\t\t\t\toutputObj = outputLoggingObj;\n\t\t\telse\n\t\t\t\toutputObj.assign(new Poco::JSON::Object);\n\n\t\t\toutputObj = readOutput(outputObj);\n\n\t\t\tloggingObj->set(\"output\", outputObj);\n\t\t}\n\t}\n\n\t// mining\n\t{\n\t\tPoco::JSON::Object::Ptr miningObj;\n\n\t\tif (config->has(\"mining\"))\n\t\t\tminingObj = config->get(\"mining\").extract<Poco::JSON::Object::Ptr>();\n\t\telse\n\t\t\tminingObj.assign(new Poco::JSON::Object);\n\n\t\tsubmissionMaxRetry_ = getOrAdd(miningObj, \"submissionMaxRetry\", 10);\n\t\tmaxBufferSizeMb_ = getOrAdd(miningObj, \"maxBufferSizeMB\", 0u);\n\n\t\tconst auto timeout = getOrAdd(miningObj, \"timeout\", 30);\n\t\ttimeout_ = static_cast<float>(timeout);\n\n\t\tminingIntensity_ = getOrAdd(miningObj, \"intensity\", 0);\n\t\tmaxPlotReaders_ = getOrAdd(miningObj, \"maxPlotReaders\", 0);\n\n\t\twalletRequestTries_ = getOrAdd(miningObj, \"walletRequestTries\", 5);\n\t\twalletRequestRetryWaitTime_ = getOrAdd(miningObj, \"walletRequestRetryWaitTime\", 3);\n\n\t\t// use insecure plotfiles\n\t\tuseInsecurePlotfiles_ = getOrAdd(miningObj, \"useInsecurePlotfiles\", false);\n\t\tgetMiningInfoInterval_ = getOrAdd(miningObj, \"getMiningInfoInterval\", 3);\n\t\trescanEveryBlock_ = getOrAdd(miningObj, \"rescanEveryBlock\", false);\n\n\t\tbufferChunkCount_ = getOrAdd(miningObj, \"bufferChunkCount\", 8);\n\t\twakeUpTime_ = getOrAdd(miningObj, \"wakeUpTime\", 0);\n\n\t\tcpuInstructionSet_ = Poco::toUpper(getOrAdd(miningObj, \"cpuInstructionSet\", std::string(\"AUTO\")));\n\t\tcpuInstructionSet_ = Poco::trim(cpuInstructionSet_);\n\n\t\tdatabasePath_ = getOrAdd(miningObj, \"databasePath\", std::string(\"data.db\"));\n\t\tworkerName_ = getOrAdd(miningObj, \"workerName\", std::string{});\n\t\tpoc2StartBlock_ = getOrAdd(miningObj, \"poc2StartBlock\", 502000);\n\n\t\t// Check if CPU instruction set was wrongly configured. Auto detect in case of wrong settings.\n\t\tif ((((cpuInstructionSet_ == \"AVX2\") && !cpuHasInstructionSet(CpuInstructionSet::Avx2))\n\t\t\t|| ((cpuInstructionSet_ == \"AVX\") && !cpuHasInstructionSet(CpuInstructionSet::Avx))\n\t\t\t|| ((cpuInstructionSet_ == \"SSE4\") && !cpuHasInstructionSet(CpuInstructionSet::Sse4)))\n\t\t\t|| ((cpuInstructionSet_ != \"AVX2\") && (cpuInstructionSet_ != \"AVX\")\n\t\t\t\t&& (cpuInstructionSet_ != \"SSE4\") && (cpuInstructionSet_ != \"SSE2\"))) {\n\t\t\tlog_warning(MinerLogger::config, \"Configured CPU instruction set %s is not supported by CPU!\",\n\t\t\t\tcpuInstructionSet_);\n\t\t\tcpuInstructionSet_ = \"AUTO\";\n\t\t}\n\t\t// auto detect the max. cpu instruction set\n\t\tif (cpuInstructionSet_ == \"AUTO\")\n\t\t{\n\t\t\tif (cpuHasInstructionSet(CpuInstructionSet::Avx2))\n\t\t\t\tcpuInstructionSet_ = \"AVX2\";\n\t\t\telse if (cpuHasInstructionSet(CpuInstructionSet::Avx))\n\t\t\t\tcpuInstructionSet_ = \"AVX\";\n\t\t\telse if (cpuHasInstructionSet(CpuInstructionSet::Sse4))\n\t\t\t\tcpuInstructionSet_ = \"SSE4\";\n\t\t\telse\n\t\t\t\tcpuInstructionSet_ = \"SSE2\";\n\t\t}\n\n\t\tSettings::setCpuInstructionSet(cpuInstructionSet_);\n\n\t\tstd::string defaultProcessorType;\n\n\t\tif (Settings::cuda)\n\t\t\tdefaultProcessorType = \"CUDA\";\n\t\telse if (Settings::openCl)\n\t\t\tdefaultProcessorType = \"OPENCL\";\n\t\telse\n\t\t\tdefaultProcessorType = \"CPU\";\n\n\t\tprocessorType_ = getOrAdd(miningObj, \"processorType\", defaultProcessorType);\n\n\t\tgpuPlatform_ = getOrAdd(miningObj, \"gpuPlatform\", 0u);\n\t\tgpuDevice_ = getOrAdd(miningObj, \"gpuDevice\", 0u);\n\n\t\t// urls\n\t\t{\n\t\t\tconst auto checkCreateUrlArrayFunc = [&checkCreateUrlFunc](Poco::JSON::Object::Ptr urlsObj, const std::string& name,\n\t\t\t                                                           Url& url,\n\t\t\t                                                           std::vector<Url>& altUrls,\n\t\t\t                                                           const std::string& defaultScheme,\n\t\t\t                                                           unsigned short defaultPort,\n\t\t\t                                                           const std::string& createUrl)\n\t\t\t{\n\t\t\t\tif (urlsObj->isArray(name))\n\t\t\t\t{\n\t\t\t\t\tconst auto urls = urlsObj->getArray(name);\n\n\t\t\t\t\tfor (unsigned i = 0; i < urls->size(); ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (i == 0)\n\t\t\t\t\t\t\turl = Url{urls->getElement<std::string>(i)};\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\taltUrls.emplace_back(urls->getElement<std::string>(i));\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\tcheckCreateUrlFunc(urlsObj, name, url, defaultScheme, defaultPort, createUrl);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tPoco::JSON::Object::Ptr urlsObj;\n\n\t\t\tif (miningObj->has(\"urls\"))\n\t\t\t\turlsObj = miningObj->get(\"urls\").extract<Poco::JSON::Object::Ptr>();\n\t\t\telse\n\t\t\t\turlsObj = new Poco::JSON::Object;\n\n\t\t\tcheckCreateUrlArrayFunc(urlsObj, \"submission\", urlPool_, urlPoolAlt_, \"https\", 443,\n\t\t\t                        \"https://pool.creepminer.net\");\n\t\t\tcheckCreateUrlArrayFunc(urlsObj, \"miningInfo\", urlMiningInfo_, urlMiningInfoAlt_, \"https\", 443,\n\t\t\t                        \"https://pool.creepminer.net\");\n\t\t\tcheckCreateUrlFunc(urlsObj, \"wallet\", urlWallet_, \"https\", 443, \"https://wallet.creepminer.net\");\n\n\t\t\tif (urlMiningInfo_.empty() && !urlPool_.empty())\n\t\t\t{\n\t\t\t\turlMiningInfo_ = urlPool_;\n\t\t\t\turlsObj->set(\"miningInfo\", urlPool_.getUri().toString());\n\t\t\t}\n\n\t\t\tconst auto urlProxy = getOrAdd(urlsObj, \"proxy\", std::string{});\n\n\t\t\tif (!urlProxy.empty())\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tstd::smatch match;\n\n\t\t\t\t\tconst auto extractEncrypted = [](const std::string& property)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto encrypted = Passphrase::fromString(property);\n\n\t\t\t\t\t\tif (encrypted.isPlainText())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (encrypted.algorithm.empty())\n\t\t\t\t\t\t\t\tencrypted.algorithm = \"aes-256-cbc\";\n\n\t\t\t\t\t\t\tencrypted.encrypt();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn encrypted;\n\t\t\t\t\t};\n\n\t\t\t\t\t// user:password@host:port\n\t\t\t\t\tif (std::regex_match(urlProxy, match, std::regex{\"^(.+)(&|:)(.+)@(.+):(.+)$\"}))\n\t\t\t\t\t{\n\t\t\t\t\t\tproxyUser_ = extractEncrypted(match[1].str());\n\t\t\t\t\t\tproxyPassword_ = extractEncrypted(match[3].str());\n\t\t\t\t\t\tproxyIp_ = match[4].str();\n\t\t\t\t\t\tproxyPort_ = static_cast<Poco::UInt16>(Poco::NumberParser::parse(match[5].str()));\n\t\t\t\t\t}\n\t\t\t\t\t// user@host:port\n\t\t\t\t\telse if (std::regex_match(urlProxy, match, std::regex{\"^(.+)@(.+):(.+)$\"}))\n\t\t\t\t\t{\n\t\t\t\t\t\tproxyUser_ = extractEncrypted(match[1].str());\n\t\t\t\t\t\tproxyIp_ = match[2].str();\n\t\t\t\t\t\tproxyPort_ = static_cast<Poco::UInt16>(Poco::NumberParser::parse(match[3].str()));\n\t\t\t\t\t}\n\t\t\t\t\t// host:port\n\t\t\t\t\telse if (std::regex_match(urlProxy, match, std::regex{\"^(.+):(.+)$\"}))\n\t\t\t\t\t{\n\t\t\t\t\t\tproxyIp_ = match[1].str();\n\t\t\t\t\t\tproxyPort_ = static_cast<Poco::UInt16>(Poco::NumberParser::parse(match[2].str()));\n\t\t\t\t\t}\n\t\t\t\t\t// host\n\t\t\t\t\telse if (std::regex_match(urlProxy, match, std::regex{\"^(.+)$\"}))\n\t\t\t\t\t{\n\t\t\t\t\t\tproxyIp_ = match[1].str();\n\t\t\t\t\t\tproxyPort_ = 8080;\n\t\t\t\t\t\tlog_warning(MinerLogger::config, \"Your proxy URL has no port definition, 8080 is assumed.\\n\"\n\t\t\t\t\t\t\t\"Please use the format [user:password@]host:port\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tlog_error(MinerLogger::config, \"Invalid proxy URL format, please use [user:password@]host:port\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (const Poco::Exception& e)\n\t\t\t\t{\n\t\t\t\t\tlog_error(MinerLogger::config, \"Could not parse the proxy URL: %s\", e.displayText());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\turlsObj->set(\"proxy\", getProxyFullUrl());\n\t\t\tminingObj->set(\"urls\", urlsObj);\n\t\t}\n\n\t\t// plots\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tconst Poco::JSON::Array::Ptr arr(new Poco::JSON::Array);\n\t\t\t\tauto plotsArr = getOrAddExtract(miningObj, \"plots\", arr);\n\n\t\t\t\tauto plotsDyn = miningObj->get(\"plots\");\n\n\t\t\t\tif (plotsDyn.type() == typeid(Poco::JSON::Array::Ptr))\n\t\t\t\t{\n\t\t\t\t\tauto plots = plotsDyn.extract<Poco::JSON::Array::Ptr>();\n\n\t\t\t\t\tfor (auto& plot : *plots)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// string means sequential plot dir\n\t\t\t\t\t\t\tif (plot.isString())\n\t\t\t\t\t\t\t\taddPlotDir(std::make_shared<PlotDir>(plot.extract<std::string>(), PlotDir::Type::Sequential));\n\t\t\t\t\t\t\t// object means custom (sequential/parallel) plot dir\n\t\t\t\t\t\t\telse if (plot.type() == typeid(Poco::JSON::Object::Ptr))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tconst auto sequential = \"sequential\";\n\t\t\t\t\t\t\t\tconst auto parallel = \"parallel\";\n\n\t\t\t\t\t\t\t\tauto plotJson = plot.extract<Poco::JSON::Object::Ptr>();\n\t\t\t\t\t\t\t\tauto type = PlotDir::Type::Sequential;\n\n\t\t\t\t\t\t\t\tauto typeStr = plotJson->optValue<std::string>(\"type\", \"\");\n\n\t\t\t\t\t\t\t\tauto path = plotJson->get(\"path\");\n\n\t\t\t\t\t\t\t\tif (path.isEmpty())\n\t\t\t\t\t\t\t\t\tlog_error(MinerLogger::config, \"Empty dir given as plot dir/file! Skipping it...\");\n\t\t\t\t\t\t\t\telse if (typeStr.empty())\n\t\t\t\t\t\t\t\t\tlog_error(MinerLogger::config, \"Invalid type of plot dir/file %s! Skipping it...\", path.toString());\n\t\t\t\t\t\t\t\telse if (typeStr != sequential && typeStr != parallel)\n\t\t\t\t\t\t\t\t\tlog_error(MinerLogger::config, \"Type of plot dir/file %s is invalid (%s)! Skipping it...\", path.toString(), typeStr);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (typeStr == sequential)\n\t\t\t\t\t\t\t\t\t\ttype = PlotDir::Type::Sequential;\n\t\t\t\t\t\t\t\t\telse if (typeStr == parallel)\n\t\t\t\t\t\t\t\t\t\ttype = PlotDir::Type::Parallel;\n\n\t\t\t\t\t\t\t\t\t// related dirs\n\t\t\t\t\t\t\t\t\tif (path.type() == typeid(Poco::JSON::Array::Ptr))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tauto relatedPathsJson = path.extract<Poco::JSON::Array::Ptr>();\n\t\t\t\t\t\t\t\t\t\tstd::vector<std::string> relatedPaths;\n\n\t\t\t\t\t\t\t\t\t\tfor (const auto& relatedPath : *relatedPathsJson)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif (relatedPath.isString())\n\t\t\t\t\t\t\t\t\t\t\t\trelatedPaths.emplace_back(relatedPath.extract<std::string>());\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\tlog_error(MinerLogger::config, \"Invalid plot dir/file %s! Skipping it...\", relatedPath.toString());\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (relatedPaths.size() == 1)\n\t\t\t\t\t\t\t\t\t\t\tplotDirs_.emplace_back(new PlotDir{ *relatedPaths.begin(), type });\n\t\t\t\t\t\t\t\t\t\telse if (relatedPaths.size() > 1)\n\t\t\t\t\t\t\t\t\t\t\tplotDirs_.emplace_back(new PlotDir{ *relatedPaths.begin(), { relatedPaths.begin() + 1, relatedPaths.end() }, type });\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// single dir\n\t\t\t\t\t\t\t\t\telse if (path.isString())\n\t\t\t\t\t\t\t\t\t\tplotDirs_.emplace_back(new PlotDir{ path, type });\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tlog_error(MinerLogger::config, \"Invalid plot dir/file %s! Skipping it...\", path.toString());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (const Poco::Exception& e)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlog_warning(MinerLogger::config, \"Error while adding the plotdir/file: %s\", e.message());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t/*else if (plotsDyn.isString())\n\t\t\t\t{\n\t\t\t\t\taddPlotLocation(plotsDyn.extract<std::string>());\n\t\t\t\t}\n\t\t\t\telse if (plotsDyn.isEmpty())\n\t\t\t\t{\n\t\t\t\t\tPoco::JSON::Array::Ptr arr = new Poco::JSON::Array;\n\t\t\t\t\tconfig->set(\"plots\", arr);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlog_warning(MinerLogger::config, \"Invalid plot file or directory in config file %s\\n%s\",\n\t\t\t\t\t\tconfigPath, plotsDyn.toString());\n\t\t\t\t}*/\n\t\t\t}\n\t\t\tcatch (Poco::Exception& exc)\n\t\t\t{\n\t\t\t\tlog_error(MinerLogger::config,\n\t\t\t\t\t\"Error while reading plot files!\\n\"\n\t\t\t\t\t\"%s\",\n\t\t\t\t\texc.displayText()\n\t\t\t\t);\n\n\t\t\t\tlog_current_stackframe(MinerLogger::config);\n\t\t\t}\n\n\t\t\t// combining all plotfiles to lists of plotfiles on the same device\n\t\t\trecalculatePlotsHash();\n\t\t}\n\n\n\t\t// max historical data\n\t\t{\n\t\tauto maxHistoricalBlocks = miningObj->get(\"maxHistoricalBlocks\");\n\n\t\tif (!maxHistoricalBlocks.isEmpty())\n\t\t{\n\t\t\tsetMaxHistoricalBlocks(maxHistoricalBlocks.convert<Poco::UInt64>());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tminingObj->set(\"maxHistoricalBlocks\", 360);\n\t\t\tsetMaxHistoricalBlocks(360);\n\t\t}\n\t\t}\n\n\t\t// submit probability\n\t\t{\n\t\t\tauto submitProbability = miningObj->get(\"submitProbability\");\n\n\t\t\tif (!submitProbability.isEmpty())\n\t\t\t{\n\t\t\t\tsetSubmitProbability( static_cast<double>(submitProbability) );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tminingObj->set(\"submitProbability\", 0.999);\n\t\t\t\tsetSubmitProbability( 0.999 );\n\t\t\t}\n\t\t}\n\n\t\t// target deadline\n\t\t{\n\t\t\tauto targetDeadline = miningObj->get(\"targetDeadline\");\n\n\t\t\tif (!targetDeadline.isEmpty())\n\t\t\t{\n\t\t\t\t// could be the raw deadline\n\t\t\t\tif (targetDeadline.isInteger())\n                    targetDeadline_ = targetDeadline.convert<Poco::UInt64>();\n\t\t\t\t// or a formated string\n\t\t\t\telse if (targetDeadline.isString())\n\t\t\t\t\ttargetDeadline_ = formatDeadline(targetDeadline.convert<std::string>());\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttargetDeadline_ = 0;\n\n\t\t\t\t\tlog_error(MinerLogger::config, \"The target deadline is not a valid!\\n\"\n\t\t\t\t\t\t\"Expected a number (amount of seconds) or a formated string (1m 1d 11:11:11)\\n\"\n\t\t\t\t\t\t\"Got: %s\", targetDeadline.toString());\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tminingObj->set(\"targetDeadline\", \"0y 0m 0d 00:00:00\");\n\t\t\t\ttargetDeadline_ = 0;\n\t\t\t}\n\t\t}\n\n\t\t// passphrase\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tif (miningObj->isObject(\"passphrase\"))\n\t\t\t\t{\n\t\t\t\t\tauto passphraseJson = miningObj->get(\"passphrase\");\n\t\t\t\t\tPoco::JSON::Object::Ptr passphrase = nullptr;\n\n\t\t\t\t\tif (!passphraseJson.isEmpty())\n\t\t\t\t\t\tpassphrase = passphraseJson.extract<Poco::JSON::Object::Ptr>();\n\n\t\t\t\t\tif (passphrase.isNull())\n\t\t\t\t\t{\n\t\t\t\t\t\tpassphrase.assign(new Poco::JSON::Object);\n\t\t\t\t\t\tminingObj->set(\"passphrase\", passphrase);\n\t\t\t\t\t}\n\n\t\t\t\t\tlog_debug(MinerLogger::config, \"Reading passphrase...\");\n\n\t\t\t\t\tif (passphrase->has(\"decrypted\") || passphrase->has(\"encrypted\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tpassphrase_.decrypted = getOrAdd<std::string>(passphrase, \"decrypted\", \"\");\n\t\t\t\t\t\tpassphrase_.encrypted = getOrAdd<std::string>(passphrase, \"encrypted\", \"\");\n\t\t\t\t\t\tpassphrase_.salt = getOrAdd<std::string>(passphrase, \"salt\", \"\");\n\t\t\t\t\t\tpassphrase_.key = getOrAdd<std::string>(passphrase, \"key\", \"\");\n\t\t\t\t\t\tpassphrase_.iterations = getOrAdd(passphrase, \"iterations\", 1000u);\n\t\t\t\t\t\tpassphrase_.deleteKey = getOrAdd(passphrase, \"deleteKey\", true);\n\t\t\t\t\t\tpassphrase_.algorithm = getOrAdd<std::string>(passphrase, \"algorithm\", \"aes-256-cbc\");\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\tpassphrase_ = Passphrase::fromString(miningObj->getValue<std::string>(\"passphrase\"));\n\t\t\t\t}\n\n\t\t\t\t// there is a decrypted passphrase, we need to encrypt it\n\t\t\t\tif (!passphrase_.decrypted.empty())\n\t\t\t\t{\n\t\t\t\t\tlog_debug(MinerLogger::config, \"Decrypted passphrase found, trying to encrypt...\");\n\n\t\t\t\t\tif (passphrase_.algorithm.empty())\n\t\t\t\t\t\tpassphrase_.algorithm = \"aes-256-cbc\";\n\n\t\t\t\t\tpassphrase_.encrypt();\n\t\t\t\t}\n\n\t\t\t\tif (!passphrase_.encrypted.empty() &&\n\t\t\t\t\t!passphrase_.key.empty() &&\n\t\t\t\t\t!passphrase_.salt.empty())\n\t\t\t\t{\n\t\t\t\t\tlog_debug(MinerLogger::config, \"Encrypted passphrase found, trying to decrypt...\");\n\n\t\t\t\t\tpassphrase_.decrypt();\n\n\t\t\t\t\tif (passphrase_.deleteKey && passphrase_.decrypted.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tlog_debug(MinerLogger::config, \"Passhrase.deleteKey == true, deleting the key...\");\n\t\t\t\t\t\tpassphrase_.key.clear();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!passphrase_.decrypted.empty())\n\t\t\t\t\t\tlog_debug(MinerLogger::config, \"Passphrase decrypted!\");\n\n\t\t\t\t\t// warn the user, he is possibly mining solo without knowing it\n\t\t\t\t\t// and sending his passphrase plain text all around the globe\n\t\t\t\t\tif (!passphrase_.encrypted.empty() && !passphrase_.key.empty())\n\t\t\t\t\t\tlog_warning(MinerLogger::config, \"WARNING! You entered a passphrase, what means you mine solo!\\n\"\n\t\t\t\t\t\t\t\"This means, your passphrase is sent in plain text to 'mining.urls.submission'!\\n\"\n\t\t\t\t\t\t\t\"If you don't want to mine solo, clear 'mining.passphrase' in your configuration file.\");\n\t\t\t\t}\n\n\t\t\t\tif (passphrase_.empty())\n\t\t\t\t\tminingObj->set(\"passphrase\", \"\");\n\t\t\t\telse\n\t\t\t\t\tminingObj->set(\"passphrase\", passphrase_.toString());\n\t\t\t}\n\t\t\tcatch (Poco::Exception& exc)\n\t\t\t{\n\t\t\t\tlog_error(MinerLogger::config,\n\t\t\t\t\t\"Error while reading passphrase in config file!\\n\"\n\t\t\t\t\t\"%s\",\n\t\t\t\t\texc.displayText()\n\t\t\t\t);\n\n\t\t\t\tlog_current_stackframe(MinerLogger::config);\n\t\t\t}\n\t\t}\n\n\t\tconfig->set(\"mining\", miningObj);\n\t}\n\n\t//http_ = config->optValue(\"http\", 1u);\n\tconfirmedDeadlinesPath_ = config->optValue<std::string>(\"confirmed deadlines\", \"\");\n\n\t// server credentials\n\t{\n\t\tauto webserverJson = config->get(\"webserver\");\n\n\t\tPoco::JSON::Object::Ptr webserverObj;\n\n\t\tif (webserverJson.type() == typeid(Poco::JSON::Object::Ptr))\n\t\t\twebserverObj = webserverJson.extract<Poco::JSON::Object::Ptr>();\n\t\telse\n\t\t\twebserverObj.assign(new Poco::JSON::Object);\n\n\t\tstartServer_ = getOrAdd(webserverObj, \"start\", true);\n\t\tcheckCreateUrlFunc(webserverObj, \"url\", urlServer_, \"http\", 8124, \"http://0.0.0.0:8124\", startServer_);\n\t\tmaxConnectionsQueued_ = getOrAdd(webserverObj, \"connectionQueue\", 64u);\n\t\tmaxConnectionsActive_ = getOrAdd(webserverObj, \"activeConnections\", 16u);\n\t\tcumulatePlotsizes_ = getOrAdd(webserverObj, \"cumulatePlotsizes\", true);\n\t\tminerNameForwarding_ = getOrAdd(webserverObj, \"forwardMinerNames\", true);\n\t\tcalculateEveryDeadline_ = getOrAdd(webserverObj, \"calculateEveryDeadline\", false);\n\n\t\t// credentials\n\t\t{\n\t\t\tauto credentialsJson = webserverObj->get(\"credentials\");\n\t\t\tPoco::JSON::Object::Ptr credentials;\n\n\t\t\tconst auto userId = \"user\";\n\t\t\tconst auto passId = \"pass\";\n\n\t\t\tif (!credentialsJson.isEmpty())\n\t\t\t\tcredentials = credentialsJson.extract<Poco::JSON::Object::Ptr>();\n\n\t\t\tif (credentials.isNull())\n\t\t\t{\n\t\t\t\tcredentials.assign(new Poco::JSON::Object);\n\t\t\t\twebserverObj->set(\"credentials\", credentials);\n\t\t\t}\n\n\t\t\tauto serverPass = getOrAdd(credentials, passId, std::string{});\n\t\t\tauto serverUser = getOrAdd(credentials, userId, std::string{});\n\n\t\t\tconst auto getOrHash = [&](std::string& property,\n\t\t\t                           auto propertyJsonId, auto credentialsJsonObject,\n\t\t\t                           const auto& defaultSalt)\n\t\t\t{\n\t\t\t\tauto encryption = Passphrase::fromString(property);\n\n\t\t\t\tif (encryption.isPlainText())\n\t\t\t\t{\n\t\t\t\t\tencryption.encrypt();\n\t\t\t\t}\n\t\t\t\telse if (encryption.salt.empty())\n\t\t\t\t{\n\t\t\t\t\tencryption.salt = defaultSalt;\n\t\t\t\t}\n\n\t\t\t\tcredentialsJsonObject->set(propertyJsonId, encryption.toString());\n\n\t\t\t\treturn encryption;\n\t\t\t};\n\n\t\t\tif (!serverUser.empty())\n\t\t\t\tserverUser_ = getOrHash(serverUser, userId, credentials, \"ms7zKm7QjsSOQEP13wHAWnraSp7yP7YSQdPzAjvO\");\n\n\t\t\tif (!serverPass.empty())\n\t\t\t\tserverPass_ = getOrHash(serverPass, passId, credentials, \"CAAwj6RTQqXZGxbNjLVqr5FwAqT7GM9Y1wppNLRp\");\n\t\t}\n\n\t\t// forwarding\n\t\t{\n\t\t\tconst Poco::JSON::Array::Ptr arr(new Poco::JSON::Array);\n\t\t\tauto forwardUrls = getOrAddExtract(webserverObj, \"forwardUrls\", arr);\n\n\t\t\tfor (const auto& url : *forwardUrls)\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tforwardingWhitelist_.emplace_back(url.extract<std::string>());\n\t\t\t\t}\n\t\t\t\tcatch (...)\n\t\t\t\t{\n\t\t\t\t\tlog_error(MinerLogger::config, \"Invalid forwarding rule in config: %s\", url.toString());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// certificate\n\t\t{\n\t\t\tauto certificateJson = webserverObj->get(\"certificate\");\n\t\t\tPoco::JSON::Object::Ptr certificate;\n\n\t\t\tif (!certificateJson.isEmpty())\n\t\t\t\tcertificate = certificateJson.extract<Poco::JSON::Object::Ptr>();\n\n\t\t\tif (certificate.isNull())\n\t\t\t{\n\t\t\t\tcertificate.assign(new Poco::JSON::Object);\n\t\t\t\tcertificate->set(\"path\", \"\");\n\t\t\t\tcertificate->set(\"pass\", \"\");\n\t\t\t\twebserverObj->set(\"certificate\", certificate);\n\t\t\t}\n\n\t\t\tserverCertificatePath_ = getOrAdd(certificate, \"path\", std::string{});\n\t\t\tserverCertificatePass_ = getOrAdd(certificate, \"pass\", std::string{});\n\n\t\t\tif (!serverCertificatePass_.empty())\n\t\t\t{\n\t\t\t\tauto encryption = Passphrase::fromString(serverCertificatePass_);\n\n\t\t\t\tif (encryption.algorithm.empty())\n\t\t\t\t\tencryption.algorithm = \"aes-256-cbc\";\n\n\t\t\t\tif (encryption.isPlainText())\n\t\t\t\t\tencryption.encrypt();\n\n\t\t\t\tcertificate->set(\"pass\", encryption.toString());\n\t\t\t}\n\t\t}\n\n\t\tconfig->set(\"webserver\", webserverObj);\n\n\t\t// warning message, when webserver is running in unsafe mode\n\t\tif ((serverUser_.empty() || serverPass_.empty()) && startServer_)\n\t\t\tlog_warning(MinerLogger::config,\n\t\t\t\t\"You are running the webserver without protecting it with an username and/or password!\\n\"\n\t\t\t\t\"Every person with access to the webserver has FULL admin rights!\");\n\n\t\tMinerLogger::refreshChannels();\n\t}\n\n\tif (!save(configPath_, *config))\n\t\tlog_error(MinerLogger::config, \"Could not save new settings!\");\n\n\treturn ReadConfigFileResult::Ok;\n}\n\nconst std::string& Burst::MinerConfig::getPath() const\n{\n\treturn configPath_;\n}\n\nstd::vector<std::shared_ptr<Burst::PlotFile>> Burst::MinerConfig::getPlotFiles() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tstd::vector<std::shared_ptr<Burst::PlotFile>> plotFiles;\n\n\tfor (auto& plotDir : plotDirs_)\n\t{\n\t\tauto plotDirFiles = plotDir->getPlotfiles();\n\n\t\tplotFiles.insert(plotFiles.end(), plotDirFiles.begin(), plotDirFiles.end());\n\n\t\tfor (const auto& relatedDir : plotDir->getRelatedDirs())\n\t\t{\n\t\t\tauto relatedPlotDirFiles = relatedDir->getPlotfiles();\n\t\t\tplotFiles.insert(plotFiles.end(), relatedPlotDirFiles.begin(), relatedPlotDirFiles.end());\n\t\t}\n\t}\n\n\treturn plotFiles;\n}\n\nuintmax_t Burst::MinerConfig::getTotalPlotsize() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tPoco::UInt64 sum = 0;\n\n\tfor (const auto& plotDir : plotDirs_)\n\t{\n\t\tsum += plotDir->getSize();\n\n\t\tfor (const auto& relatedDir : plotDir->getRelatedDirs())\n\t\t\tsum += relatedDir->getSize();\n\t}\n\n\treturn sum;\n}\n\nfloat Burst::MinerConfig::getReceiveTimeout() const\n{\n\treturn getTimeout();\n}\n\nfloat Burst::MinerConfig::getSendTimeout() const\n{\n\treturn getTimeout();\n}\n\nfloat Burst::MinerConfig::getTimeout() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn timeout_;\n}\n\ndouble Burst::MinerConfig::getTargetDLFactor() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn targetDlFactor_;\n}\n\ndouble Burst::MinerConfig::getDeadlinePerformanceFac() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn deadlinePerformanceFac_;\n}\n\ndouble Burst::MinerConfig::getSubmitProbability() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn submitProbability_;\n}\n\nBurst::Url Burst::MinerConfig::getPoolUrl() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn urlPool_;\n}\n\nconst std::vector<Burst::Url>& Burst::MinerConfig::getPoolUrlAlt() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn urlPoolAlt_;\n}\n\nBurst::Url Burst::MinerConfig::getMiningInfoUrl() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn urlMiningInfo_;\n}\n\nconst std::vector<Burst::Url>& Burst::MinerConfig::getMiningInfoUrlAlt() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn urlMiningInfoAlt_;\n}\n\nBurst::Url Burst::MinerConfig::getWalletUrl() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn urlWallet_;\n}\n\nstd::string Burst::MinerConfig::getProxyFullUrl() const\n{\n\tPoco::Mutex::ScopedLock lock{mutex_};\n\n\tif (proxyUser_.empty())\n\t\treturn \"\";\n\n\tstd::stringstream sstream;\n\n\tif (!proxyUser_.empty())\n\t{\n\t\tsstream << proxyUser_.toString();\n\t\t\n\t\tif (!proxyPassword_.empty())\n\t\t\tsstream << '&' << proxyPassword_.toString();\n\n\t\tsstream << '@';\n\t}\n\n\tsstream << proxyIp_ << ':' << proxyPort_;\n\n\treturn sstream.str(); \n}\n\nPoco::Net::HTTPClientSession::ProxyConfig Burst::MinerConfig::getProxyConfig() const\n{\n\tPoco::Net::HTTPClientSession::ProxyConfig proxyConfig;\n\n\tif (proxyIp_.empty() || proxyPort_ == 0)\n\t\treturn proxyConfig;\n\n\tproxyConfig.host = proxyIp_;\n\tproxyConfig.port = proxyPort_;\n\n\tif (!proxyUser_.empty())\n\t{\n\t\tauto passphrase = proxyUser_;\n\t\tproxyConfig.username = passphrase.decrypt();\n\t}\n\n\tif (!proxyPassword_.empty())\n\t{\n\t\tauto passphrase = proxyPassword_;\n\t\tproxyConfig.password = passphrase.decrypt();\n\t}\n\n\treturn proxyConfig;\n}\n\nunsigned Burst::MinerConfig::getReceiveMaxRetry() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn receiveMaxRetry_;\n}\n\nunsigned Burst::MinerConfig::getSendMaxRetry() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn sendMaxRetry_;\n}\n\nunsigned Burst::MinerConfig::getSubmissionMaxRetry() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn submissionMaxRetry_;\n}\n\nunsigned Burst::MinerConfig::getHttp() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn http_;\n}\n\nconst std::string& Burst::MinerConfig::getConfirmedDeadlinesPath() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn confirmedDeadlinesPath_;\n}\n\nbool Burst::MinerConfig::getStartServer() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn startServer_;\n}\n\nconst std::string& Burst::MinerConfig::getServerCertificatePath() const\n{\n\treturn serverCertificatePath_;\n}\n\nconst std::string& Burst::MinerConfig::getServerCertificatePass() const\n{\n\treturn serverCertificatePass_;\n}\n\nconst std::string& Burst::MinerConfig::getDatabasePath() const\n{\n\treturn databasePath_;\n}\n\nconst std::string& Burst::MinerConfig::getWorkerName() const\n{\n\treturn workerName_;\n}\n\nPoco::UInt64 Burst::MinerConfig::getTargetDeadline(TargetDeadlineType type) const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tswitch (type)\n\t{\n\tcase TargetDeadlineType::Pool:\n\t\treturn targetDeadlinePool_;\n\tcase TargetDeadlineType::Local:\n\t\treturn targetDeadline_;\n\tcase TargetDeadlineType::Combined:\n\t{\n\t\tauto targetDeadline = targetDeadlinePool_;\n\t\tconst auto manualTargetDeadline = targetDeadline_;\n\n\t\tif (targetDeadline == 0)\n\t\t\ttargetDeadline = manualTargetDeadline;\n\t\telse if (targetDeadline > manualTargetDeadline &&\n\t\t\tmanualTargetDeadline > 0)\n\t\t\ttargetDeadline = manualTargetDeadline;\n\n\t\treturn targetDeadline;\n\t}\n\tdefault:\n\t\treturn 0;\n\t}\n}\n\nBurst::Url Burst::MinerConfig::getServerUrl() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn urlServer_;\n}\n\nstd::unique_ptr<Poco::Net::HTTPClientSession> Burst::MinerConfig::createSession(HostType hostType) const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tconst Url* url;\n\n\tif (hostType == HostType::Pool)\n\t\turl = &urlPool_;\n\telse if (hostType == HostType::MiningInfo)\n\t\turl = &urlMiningInfo_;\n\telse if (hostType == HostType::Wallet)\n\t\turl = &urlWallet_;\n\telse\n\t\turl = nullptr;\n\n\tif (url == nullptr)\n\t\treturn nullptr;\n\n\treturn createSession(*url);\n}\n\nstd::unique_ptr<Poco::Net::HTTPClientSession> Burst::MinerConfig::createSession(const Url& url) const\n{\n\tif (!url.empty())\n\t{\n\t\tauto session = url.createSession();\n\t\tsession->setTimeout(secondsToTimespan(getTimeout()));\n\t\treturn session;\n\t}\n\n\treturn nullptr;\n}\n\nBurst::MinerConfig& Burst::MinerConfig::getConfig()\n{\n\tstatic MinerConfig config;\n\treturn config;\n}\n\nPoco::JSON::Object::Ptr Burst::MinerConfig::readOutput(Poco::JSON::Object::Ptr json)\n{\n\tif (json.isNull())\n\t\treturn nullptr;\n\n\tfor (auto& output : OutputHelper::outputNames)\n\t{\n\t\tconst auto id = output.first;\n\t\tconst auto name = output.second;\n\n\t\tauto obj = json->get(name);\n\n\t\tif (!obj.isEmpty() && obj.isBoolean())\n\t\t\tMinerLogger::setOutput(id, obj.extract<bool>());\n\t\telse\n\t\t\tjson->set(name, MinerLogger::hasOutput(id));\n\t}\n\n\treturn json;\n}\n\nunsigned Burst::MinerConfig::getMiningIntensity(bool real) const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tif (!real)\n\t\treturn miningIntensity_;\n\n\tif (miningIntensity_ == 0)\n\t\treturn getMaxPlotReaders(true);\n\n\treturn miningIntensity_;\n}\n\nbool Burst::MinerConfig::forPlotDirs(const std::function<bool(PlotDir&)>& traverseFunction) const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tauto success = true;\n\n\tfor (auto iter = plotDirs_.begin();\n\t\titer != plotDirs_.end() && success;\n\t\t++iter)\n\t{\n\t\tsuccess = traverseFunction(**iter);\n\t}\n\n\treturn success;\n}\n\n//const std::string& Burst::MinerConfig::getPlotsHash() const\n//{\n//\tPoco::Mutex::ScopedLock lock{ mutex_ };\n//\treturn plotsHash_;\n//}\n\nconst std::string& Burst::MinerConfig::getPassphrase() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn passphrase_.decrypted;\n}\n\nunsigned Burst::MinerConfig::getMaxPlotReaders(bool real) const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\t// if maxPlotReaders is zero it means we have to set it to\n\t// the amount of active plot dirs\n\tif (maxPlotReaders_ == 0 && real)\n\t{\n\t\tunsigned notEmptyPlotdirs = 0;\n\n\t\t// count only the plotdirs that are not empty\n\t\tfor (const auto& plotDir : plotDirs_)\n\t\t\tif (!plotDir->getPlotfiles().empty())\n\t\t\t\t++notEmptyPlotdirs;\n\n\t\treturn notEmptyPlotdirs;\n\t}\n\n\treturn maxPlotReaders_;\n}\n\nPoco::Path Burst::MinerConfig::getPathLogfile() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn pathLogfile_;\n}\n\nstd::string Burst::MinerConfig::getLogDir() const\n{\n\treturn Poco::Path(getPathLogfile().parent()).toString();\n}\n\nconst Burst::Passphrase& Burst::MinerConfig::getServerUser() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn serverUser_;\n}\n\nconst Burst::Passphrase& Burst::MinerConfig::getServerPass() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn serverPass_;\n}\n\nvoid Burst::MinerConfig::setUrl(const std::string& url, const HostType hostType)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tUrl* uri;\n\n\tswitch (hostType)\n\t{\n\tcase HostType::MiningInfo: uri = &urlMiningInfo_; break;\n\tcase HostType::Pool: uri = &urlPool_; break;\n\tcase HostType::Wallet: uri = &urlWallet_; break;\n\tcase HostType::Server: uri = &urlServer_; break;\n\tdefault: uri = nullptr;\n\t}\n\n\tif (uri != nullptr)\n\t{\n\t\t*uri = Url(url); // change url\n\t\t//printUrl(hostType); // print url\n\t}\n}\n\nvoid Burst::MinerConfig::setBufferSize(Poco::UInt64 bufferSize)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tmaxBufferSizeMb_ = bufferSize;\n}\n\nvoid Burst::MinerConfig::setMaxSubmissionRetry(unsigned value)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tsubmissionMaxRetry_ = value;\n}\n\nvoid Burst::MinerConfig::setTimeout(float value)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\ttimeout_ = value;\n}\n\nvoid Burst::MinerConfig::setMaxHistoricalBlocks(Poco::UInt64 maxHistData)\n{\n\tif (maxHistData < 30)\n\t\tmaxHistoricalBlocks_ = 30;\n\telse if (maxHistData > 3600)\n\t\tmaxHistoricalBlocks_ = 3600;\n\telse\n\t\tmaxHistoricalBlocks_ = maxHistData;\n}\n\nvoid Burst::MinerConfig::setSubmitProbability(double subP)\n{\n\tif (subP < 0)\n\t\tsubmitProbability_ = 0;\n\telse if (subP >=0.999999)\n\t\tsubmitProbability_ = 0.999999;\n\telse\n\t\tsubmitProbability_ = subP;\n\n\tif (submitProbability_ > 0)\n\t\tdeadlinePerformanceFac_ = (1.0 + (1.0 - subP) / subP * log(1.0 - subP)) * 240.0;\n\telse\n\t\tdeadlinePerformanceFac_ = 1.0 * 240.0;\n\n\ttargetDlFactor_ = -log(1.0 - submitProbability_) * 240.0;\n}\n\n\nvoid Burst::MinerConfig::setTargetDeadline(const std::string& target_deadline, TargetDeadlineType type)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tsetTargetDeadline(formatDeadline(target_deadline), type);\n}\n\nvoid Burst::MinerConfig::setTargetDeadline(Poco::UInt64 target_deadline, TargetDeadlineType type)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tif (type == TargetDeadlineType::Local)\n\t\ttargetDeadline_ = target_deadline;\n\telse if (type == TargetDeadlineType::Pool)\n\t\ttargetDeadlinePool_ = target_deadline;\n}\n\nPoco::UInt64 Burst::MinerConfig::getMaxBufferSize() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tif (maxBufferSizeMb_ == 0)\n\t{\n\t\tPoco::UInt64 maxSize = 0;\n\n\t\tfor (const auto& plot : getPlotFiles())\n\t\t\tif (plot->getStaggerScoopBytes() > maxSize)\n\t\t\t\tmaxSize = plot->getStaggerScoopBytes();\n\n\t\treturn maxSize * getBufferChunkCount();\n\t}\n\n\treturn maxBufferSizeMb_ * 1024 * 1024;\n}\n\nPoco::UInt64 Burst::MinerConfig::getMaxBufferSizeRaw() const\n{\n\treturn maxBufferSizeMb_;\n}\n\nPoco::UInt64 Burst::MinerConfig::getMaxHistoricalBlocks() const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\treturn maxHistoricalBlocks_;\n}\n\nvoid Burst::MinerConfig::setMininigIntensity(unsigned intensity)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tminingIntensity_ = intensity;\n\tlog_system(MinerLogger::config, \"\", intensity);\n}\n\nvoid Burst::MinerConfig::setMaxPlotReaders(unsigned max_reader)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tmaxPlotReaders_ = max_reader;\n}\n\nunsigned Burst::MinerConfig::getWalletRequestTries() const\n{\n\treturn walletRequestTries_;\n}\n\nunsigned Burst::MinerConfig::getWalletRequestRetryWaitTime() const\n{\n\treturn walletRequestRetryWaitTime_;\n}\n\nunsigned Burst::MinerConfig::getWakeUpTime() const\n{\n\treturn wakeUpTime_;\n}\n\nconst std::string& Burst::MinerConfig::getCpuInstructionSet() const\n{\n\treturn cpuInstructionSet_;\n}\n\nconst std::string& Burst::MinerConfig::getProcessorType() const\n{\n\treturn processorType_;\n}\n\nunsigned Burst::MinerConfig::getGpuPlatform() const\n{\n\treturn gpuPlatform_;\n}\n\nunsigned Burst::MinerConfig::getGpuDevice() const\n{\n\treturn gpuDevice_;\n}\n\nvoid Burst::MinerConfig::printTargetDeadline() const\n{\n\tif (getTargetDeadline() > 0)\n\t\tlog_system(MinerLogger::config, \"Target deadline : %s\", deadlineFormat(getTargetDeadline(TargetDeadlineType::Local)));\n}\n\nvoid Burst::MinerConfig::printSubmitProbability() const\n{\n\t\tlog_system(MinerLogger::config, \"Submit probability : %s\", numberToString(getSubmitProbability()));\n}\n\nbool Burst::MinerConfig::save() const\n{\n\treturn save(configPath_);\n}\n\nbool Burst::MinerConfig::save(const std::string& path) const\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tPoco::JSON::Object json;\n\n\t// logging\n\t{\n\t\t// logger\n\t\tPoco::JSON::Object logging;\n\n\t\tfor (auto& priority : MinerLogger::getChannelPriorities())\n\t\t\tlogging.set(priority.first, priority.second);\n\n\t\t// output\n\t\tPoco::JSON::Object outputs;\n\n\t\tfor (auto& output : MinerLogger::getOutput())\n\t\t\toutputs.set(OutputHelper::outputToString(output.first), output.second);\n\n\t\tlogging.set(\"output\", outputs);\n\n\t\tlogging.set(\"path\", getLogDir());\n\t\tlogging.set(\"logfile\", isLogfileUsed());\n\t\tlogging.set(\"useColors\", isUsingLogColors());\n\n\t\t// output type\n\t\tif (logOutputType_ == LogOutputType::Terminal)\n\t\t\tlogging.set(\"outputType\", \"terminal\");\n\t\telse if (logOutputType_ == LogOutputType::Service)\n\t\t\tlogging.set(\"outputType\", \"service\");\n\t\telse\n\t\t\tlogging.set(\"outputType\", \"terminal\");\n\n\n\t\t// progress bar\n\t\t{\n\t\t\tPoco::JSON::Object progressBar;\n\t\t\tprogressBar.set(\"steady\", isSteadyProgressBar());\n\t\t\tprogressBar.set(\"fancy\", isFancyProgressBar());\n\t\t\tlogging.set(\"progressBar\", progressBar);\n\t\t}\n\n\t\tjson.set(\"logging\", logging);\n\t}\n\n\t// mining\n\t{\n\t\tPoco::JSON::Object mining;\n\n\t\t// miningInfoInterval\n\t\tmining.set(\"getMiningInfoInterval\", getMiningInfoInterval());\n\t\tmining.set(\"intensity\", miningIntensity_);\n\t\tmining.set(\"maxBufferSizeMB\", maxBufferSizeMb_);\n\t\tmining.set(\"maxPlotReaders\", maxPlotReaders_);\n\t\tmining.set(\"submissionMaxRetry\", submissionMaxRetry_);\n\t\tmining.set(\"maxHistoricalBlocks\", maxHistoricalBlocks_);\n\t\tmining.set(\"submitProbability\", submitProbability_);\n\t\tmining.set(\"targetDeadline\", deadlineFormat(targetDeadline_));\n\t\tmining.set(\"timeout\", static_cast<Poco::UInt64>(timeout_));\n\t\tmining.set(\"walletRequestRetryWaitTime\", walletRequestRetryWaitTime_);\n\t\tmining.set(\"walletRequestTries\", walletRequestTries_);\n\t\tmining.set(\"useInsecurePlotfiles\", useInsecurePlotfiles());\n\t\tmining.set(\"rescanEveryBlock\", isRescanningEveryBlock());\n\t\tmining.set(\"bufferChunkCount\", getBufferChunkCount());\n\t\tmining.set(\"wakeUpTime\", getWakeUpTime());\n\t\tmining.set(\"cpuInstructionSet\", getCpuInstructionSet());\n\t\tmining.set(\"processorType\", getProcessorType());\n\t\tmining.set(\"gpuDevice\", getGpuDevice());\n\t\tmining.set(\"gpuPlatform\", getGpuPlatform());\n\t\tmining.set(\"databasePath\", getDatabasePath());\n\t\tmining.set(\"workerName\", getWorkerName());\n\n\t\t// passphrase\n\t\t{\n\t\t\tPoco::JSON::Object passphrase;\n\t\t\tpassphrase.set(\"algorithm\", passphrase_.algorithm);\n\t\t\tpassphrase.set(\"decrypted\", \"\"); // don't leak it\n\t\t\tpassphrase.set(\"deleteKey\", passphrase_.deleteKey);\n\t\t\tpassphrase.set(\"encrypted\", passphrase_.encrypted);\n\t\t\tpassphrase.set(\"iterations\", passphrase_.iterations);\n\t\t\tpassphrase.set(\"encrypted\", passphrase_.encrypted);\n\t\t\tpassphrase.set(\"key\", passphrase_.deleteKey ? \"\" : passphrase_.key);\n\t\t\tpassphrase.set(\"salt\", passphrase_.salt);\n\t\t\tmining.set(\"passphrase\", passphrase);\n\t\t}\n\n\t\t// plots\n\t\t{\n\t\t\tPoco::JSON::Array plots;\n\t\t\tfor (auto& plotDir : plotDirs_)\n\t\t\t\tplots.add(plotDir->getPath());\n\t\t\tmining.set(\"plots\", plots);\n\t\t}\n\n\t\t// urls\n\t\t{\n\t\t\tPoco::JSON::Object urls;\n\t\t\turls.set(\"miningInfo\", urlMiningInfo_.getUri().toString());\n\t\t\turls.set(\"submission\", urlPool_.getUri().toString());\n\t\t\turls.set(\"wallet\", urlWallet_.getUri().toString());\n\t\t\turls.set(\"proxy\", getProxyFullUrl());\n\t\t\tmining.set(\"urls\", urls);\n\t\t}\n\n\t\tjson.set(\"mining\", mining);\n\t}\n\n\t// webserver\n\t{\n\t\tPoco::JSON::Object webserver;\n\n\t\t// credentials\n\t\t{\n\t\t\tPoco::JSON::Object credentials;\n\t\t\tcredentials.set(\"pass\", serverPass_.empty() ? \"\" : serverPass_.toString());\n\t\t\tcredentials.set(\"user\", serverUser_.empty() ? \"\" : serverUser_.toString());\n\t\t\twebserver.set(\"credentials\", credentials);\n\t\t}\n\n\t\twebserver.set(\"start\", startServer_);\n\t\twebserver.set(\"activeConnections\", getMaxConnectionsActive());\n\t\twebserver.set(\"calculateEveryDeadline\", isCalculatingEveryDeadline());\n\t\twebserver.set(\"connectionQueue\", getMaxConnectionsQueued());\n\t\twebserver.set(\"cumulatePlotsizes\", isCumulatingPlotsizes());\n\t\twebserver.set(\"forwardMinerNames\", isForwardingMinerName());\n\t\twebserver.set(\"url\", urlServer_.getUri().toString());\n\n\t\t// forwardUrls\n\t\t{\n\t\t\tPoco::JSON::Array forwardUrls;\n\t\t\tfor (const auto& forward : getForwardingWhitelist())\n\t\t\t\tforwardUrls.add(forward);\n\t\t\twebserver.set(\"forwardUrls\", forwardUrls);\n\t\t}\n\n\t\t// certificate\n\t\t{\n\t\t\tPoco::JSON::Object certificate;\n\t\t\tcertificate.set(\"path\", getServerCertificatePath());\n\t\t\tcertificate.set(\"pass\", getServerCertificatePass());\n\t\t\twebserver.set(\"certificate\", certificate);\n\t\t}\n\n\t\tjson.set(\"webserver\", webserver);\n\t}\n\n\treturn save(path, json);\n}\n\nbool Burst::MinerConfig::save(const std::string& path, const Poco::JSON::Object& json)\n{\n\ttry\n\t{\n\t\tstd::ofstream outputFileStream {path};\n\n\t\tstd::stringstream sstr;\n\t\tjson.stringify(sstr, 4);\n\t\tauto outJsonStr = sstr.str();\n\n\t\tPoco::replaceInPlace(outJsonStr, \"\\\\/\", \"/\");\n\n\t\tif (outputFileStream.is_open())\n\t\t{\n\t\t\toutputFileStream << outJsonStr << std::flush;\n\t\t\toutputFileStream.close();\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_exception(MinerLogger::config, exc);\n\t\treturn false;\n\t}\n\tcatch (std::exception& exc)\n\t{\n\t\tlog_error(MinerLogger::config, \"Exception: %s\", std::string(exc.what()));\n\t\treturn false;\n\t}\n}\n\nbool Burst::MinerConfig::isCalculatingEveryDeadline() const\n{\n\treturn calculateEveryDeadline_;\n}\n\nbool Burst::MinerConfig::isForwardingEverything() const\n{\n\treturn forwardingWhitelist_.empty();\n}\n\nconst std::vector<std::string>& Burst::MinerConfig::getForwardingWhitelist() const\n{\n\treturn forwardingWhitelist_;\n}\n\nbool Burst::MinerConfig::isCumulatingPlotsizes() const\n{\n\treturn cumulatePlotsizes_;\n}\n\nunsigned Burst::MinerConfig::getMaxConnectionsQueued() const\n{\n\treturn maxConnectionsQueued_;\n}\n\nunsigned Burst::MinerConfig::getMaxConnectionsActive() const\n{\n\treturn maxConnectionsActive_;\n}\n\nbool Burst::MinerConfig::addPlotDir(std::shared_ptr<PlotDir> plotDir)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tconst auto iter = std::find_if(plotDirs_.begin(), plotDirs_.end(), [&](const std::shared_ptr<PlotDir>& element)\n\t{\n\t\treturn element->getPath() == plotDir->getPath() ||\n\t\t\telement->getHash() == plotDir->getHash();\n\t});\n\n\t// same plotdir already in collection\n\tif (iter != plotDirs_.end())\n\t\tthrow Poco::Exception{Poco::format(\"The plotfile/dir %s already exists!\", plotDir->getPath())};\n\n\tplotDirs_.emplace_back(plotDir);\n\treturn true;\n}\n\nvoid Burst::MinerConfig::setLogDir(const std::string& log_dir)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tauto logDirAndFile = MinerLogger::setLogDir(log_dir);\n\tpathLogfile_ = logDirAndFile;\n\n\tif (!logfile_)\n\t{\n\t\t// remove the logfile\n\t\tPoco::File file{ logDirAndFile };\n\n\t\tif (file.exists())\n\t\t\tfile.remove();\n\n\t\t// refresh the channels\n\t\tMinerLogger::refreshChannels();\n\n\t\tlog_debug(MinerLogger::config, \"Logfile deactivated\");\n\t}\n\telse if (logDirAndFile.empty())\n\t\tlog_warning(MinerLogger::config, \"Could not create logfile\");\n\telse\n\t\tlog_system(MinerLogger::config, \"Changed logfile path to\\n\\t%s\", logDirAndFile);\n}\n\nvoid Burst::MinerConfig::setGetMiningInfoInterval(unsigned interval)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tgetMiningInfoInterval_ = interval;\n}\n\nvoid Burst::MinerConfig::setBufferChunkCount(unsigned bufferChunkCount)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tbufferChunkCount_ = bufferChunkCount;\n}\n\nvoid Burst::MinerConfig::setPoolTargetDeadline(Poco::UInt64 targetDeadline)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\ttargetDeadlinePool_ = targetDeadline;\n}\n\nvoid Burst::MinerConfig::setProcessorType(const std::string& processorType)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tprocessorType_ = processorType;\n}\n\nvoid Burst::MinerConfig::setCpuInstructionSet(const std::string& instructionSet)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tcpuInstructionSet_ = instructionSet;\n}\n\nvoid Burst::MinerConfig::setGpuPlatform(const unsigned platformIndex)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tgpuPlatform_ = platformIndex;\n}\n\nvoid Burst::MinerConfig::setGpuDevice(const unsigned deviceIndex)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tgpuDevice_ = deviceIndex;\n}\n\nvoid Burst::MinerConfig::setPlotDirs(const std::vector<std::string>& plotDirs)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tplotDirs_.clear();\n\tfor (const auto& plotDir : plotDirs)\n\t\taddPlotDir(plotDir);\n}\n\nvoid Burst::MinerConfig::setWebserverUri(const std::string& uri)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\turlServer_ = uri;\n}\n\nvoid Burst::MinerConfig::setProgressbar(bool fancy, bool steady)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tfancyProgressBar_ = fancy;\n\tsteadyProgressBar_ = steady;\n}\n\nvoid Burst::MinerConfig::setPassphrase(const std::string& passphrase)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tpassphrase_.decrypted = passphrase;\n\tpassphrase_.encrypt();\n}\n\nvoid Burst::MinerConfig::setWebserverCredentials(const std::string& user, const std::string& pass)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tserverUser_.decrypted = user;\n\tserverPass_.decrypted = pass;\n\n\tserverUser_.encrypt();\n\tserverPass_.encrypt();\n}\n\nvoid Burst::MinerConfig::setStartWebserver(bool start)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\tstartServer_ = start;\n}\n\nvoid Burst::MinerConfig::setDatabasePath(std::string databasePath)\n{\n\tdatabasePath_ = std::move(databasePath);\n}\n\nbool Burst::MinerConfig::addPlotDir(const std::string& dir)\n{\n\treturn addPlotDir(std::make_shared<PlotDir>(Poco::replace(dir, \"\\\\\", \"/\"), PlotDir::Type::Sequential));\n}\n\nbool Burst::MinerConfig::removePlotDir(const std::string& dir)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tconst auto normalizedPath = Poco::replace(dir, \"\\\\\", \"/\");\n\n\tconst auto iter = std::find_if(plotDirs_.begin(), plotDirs_.end(), [&](const std::shared_ptr<PlotDir>& element)\n\t{\n\t\t// TODO: look in Burst::MinerConfig::addPlotDir\n\t\treturn element->getPath() == normalizedPath;\n\t});\n\n\tif (iter == plotDirs_.end())\n\t\tthrow Poco::Exception{Poco::format(\"The plot dir '%s' does not exist\", dir)};\n\n\tplotDirs_.erase(iter);\n\treturn true;\n}\n\nstd::string Burst::Passphrase::toString() const\n{\n\tstd::stringstream sstream;\n\t\n\tif (isOneWayHash())\n\t\tsstream <<\n\t\t\tdelimiter << salt <<\n\t\t\tdelimiter << encrypted;\n\telse\n\t\tsstream <<\n\t\t\tdelimiter << algorithm <<\n\t\t\tdelimiter << iterations <<\n\t\t\tdelimiter << salt <<\n\t\t\tdelimiter << key <<\n\t\t\tdelimiter << encrypted;\n\n\treturn sstream.str();\t\n}\n\nbool Burst::Passphrase::isOneWayHash() const\n{\n\treturn algorithm.empty() && key.empty();\n}\n\nbool Burst::Passphrase::isTwoWayHash() const\n{\n\treturn !isOneWayHash();\n}\n\nbool Burst::Passphrase::isEncrypted() const\n{\n\treturn !encrypted.empty();\n}\n\nbool Burst::Passphrase::isPlainText() const\n{\n\treturn !decrypted.empty();\n}\n\nbool Burst::Passphrase::check(const std::string& plainText) const\n{\n\t// if there is no hash\n\tif (encrypted.empty())\n\t\t// there is no password\n\t\treturn plainText.empty();\n\n\tPassphrase toCheck;\n\ttoCheck.algorithm = algorithm;\n\ttoCheck.iterations = iterations;\n\ttoCheck.salt = salt;\n\ttoCheck.decrypted = plainText;\n\treturn toCheck.encrypt() == encrypted;\n}\n\nbool Burst::Passphrase::empty() const\n{\n\treturn decrypted.empty() && encrypted.empty();\n}\n\nBurst::Passphrase Burst::Passphrase::fromString(const std::string& string)\n{\n\tstd::smatch match;\n\tPassphrase passphrase{};\n\n\tif (std::regex_match(string, match, std::regex{\"::::(.*)::::(.*)::::(.*)::::(.*)::::(.*)\"}))\n\t{\n\t\tpassphrase.algorithm = match[1].str();\n\t\tpassphrase.iterations = Poco::NumberParser::parse(match[2].str());\n\t\tpassphrase.salt = match[3].str();\n\t\tpassphrase.key = match[4].str();\n\t\tpassphrase.encrypted = match[5].str();\n\t}\n\telse if (std::regex_match(string, match, std::regex{\"::::(.*)::::(.*)\"}))\n\t{\n\t\tpassphrase.salt = match[1].str();\n\t\tpassphrase.encrypted = match[2].str();\n\t}\n\telse if (std::regex_match(string, match, std::regex{\"::::(.*)\"}))\n\t{\n\t\tpassphrase.encrypted = match[1].str();\n\t}\n\telse\n\t{\n\t\tpassphrase.decrypted = string;\n\t}\n\n\treturn passphrase;\n}\n\nstd::string Burst::Passphrase::createSalt(size_t length)\n{\n\tstd::stringstream sstream;\n\tPoco::Random random;\n\trandom.seed();\n\n\tfor (size_t i = 0; i < length; ++i)\n\t\tsstream << random.nextChar();\n\n\treturn toHex(sstream.str());\n}\n\nconst std::string& Burst::Passphrase::decrypt()\n{\n\tif (isTwoWayHash())\n\t\tdecrypted = Burst::decrypt(encrypted, algorithm, key, salt, iterations);\n\n\treturn decrypted;\n}\n\nconst std::string& Burst::Passphrase::encrypt()\n{\n\tif (salt.empty())\n\t\tsalt = createSalt();\n\n\tif (isOneWayHash())\n\t\tencrypted = hashHmacSha1(decrypted, salt);\n\n\tif (isTwoWayHash())\n\t{\n\t\tif (algorithm.empty())\n\t\t\talgorithm = \"aes-256-cbc\";\n\n\t\tif (key.empty())\n\t\t\tkey = createSalt();\n\n\t\tif (iterations == 0)\n\t\t\titerations = 1000;\n\t\t\n\t\tconst Poco::Crypto::CipherKey cipherKey(algorithm, key, salt, iterations);\n\t\tauto& factory = Poco::Crypto::CipherFactory::defaultFactory();\n\t\tauto cipher = factory.createCipher(cipherKey);\n\t\t\n\t\tencrypted = cipher->encryptString(decrypted, Poco::Crypto::Cipher::ENC_BINHEX_NO_LF);\n\t}\n\n\tdecrypted.clear();\n\n\treturn encrypted;\n}\n\nbool Burst::MinerConfig::useInsecurePlotfiles() const\n{\n\treturn useInsecurePlotfiles_;\n}\n\nbool Burst::MinerConfig::isLogfileUsed() const\n{\n\treturn logfile_;\n}\n\nunsigned Burst::MinerConfig::getMiningInfoInterval() const\n{\n\treturn getMiningInfoInterval_;\n}\n\nbool Burst::MinerConfig::isRescanningEveryBlock() const\n{\n\treturn rescanEveryBlock_;\n}\n\nBurst::LogOutputType Burst::MinerConfig::getLogOutputType() const\n{\n\treturn logOutputType_;\n}\n\nbool Burst::MinerConfig::isUsingLogColors() const\n{\n\treturn logUseColors_;\n}\n\nbool Burst::MinerConfig::isSteadyProgressBar() const\n{\n\treturn steadyProgressBar_;\n}\n\nbool Burst::MinerConfig::isFancyProgressBar() const\n{\n\treturn fancyProgressBar_;\n}\n\nunsigned Burst::MinerConfig::getBufferChunkCount() const\n{\n\treturn bufferChunkCount_;\n}\n\nvoid Burst::MinerConfig::useLogfile(bool use)\n{\n\tPoco::Mutex::ScopedLock lock(mutex_);\n\n\tif (logfile_ == use)\n\t\treturn;\n\n\t// do we use a logfile?\n\tlogfile_ = use;\n\n\t// refresh the log channels\n\t// because we need to open or close the filechannel\n\tMinerLogger::refreshChannels();\n}\n\nbool Burst::MinerConfig::isForwardingMinerName() const\n{\n\treturn minerNameForwarding_;\n}\n\nPoco::UInt64 Burst::MinerConfig::getPoc2StartBlock() const\n{\n\treturn poc2StartBlock_;\n}\n\nbool Burst::MinerConfig::isVerboseLogging() const\n{\n\treturn verboseLogging_;\n}\n"
  },
  {
    "path": "src/mining/MinerConfig.hpp",
    "content": "// ==========================================================================\n//\n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n//\n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n//\n// ==========================================================================\n\n#pragma once\n\n#include <memory>\n#include <vector>\n#include <Poco/Net/HTTPClientSession.h>\n#include \"network/Url.hpp\"\n#include <Poco/Path.h>\n#include <Poco/JSON/Object.h>\n#include <functional>\n#include \"Declarations.hpp\"\n#include <chrono>\n\nnamespace Poco\n{\n\tclass File;\n}\n\nnamespace Burst\n{\n\tclass PlotDir;\n\tclass PlotFile;\n\tclass MinerData;\n\n\tenum class HostType\n\t{\n\t\tPool,\n\t\tWallet,\n\t\tMiningInfo,\n\t\tMiningInfoAlts,\n\t\tServer\n\t};\n\n\tenum class TargetDeadlineType\n\t{\n\t\tPool,\n\t\tLocal,\n\t\tCombined\n\t};\n\n\t/**\n\t * \\brief Represents a passphrase, used for solo-mining.\n\t * Includes informations for en-/decrypting a passphrase.\n\t */\n\tstruct Passphrase\n\t{\n\t\tstd::string algorithm;\n\t\tPoco::UInt32 iterations = 1000;\n\t\tstd::string key;\n\t\tstd::string salt;\n\t\tstd::string decrypted;\n\t\tbool deleteKey = true;\n\t\tstd::string encrypted;\n\t\tstatic const std::string delimiter;\n\n\t\t/**\n\t\t * \\brief Decrypts the encrypted passphrase.\n\t\t * \\return The plain-text passphrase.\n\t\t */\n\t\tconst std::string& decrypt();\n\n\t\t/**\n\t\t * \\brief Encrypts the plain-text passphrase.\n\t\t * \\return The encrypted passphrase.\n\t\t */\n\t\tconst std::string& encrypt();\n\n\t\tbool isOneWayHash() const;\n\t\tbool isTwoWayHash() const;\n\t\tbool isEncrypted() const;\n\t\tbool isPlainText() const;\n\t\tbool check(const std::string& plainText) const;\n\t\tbool empty() const;\n\n\t\tstd::string toString() const;\n\n\t\tstatic Passphrase fromString(const std::string& string);\n\t\tstatic std::string createSalt(size_t length = 20);\n\t};\n\n\tenum class ReadConfigFileResult\n\t{\n\t\tOk,\n\t\tNotFound,\n\t\tInvalid,\n\t\tError\n\t};\n\t\n\tclass MinerConfig\n\t{\n\tpublic:\n\t\tvoid recalculatePlotsHash();\n\t\tReadConfigFileResult readConfigFile(const std::string& configPath);\n\t\tvoid rescan();\n\n\t\t/**\n\t\t * \\brief Rescans all plot dirs that are currently in use.\n\t\t * Does NOT read new plot dirs from the configuration file!\n\t\t */\n\t\tbool rescanPlotfiles();\n\t\tvoid checkPlotOverlaps() const;\n\t\tvoid printConsole() const;\n\t\tvoid printConsolePlots() const;\n\t\tvoid printUrl(HostType type) const;\n\t\tvoid printTargetDeadline() const;\n\t\tvoid printSubmitProbability() const;\n\t\tstatic void printUrl(const Url& url, const std::string& url_name);\n\t\tvoid printBufferSize() const;\n\t\tvoid printBufferChunks() const;\n\n\t\t/**\n\t\t * \\brief Saves the current settings by creating a JSON Object for it and saving it\n\t\t * into the configuration file.\n\t\t * \\return true, if saved, false otherwise.\n\t\t */\n\t\tbool save() const;\n\n\t\t/**\n\t\t * \\brief Saves the current settings by creating a JSON object for it and saving it\n\t\t * into a file.\n\t\t * \\param path The path to the file, where the setting is written into.\n\t\t * \\return true, if saved, false otherwise\n\t\t */\n\t\tbool save(const std::string& path) const;\n\n\t\t/**\n\t\t * \\brief Saves a JSON object into a file.\n\t\t * \\param path The path to the file, where the JSON object is written into.\n\t\t * \\param json The JSON object, that needs to be saved.\n\t\t * \\return true, if saved, false otherwise.\n\t\t */\n\t\tstatic bool save(const std::string& path, const Poco::JSON::Object& json);\n\n\t\tbool addPlotDir(std::shared_ptr<PlotDir> plotDir);\n\n\t\tconst std::string& getPath() const;\n\n\t\tstd::vector<std::shared_ptr<PlotFile>> getPlotFiles() const;\n\t\tuintmax_t getTotalPlotsize() const;\n\n\t\tPoco::UInt64 getMaxBufferSize() const;\n\t\tPoco::UInt64 getMaxBufferSizeRaw() const;\n\t\tPoco::UInt64 getMaxHistoricalBlocks() const;\n\t\tfloat getReceiveTimeout() const;\n\t\tfloat getSendTimeout() const;\n\t\tfloat getTimeout() const;\n\t\tUrl getPoolUrl() const;\n\t\tconst std::vector<Url>& getPoolUrlAlt() const;\n\t\tUrl getMiningInfoUrl() const;\n\t\tconst std::vector<Url>& getMiningInfoUrlAlt() const;\n\t\tUrl getWalletUrl() const;\n\t\tstd::string getProxyFullUrl() const;\n\t\tPoco::Net::HTTPClientSession::ProxyConfig getProxyConfig() const;\n\n\t\tunsigned getReceiveMaxRetry() const;\n\t\tunsigned getSendMaxRetry() const;\n\t\tunsigned getSubmissionMaxRetry() const;\n\t\tunsigned getHttp() const;\n\t\tconst std::string& getConfirmedDeadlinesPath() const;\n\t\tbool getStartServer() const;\n\t\tconst std::string& getServerCertificatePath() const;\n\t\tconst std::string& getServerCertificatePass() const;\n\t\tconst std::string& getDatabasePath() const;\n\t\tconst std::string& getWorkerName() const;\n\n\t\tUrl getServerUrl() const;\n\t\tdouble getSubmitProbability() const;\n\t\tdouble getTargetDLFactor() const;\n\t\tdouble getDeadlinePerformanceFac() const;\n\t\tPoco::UInt64 getTargetDeadline(TargetDeadlineType type = TargetDeadlineType::Combined) const;\n\t\tunsigned getMiningIntensity(bool real = true) const;\n\t\tbool forPlotDirs(const std::function<bool(PlotDir&)>& traverseFunction) const;\n\t\t//const std::string& getPlotsHash() const;\n\t\tconst std::string& getPassphrase() const;\n\t\tbool useInsecurePlotfiles() const;\n\t\tbool isLogfileUsed() const;\n\t\tunsigned getMiningInfoInterval() const;\n\t\tbool isRescanningEveryBlock() const;\n\t\tLogOutputType getLogOutputType() const;\n\t\tbool isUsingLogColors() const;\n\t\tbool isSteadyProgressBar() const;\n\t\tbool isFancyProgressBar() const;\n\t\tunsigned getBufferChunkCount() const;\n\t\tbool isCalculatingEveryDeadline() const;\n\n\t\t/**\n\t\t * \\brief Returns the maximal amount of simultane plot reader.\n\t\t * \\param real If true and the value == 0, the amount of plot drives will be returned.\n\t\t * If false the actual value will be returned.\n\t\t * \\return The maximal amount of simultane plot reader.\n\t\t */\n\t\tunsigned getMaxPlotReaders(bool real = true) const;\n\t\tPoco::Path getPathLogfile() const;\n\t\tstd::string getLogDir() const;\n\t\tconst Passphrase& getServerUser() const;\n\t\tconst Passphrase& getServerPass() const;\n\t\tunsigned getWalletRequestTries() const;\n\t\tunsigned getWalletRequestRetryWaitTime() const;\n\t\tunsigned getWakeUpTime() const;\n\t\tconst std::string& getCpuInstructionSet() const;\n\t\tconst std::string& getProcessorType() const;\n\t\tunsigned getGpuPlatform() const;\n\t\tunsigned getGpuDevice() const;\n\t\tunsigned getMaxConnectionsQueued() const;\n\t\tunsigned getMaxConnectionsActive() const;\n\t\tbool isForwardingEverything() const;\n\t\tconst std::vector<std::string>& getForwardingWhitelist() const;\n\t\tbool isCumulatingPlotsizes() const;\n\t\tbool isForwardingMinerName() const;\n\t\tPoco::UInt64 getPoc2StartBlock() const;\n\t\tbool isVerboseLogging() const;\n\n\t\tvoid setUrl(const std::string& url, HostType hostType);\n\t\tvoid setBufferSize(Poco::UInt64 bufferSize);\n\t\tvoid setMaxHistoricalBlocks(Poco::UInt64 maxHistData);\n\t\tvoid setMaxSubmissionRetry(unsigned value);\n\t\tvoid setTimeout(float value);\n\t\tvoid setSubmitProbability(double subP);\n\t\tvoid setTargetDeadline(const std::string& target_deadline, TargetDeadlineType type);\n\t\tvoid setTargetDeadline(Poco::UInt64 target_deadline, TargetDeadlineType type);\n\t\tvoid setMininigIntensity(unsigned intensity);\n\t\tvoid setMaxPlotReaders(unsigned max_reader);\n\t\tvoid setLogDir(const std::string& log_dir);\n\t\tvoid setGetMiningInfoInterval(unsigned interval);\n\t\tvoid setBufferChunkCount(unsigned bufferChunkCount);\n\t\tvoid setPoolTargetDeadline(Poco::UInt64 targetDeadline);\n\t\tvoid setProcessorType(const std::string& processorType);\n\t\tvoid setCpuInstructionSet(const std::string& instructionSet);\n\t\tvoid setGpuPlatform(unsigned platformIndex);\n\t\tvoid setGpuDevice(unsigned deviceIndex);\n\t\tvoid setPlotDirs(const std::vector<std::string>& plotDirs);\n\t\tvoid setWebserverUri(const std::string& uri);\n\t\tvoid setProgressbar(bool fancy, bool steady);\n\t\tvoid setPassphrase(const std::string& passphrase);\n\t\tvoid setWebserverCredentials(const std::string& user, const std::string& pass);\n\t\tvoid setStartWebserver(bool start);\n\t\tvoid setDatabasePath(std::string databasePath);\n\n\t\t/**\n\t\t * \\brief Instructs the miner wether he should use a logfile.\n\t\t * \\note If true and so far no logfile was used, a new logfile will be created.\n\t\t * If false and so far a logfile has been used, the logfile will be closed.\n\t\t * \\param use Indicates, if the miner uses a logfile.\n\t\t */\n\t\tvoid useLogfile(bool use);\n\n\t\tbool addPlotDir(const std::string& dir);\n\t\tbool removePlotDir(const std::string& dir);\n\n\t\t/**\n\t\t * \\brief Creates a session for network communication over http.\n\t\t * \\param hostType The type of the far-end peer.\n\t\t * \\return The http session, if the connection was successful, nullptr otherwise.\n\t\t */\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> createSession(HostType hostType) const;\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> createSession(const Url& url) const;\n\n\t\t/**\n\t\t * \\brief Returns the singleton-instance of the configuration.\n\t\t * \\return the current configuration.\n\t\t */\n\t\tstatic MinerConfig& getConfig();\n\n\tprivate:\n\t\tstatic Poco::JSON::Object::Ptr readOutput(Poco::JSON::Object::Ptr json);\n\n\t\tstd::string configPath_;\n\t\tstd::vector<std::shared_ptr<PlotDir>> plotDirs_;\n\t\tfloat timeout_ = 45.f;\n\t\tunsigned sendMaxRetry_ = 3;\n\t\tunsigned receiveMaxRetry_ = 3;\n\t\tunsigned submissionMaxRetry_ = 10;\n\t\tunsigned http_ = 1;\n\t\tstd::string confirmedDeadlinesPath_ = \"\";\n\t\tUrl urlPool_{\"https://pool.creepminer.net\"};\n\t\tUrl urlMiningInfo_{\"https://pool.creepminer.net\"};\n\t\tUrl urlWallet_{\"https://wallet.creepminer.net\"};\n\t\tUrl urlServer_{\"http://0.0.0.0:8124\"};\n\t\tstd::vector<Url> urlMiningInfoAlt_{};\n\t\tstd::vector<Url> urlPoolAlt_{};\n\t\tstd::string proxyIp_{};\n\t\tPoco::UInt16 proxyPort_{};\n\t\tPassphrase proxyUser_{}, proxyPassword_{};\n\t\tbool startServer_ = true;\n\t\tdouble targetDlFactor_ = 1.0;\n\t\tdouble deadlinePerformanceFac_ = 1.0;\n\t\tdouble submitProbability_ = 0.999;\n\t\tPoco::UInt64 targetDeadline_ = 0, targetDeadlinePool_ = 0;\n\t\tunsigned miningIntensity_ = 0;\n\t\tstd::string plotsHash_;\n\t\tPassphrase serverUser_{}, serverPass_{};\n\t\tunsigned maxPlotReaders_ = 0;\n\t\tPoco::Path pathLogfile_ = \"\";\n\t\tPoco::UInt64 maxBufferSizeMb_ = 0;\n\t\tPoco::UInt64 maxHistoricalBlocks_ = 360;\n\t\tunsigned bufferChunkCount_ = 16;\n\t\tunsigned walletRequestTries_ = 3;\n\t\tunsigned walletRequestRetryWaitTime_ = 3;\n\t\tPassphrase passphrase_ = {};\n\t\tbool useInsecurePlotfiles_ = false;\n\t\tbool logfile_ = false;\n\t\tunsigned getMiningInfoInterval_ = 3;\n\t\tbool rescanEveryBlock_ = false;\n\t\tLogOutputType logOutputType_ = LogOutputType::Terminal;\n\t\tbool logUseColors_ = true;\n\t\tbool steadyProgressBar_ = true;\n\t\tbool fancyProgressBar_ = true;\n\t\tunsigned wakeUpTime_ = 0;\n\t\tstd::string cpuInstructionSet_ = \"AUTO\";\n\t\tstd::string processorType_ = \"CPU\";\n\t\tunsigned gpuPlatform_ = 0, gpuDevice_ = 0;\n\t\tunsigned maxConnectionsQueued_ = 64, maxConnectionsActive_ = 32;\n\t\tstd::vector<std::string> forwardingWhitelist_;\n\t\tbool cumulatePlotsizes_ = true;\n\t\tbool minerNameForwarding_ = true;\n\t\tbool calculateEveryDeadline_ = false;\n\t\tstd::string serverCertificatePath_;\n\t\tstd::string serverCertificatePass_;\n\t\tstd::string databasePath_;\n\t\tstd::string workerName_;\n\t\tPoco::UInt64 poc2StartBlock_ = 0;\n\t\tbool verboseLogging_ = false;\n\t\tmutable Poco::Mutex mutex_;\n\t};\n}\n"
  },
  {
    "path": "src/mining/MinerData.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"MinerData.hpp\"\n#include \"MinerConfig.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include \"shabal/MinerShabal.hpp\"\n#include \"logging/Output.hpp\"\n#include \"MinerUtil.hpp\"\n#include \"wallet/Wallet.hpp\"\n#include \"wallet/Account.hpp\"\n\nusing namespace Poco::Data::Keywords;\n\nBurst::BlockData::BlockData(const Poco::UInt64 blockHeight, const Poco::UInt64 baseTarget, const std::string& genSigStr,\n                            MinerData* parent, const Poco::UInt64 blockTargetDeadline)\n\t: blockHeight_ {blockHeight},\n\t  baseTarget_ {baseTarget},\n\t  blockTargetDeadline_{ blockTargetDeadline },\n\t  genSigStr_ {genSigStr},\n\t  parent_{parent}\n{\n\tpoco_ndc(BlockData::BlockData);\n\n\ttry\n\t{\n\t\tentries_ = std::make_shared<std::vector<Poco::JSON::Object>>();\n\t\t//deadlines_ = std::make_shared<std::unordered_map<AccountId, Deadlines>>();\n\n\t\tfor (auto i = 0; i < 32; ++i)\n\t\t{\n\t\t\tconst auto byteStr = genSigStr.substr(i * 2, 2);\n\t\t\tgenSig_[i] = static_cast<uint8_t>(std::stoi(byteStr, nullptr, 16));\n\t\t}\n\n\t\tShabal256Sse2 hash;\n\t\tGensigData newGenSig;\n\t\t\n\t\thash.update(&genSig_[0], genSig_.size());\n\t\thash.update(blockHeight);\n\t\thash.close(&newGenSig[0]);\n\n\t\troundTime_ = 0;\n\t\tscoop_ = (static_cast<int>(newGenSig[newGenSig.size() - 2] & 0x0F) << 8) | static_cast<int>(newGenSig[newGenSig.size() - 1]);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not create the block data: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\tthrow;\n\t}\n}\n\nbool Burst::BlockData::addDeadlineUnlocked(std::shared_ptr<Deadline> deadline)\n{\n\tpoco_ndc(BlockData::BlockData);\n\n\ttry\n\t{\n\t\tauto accountId = deadline->getAccountId();\n\t\t\n\t\tauto iter = deadlines_.find(accountId);\n\n\t\tif (iter == deadlines_.end())\n\t\t{\n\t\t\tdeadlines_.insert(std::make_pair(accountId, std::make_shared<Deadlines>(this)));\n\t\t\tdeadlines_[accountId]->add(std::move(deadline));\n\t\t}\n\t\telse\n\t\t{\n\t\t\titer->second->add(std::move(deadline));\n\t\t}\n\n\t\treturn true;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not add the new deadline: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn false;\n\t}\n}\n\nbool Burst::BlockData::addDeadline(std::shared_ptr<Deadline> deadline)\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\treturn addDeadlineUnlocked(std::move(deadline));\n}\n\nvoid Burst::BlockData::setBaseTarget(Poco::UInt64 baseTarget)\n{\n\tbaseTarget_ = baseTarget;\n}\n\nvoid Burst::BlockData::confirmedDeadlineEvent(const std::shared_ptr<Deadline>& deadline)\n{\n\tif (deadline == nullptr)\n\t\treturn;\n\n\taddBlockEntry(createJsonDeadline(*deadline, \"nonce confirmed\"));\n\n\t// set the best deadline for this block\n\t{\n\t\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\t\tif (bestDeadline_ == nullptr ||\n\t\t\tbestDeadline_->getDeadline() > deadline->getDeadline())\n\t\t\tbestDeadline_ = deadline;\n\t}\n}\n\nBurst::BlockData::DataLoader::DataLoader()\n\t: getLastWinner{this, &DataLoader::runGetLastWinner}\n{}\n\nBurst::BlockData::DataLoader::~DataLoader() = default;\n\nBurst::BlockData::DataLoader& Burst::BlockData::DataLoader::getInstance()\n{\n\tstatic DataLoader data_loader;\n\treturn data_loader;\n}\n\nstd::shared_ptr<Burst::Account> Burst::BlockData::DataLoader::runGetLastWinner(const std::tuple<const Wallet&, Accounts&, BlockData&>& args)\n{\n\tpoco_ndc(BlockData::DataLoader::runGetLastWinner);\n\n\ttry\n\t{\n\t\tauto& wallet = std::get<0>(args);\n\t\tauto& accounts = std::get<1>(args);\n\t\tauto& blockdata = std::get<2>(args);\n\t\t\n\t\tAccountId lastWinner;\n\t\tconst auto lastBlockheight = blockdata.blockHeight_ - 1;\n\t\t\n\t\tif (!wallet.isActive())\n\t\t\treturn nullptr;\n\n\t\tif (wallet.getWinnerOfBlock(lastBlockheight, lastWinner))\n\t\t{\n\t\t\tauto winnerAccount = accounts.getAccount(lastWinner, wallet, false);\n\n\t\t\twinnerAccount->getOrLoadName().wait();\n\t\t\twinnerAccount->getOrLoadRewardRecipient().wait();\n\n\t\t\tstd::string rewardRecipient;\n\n\t\t\tif (winnerAccount->getRewardRecipient() == winnerAccount->getId())\n\t\t\t\trewardRecipient = \"                   Solo mining\";\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto rewardRecipientAccount = accounts.getAccount(winnerAccount->getRewardRecipient(), wallet, false);\n\t\t\t\trewardRecipientAccount->getOrLoadName().wait();\n\t\t\t\trewardRecipient = \"Pool               \" + rewardRecipientAccount->getName();\n\t\t\t}\n\n\t\t\tlog_ok_if(MinerLogger::miner, MinerLogger::hasOutput(LastWinner), std::string(50, '-') + \"\\n\"\n\t\t\t\t\"last block winner: \\n\"\n\t\t\t\t\"block#             %s\\n\"\n\t\t\t\t\"winner-numeric     %Lu\\n\"\n\t\t\t\t\"winner-address     %s\\n\"\n\t\t\t\t\"%s\" +\n\t\t\t\t\"%s\\n\" +\n\t\t\t\tstd::string(50, '-'),\n\t\t\t\tnumberToString(lastBlockheight), lastWinner, winnerAccount->getAddress(),\n\t\t\t\twinnerAccount->getName().empty() ? \"\" : Poco::format(\"winner-name        %s\\n\", winnerAccount->getName()),\n\t\t\t\trewardRecipient\n\t\t\t);\n\n\t\t\tblockdata.setLastWinner(winnerAccount);\n\n\t\t\treturn winnerAccount;\n\t\t}\n\n\t\treturn nullptr;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not load the last winner: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn nullptr;\n\t}\n}\n\nvoid Burst::BlockData::setLastWinner(const std::shared_ptr<Account>& account)\n{\n\tpoco_ndc(BlockData::setLastWinner);\n\n\ttry\n\t{\n\t\t// set the winner for the last block\n\t\t{\n\t\t\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\t\t\tlastWinner_ = account;\n\t\t}\n\n\t\tauto lastWinnerJson = account->toJSON();\n\t\tlastWinnerJson->set(\"type\", \"lastWinner\");\n\t\taddBlockEntry(*lastWinnerJson);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not set the last winner: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t}\n}\n\nvoid Burst::BlockData::refreshBlockEntry() const\n{\n\tpoco_ndc(MinerData::refreshBlockEntry);\n\tif (parent_ != nullptr)\n\t\taddBlockEntry(createJsonNewBlock(*parent_));\n}\n\nvoid Burst::BlockData::refreshConfig() const\n{\n\tpoco_ndc(MinerData::refreshConfig);\n\taddBlockEntry(createJsonConfig());\n}\n\nvoid Burst::BlockData::refreshPlotDirs() const\n{\n\tpoco_ndc(MinerData::refreshPlotDirs);\n\taddBlockEntry(createJsonPlotDirsRescan());\n}\n\nvoid Burst::BlockData::setProgress(const float progressRead, const float progressVerification, const Poco::UInt64 blockheight)\n{\n\tpoco_ndc(BlockData::setProgress);\n\n\ttry\n\t{\n\t\tif (blockheight != getBlockheight())\n\t\t\treturn;\n\n\t\t{\n\t\t\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\t\t\tjsonProgress_ = new Poco::JSON::Object{createJsonProgress(progressRead, progressVerification)};\n\t\t}\n\n\t\tif (parent_ != nullptr)\n\t\t\tparent_->blockDataChangedEvent.notify(this, *jsonProgress_);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not set the progress: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t}\n}\n\nvoid Burst::BlockData::setProgress(const std::string& plotDir, const float progress, const Poco::UInt64 blockheight)\n{\n\tpoco_ndc(BlockData::setProgress);\n\n\ttry\n\t{\n\t\tif (blockheight != getBlockheight())\n\t\t\treturn;\n\n\t\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\t\tauto json = new Poco::JSON::Object{ createJsonProgress(progress, 0.f) };\n\t\tjson->set(\"type\", \"plotdir-progress\");\n\t\tjson->set(\"dir\", plotDir);\n\n\t\tjsonDirProgress_[plotDir].assign(json);\n\n\t\tif (parent_ != nullptr)\n\t\t\tparent_->blockDataChangedEvent.notify(this, *json);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not set the progress: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t}\n}\n\nvoid Burst::BlockData::setRoundTime(double rTime)\n{\n\troundTime_ = rTime;\n}\n\nvoid Burst::BlockData::addBlockEntry(Poco::JSON::Object entry) const\n{\n\tpoco_ndc(BlockData::addBlockEntry);\n\n\ttry\n\t{\n\t\t{\n\t\t\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\t\t\tentries_->emplace_back(entry);\t\n\t\t}\n\t\t\n\t\tif (parent_ != nullptr)\n\t\t\tparent_->blockDataChangedEvent.notify(this, entry);\t\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not add the block entry: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t}\n}\n\nPoco::UInt64 Burst::BlockData::getBlockheight() const\n{\n\treturn blockHeight_.load();\n}\n\nPoco::UInt64 Burst::BlockData::getScoop() const\n{\n\treturn scoop_.load();\n}\n\nPoco::UInt64 Burst::BlockData::getBasetarget() const\n{\n\treturn baseTarget_.load();\n}\n\nPoco::UInt64 Burst::BlockData::getDifficulty() const\n{\n\treturn 18325193796 / getBasetarget();\n}\n\ndouble Burst::BlockData::getRoundTime() const\n{\n\treturn roundTime_;\n}\n\nPoco::UInt64 Burst::BlockData::getBlockTargetDeadline() const\n{\n\treturn blockTargetDeadline_.load();\n}\n\nstd::shared_ptr<Burst::Account> Burst::BlockData::getLastWinner() const\n{\n\treturn lastWinner_;\n}\n \nconst Burst::GensigData& Burst::BlockData::getGensig() const\n{\n\treturn genSig_;\n}\n\nconst std::string& Burst::BlockData::getGensigStr() const\n{\n\treturn genSigStr_;\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::BlockData::getBestDeadline() const\n{\n\treturn bestDeadline_;\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::BlockData::getBestDeadline(const DeadlineSearchType searchType) const\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\tstd::shared_ptr<Deadline> bestDeadline;\n\n\tpoco_ndc(BlockData::getBestDeadline);\n\n\ttry\n\t{\n\t\tfor (const auto& accountDeadlines : deadlines_)\n\t\t{\n\t\t\tif (accountDeadlines.second == nullptr)\n\t\t\t\tcontinue;\n\t\t\n\t\t\tstd::shared_ptr<Deadline> accountBestDeadline;\n\n\t\t\tif (searchType == DeadlineSearchType::Found)\n\t\t\t\taccountBestDeadline = accountDeadlines.second->getBestFound();\n\t\t\telse if (searchType == DeadlineSearchType::Sent)\n\t\t\t\taccountBestDeadline = accountDeadlines.second->getBestSent();\n\t\t\telse if (searchType == DeadlineSearchType::Confirmed)\n\t\t\t\taccountBestDeadline = accountDeadlines.second->getBestConfirmed();\n\n\t\t\tif (accountBestDeadline == nullptr)\n\t\t\t\tcontinue;\n\n\t\t\tif (bestDeadline == nullptr ||\n\t\t\t\tbestDeadline->getDeadline() > accountBestDeadline->getDeadline())\n\t\t\t\tbestDeadline = accountBestDeadline;\n\t\t}\n\n\t\treturn bestDeadline;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get the best specific deadline: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn nullptr;\n\t}\n}\n\nbool Burst::BlockData::forEntries(const std::function<bool(const Poco::JSON::Object&)>& traverseFunction) const\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\tpoco_ndc(BlockData::forEntries);\n\n\ttry\n\t{\n\t\tif (entries_ == nullptr)\n\t\t\treturn false;\n\n\t\tauto error = false;\n\n\t\tfor (auto iter = entries_->begin(); iter != entries_->end() && !error; ++iter)\n\t\t\terror = !traverseFunction(*iter);\n\n\t\t// send the overall progress, if any\n\t\tif (!error && !jsonProgress_.isNull())\n\t\t\terror = !traverseFunction(*jsonProgress_);\n\n\t\t// send the dir progress\n\t\tif (!error)\n\t\t\tfor (auto iter = jsonDirProgress_.begin(); !error && iter != jsonDirProgress_.end(); ++iter)\n\t\t\t\terror = !traverseFunction(*iter->second);\n\n\t\treturn error;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not traverse the entries: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn false;\n\t}\n}\n\n//std::vector<Poco::JSON::Object> Burst::BlockData::getEntries() const\n//{\n//\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n//\treturn *entries_;\n//}\n\n//const std::unordered_map<Burst::AccountId, Burst::Deadlines>& Burst::BlockData::getDeadlines() const\n//{\n//\tPoco::ScopedLock<Poco::FastMutex> lock{mutex_};\n//\treturn deadlines_;\n//}\n\nstd::shared_ptr<Burst::Deadline> Burst::BlockData::getBestDeadlineUnlocked(const Poco::UInt64 accountId, const DeadlineSearchType searchType) const\n{\n\tpoco_ndc(BlockData::getBestDeadlineUnlocked);\n\n\ttry\n\t{\n\t\tconst auto iter = deadlines_.find(accountId);\n\n\t\tif (iter == deadlines_.end())\n\t\t\treturn nullptr;\n\n\t\tswitch (searchType)\n\t\t{\n\t\tcase DeadlineSearchType::Found:\n\t\t\treturn iter->second->getBestFound();\n\t\tcase DeadlineSearchType::Sent:\n\t\t\treturn iter->second->getBestSent();\n\t\tcase DeadlineSearchType::Confirmed:\n\t\t\treturn iter->second->getBestConfirmed();\n\t\tdefault:\n\t\t\treturn nullptr;\n\t\t}\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get the best deadline: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn nullptr;\n\t}\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::BlockData::getBestDeadline(const Poco::UInt64 accountId, const DeadlineSearchType searchType) const\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\treturn getBestDeadlineUnlocked(accountId, searchType);\n}\n\nPoco::ActiveResult<std::shared_ptr<Burst::Account>> Burst::BlockData::getLastWinnerAsync(const Wallet& wallet, Accounts& accounts)\n{\n\treturn DataLoader::getInstance().getLastWinner(make_tuple(std::cref(wallet), std::ref(accounts), std::ref(*this)));\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::BlockData::addDeadlineIfBest(Deadline deadline)\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\tpoco_ndc(BlockData::addDeadlineIfBest);\n\n\ttry\n\t{\n\t\tconst auto bestDeadline = getBestDeadlineUnlocked(deadline.getAccountId(), DeadlineSearchType::Found);\n\n\t\tif (bestDeadline == nullptr || bestDeadline->getDeadline() > deadline.getDeadline())\n\t\t{\n\t\t\tauto deadlinePtr = std::make_shared<Deadline>(std::move(deadline));\n\t\t\t\n\t\t\tif (addDeadlineUnlocked(deadlinePtr))\n\t\t\t\treturn deadlinePtr;\n\n\t\t\treturn nullptr;\n\t\t}\n\n\t\treturn nullptr;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not add a new (best) deadline: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn nullptr;\n\t}\n}\n\nvoid Burst::BlockData::addMessage(const Poco::Message& message) const\n{\n\tPoco::JSON::Object json;\n\tpoco_ndc(BlockData::addMessage);\n\n\ttry\n\t{\n\t\t{\n\t\t\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\t\t\tif (entries_ == nullptr)\n\t\t\t\treturn;\n\t\t\t\n\t\t\tjson.set(\"type\", std::to_string(static_cast<int>(message.getPriority())));\n\t\t\tjson.set(\"text\", message.getText());\n\t\t\tjson.set(\"source\", message.getSource());\n\t\t\tjson.set(\"line\", message.getSourceLine());\n\t\t\tjson.set(\"file\", message.getSourceFile());\n\t\t\tjson.set(\"time\", Poco::DateTimeFormatter::format(Poco::LocalDateTime(message.getTime()), \"%H:%M:%S\"));\n\n\t\t\tentries_->emplace_back(json);\n\t\t}\n\n\t\tif (parent_ != nullptr)\n\t\t\tparent_->blockDataChangedEvent.notify(this, json);\t\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not add a new message: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t}\n}\n\nvoid Burst::BlockData::clearEntries() const\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\tentries_->clear();\n}\n\nbool Burst::BlockData::forDeadlines(const std::function<bool(const Deadline&)>& traverseFunction) const\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\tpoco_ndc(BlockData::forDeadlines);\n\n\ttry\n\t{\n\t\tif (deadlines_.empty())\n\t\t\treturn false;\n\n\t\tauto error = false;\n\n\t\tfor (auto iterAccounts = deadlines_.begin(); iterAccounts != deadlines_.end() && !error; ++iterAccounts)\n\t\t{\n\t\t\tif (iterAccounts->second == nullptr)\n\t\t\t\tcontinue;\n\n\t\t\tconst auto deadlines = iterAccounts->second->getDeadlines();\n\n\t\t\tfor (auto iter = deadlines.begin(); iter != deadlines.end() && !error; ++iter)\n\t\t\t\terror = traverseFunction(**iter);\n\t\t}\n\n\t\treturn error;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not traverse deadlines: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn false;\n\t}\n}\n\nBurst::MinerData::MinerData()\n\t: blocksWon_(0),\n\t  activityWonBlocks_{this, &MinerData::runGetWonBlocks}\n{\n\tpoco_ndc(MinerData::MinerData);\n\n\tconst auto databasePath = MinerConfig::getConfig().getDatabasePath();\n\n\ttry\n\t{\n\t\tdbSession_ = std::make_unique<Poco::Data::Session>(\"SQLite\", databasePath);\n\t\t\n\t\t*dbSession_ <<\n\t\t\t\"CREATE TABLE IF NOT EXISTS deadline (\" <<\n\t\t\t\"\tid\t\t\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\theight\t\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\taccount\t\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\tnonce\t\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\tvalue\t\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\tfile\t\t\tTEXT NOT NULL,\" <<\n\t\t\t\"\tminer\t\t\tTEXT NOT NULL,\" <<\n\t\t\t\"\ttotalplotsize\tREAL NOT NULL,\" <<\n\t\t\t\"\tstatus\t\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\tPRIMARY KEY (id)\" <<\n\t\t\t\")\", now;\n\n\t\t*dbSession_ <<\n\t\t\t\"CREATE TABLE IF NOT EXISTS block (\" <<\n\t\t\t\"\tid\t\t\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\theight\t\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\tscoop\t\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\tbaseTarget\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\tgensig\t\t\tTEXT NOT NULL,\" <<\n\t\t\t\"\tdifficulty\t\tINTEGER NOT NULL,\" <<\n\t\t\t\"\ttargetDeadline\tINTEGER NOT NULL,\" <<\n\t\t\t\"\troundTime\t\tREAL NOT NULL,\" <<\n\t\t\t\"\tblockTime\t\tREAL NOT NULL,\" <<\n\t\t\t\"\tPRIMARY KEY (id)\" <<\n\t\t\t\")\", now;\n\t}\n\tcatch (Poco::Exception& e)\n\t{\n\t\tthrow Poco::Exception{Poco::format(\"Could not load/create the database '%s'\\n\\tReason: %s\", databasePath, e.displayText())};\n\t}\n}\n\nBurst::MinerData::~MinerData() = default;\n\nstd::shared_ptr<Burst::BlockData> Burst::MinerData::startNewBlock(Poco::UInt64 block, Poco::UInt64 baseTarget,\n                                                                  const std::string& genSig,\n                                                                  Poco::UInt64 blockTargetDeadline)\n{\n\tpoco_ndc(MinerData::startNewBlock);\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\t// save the old data in the historical container\n\tif (blockData_ != nullptr)\n\t{\n\t\t// add the block to the database\n\t\ttry\n\t\t{\n\t\t\t*dbSession_ <<\n\t\t\t\t\"INSERT INTO block VALUES (NULL, :height, :scoop, :btarget, :gensig, :diff, :targdl, :roundt, :blockt)\",\n\t\t\t\tbind(blockData_->getBlockheight()), bind(blockData_->getScoop()), bind(blockData_->getBasetarget()),\n\t\t\t\tuseRef(blockData_->getGensigStr()), bind(blockData_->getDifficulty()), bind(blockData_->getBlockTargetDeadline()),\n\t\t\t\tbind(blockData_->getRoundTime()), bind(blockData_->getBlockTime()), now;\n\n\t\t\tblockData_->forDeadlines([this](const Deadline& deadline)\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tconst auto status = [&]()\n\t\t\t\t\t{\n\t\t\t\t\t\tif (deadline.isConfirmed())\n\t\t\t\t\t\t\treturn 3;\n\n\t\t\t\t\t\tif (deadline.isSent())\n\t\t\t\t\t\t\treturn 2;\n\n\t\t\t\t\t\tif (deadline.isOnTheWay())\n\t\t\t\t\t\t\treturn 1;\n\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}();\n\n\t\t\t\t\t*dbSession_ <<\n\t\t\t\t\t\t\"INSERT INTO deadline VALUES (NULL, :height, :account, :nonce, :value, :file, :miner, :totalplotsize, :status)\",\n\t\t\t\t\t\tbind(deadline.getBlock()), bind(deadline.getAccountId()), bind(deadline.getNonce()), bind(deadline.getDeadline()),\n\t\t\t\t\t\tbind(deadline.getPlotFile()), bind(deadline.getMiner()), bind(deadline.getTotalPlotsize()), bind(status), now;\n\t\t\t\t}\n\t\t\t\tcatch (Poco::Exception& e)\n\t\t\t\t{\n\t\t\t\t\tlog_error(MinerLogger::general, \"Could not insert deadline %s for block %Lu\\n\\tReason: %s\",\n\t\t\t\t\t\tdeadline.deadlineToReadableString(), deadline.getBlock(), e.displayText());\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t});\n\t\t}\n\t\tcatch (Poco::Exception& e)\n\t\t{\n\t\t\tlog_error(MinerLogger::general, \"Could not insert block %Lu\\n\\tReason: %s\",\n\t\t\t\tblockData_->getBlockheight(), e.displayText());\n\t\t}\n\t}\n\n\ttry\n\t{\n\t\tlastBlockData_ = blockData_;\n\t\tblockData_ = std::make_shared<BlockData>(block, baseTarget, genSig, this, blockTargetDeadline);\n\t\treturn blockData_;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not create new block data: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn nullptr;\n\t}\n}\n\nstd::vector<std::shared_ptr<Burst::BlockData>> Burst::MinerData::getHistoricalBlocks(const Poco::UInt64 from, const Poco::UInt64 to) const\n{\n\tstd::vector<std::shared_ptr<BlockData>> historicalBlocks;\n\tforAllBlocks(from, to, [&](const auto& block)\n\t{\n\t\thistoricalBlocks.emplace_back(block);\n\t\treturn false;\n\t});\n\treturn historicalBlocks;\n}\n\nvoid Burst::MinerData::forAllBlocks(const Poco::UInt64 from, const Poco::UInt64 to,\n\tconst std::function<bool(std::shared_ptr<BlockData>&)>& traverseFunction) const\n{\n\tpoco_ndc(MinerData::forAllBlocks);\n\n\ttry\n\t{\n\t\tstd::vector<Poco::UInt64> nonces, values, accounts, totalPlotSizes, status;\n\t\tstd::vector<std::string> files;\n\n\t\tstd::vector<Poco::UInt64> heights, baseTargets, targetDeadlines, blockTimes;\n\t\tstd::vector<double> roundTimes;\n\t\tstd::vector<std::string> gensigs;\n\n\t\tconst auto fetchAll = from == 0 && to == 0;\n\t\tstd::string query = \"SELECT height, baseTarget, gensig, targetDeadline, roundTime, blockTime FROM block\";\n\n\t\tif (!fetchAll)\n\t\t\tquery += \" WHERE height >= :from AND height <= :to\";\n\n\t\tauto stmt = (*dbSession_ << query,\tinto(heights), into(baseTargets), into(gensigs),\n\t\t\t\t\t\t\t\t\t\t\tinto(targetDeadlines), into(roundTimes), into(blockTimes));\n\n\t\tif (!fetchAll)\n\t\t{\n\t\t\tstmt.bind(from);\n\t\t\tstmt.bind(to);\n\t\t}\n\n\t\tstmt.execute();\n\n\t\tPoco::UInt64 height;\n\n\t\tauto stmtDeadlines = (*dbSession_ << \"SELECT nonce, value, account, file, totalplotsize, status \" <<\n\t\t\t\t\t\t\t\t\t\t\t \"FROM deadline WHERE height = :height\",\n\t\t\tinto(nonces), into(values), into(accounts), into(files), into(totalPlotSizes), into(status), use(height));\n\n\t\tauto stop = false;\n\n\t\tfor (size_t i = 0; i < heights.size() && !stop; ++i)\n\t\t{\n\t\t\tnonces.clear();\n\t\t\tvalues.clear();\n\t\t\taccounts.clear();\n\t\t\tfiles.clear();\n\t\t\ttotalPlotSizes.clear();\n\t\t\tstatus.clear();\n\n\t\t\theight = heights[i];\n\n\t\t\tauto historicBlock = std::make_shared<BlockData>(\n\t\t\t\theight,\n\t\t\t\tbaseTargets[i],\n\t\t\t\tgensigs[i],\n\t\t\t\tnullptr,\n\t\t\t\ttargetDeadlines[i]\n\t\t\t);\n\n\t\t\thistoricBlock->setRoundTime(roundTimes[i]);\n\t\t\thistoricBlock->setBlockTime(blockTimes[i]);\n\n\t\t\tstmtDeadlines.execute();\n\n\t\t\tfor (size_t j = 0; j < nonces.size(); ++j)\n\t\t\t{\n\t\t\t\tauto deadline = std::make_shared<Deadline>(nonces[j], values[j],std::make_shared<Account>(accounts[j]), height, files[j]);\n\n\t\t\t\thistoricBlock->addDeadline(deadline);\n\n\t\t\t\tswitch (status[j])\n\t\t\t\t{\n\t\t\t\tcase 3:\n\t\t\t\t\tdeadline->confirm();\n\t\t\t\tcase 2:\n\t\t\t\t\tdeadline->send();\n\t\t\t\tcase 1:\n\t\t\t\t\tdeadline->onTheWay();\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstop = traverseFunction(historicBlock);\n\t\t}\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not use function for all blocks: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t}\n}\n\nPoco::UInt64 Burst::MinerData::runGetWonBlocks(const std::pair<const Wallet*, const Accounts*>& args)\n{\n\tpoco_ndc(BlockData::runGetWonBlocks);\n\n\ttry\n\t{\n\t\tauto& wallet = *args.first;\n\t\tauto& accounts = *args.second;\n\t\tsize_t wonBlocks = 0;\n\n\t\tif (!wallet.isActive())\n\t\t\treturn 0;\n\n\t\tstd::vector<Block> blocks;\n\n\t\tfor (auto& account : accounts.getAccounts())\n\t\t\tif (wallet.getAccountBlocks(account->getId(), blocks))\n\t\t\t\twonBlocks += blocks.size();\n\n\t\tbool refresh;\n\n\t\t{\n\t\t\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\t\t\tconst auto before = blocksWon_.load();\n\t\t\tblocksWon_.store(wonBlocks);\n\t\t\trefresh = before != wonBlocks;\n\t\t}\n\n\t\tif (blockData_ != nullptr && refresh)\n\t\t\tblockData_->refreshBlockEntry();\n\n\t\treturn wonBlocks;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get the number of won block: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn 0;\n\t}\n}\n\nvoid Burst::MinerData::addMessage(const Poco::Message& message)\n{\n\tconst auto blockData = getBlockData();\n\n\tif (blockData != nullptr)\n\t\tblockData->addMessage(message);\n}\n\nstd::shared_ptr<Burst::Deadline> Burst::MinerData::getBestDeadlineOverall(bool onlyHistorical) const\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\ttry\n\t{\n\t\tPoco::UInt64 from = 0, to = 0;\n\n\t\tif (onlyHistorical)\n\t\t{\n\t\t\tif (blockData_ == nullptr)\n\t\t\t\t*dbSession_ << \"SELECT MAX(height) FROM block\", into(to), now;\n\t\t\telse\n\t\t\t\tto = blockData_->getBlockheight();\n\n\t\t\tif (to == 0)\n\t\t\t\treturn nullptr;\n\n\t\t\tconst auto maxHistoricalBlocks = MinerConfig::getConfig().getMaxHistoricalBlocks();\n\n\t\t\tif (maxHistoricalBlocks > to)\n\t\t\t\tfrom = 0;\n\t\t\telse\n\t\t\t\tfrom = to - MinerConfig::getConfig().getMaxHistoricalBlocks();\n\t\t}\n\n\t\tstd::string query = \"SELECT nonce, value, account, height, file, MIN(value) FROM deadline WHERE status = 3 \";\n\t\t\n\t\tif (onlyHistorical)\n\t\t\tquery += \" AND height >= :from AND height < :to\";\n\n\t\tPoco::UInt64 nonce, value, account, height, minValue;\n\t\tstd::string file;\n\n\t\tauto stmt = (*dbSession_ << query, into(nonce), into(value), into(account), into(height), into(file), into(minValue));\n\n\t\tif (onlyHistorical)\n\t\t{\n\t\t\tstmt.bind(from);\n\t\t\tstmt.bind(to);\n\t\t}\n\n\t\tstmt.execute();\n\n\t\tif (file.empty())\n\t\t\treturn nullptr;\n\n\t\treturn std::make_shared<Deadline>(nonce, value, std::make_shared<Account>(account), height, file);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get best overall deadline: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn nullptr;\n\t}\n}\n\nconst Poco::Timestamp& Burst::MinerData::getStartTime() const\n{\n\treturn startTime_;\n}\n\nPoco::Timespan Burst::MinerData::getRunTime() const\n{\n\treturn Poco::Timestamp{} - getStartTime();\n}\n\nvoid Burst::BlockData::setBlockTime(Poco::UInt64 bTime)\n{\n\tblockTime_ = bTime;\n}\n\nPoco::UInt64 Burst::BlockData::getBlockTime() const\n{\n\treturn blockTime_;\n}\n\nPoco::UInt64 Burst::MinerData::getBlocksMined() const\n{\n\tpoco_ndc(MinerData::getBlocksMined);\n\n\ttry\n\t{\n\t\tPoco::UInt64 blocksMined;\n\t\t*dbSession_ << \"SELECT COUNT(*) FROM block\", into(blocksMined), now;\n\t\treturn blocksMined;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get mined blocks: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn 0;\n\t}\n}\n\nPoco::UInt64 Burst::MinerData::getBlocksWon() const\n{\n\treturn blocksWon_.load();\n}\n\nstd::shared_ptr<Burst::BlockData> Burst::MinerData::getBlockData()\n{\n\treturn blockData_;\n}\n\nstd::shared_ptr<const Burst::BlockData> Burst::MinerData::getBlockData() const\n{\n\treturn blockData_;\n}\n\nstd::shared_ptr<const Burst::BlockData> Burst::MinerData::getHistoricalBlockData(const Poco::UInt32 roundsBefore) const\n{\n\tpoco_ndc(MinerData::getHistoricalBlockData);\n\n\ttry\n\t{\n\t\tif (blockData_ == nullptr)\n\t\t\treturn nullptr;\n\n\t\tif (roundsBefore == 0)\n\t\t\treturn blockData_;\n\n\t\tconst auto currentHeight = getCurrentBlockheight();\n\t\tconst auto from = [&]()\n\t\t{\n\t\t\tconst auto maxHistoricalBlocks = MinerConfig::getConfig().getMaxHistoricalBlocks();\n\t\t\t\n\t\t\tif (maxHistoricalBlocks > currentHeight)\n\t\t\t\treturn Poco::UInt64{0};\n\n\t\t\treturn currentHeight - maxHistoricalBlocks;\n\t\t}();\n\n\t\tstd::shared_ptr<const BlockData> historicBlock;\n\n\t\tforAllBlocks(from, currentHeight, [&](const auto& block)\n\t\t{\n\t\t\thistoricBlock = block;\n\t\t\treturn true;\n\t\t});\n\n\t\treturn historicBlock;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get historical block data: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn nullptr;\n\t}\n}\n\n//std::shared_ptr<const Poco::JSON::Object> Burst::MinerData::getLastWinner() const\n//{\n//\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n//\n//\t// we make a local copy here, because the block data could be changed\n//\t// every second and we would have undefined behaviour\n//\tauto blockData = getBlockData();\n//\n//\tif (blockData == nullptr)\n//\t\treturn nullptr;\n//\n//\treturn blockData->getLastWinner();\n//}\n\nstd::vector<std::shared_ptr<Burst::BlockData>> Burst::MinerData::getAllHistoricalBlockData() const\n{\n\tpoco_ndc(MinerData::getAllHistoricalBlockData);\n\n\ttry\n\t{\n\t\tconst auto from = getCurrentBlockheight() - MinerConfig::getConfig().getMaxHistoricalBlocks();\n\t\tconst auto to = getCurrentBlockheight();\n\t\treturn getHistoricalBlocks(from, to);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get all historical block data: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn {};\n\t}\n}\n\nPoco::UInt64 Burst::MinerData::getConfirmedDeadlines() const\n{\n\tpoco_ndc(MinerData::getConfirmedDeadlines);\n\n\ttry\n\t{\n\t\tPoco::UInt64 deadlinesConfirmed;\n\t\t*dbSession_ << \"SELECT COUNT(*) FROM deadline WHERE status = 3\", into(deadlinesConfirmed), now;\n\t\treturn deadlinesConfirmed;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get confirmed deadlines: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn 0;\n\t}\n}\n\nPoco::UInt64 Burst::MinerData::getAverageDeadline() const\n{\n\tpoco_ndc(MinerData::getAverageDeadline);\n\n\ttry\n\t{\n\t\tPoco::UInt64 avg = 0;\n\t\t*dbSession_ << \"SELECT AVG(value) FROM deadline WHERE status = 3\", into(avg), now;\n\t\treturn avg;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get average deadline: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn 0;\n\t}\n}\n\nPoco::Int64 Burst::MinerData::getDifficultyDifference() const\n{\n\tpoco_ndc(MinerData::getDifficultyDifference);\n\n\ttry\n\t{\n\t\tif (blockData_ == nullptr)\n\t\t\treturn 0;\n\n\t\tconst Poco::Int64 difficulty = blockData_->getDifficulty();\n\n\t\tif (lastBlockData_ == nullptr)\n\t\t\treturn difficulty;\n\t\t\n\t\treturn difficulty - lastBlockData_->getDifficulty();\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get difficulty difference: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn 0;\n\t}\n}\n\nBurst::HighscoreValue<Poco::UInt64> Burst::MinerData::getLowestDifficulty() const\n{\n\tpoco_ndc(MinerData::getLowestDifficulty);\n\n\ttry\n\t{\n\t\tPoco::UInt64 height, difficulty;\n\t\t*dbSession_ << \"SELECT height, MIN(difficulty) FROM block\", into(height), into(difficulty), now;\n\t\treturn {height, difficulty};\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get lowest difficulty: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn {};\n\t}\n}\n\nBurst::HighscoreValue<Poco::UInt64> Burst::MinerData::getHighestDifficulty() const\n{\n\tpoco_ndc(MinerData::getHighestDifficulty);\n\n\ttry\n\t{\n\t\tPoco::UInt64 height, difficulty;\n\t\t*dbSession_ << \"SELECT height, MAX(difficulty) FROM block\", into(height), into(difficulty), now;\n\t\treturn {height, difficulty};\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::miner, \"Could not get highest difficulty: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::miner);\n\t\treturn {};\n\t}\n}\n\nPoco::UInt64 Burst::MinerData::getCurrentBlockheight() const\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\treturn blockData_ == nullptr ? 0 : blockData_->getBlockheight();\n}\n\nPoco::UInt64 Burst::MinerData::getCurrentBasetarget() const\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\treturn blockData_ == nullptr ? 0 : blockData_->getBasetarget();\n}\n\nPoco::UInt64 Burst::MinerData::getCurrentScoopNum() const\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\treturn blockData_ == nullptr ? 0 : blockData_->getScoop();\n}\n\nPoco::ActiveResult<Poco::UInt64> Burst::MinerData::getWonBlocksAsync(const Wallet& wallet, const Accounts& accounts)\n{\n\tconst auto tuple = std::make_pair(&wallet, &accounts);\n\treturn activityWonBlocks_(tuple);\n}\n"
  },
  {
    "path": "src/mining/MinerData.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"Deadline.hpp\"\n#include <Poco/Timestamp.h>\n#include <Poco/Timespan.h>\n#include <Poco/JSON/Object.h>\n#include <mutex>\n#include <Poco/ActiveDispatcher.h>\n#include <Poco/ActiveMethod.h>\n#include <unordered_map>\n#include <atomic>\n#include <functional>\n#include <Poco/BasicEvent.h>\n#include <Poco/Message.h>\n#include <Poco/Data/Session.h>\n\nnamespace Burst\n{\n\tclass MinerData;\n\tclass Accounts;\n\tclass Wallet;\n\tclass Account;\n\n\tclass BlockData\n\t{\n\tpublic:\n\t\tenum class DeadlineSearchType\n\t\t{\n\t\t\tFound,\n\t\t\tSent,\n\t\t\tConfirmed\n\t\t};\n\n\tpublic:\n\t\tBlockData(Poco::UInt64 blockHeight, Poco::UInt64 baseTarget, const std::string& genSigStr, MinerData* parent = nullptr, Poco::UInt64 blockTargetDeadline = 0);\n\n\t\tbool addDeadline(std::shared_ptr<Deadline> deadline);\n\t\tvoid setBaseTarget(Poco::UInt64 baseTarget);\n\t\tvoid setLastWinner(const std::shared_ptr<Account>& account);\n\t\tvoid setRoundTime(double rTime);\n\t\t\n\t\tvoid refreshBlockEntry() const;\n\t\tvoid refreshConfig() const;\n\t\tvoid refreshPlotDirs() const;\n\t\tvoid setProgress(float progressRead, float progressVerification, Poco::UInt64 blockheight);\n\t\tvoid setProgress(const std::string& plotDir, float progress, Poco::UInt64 blockheight);\n\t\tvoid setBlockTime(Poco::UInt64 bTime);\n\n\t\tPoco::UInt64 getBlockheight() const;\n\t\tPoco::UInt64 getScoop() const;\n\t\tPoco::UInt64 getBasetarget() const;\n\t\tPoco::UInt64 getDifficulty() const;\n\t\tPoco::UInt64 getBlockTargetDeadline() const;\n\t\tstd::shared_ptr<Account> getLastWinner() const;\n\t\tdouble getRoundTime() const;\n\t\tPoco::UInt64 getBlockTime() const;\n\t\t\n\t\tconst GensigData& getGensig() const;\n\t\tconst std::string& getGensigStr() const;\n\t\tstd::shared_ptr<Deadline> getBestDeadline() const;\n\t\tstd::shared_ptr<Deadline> getBestDeadline(DeadlineSearchType searchType) const;\n\t\t//std::vector<Poco::JSON::Object> getEntries() const;\n\t\tbool forEntries(const std::function<bool(const Poco::JSON::Object&)>& traverseFunction) const;\n\t\t//const std::unordered_map<AccountId, Deadlines>& getDeadlines() const;\n\t\tstd::shared_ptr<Deadline> getBestDeadline(Poco::UInt64 accountId, DeadlineSearchType searchType) const;\n\t\tPoco::ActiveResult<std::shared_ptr<Account>> getLastWinnerAsync(const Wallet& wallet, Accounts& accounts);\n\n\t\tstd::shared_ptr<Deadline> addDeadlineIfBest(Deadline deadline);\n\n\t\tvoid addMessage(const Poco::Message& message) const;\n\t\tvoid clearEntries() const;\n\n\t\tbool forDeadlines(const std::function<bool(const Deadline&)>& traverseFunction) const;\n\n\tprotected:\n\t\t\n\t\tvoid addBlockEntry(Poco::JSON::Object entry) const;\n\t\tvoid confirmedDeadlineEvent(const std::shared_ptr<Deadline>& deadline);\n\n\tprivate:\n\t\tclass DataLoader : public Poco::ActiveDispatcher\n\t\t{\n\t\tpublic:\n\t\t\tDataLoader();\n\t\t\t~DataLoader() override;\n\n\t\t\tstatic DataLoader& getInstance();\n\n\t\t\tPoco::ActiveMethod<std::shared_ptr<Account>, std::tuple<const Wallet&, Accounts&, BlockData&>, DataLoader,\n\t\t\t                   Poco::ActiveStarter<ActiveDispatcher>> getLastWinner;\n\n\t\tprivate:\n\t\t\tstd::shared_ptr<Account> runGetLastWinner(const std::tuple<const Wallet&, Accounts&, BlockData&>& args);\n\t\t};\n\n\tprivate:\n\t\tstd::shared_ptr<Deadline> getBestDeadlineUnlocked(Poco::UInt64 accountId,\n\t\t\tDeadlineSearchType searchType) const;\n\n\t\tbool addDeadlineUnlocked(std::shared_ptr<Deadline> deadline);\n\n\t\tstd::atomic<Poco::UInt64> blockHeight_;\n\t\tstd::atomic<Poco::UInt64> scoop_{};\n\t\tstd::atomic<Poco::UInt64> baseTarget_;\n\t\tstd::atomic<Poco::UInt64> blockTargetDeadline_;\n\t\tGensigData genSig_{};\n\t\tstd::string genSigStr_ = \"\";\n\t\tdouble roundTime_;\n\t\tPoco::UInt64 blockTime_{};\n\t\tstd::shared_ptr<std::vector<Poco::JSON::Object>> entries_;\n\t\tstd::shared_ptr<Account> lastWinner_ = nullptr;\n\t\tstd::unordered_map<AccountId, std::shared_ptr<Deadlines>> deadlines_;\n\t\tstd::shared_ptr<Deadline> bestDeadline_;\n\t\tMinerData* parent_;\n\t\tPoco::JSON::Object::Ptr jsonProgress_;\n\t\tstd::unordered_map<std::string, Poco::JSON::Object::Ptr> jsonDirProgress_;\n\t\tmutable Poco::Mutex mutex_;\n\n\t\tfriend class Deadlines;\n\t};\n\n\ttemplate <typename T>\n\tstruct HighscoreValue\n\t{\n\t\tPoco::UInt64 height;\n\t\tT value;\n\t};\n\n\tclass MinerData : public Poco::ActiveDispatcher\n\t{\n\tpublic:\n\t\tMinerData();\n\t\t~MinerData() override;\n\t\t\n\t\tstd::shared_ptr<BlockData> startNewBlock(Poco::UInt64 block, Poco::UInt64 baseTarget, const std::string& genSig, Poco::UInt64 blockTargetDeadline);\n\t\tvoid addMessage(const Poco::Message& message);\n\n\t\tstd::shared_ptr<Deadline> getBestDeadlineOverall(bool onlyHistorical = false) const;\n\t\tconst Poco::Timestamp& getStartTime() const;\n\t\tPoco::Timespan getRunTime() const;\n\t\tPoco::UInt64 getBlocksMined() const;\n\t\tPoco::UInt64 getBlocksWon() const;\n\t\tstd::shared_ptr<BlockData> getBlockData();\n\t\tstd::shared_ptr<const BlockData> getBlockData() const;\n\t\tstd::shared_ptr<const BlockData> getHistoricalBlockData(Poco::UInt32 roundsBefore) const;\n\t\tstd::vector<std::shared_ptr<BlockData>> getAllHistoricalBlockData() const;\n\t\tPoco::UInt64 getConfirmedDeadlines() const;\n\t\tPoco::UInt64 getAverageDeadline() const;\n\t\tPoco::Int64 getDifficultyDifference() const;\n\t\tHighscoreValue<Poco::UInt64> getLowestDifficulty() const;\n\t\tHighscoreValue<Poco::UInt64> getHighestDifficulty() const;\n\n\t\tPoco::UInt64 getCurrentBlockheight() const;\n\t\tPoco::UInt64 getCurrentBasetarget() const;\n\t\tPoco::UInt64 getCurrentScoopNum() const;\n\t\tPoco::ActiveResult<Poco::UInt64> getWonBlocksAsync(const Wallet& wallet, const Accounts& accounts);\n\n\t\tPoco::BasicEvent<const Poco::JSON::Object> blockDataChangedEvent;\n\t\tstd::vector<std::shared_ptr<BlockData>> getHistoricalBlocks(Poco::UInt64 from, Poco::UInt64 to) const;\n\n\t\tvoid forAllBlocks(Poco::UInt64 from, Poco::UInt64 to, const std::function<bool(std::shared_ptr<BlockData>&)>& traverseFunction) const;\n\n\tprotected:\n\t\tPoco::UInt64 runGetWonBlocks(const std::pair<const Wallet*, const Accounts*>& args);\n\n\tprivate:\n\t\tPoco::Timestamp startTime_ = {};\n\t\tstd::atomic<Poco::UInt64> blocksWon_;\n\t\tstd::shared_ptr<BlockData> blockData_ = nullptr, lastBlockData_ = nullptr;\n\t\tmutable Poco::Mutex mutex_;\n\n\t\tstd::unique_ptr<Poco::Data::Session> dbSession_ = nullptr;\n\n\t\tPoco::ActiveMethod<Poco::UInt64, std::pair<const Wallet*, const Accounts*>, MinerData,\n\t\t\t\t\t\t   Poco::ActiveStarter<MinerData>> activityWonBlocks_;\n\n\t\tfriend class BlockData;\n\t};\n}\n"
  },
  {
    "path": "src/mining/WorkerList.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <vector>\n#include <Poco/Task.h>\n#include <Poco/Thread.h>\n#include <memory>\n#if __cplusplus < 201402L\n#include \"MinerUtil.hpp\"\n#endif\n\nnamespace Burst\n{\n\ttemplate <typename T>\n\tclass WorkerList\n\t{\n\tpublic:\n\t\ttemplate <typename ...Args>\n\t\tWorkerList(Poco::Thread::Priority priority, size_t size, Args&&... args)\n\t\t{\n\t\t\tfor (size_t i = 0; i < size; ++i)\n\t\t\t\tcreate(priority, std::forward<Args>(args)...);\n\t\t}\n\n\t\tvoid stop()\n\t\t{\n\t\t\tfor (auto& worker : worker_)\n\t\t\t{\n\t\t\t\tworker.task->cancel();\n\t\t\t\tworker.thread->tryJoin(10 * 1000);\n\t\t\t}\n\t\t}\n\n\t\tsize_t size() const\n\t\t{\n\t\t\treturn worker_.size();\n\t\t}\n\n\t\tbool empty() const\n\t\t{\n\t\t\treturn worker_.empty();\n\t\t}\n\n\tprivate:\n\t\tstruct Worker\n\t\t{\n\t\t\tstd::shared_ptr<Poco::Task> task;\n\t\t\tstd::shared_ptr<Poco::Thread> thread;\n\t\t};\n\n\t\ttemplate <typename ...Args>\n\t\tbool create(Poco::Thread::Priority priority, Args&&... args)\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tWorker worker;\n\t\t\t\tworker.task = std::make_unique<T>(std::forward<Args>(args)...);\n\t\t\t\tworker.thread = std::make_unique<Poco::Thread>();\n\t\t\t\tworker.thread->setPriority(priority);\n\t\t\t\tworker.thread->start(*worker.task);\n\n\t\t\t\tworker_.emplace_back(worker);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcatch (...)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t}\n\n\t\tstd::vector<Worker> worker_;\n\t};\n}\n"
  },
  {
    "path": "src/network/NonceSubmitter.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"NonceSubmitter.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include \"mining/Deadline.hpp\"\n#include \"MinerUtil.hpp\"\n#include \"Request.hpp\"\n#include \"mining/MinerConfig.hpp\"\n#include \"mining/Miner.hpp\"\n#include \"logging/Output.hpp\"\n#include <chrono>\n#include <thread>\n#include <Poco/JSON/Parser.h>\n\nBurst::NonceSubmitter::NonceSubmitter(Miner& miner, const std::shared_ptr<Deadline>& deadline)\n\t: Task(serializeDeadline(*deadline)),\n\t  miner_(miner),\n\t  deadline_(deadline)\n{}\n\nvoid Burst::NonceSubmitter::runTask()\n{\n\t// ReSharper disable CppExpressionWithoutSideEffects\n\tsubmit();\n\t// ReSharper restore CppExpressionWithoutSideEffects\n}\n\nBurst::NonceConfirmation Burst::NonceSubmitter::submit() const\n{\n\treturn submit(deadline_, miner_);\n}\n\nBurst::NonceConfirmation Burst::NonceSubmitter::submit(const std::shared_ptr<Deadline>& deadline, const Miner& miner)\n{\n\tauto accountName = deadline->getAccountName();\n\tNonceConfirmation confirmation{0, SubmitResponse::None, \"\", 0, \"\"};\n\tPoco::JSON::Parser jsonParser;\n\n\tconst auto& altUrls = MinerConfig::getConfig().getPoolUrlAlt();\n\tstd::vector<Url> urls;\n\turls.reserve(altUrls.size() + 1);\n\turls.emplace_back(MinerConfig::getConfig().getPoolUrl());\n\turls.insert(urls.end(), altUrls.begin(), altUrls.end());\n\tauto urlIter = urls.begin();\n\n\tconst auto loopConditionHelper = [&deadline, &miner, &confirmation, &urls](unsigned& tryCount,\n\t                                                              unsigned maxTryCount,\n\t                                                              std::vector<Url>::iterator* urlIter)\n\t{\n\t\tif (confirmation.errorCode == SubmitResponse::Confirmed ||\n\t\t\tconfirmation.errorCode == SubmitResponse::NotBest ||\n\t\t\tdeadline->getBlock() != miner.getBlockheight())\n\t\t\treturn false;\n\n\t\tif ((maxTryCount > 0 && tryCount >= maxTryCount) || confirmation.errorCode == SubmitResponse::Error)\n\t\t{\n\t\t\tif (urlIter != nullptr)\n\t\t\t{\n\t\t\t\t++*urlIter;\n\n\t\t\t\tif (*urlIter != urls.end())\n\t\t\t\t{\n\t\t\t\t\ttryCount = 0;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tconst auto bestSent = miner.getBestSent(deadline->getAccountId(), deadline->getBlock());\n\n\t\tif (bestSent != nullptr)\n\t\t{\n\t\t\tif (bestSent->getDeadline() < deadline->getDeadline())\n\t\t\t\tconfirmation.errorCode = SubmitResponse::NotBest;\n\t\t\t\t\n\t\t\t//MinerLogger::write(\"Best sent nonce so far: \" + bestSent->deadlineToReadableString() + \" vs. this deadline: \"\n\t\t\t//+ deadlineFormat(deadline->getDeadline()), TextType::Debug);\n\t\t}\n\n\t\tif (confirmation.errorCode == SubmitResponse::NotBest)\n\t\t{\n\t\t\tlog_debug(MinerLogger::nonceSubmitter, deadline->toActionString(\"nonce discarded - not best\"));\n\t\t\treturn false;\n\t\t}\n\t\t\t\n\t\treturn true;\n\t};\n\n\t//MinerLogger::write(\"sending nonce from thread, \" + deadlineFormat(deadlineValue), TextType::System);\n\n\tunsigned submitTryCount = 0;\n\tauto firstSendAttempt = true;\n\tconst auto submissionMaxRetry = MinerConfig::getConfig().getSubmissionMaxRetry();\n\n\t// submit-loop\n\twhile (loopConditionHelper(submitTryCount, submissionMaxRetry, &urlIter))\n\t{\n\t\tNonceRequest request{MinerConfig::getConfig().createSession(*urlIter)};\n\n\t\tauto response = request.submit(*deadline);\n\t\tauto receiveTryCount = 0u;\n\n\t\tif (response.canReceive())\n\t\t{\n\t\t\tif (firstSendAttempt)\n\t\t\t{\n\t\t\t\tdeadline->send();\n\t\t\t\tconfirmation.errorCode = SubmitResponse::Submitted;\n\t\t\t\tlog_ok_if(MinerLogger::nonceSubmitter, MinerLogger::hasOutput(NonceSent), deadline->toActionString(\"nonce submitted\"));\n\t\t\t\tfirstSendAttempt = false;\n\t\t\t}\n\n\t\t\twhile (loopConditionHelper(receiveTryCount,\n\t\t\t                           MinerConfig::getConfig().getReceiveMaxRetry(),\n\t\t\t                           nullptr))\n\t\t\t{\n\t\t\t\tconfirmation = response.getConfirmation();\n\t\t\t\t++receiveTryCount;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconfirmation.errorCode = SubmitResponse::Error;\n\n\t\t\tlog_debug(MinerLogger::nonceSubmitter, deadline->toActionString(Poco::format(\"no connection to %s %u/%u\",\n\t\t\t\turlIter->getCanonical(), submitTryCount, submissionMaxRetry)));\n\t\t}\n\n\t\t++submitTryCount;\n\t\t\n\t\tif (confirmation.errorCode != SubmitResponse::Confirmed &&\n\t\t\tconfirmation.errorCode != SubmitResponse::NotBest &&\n\t\t\tconfirmation.errorCode != SubmitResponse::TooHigh &&\n\t\t\tconfirmation.errorCode != SubmitResponse::WrongBlock)\n\t\t\tstd::this_thread::sleep_for(std::chrono::seconds(3));\n\t}\n\t\n\t// it has to be the same block\n\tif (deadline->getBlock() == miner.getBlockheight())\n\t{\n\t\tif (confirmation.errorCode == SubmitResponse::Confirmed)\n\t\t{\n\t\t\t// our calculated deadlines differs from the pools one\n\t\t\tif (confirmation.deadline != deadline->getDeadline())\n\t\t\t{\n\t\t\t\tlog_error(MinerLogger::nonceSubmitter,\n\t\t\t\t\t\"The pool calculated a different deadline for your nonce than your miner has!\\n\"\n\t\t\t\t\t\"\\tPlot file: %s\\n\"\n\t\t\t\t\t\"\\tPools deadline: %s\\n\"\n\t\t\t\t\t\"\\tYour deadline: %s\",\n\t\t\t\t\tdeadline->getPlotFile(),\n\t\t\t\t\tdeadlineFormat(confirmation.deadline),\n\t\t\t\t\tdeadlineFormat(deadline->getDeadline()));\n\n\t\t\t\t// change the deadline\n\t\t\t\tdeadline->setDeadline(confirmation.deadline);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto bestConfirmed = miner.getBestConfirmed(deadline->getAccountId(), deadline->getBlock());\n\t\t\t\t//auto showConfirmation = true;\n\n\t\t\t\t// it is better to show all confirmations...\n\t\t\t\t\t// only show the confirmation, if the confirmed deadline is better then the best already confirmed\n\t\t\t\t\t//if (bestConfirmed != nullptr)\n\t\t\t\t\t//\tshowConfirmation = bestConfirmed->getDeadline() > deadline->getDeadline();\n\n\t\t\t\t//if (showConfirmation)\n\t\t\t\tlog_success_if(MinerLogger::nonceSubmitter, MinerLogger::hasOutput(NonceConfirmed), deadline->toActionString(\"nonce confirmed\"));\n\n\t\t\t\t// we have to confirm it at the very last position\n\t\t\t\t// because we work with the best confirmed deadline so far before\n\t\t\t\t// this point\n\t\t\t\tdeadline->confirm();\n\t\t\t}\n\t\t}\n\t\telse if (confirmation.errorCode == SubmitResponse::NotBest)\n\t\t\tlog_debug(MinerLogger::nonceSubmitter, deadline->toActionString(\"nonce discarded - not best\"));\n\t\telse\n\t\t{\n\t\t\tstd::vector<std::pair<std::string, std::string>> errorDescription;\n\n\t\t\tif (confirmation.errorNumber > 0)\n\t\t\t\terrorDescription.emplace_back(\"error-code\", std::to_string(confirmation.errorNumber));\n\n\t\t\tif (confirmation.errorText.empty())\n\t\t\t{\n\t\t\t\tif (!confirmation.json.empty())\n\t\t\t\t\terrorDescription.emplace_back(\"error-text\", confirmation.json);\n\t\t\t}\n\t\t\telse\n\t\t\t\terrorDescription.emplace_back(\"error-text\", confirmation.errorText);\n\n\t\t\t// sent, but not confirmed\n\t\t\tif (firstSendAttempt)\n\t\t\t\tlog_warning(MinerLogger::nonceSubmitter, deadline->toActionString(\"could not submit nonce! This is probably a network issue.\", errorDescription));\n\t\t\telse if (confirmation.errorCode == SubmitResponse::Error)\n\t\t\t\tlog_error(MinerLogger::nonceSubmitter, deadline->toActionString(\"error on submitting nonce!\", errorDescription));\n\t\t\telse\n\t\t\t\tlog_warning(MinerLogger::nonceSubmitter, deadline->toActionString(\"got no confirmation from pool!\", errorDescription));\n\t\t}\n\t}\n\telse\n\t{\n\t\tlog_debug(MinerLogger::nonceSubmitter, deadline->toActionString(\"found nonce was for the last block, stopped submitting!\"));\n\t}\n\n\treturn confirmation;\n}\n"
  },
  {
    "path": "src/network/NonceSubmitter.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <memory>\n#include <Poco/Task.h>\n#include \"Response.hpp\"\n\nnamespace Burst\n{\n\tclass Miner;\n\tclass Deadline;\n\n\tclass NonceSubmitter : public Poco::Task\n\t{\n\tpublic:\n\t\tNonceSubmitter(Miner& miner, const std::shared_ptr<Deadline>& deadline);\n\t\t~NonceSubmitter() override = default;\n\n\t\tNonceConfirmation submit() const;\n\t\tstatic NonceConfirmation submit(const std::shared_ptr<Deadline>& deadline, const Miner& miner);\n\n\t\tvoid runTask() override;\n\n\tprivate:\n\t\tMiner& miner_;\n\t\tstd::shared_ptr<Deadline> deadline_;\n\t};\n}\n"
  },
  {
    "path": "src/network/Request.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"Request.hpp\"\n#include \"Response.hpp\"\n#include \"nxt/nxt_address.h\"\n#include \"logging/MinerLogger.hpp\"\n#include \"mining/MinerConfig.hpp\"\n#include \"Poco/Net/HTTPClientSession.h\"\n#include \"Poco/Net/HTTPRequest.h\"\n#include <Poco/Net/HTTPResponse.h>\n#include <Poco/NestedDiagnosticContext.h>\n#include \"Poco/StreamCopier.h\"\n#include \"Declarations.hpp\"\n#include \"plots/PlotSizes.hpp\"\n#include <Poco/Net/HTMLForm.h>\n#include \"mining/Deadline.hpp\"\n\nusing namespace Poco::Net;\n\nBurst::Request::Request(std::unique_ptr<HTTPClientSession> session)\n\t: session_(std::move(session))\n{}\n\nBurst::Request::~Request()\n{\n\tif (session_ != nullptr)\n\t\tsession_->reset();\n}\n\nbool Burst::Request::canSend() const\n{\n\treturn session_ != nullptr;\n}\n\nBurst::Response Burst::Request::send(Poco::Net::HTTPRequest& request)\n{\n\tpoco_ndc(Request::send(Poco::Net::HTTPRequest&));\n\t\n\tif (!canSend())\n\t\treturn {nullptr};\n\n\trequest.set(\"User-Agent\", Settings::project.nameAndVersion);\n\n\ttry\n\t{\n\t\tsession_->sendRequest(request);\n\t}\n\tcatch(Poco::Exception& exc)\n\t{\n\t\tlog_error(MinerLogger::socket, \"Error on sending request\\n\"\n\t\t\t\"\\tURI:    %s %s %s\\n\"\n\t\t\t\"\\tHost:   %s\\n\"\n\t\t\t\"\\tReason: %s\",\n\t\t\trequest.getMethod(), request.getURI(), request.getVersion(), request.getHost(), exc.displayText());\n\n\t\tlog_current_stackframe(MinerLogger::socket);\n\n\t\tsession_->reset();\n\t\treturn {nullptr};\n\t}\n\n\treturn {transferSession()};\n}\n\nstd::unique_ptr<Poco::Net::HTTPClientSession> Burst::Request::transferSession()\n{\n\treturn std::move(session_);\n}\n\nBurst::NonceRequest::NonceRequest(std::unique_ptr<Poco::Net::HTTPClientSession> socket)\n\t: request_(std::move(socket))\n{}\n\nBurst::NonceResponse Burst::NonceRequest::submit(const Deadline& deadline)\n{\n\tpoco_ndc(NonceRequest::submit);\n\n\tPoco::URI uri;\n\n\turi.setPath(\"/burst\");\n\n\turi.addQueryParameter(\"requestType\", \"submitNonce\");\n\turi.addQueryParameter(\"nonce\", std::to_string(deadline.getNonce()));\n\turi.addQueryParameter(\"accountId\", std::to_string(deadline.getAccountId()));\n\turi.addQueryParameter(\"blockheight\", std::to_string(deadline.getBlock()));\n\t\n\tif (!MinerConfig::getConfig().getPassphrase().empty())\n\t\turi.addQueryParameter(\"secretPhrase\", MinerConfig::getConfig().getPassphrase());\n\t\n\tstd::string plotFileStr;\n\tconst auto& plotFileStrDecoded = deadline.getPlotFile();\n\tPoco::URI::encode(plotFileStrDecoded, \"\", plotFileStr);\n\n\tHTTPRequest request{HTTPRequest::HTTP_POST, uri.getPathAndQuery(), HTTPRequest::HTTP_1_1};\n\trequest.set(xCapacity, std::to_string(deadline.getTotalPlotsize()));\n\trequest.set(xMiner, deadline.getMiner());\n\trequest.set(xDeadline, std::to_string(deadline.getDeadline()));\n\trequest.set(xPlotfile, plotFileStr);\n\trequest.set(xWorker, deadline.getWorker());\n\trequest.setKeepAlive(false);\n\trequest.setContentLength(0);\n\n\tauto response = request_.send(request);\n\n\tif (response.canReceive())\n\t\treturn{ response.transferSession() };\n\n\treturn{ nullptr };\n}\n\nstd::unique_ptr<Poco::Net::HTTPClientSession> Burst::NonceRequest::transferSession()\n{\n\treturn request_.transferSession();\n}\n"
  },
  {
    "path": "src/network/Request.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <memory>\n#include <string>\n#include \"Response.hpp\"\n#include <Poco/Net/HTTPClientSession.h>\n\nnamespace Poco {namespace Net {\n\tclass HTTPRequest;\n}}\n\nnamespace Burst\n{\n\tconst std::string xPlotfile = \"X-Plotfile\";\n\tconst std::string xDeadline = \"X-Deadline\";\n\tconst std::string xCapacity = \"X-Capacity\";\n\tconst std::string xMiner = \"X-Miner\";\n\tconst std::string xWorker = \"X-Worker\";\n\n\tclass Deadline;\n\n\tclass Request\n\t{\n\tpublic:\n\t\tRequest(std::unique_ptr<Poco::Net::HTTPClientSession> session);\n\t\tRequest(const Request& rhs) = delete;\n\t\tRequest(Request&& rhs) = default;\n\t\t~Request();\n\n\t\tRequest& operator=(const Request& rhs) = delete;\n\t\tRequest& operator=(Request&& rhs) = default;\n\n\t\tbool canSend() const;\n\t\tResponse send(Poco::Net::HTTPRequest& request);\n\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> transferSession();\n\n\tprivate:\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> session_;\n\t};\n\n\tclass NonceRequest\n\t{\n\tpublic:\n\t\tNonceRequest(std::unique_ptr<Poco::Net::HTTPClientSession> socket);\n\n\t\tNonceResponse submit(const Deadline& deadline);\n\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> transferSession();\n\n\tprivate:\n\t\tRequest request_;\n\t};\n}\n"
  },
  {
    "path": "src/network/Response.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include <Poco/JSON/Parser.h>\n#include <Poco/NestedDiagnosticContext.h>\n#include \"Response.hpp\"\n#include \"MinerUtil.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include \"Poco/Net/HTTPClientSession.h\"\n#include \"Poco/Net/HTTPResponse.h\"\n\nusing namespace Poco::Net;\n\nBurst::Response::Response(std::unique_ptr<Poco::Net::HTTPClientSession> session)\n\t: session_(std::move(session))\n{}\n\nBurst::Response::~Response()\n{\n\tif (session_ != nullptr)\n\t\tsession_->reset();\n}\n\nbool Burst::Response::canReceive() const\n{\n\treturn session_ != nullptr;\n}\n\nbool Burst::Response::receive(std::string& data) const\n{\n\tint status;\n\treturn receive(data, status);\n}\n\nbool Burst::Response::receive(std::string& data, int& status) const\n{\n\tpoco_ndc(Response::receive);\n\t\n\tif (!canReceive())\n\t\treturn false;\n\n\ttry\n\t{\n\t\tHTTPResponse response;\n\t\tconst auto responseStream = &session_->receiveResponse(response);\n\t\tdata = {std::istreambuf_iterator<char>(*responseStream), {}};\n\t\tstatus = response.getStatus();\n\t\treturn status == HTTPResponse::HTTP_OK;\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_error(MinerLogger::socket,\n\t\t\t\"Error on receiving response!\\n%s\",\n\t\t\texc.displayText()\n\t\t);\n\n\t\tlog_current_stackframe(MinerLogger::socket);\n\n\t\tsession_->reset();\n\t\treturn false;\n\t}\n}\n\nstd::unique_ptr<Poco::Net::HTTPClientSession> Burst::Response::transferSession()\n{\n\treturn std::move(session_);\n}\n\nconst Poco::Exception* Burst::Response::getLastError() const\n{\n\treturn session_->networkException();\n}\n\nbool Burst::Response::isDataThere() const\n{\n\treturn session_->socket().poll(Poco::Timespan{60, 0},\n\t\tPoco::Net::Socket::SELECT_READ);\n}\n\nBurst::NonceConfirmation Burst::NonceConfirmation::createWrongBlock(Poco::UInt64 currentHeight, Poco::UInt64 yourHeight,\n\tPoco::UInt64 nonce, Poco::UInt64 deadline)\n{\n\tNonceConfirmation c;\n\tc.json = Poco::format(\n\t\tR\"({ \"result\" : \"Your submitted deadline is for another block!\", \"nonce\" : %Lu, \"blockheight\" : %Lu, \"currentBlockheight\" : %Lu })\",\n\t\tnonce, yourHeight, currentHeight);\n\tc.errorText = \"Your submitted deadline is for another block!\";\n\tc.errorCode = SubmitResponse::WrongBlock;\n\tc.errorNumber = 1005;\n\tc.deadline = deadline;\n\treturn c;\n}\n\nBurst::NonceConfirmation Burst::NonceConfirmation::createTooHigh(Poco::UInt64 nonce, Poco::UInt64 deadline,\n\tPoco::UInt64 targetDeadline)\n{\n\tNonceConfirmation c;\n\tc.json = Poco::format(\n\t\tR\"({ \"result\" : \"Your deadline was too high!\", \"nonce\": %Lu, \"deadline\" : %Lu, \"targetDeadline\" : %Lu, \"\" })\",\n\t\tnonce, deadline, targetDeadline);\n\tc.errorText = \"Your deadline was too high!\";\n\tc.errorCode = SubmitResponse::TooHigh;\n\tc.errorNumber = 1008;\n\tc.deadline = deadline;\n\treturn c;\n}\n\nBurst::NonceConfirmation Burst::NonceConfirmation::createNotBest(Poco::UInt64 nonce, Poco::UInt64 deadline,\n\tPoco::UInt64 best)\n{\n\tNonceConfirmation c;\n\tc.json = Poco::format(\n\t\tR\"({ \"result\" : \"Your deadline was not the best one!\", \"nonce\": %Lu, \"deadline\" : %Lu, \"bestDeadline\" : %Lu })\",\n\t\tnonce, deadline, best);\n\tc.errorText = \"Your deadline was not the best one!\";\n\tc.errorCode = SubmitResponse::NotBest;\n\tc.errorNumber = -1;\n\tc.deadline = deadline;\n\treturn c;\n}\n\nBurst::NonceConfirmation Burst::NonceConfirmation::createError(Poco::UInt64 nonce, Poco::UInt64 deadline,\n\tconst std::string& errorMessage)\n{\n\tNonceConfirmation c;\n\tc.json = Poco::format(\n\t\tR\"({ \"result\" : \"Error occured: %s!\", \"nonce\": %Lu, \"deadline\" : %Lu, \"error\" : %s })\",\n\t\terrorMessage, nonce, deadline, errorMessage);\n\tc.errorText = errorMessage;\n\tc.errorCode = SubmitResponse::Error;\n\tc.errorNumber = -1;\n\tc.deadline = deadline;\n\treturn c;\n}\n\nBurst::NonceConfirmation Burst::NonceConfirmation::createSuccess(Poco::UInt64 nonce, Poco::UInt64 deadline,\n\tconst std::string& deadlineText)\n{\n\tNonceConfirmation c;\n\tc.json = Poco::format(\n\t\tR\"({ \"result\" : \"success\", \"deadline\" : %Lu, \"deadlineText\" : \"%s\", \"deadlineString\" : \"%s\" })\",\n\t\tdeadline, deadlineText, deadlineText);\n\tc.errorText = \"Deadline confirmed!\";\n\tc.errorCode = SubmitResponse::Error;\n\tc.errorNumber = -1;\n\tc.deadline = deadline;\n\treturn c;\n}\n\nBurst::NonceResponse::NonceResponse(std::unique_ptr<HTTPClientSession> session)\n\t: response_(std::move(session))\n{}\n\nbool Burst::NonceResponse::canReceive() const\n{\n\treturn response_.canReceive();\n}\n\nBurst::NonceConfirmation Burst::NonceResponse::getConfirmation() const\n{\n\tpoco_ndc(NonceResponse::getConfirmation);\n\t\n\tstd::string response;\n\tint status;\n\tNonceConfirmation confirmation{0, SubmitResponse::None, \"\", 0, \"\"};\n\n\tif (response_.receive(response, status))\n\t{\n\t\ttry\n\t\t{\n\t\t\tPoco::JSON::Parser parser;\n\t\t\tauto root = parser.parse(response).extract<Poco::JSON::Object::Ptr>();\n\n\t\t\tconfirmation.json = response;\n\n\t\t\tif (root->has(\"deadline\"))\n\t\t\t{\n                confirmation.deadline = static_cast<Poco::UInt64>(root->get(\"deadline\"));\n\t\t\t\tconfirmation.errorCode = SubmitResponse::Confirmed;\n\t\t\t}\n\t\t\telse if (root->has(\"errorCode\"))\n\t\t\t{\n\t\t\t\tlog_warning(MinerLogger::nonceSubmitter, \"Error: %s\", root->get(\"errorDescription\").convert<std::string>());\n\t\t\t\t// we send true so we dont send it again and again\n\t\t\t\tconfirmation.errorCode = SubmitResponse::Error;\n\t\t\t}\n\t\t\telse if (root->has(\"result\"))\n\t\t\t{\n\t\t\t\tlog_warning(MinerLogger::nonceSubmitter, \"Error: %s\", root->get(\"result\").convert<std::string>());\n\t\t\t\tconfirmation.errorCode = SubmitResponse::Error;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_warning(MinerLogger::nonceSubmitter, response);\n\t\t\t\tconfirmation.errorCode = SubmitResponse::Error;\n\t\t\t}\n\t\t}\n\t\tcatch (Poco::Exception& exc)\n\t\t{\t\t\t\n\t\t\tlog_error(MinerLogger::socket,\n\t\t\t\t\"Error while waiting for confirmation!\\n%s\",\n\t\t\t\texc.displayText()\n\t\t\t);\n\t\t\t\n\t\t\tlog_current_stackframe(MinerLogger::socket);\n\n\t\t\tconfirmation.errorCode = SubmitResponse::Error;\n\t\t}\n\t}\n\telse\n\t{\n\t\tconfirmation.errorCode = SubmitResponse::Error;\n\t\tconfirmation.json = response;\n\t\tPoco::JSON::Parser jsonParser;\n\n\t\ttry\n\t\t{\n\t\t\tauto json = jsonParser.parse(response).extract<Poco::JSON::Object::Ptr>();\n\t\t\tif (json->has(\"errorDescription\"))\n\t\t\t\tconfirmation.errorText = json->getValue<std::string>(\"errorDescription\");\n\t\t\telse if (json->has(\"result\"))\n\t\t\t\tconfirmation.errorText = json->getValue<std::string>(\"result\");\n\n\t\t\tif (json->has(\"errorCode\"))\n\t\t\t\tconfirmation.errorNumber = json->getValue<int>(\"errorCode\");\n\t\t\telse\n\t\t\t\tconfirmation.errorNumber = -1;\n\t\t}\n\t\tcatch (...)\n\t\t{}\n\t}\n\n\treturn confirmation;\n}\n\nbool Burst::NonceResponse::isDataThere() const\n{\n\treturn response_.isDataThere();\n}\n\nstd::unique_ptr<Poco::Net::HTTPClientSession> Burst::NonceResponse::transferSession()\n{\n\treturn response_.transferSession();\n}\n\nconst Poco::Exception* Burst::NonceResponse::getLastError() const\n{\n\treturn response_.getLastError();\n}\n\nBurst::HttpResponse::HttpResponse(const std::string& response)\n{\n\tsetResponse(response);\n}\n\nvoid Burst::HttpResponse::setResponse(const std::string& response)\n{\n\tresponse_ = response;\n\ttokens_ = splitStr(response_, \"\\r\\n\");\n}\n\nconst std::string& Burst::HttpResponse::getResponse() const\n{\n\treturn response_;\n}\n\nconst std::string& Burst::HttpResponse::getStatus() const\n{\n\treturn getPart(0);\n}\n\nconst std::string& Burst::HttpResponse::getContentLength() const\n{\n\treturn getPart(1);\n}\n\nconst std::string& Burst::HttpResponse::getContentType() const\n{\n\treturn getPart(2);\n}\n\nconst std::string& Burst::HttpResponse::getDate() const\n{\n\treturn getPart(tokens_.size() - 2);\n}\n\nconst std::string& Burst::HttpResponse::getMessage() const\n{\n\treturn getPart(tokens_.size() - 1);\n}\n\nconst std::string& Burst::HttpResponse::getPart(size_t index) const\n{\n\tstatic std::string empty;\n\n\tif (index >= tokens_.size())\n\t\treturn empty;\n\n\treturn tokens_[index];\n}\n"
  },
  {
    "path": "src/network/Response.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <memory>\n#include <string>\n#include <vector>\n#include <Poco/Net/HTTPClientSession.h>\n\nnamespace Burst\n{\n\tclass Response\n\t{\n\tpublic:\n\t\tResponse(std::unique_ptr<Poco::Net::HTTPClientSession> session);\n\t\tResponse(const Response& rhs) = delete;\n\t\tResponse(Response&& rhs) = default;\n\t\t~Response();\n\n\t\tResponse& operator=(const Response& rhs) = delete;\n\t\tResponse& operator=(Response&& rhs) = default;\n\n\t\tbool canReceive() const;\n\t\tbool receive(std::string& data) const;\n\t\tbool receive(std::string& data, int& status) const;\n\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> transferSession();\n\t\tconst Poco::Exception* getLastError() const;\n\t\tbool isDataThere() const;\n\n\tprivate:\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> session_;\n\t};\n\n\tenum class SubmitResponse\n\t{\n\t\tConfirmed,\n\t\tSubmitted,\n\t\tNotBest,\n\t\tTooHigh,\n\t\tWrongBlock,\n\t\tError,\n\t\tFound,\n\t\tNone\n\t};\n\n\tstruct NonceConfirmation\n\t{\n\t\tPoco::UInt64 deadline;\n\t\tSubmitResponse errorCode;\n\t\tstd::string json;\n\t\tint errorNumber;\n\t\tstd::string errorText;\n\n\t\tstatic NonceConfirmation createWrongBlock(Poco::UInt64 currentHeight, Poco::UInt64 yourHeight, Poco::UInt64 nonce, Poco::UInt64 deadline);\n\t\tstatic NonceConfirmation createTooHigh(Poco::UInt64 nonce, Poco::UInt64 deadline, Poco::UInt64 targetDeadline);\n\t\tstatic NonceConfirmation createNotBest(Poco::UInt64 nonce, Poco::UInt64 deadline, Poco::UInt64 best);\n\t\tstatic NonceConfirmation createError(Poco::UInt64 nonce, Poco::UInt64 deadline, const std::string& errorMessage);\n\t\tstatic NonceConfirmation createSuccess(Poco::UInt64 nonce, Poco::UInt64 deadline, const std::string& deadlineText);\n\t};\n\n\tclass NonceResponse\n\t{\n\tpublic:\n\t\tNonceResponse(std::unique_ptr<Poco::Net::HTTPClientSession> session);\n\n\t\tbool canReceive() const;\n\t\tNonceConfirmation getConfirmation() const;\n\t\tbool isDataThere() const;\n\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> transferSession();\n\t\tconst Poco::Exception* getLastError() const;\n\n\tprivate:\n\t\tResponse response_;\n\t};\n\n\tclass HttpResponse\n\t{\n\tpublic:\n\t\tHttpResponse(const std::string& response);\n\n\t\tvoid setResponse(const std::string& response);\n\n\t\tconst std::string& getResponse() const;\n\t\tconst std::string& getStatus() const;\n\t\tconst std::string& getContentLength() const;\n\t\tconst std::string& getContentType() const;\n\t\tconst std::string& getDate() const;\n\t\tconst std::string& getMessage() const;\n\n\tprivate:\n\t\tconst std::string& getPart(size_t index) const;\n\n\t\tstd::string response_;\n\t\tstd::vector<std::string> tokens_;\n\t};\n}\n"
  },
  {
    "path": "src/network/Url.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"Url.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include <Poco/Net/HostEntry.h>\n#include <Poco/Net/HTTPSessionFactory.h>\n#include <Poco/Net/HTTPClientSession.h>\n#include <Poco/String.h>\n\nBurst::Url::Url(const std::string& url, const std::string& defaultScheme, unsigned short defaultPort)\n\t: uri_{url}\n{\n\ttry\n\t{\n\t\t// if something is wrong with the uri...\n\t\tauto invalid = uri_.getScheme().empty() || uri_.getHost().empty() || uri_.getPort() == 0;\n\t\t//\n\t\tif (invalid && !defaultScheme.empty() && !url.empty())\n\t\t{\n\t\t\t// we try to prepend the default scheme and hope that it can get resolved now\n\t\t\turi_ = defaultScheme + \"://\" + url + (defaultPort == 0 ? \"\" : \":\" + std::to_string(defaultPort));\n\n\t\t\tif (uri_.getPort() == 0)\n\t\t\t\turi_.setPort(defaultPort);\n\t\t}\n\n//\t\tif (!uri_.empty())\n//\t\t\tip_ = Poco::Net::DNS::resolveOne(uri_.getHost());\n\t}\n\tcatch (...)\n\t{}\n}\n\nstd::string Burst::Url::getCanonical(bool withScheme) const\n{\n\treturn (withScheme ? uri_.getScheme() + \"://\" : \"\") + uri_.getHost();\n}\n\nstd::string Burst::Url::getIp() const\n{\n\treturn ip_.toString();\n}\n\nuint16_t Burst::Url::getPort() const\n{\n\treturn uri_.getPort();\n}\n\nconst Poco::URI& Burst::Url::getUri() const\n{\n\treturn uri_;\n}\n\nPoco::URI& Burst::Url::getUri()\n{\n\treturn uri_;\n}\n\nbool Burst::Url::empty() const\n{\n\treturn uri_.getHost().empty() ||\n\t\turi_.getScheme().empty();\n}\n\nstd::unique_ptr<Poco::Net::HTTPClientSession> Burst::Url::createSession() const\n{\n\ttry\n\t{\n\t\treturn std::unique_ptr<Poco::Net::HTTPClientSession> {\n\t\t\tPoco::Net::HTTPSessionFactory::defaultFactory().createClientSession(uri_)\n\t\t};\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_warning(MinerLogger::session, \"Could not send request to host: unknown protocol '%s'!\\n\\tURI: %s\\n\\t%s\",\n\t\t\turi_.getScheme(), getCanonical(), exc.displayText());\n\t\tlog_current_stackframe(MinerLogger::session);\n\n\t\treturn nullptr;\n\t}\n}\n"
  },
  {
    "path": "src/network/Url.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <string>\n#include <Poco/URI.h>\n#include <Poco/Net/IPAddress.h>\n#include <memory>\n#include <functional>\n\nnamespace Poco { namespace Net\n{\n\tclass HTTPClientSession;\n\tclass HTTPSessionFactory;\n} }\n\nnamespace Burst\n{\n\tclass Url\n\t{\n\tpublic:\n\t\tUrl() = default;\n\t\tUrl(const std::string& url, const std::string& defaultScheme = \"\", unsigned short defaultPort = 0);\n\n\t\tstd::string getCanonical(bool withScheme = false) const;\n\t\tstd::string getIp() const;\n\t\tuint16_t getPort() const;\n\t\tconst Poco::URI& getUri() const;\n\t\tPoco::URI& getUri();\n\t\tbool empty() const;\n\t\tstd::unique_ptr<Poco::Net::HTTPClientSession> createSession() const;\n\n\tprivate:\n\t\tPoco::URI uri_;\n\t\tPoco::Net::IPAddress ip_;\n\t};\n}\n"
  },
  {
    "path": "src/nxt/nxt_address.cpp",
    "content": "//\n//  nxt_address.cpp\n//  cryptoport-miner\n//\n//  Created by Uray Meiviar on 9/19/14.\n//  Copyright (c) 2014 Miner. All rights reserved.\n//\n\n#include \"nxt_address.h\"\n\n#if defined _WIN32 || defined WIN32\n#\tdefine strcasecmp _stricmp \n#\tdefine strncasecmp _strnicmp \n#endif\n\nchar NxtAddress::alphabet[33] = \"23456789ABCDEFGHJKLMNPQRSTUVWXYZ\";\nchar cwmap[17] = { 3, 2, 1, 0, 7, 6, 5, 4, 13, 14, 15, 16, 12, 8, 9, 10, 11, };\nint NxtAddress::gexp[32] = { 1, 2, 4, 8, 16, 5, 10, 20, 13, 26, 17, 7, 14, 28, 29, 31, 27, 19, 3, 6, 12, 24, 21, 15, 30, 25, 23, 11, 22, 9, 18, 1 };\nint NxtAddress::glog[32] = { 0, 0, 1, 18, 2, 5, 19, 11, 3, 29, 6, 27, 20, 8, 12, 23, 4, 10, 30, 17, 7, 22, 28, 26, 21, 25, 9, 16, 13, 14, 24, 15  };\n\nNxtAddress::NxtAddress(uint64_t id)\n{\n    for(int i = 0; i < 13; i++)\n\t{\n\t\tcodeword[i] = (id >> (5 * i)) & 31;\n\t}\n    \n\tencode();\n}\n\nNxtAddress::operator uint64_t()\n{\n\tuint64_t acc = 0;\n    \n\tfor(int i = 0; i < 13; i++)\n\t{\n\t\tacc |= uint64_t(codeword[i] & 31) << (5 * i);\n\t}\n    \n\treturn acc;\n}\n\nvoid NxtAddress::operator=(uint64_t acc)\n{\n\tfor(int i = 0; i < 13; i++)\n\t{\n\t\tcodeword[i] = (acc >> (5 * i)) & 31;\n\t}\n    \n\tencode();\n}\n\nchar* NxtAddress::c_str(bool prefix)\n{\n\tstatic char out[32]; int pos = 0;\n    \n\tif(prefix){ strcpy(out, \"BURST-\"); pos = 4; }\n    \n\tfor(int i = 0; i < 17; i++)\n\t{\n\t\tout[pos++] = alphabet[(int)codeword[(int)cwmap[i]]];\n        \n\t\tif((i & 3) == 3 && i < 13) out[pos++] = '-';\n\t}\n    \n\tout[pos] = 0;\n    \n\treturn out;\n}\n\nstd::string NxtAddress::to_string()\n{\n    return std::string(this->c_str());\n}\n\nchar* NxtAddress::account_id()\n{\n\tstatic char out[21];\n    \n\tsprintf(out, \"%llu\", (unsigned long long)(*this));\n    \n\treturn out;\n}\n\nbool NxtAddress::set(char *adr)\n{\n\tint len = 0; memset(codeword, 1, 17);\n    \n\tif(!strncasecmp(adr, \"BURST-\", 4)) adr += 4;\n    \n\tsize_t digits = strspn(adr, \"0123456789 \\t\");\n    \n\tif(adr[digits] == 0) // account id\n\t{\n\t\tif(digits > 5 && digits < 21)\n\t\t{\n            uint64_t acc;\n            \n\t\t\tif(digits == 20 && *adr != '1') return false;\n\t\t\t\n\t\t\tif(sscanf(adr, \"%llu\", (unsigned long long*)(&acc)) == 1)\n\t\t\t{\n\t\t\t\t*this = acc; return true;\n\t\t\t}\n\t\t}\n\t}\n\telse // address\n\t{\n\t\twhile(*adr)\n\t\t{\n\t\t\tchar c = *adr++;\n            \n\t\t\tif(c >= 'a' && c <= 'z') c -= 'a'-'A';\n            \n\t\t\tchar *p = strchr(alphabet, c); if(!p) continue;\n            \n\t\t\tif(len > 16) return false;\n            \n\t\t\tcodeword[(int)cwmap[len++]] = (char)(p - alphabet);\n\t\t}\n\t}\n    \n\treturn (len == 17 ? ok() : false);\n}\n\nint NxtAddress::gmult(int a, int b)\n{\n    if(a == 0 || b == 0) return 0;\n\t\n    int idx = (glog[a] + glog[b]) % 31;\n\t\n    return gexp[idx];\n}\n\nvoid NxtAddress::encode()\n{\n    char *p = codeword + 13;\n    \n    p[3] = p[2] = p[1] = p[0] = 0;\n    \n    for(int i = 12; i >= 0; i--)\n    {\n        int fb = codeword[i] ^ p[3];\n        \n        p[3] = p[2] ^ gmult(30, fb);\n        p[2] = p[1] ^ gmult( 6, fb);\n        p[1] = p[0] ^ gmult( 9, fb);\n        p[0] =        gmult(17, fb);\n    }\n}\n\nbool NxtAddress::ok()\n{\n    int sum = 0;\n    int t = 0;\n\t\n    for(int i = 1; i < 5; i++)\n    {\n\t\tt = 0;\n        for(int j = 0; j < 31; j++)\n        {\n            if(j > 12 && j < 27) continue;\n            \n            int pos = j; if(j > 26) pos -= 14;\n            \n            t ^= gmult(codeword[pos], gexp[(i*j)%31]);\n        }\n        \n        sum |= t;\n        syndrome[i] = t;\n    }\n    \n    return (sum == 0);\n}\n"
  },
  {
    "path": "src/nxt/nxt_address.h",
    "content": "/*\n\tBasic NXT address (without error correction).\n\n\tMore info: http://wiki.nxtcrypto.org/wiki/New_Address_Format\n\n    Version: 1.0, license: Public Domain, coder: NxtChg (admin@nxtchg.com).\n*/\n\n#include <stdio.h>\n#include <string.h>\n#include <cstring>\n#include <stdint.h>\n#include <string>\n\nclass NxtAddress\n{\n public:\n    NxtAddress(uint64_t id);\n\tstatic char alphabet[33];\n\tchar* account_id();\n\tbool  set(char *adr);\n\tchar* c_str(bool prefix = false);\n    std::string to_string();\n\toperator uint64_t();\n\tvoid operator=(uint64_t acc);\n    \nprivate:\n    char codeword[17];\n    char syndrome[5];\n    static int gexp[32];\n    static int glog[32];\n    int gmult(int a, int b);\n    void encode();\n    bool ok();\n};\n"
  },
  {
    "path": "src/plots/Plot.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include <fstream>\n#if defined __linux__ || defined __APPLE__\n  #include <libgen.h>\n#endif\n#include \"Plot.hpp\"\n#include <Poco/SHA1Engine.h>\n#include <Poco/DigestStream.h>\n#include \"mining/Miner.hpp\"\n#include <Poco/File.h>\n#include <Poco/DirectoryIterator.h>\n#include \"logging/MinerLogger.hpp\"\n#include \"MinerUtil.hpp\"\n\n// Status of plot files on BFS file system\n#define ST_OK 1\n#define ST_INCOMPLETE 2\n\nBurst::PlotFile::PlotFile(std::string&& path, const Poco::UInt64 startPos)\n\t: path_(move(path))\n{\n\taccountId_ = stoull(getAccountIdFromPlotFile(path_));\n\tnonceStart_ = stoull(getStartNonceFromPlotFile(path_));\n\tnonces_ = stoull(getNonceCountFromPlotFile(path_));\n\tsize_ = nonces_ * Settings::plotSize;\n\n\tconst auto staggerSize = getStaggerSizeFromPlotFile(path_);\n\tconst auto version = getVersionFromPlotFile(path_);\n\n\tif (staggerSize.empty())\n\t{\n\t\tstaggerSize_ = nonces_;\n\t\tversion_ = 2;\n\t}\n\telse\n\t{\n\t\tstaggerSize_ = stoull(staggerSize);\n\t\tversion_ = 1;\n\t}\n\n\tif (!version.empty())\n\t\tversion_ = stoull(version);\n\n#if defined __linux__ || defined __APPLE__\n        if (startPos > 0ULL) {\n            devicePath_ = std::string(dirname((char *)path_.c_str()));\n        }\n#endif\n\tstartPos_ = startPos;\n}\n\nconst std::string& Burst::PlotFile::getPath() const\n{\n\treturn path_;\n}\n\nPoco::UInt64 Burst::PlotFile::getSize() const\n{\n\treturn size_;\n}\n\nPoco::UInt64 Burst::PlotFile::getAccountId() const\n{\n\treturn accountId_;\n}\n\nPoco::UInt64 Burst::PlotFile::getNonceStart() const\n{\n\treturn nonceStart_;\n}\n\nPoco::UInt64 Burst::PlotFile::getNonces() const\n{\n\treturn nonces_;\n}\n\nPoco::UInt64 Burst::PlotFile::getStaggerSize() const\n{\n\treturn staggerSize_;\n}\n\nPoco::UInt64 Burst::PlotFile::getStaggerCount() const\n{\n\tif (getStaggerSize() > 0)\n\t\treturn getNonces() / getStaggerSize();\n\treturn 1;\n}\n\nPoco::UInt64 Burst::PlotFile::getStaggerBytes() const\n{\n\treturn getStaggerSize() * Settings::plotSize;\n}\n\nPoco::UInt64 Burst::PlotFile::getStaggerScoopBytes() const\n{\n\treturn getStaggerSize() * Settings::scoopSize;\n}\n\nbool Burst::PlotFile::isOptimized() const\n{\n\treturn getStaggerCount() == getNonces();\n}\n\nbool Burst::PlotFile::isPoC(const int version) const\n{\n\tpoco_assert(version >= 0);\n\treturn version_ == static_cast<Poco::UInt64>(version);\n}\n\nconst std::string& Burst::PlotFile::getDevicePath() const\n{\n\treturn devicePath_;\n}\n\nPoco::UInt64 Burst::PlotFile::getStartPos() const\n{\n\treturn startPos_;\n}\n\nBurst::PlotDir::PlotDir(std::string plotPath, Type type)\n\t: path_{std::move(plotPath)},\n\t  type_{type},\n\t  size_{0}\n{\n\taddPlotLocation(path_);\n\trecalculateHash();\n}\n\nBurst::PlotDir::PlotDir(std::string path, const std::vector<std::string>& relatedPaths, Type type)\n\t: path_{std::move(path)},\n\t  type_{type},\n\t  size_{0}\n{\n\taddPlotLocation(path_);\n\n\tfor (const auto& relatedPath : relatedPaths)\n\t\trelatedDirs_.emplace_back(new PlotDir{relatedPath, type_});\n\n\trecalculateHash();\n}\n\nBurst::PlotDir::PlotList Burst::PlotDir::getPlotfiles(bool recursive) const\n{\n\t// copy all plot files inside this plot directory\n\tPlotList plotFiles;\n\n\tplotFiles.insert(plotFiles.end(), plotfiles_.begin(), plotfiles_.end());\n\n\tif (recursive)\n\t{\n\t\t// copy also all plot files inside all related plot directories\n\t\tfor (const auto& relatedPlotDir : getRelatedDirs())\n\t\t{\n\t\t\tauto relatedPlotFiles = relatedPlotDir->getPlotfiles(true);\n\t\t\tplotFiles.insert(std::end(plotFiles), std::begin(relatedPlotFiles), std::end(relatedPlotFiles));\n\t\t}\n\t}\n\n\treturn plotFiles;\n}\n\nconst std::string& Burst::PlotDir::getPath() const\n{\n\treturn path_;\n}\n\nPoco::UInt64 Burst::PlotDir::getSize() const\n{\n\treturn size_;\n}\n\nBurst::PlotDir::Type Burst::PlotDir::getType() const\n{\n\treturn type_;\n}\n\nstd::vector<std::shared_ptr<Burst::PlotDir>> Burst::PlotDir::getRelatedDirs() const\n{\n\treturn relatedDirs_;\n}\n\nconst std::string& Burst::PlotDir::getHash() const\n{\n\treturn hash_;\n}\n\nvoid Burst::PlotDir::rescan()\n{\n\tplotfiles_.clear();\n\tsize_ = 0;\n\n\taddPlotLocation(path_);\n\n\tfor (auto& relatedDir : relatedDirs_)\n\t\trelatedDir->rescan();\n\n\trecalculateHash();\n}\n\nbool Burst::PlotDir::addPlotLocation(const std::string& fileOrPath)\n{\n\tPoco::Path path;\n\n\tif (!path.tryParse(fileOrPath))\n\t\tthrow Poco::Exception{Poco::format(\"%s is an invalid file/dir (syntax), skipping it!\", fileOrPath)};\n\n\tPoco::File fileOrDir{path};\n\n\tif (!fileOrDir.exists())\n\t\tthrow Poco::Exception{Poco::format(\"Plot file/dir does not exist: '%s'\", path.toString())};\n\n\t// its a single plot file, add it if its really a plot file\n\tif (fileOrDir.isFile())\n\t\treturn addPlotFile(fileOrPath) != nullptr;\n\n\t// its a dir, so we need to parse all plot files in it and add them\n\tif (fileOrDir.isDirectory())\n\t{\n\t\tPoco::DirectoryIterator iter{fileOrDir};\n\t\tconst Poco::DirectoryIterator end;\n\n\t\twhile (iter != end)\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tif (iter->isFile())\n\t\t\t\t\taddPlotFile(*iter);\n\t\t\t}\n\t\t\tcatch (const Poco::Exception& e)\n\t\t\t{\n\t\t\t\tlog_warning(MinerLogger::config, \"Found an invalid plotfile, skipping it!\\n\\tPath: %s\\n\\tReason: %s\",\n\t\t\t\t\titer->path(), e.displayText());\n\t\t\t}\n\n\t\t\t++iter;\n\t\t}\n\n\t\treturn true;\n\t}\n\n#if defined __linux__ || defined __APPLE__\n    if ((fileOrPath.find(\"/dev/\") == 0) && fileOrDir.isDevice()) {\n        std::ifstream device(fileOrPath, std::ios::binary);\n        char tocData[1024];\n        std::list<std::string> toc;\n\n        device.read(tocData, 1024);\n        if (strncmp(\"BFS0\", tocData, 4) != 0)\n            throw Poco::Exception{Poco::format(\"%s has no BFS, skipping it!\", fileOrPath)};\n\n        uint32_t *uTocData = (uint32_t *)tocData;\n\n        for (int pos = 1; pos < 256; pos += 8) {\n            uint64_t key = (uint64_t)uTocData[pos] | ((uint64_t)uTocData[pos + 1] << 32);\n            uint64_t startNonce = (uint64_t)uTocData[pos + 2] | ((uint64_t)uTocData[pos + 3] << 32);\n            uint32_t nonces = uTocData[pos + 4];\n            uint32_t stagger = uTocData[pos + 5];\n            uint32_t status = uTocData[pos + 7];\n            uint64_t startPos = (((uint64_t)status & 0xffff) << 32) | (uint64_t)uTocData[pos + 6];\n\n            if (key == 0ULL)\n                continue;\n            status >>= 16;\n            if (status != ST_OK) // File is incomplete\n                continue;\n            // make a new plotfile and add it to the list\n            std::stringstream filePath;\n\t    if (stagger > 0) {\n\t\tfilePath << fileOrPath << \"/\" << key << \"_\" << startNonce << \"_\" << nonces << \"_\" << stagger;\n\t    } else {\n\t\tfilePath << fileOrPath << \"/\" << key << \"_\" << startNonce << \"_\" << nonces;\n\t    }\n            auto plotFile = std::make_shared<PlotFile>(filePath.str(), startPos);\n            plotfiles_.emplace_back(plotFile);\n            size_ += plotFile->getSize();\n        }\n        return true;\n    }\n#endif\n\n\treturn false;\n}\n\nstd::shared_ptr<Burst::PlotFile> Burst::PlotDir::addPlotFile(const Poco::File& file)\n{\n\tconst auto result = isValidPlotFile(file.path());\n\n\tif (result == PlotCheckResult::Ok)\n\t{\n\t\t// plot file is already in our list\n\t\tfor (auto& plotfile : plotfiles_)\n\t\t\tif (plotfile->getPath() == file.path())\n\t\t\t\treturn plotfile;\n\n\t\t// make a new plotfile and add it to the list\n\t\tauto plotFile = std::make_shared<PlotFile>(std::string(file.path()));\n\t\tplotfiles_.emplace_back(plotFile);\n\t\tsize_ += file.getSize();\n\n\t\treturn plotFile;\n\t}\n\n\tif (result == PlotCheckResult::EmptyParameter)\n\t\treturn nullptr;\n\n\tstd::string errorString;\n\n\tif (result == PlotCheckResult::Incomplete)\n\t\tthrow Poco::Exception{\"The plotfile is incomplete!\"};\n\n\tif (result == PlotCheckResult::InvalidParameter)\n\t\tthrow Poco::Exception{\"The plotfile has invalid parameters!\"};\n\n\tif (result == PlotCheckResult::WrongStaggersize)\n\t\tthrow Poco::Exception{\"The plotfile has an invalid staggersize!\"};\n\n\treturn nullptr;\n}\n\nvoid Burst::PlotDir::recalculateHash()\n{\n\tPoco::SHA1Engine sha;\n\tPoco::DigestOutputStream shaStream{sha};\n\n\thash_.clear();\n\n\tfor (const auto& plotFile : getPlotfiles(true))\n\t\tshaStream << plotFile->getPath();\n\n\tshaStream << std::flush;\n\thash_ = Poco::SHA1Engine::digestToHex(sha.digest());\n}\n"
  },
  {
    "path": "src/plots/Plot.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <Poco/Types.h>\n#include <memory>\n#include <vector>\n\nnamespace Poco {\n\tclass File;\n}\n\nnamespace Burst\n{\n\t/**\n\t * \\brief Represents a plotfile.\n\t * This class is not an actual representation of the physical file,\n\t * but holds meta-informations about the plotfile.\n\t */\n\tclass PlotFile\n\t{\n\tpublic:\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * \\param path The path to the plotfile.\n\t\t * \\param startPos The start position of the plotfile on the device (in bytes).\n\t\t */\n\t\tPlotFile(std::string&& path, Poco::UInt64 startPos = 0);\n\n\t\t/**\n\t\t * \\brief Returns the path to the plotfile.\n\t\t * \\return A string, that holds the path to he plotfile.\n\t\t */\n\t\tconst std::string& getPath() const;\n\n\t\t/**\n\t\t * \\brief Returns the size of the plotfile.\n\t\t * \\return The size of the plotfile in Bytes.\n\t\t */\n\t\tPoco::UInt64 getSize() const;\n\n\t\t/**\n\t\t * \\brief Returns the account id that the plotfile is bound to.\n\t\t * \\return The account id.\n\t\t */\n\t\tPoco::UInt64 getAccountId() const;\n\n\t\t/**\n\t\t * \\brief Returns the nonce, that is the first nonce of the plot file.\n\t\t * \\return The first nonce of the plotfile.\n\t\t */\n\t\tPoco::UInt64 getNonceStart() const;\n\n\t\t/**\n\t\t * \\brief Returns the number of nonces inside the plotfile.\n\t\t * \\return The size of the nonces.\n\t\t */\n\t\tPoco::UInt64 getNonces() const;\n\n\t\t/**\n\t\t * \\brief Returns the size of the stagger.\n\t\t * \\return The staggersize.\n\t\t */\n\t\tPoco::UInt64 getStaggerSize() const;\n\n\t\t/**\n\t\t * \\brief Returns the number of staggers.\n\t\t * \\return The number of the stagger, of which the plotfile consists.\n\t\t */\n\t\tPoco::UInt64 getStaggerCount() const;\n\n\t\t/**\n\t\t * \\brief Returns the size of one stagger.\n\t\t * \\return The size of a stagger in bytes.\n\t\t */\n\t\tPoco::UInt64 getStaggerBytes() const;\n\n\t\t/**\n\t\t * \\brief Returns the size of the scoops inside a stagger.\n\t\t * \\return The size of a scoop of all nonces inside a stagger in bytes.\n\t\t */\n\t\tPoco::UInt64 getStaggerScoopBytes() const;\n\n\t\t/** \n\t     * \\brief Returns, if the plot file is optimized. \n\t     * \\return true, if optimized, false otherwise. \n\t     */\n\t\tbool isOptimized() const;\n\n\t\t/** \n\t\t * \\brief Returns, if the plot file is optimized for PoC2. \n\t\t * \\return true, if optimized for PoC2, false otherwise. \n\t\t */\n\t\tbool isPoC(int version) const;\n\n        /**\n\t\t * \\brief Returns the device path for the plotfile-\n\t\t * \\return A string, that holds the device path for the plotfile.\n\t\t */\n\t\tconst std::string& getDevicePath() const;\n\n\t\t/**\n\t\t * \\brief Returns the start position of the plotfile on the device.\n\t\t * \\return The start position of the plotfile on the device (in bytes).\n\t\t */\n\t\tPoco::UInt64 getStartPos() const;\n\n\tprivate:\n\t\tstd::string path_;\n\t\tstd::string devicePath_;\n\t\tPoco::UInt64 startPos_;\n\t\tPoco::UInt64 size_;\n\t\tPoco::UInt64 accountId_, nonceStart_, nonces_, staggerSize_, version_;\n\t};\n\n\t/**\n\t * \\brief Represents a plot directory.\n\t */\n\tclass PlotDir\n\t{\n\tpublic:\n\t\t/**\n\t\t * \\brief The type of the plot directory.\n\t\t */\n\t\tenum class Type\n\t\t{\n\t\t\t/**\n\t\t\t * \\brief Sequential; all files inside the plot directory are read by max. 1 plot reader.\n\t\t\t */\n\t\t\tSequential,\n\t\t\t/**\n\t\t\t * \\brief Parallel; all files inside the plot directory are read by min. 1 plot reader.\n\t\t\t */\n\t\t\tParallel\n\t\t};\n\n\t\t/**\n\t\t * \\brief Alias for std::vector<std::shared_ptr<PlotFile>>.\n\t\t */\n\t\tusing PlotList = std::vector<std::shared_ptr<PlotFile>>;\n\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * Searches for all valid plot files inside the plot directory and adds them\n\t\t * to a local list.\n\t\t * Also a unique hash value for the specific directory is created.\n\t\t * \\param path The path of the plot directory.\n\t\t * \\param type The type of the plot directory.\n\t\t */\n\t\tPlotDir(std::string path, Type type);\n\n\t\t/**\n\t\t * \\brief Constructor.\n\t\t * Searches for all valid plot files inside the plot directory and adds them\n\t\t * to a local list.\n\t\t * Also a unique hash value for the specific directory is created.\n\t\t * \\param path The path of the plot directory.\n\t\t * \\param relatedPaths A list of all related plot directories.\n\t\t * \\param type The type of the plot directory.\n\t\t * If Parallel, files of all related directories are also considered as parallel.\n\t\t */\n\t\tPlotDir(std::string path, const std::vector<std::string>& relatedPaths, Type type);\n\n\t\t/**\n\t\t* \\brief Returns all plot files inside the directory.\n\t\t* \\param recursive If true, also all plot files in all related plot directories are gathered.\n\t\t* \\return A list of all plot files.\n\t\t*/\n\t\tPlotList getPlotfiles(bool recursive = false) const;\n\n\t\t/**\n\t\t * \\brief Returns the path of the directory.\n\t\t * \\return The absolute path of the directory.\n\t\t */\n\t\tconst std::string& getPath() const;\n\n\t\t/**\n\t\t * \\brief The size of all valid plot files inside the directory.\n\t\t * \\return The size in Bytes.\n\t\t */\n\t\tPoco::UInt64 getSize() const;\n\n\t\t/**\n\t\t * \\brief Returns the type of the directory.\n\t\t * \\return A value of \\enum Type.\n\t\t */\n\t\tType getType() const;\n\n\t\t/**\n\t\t * \\brief Returns a list of all related plot directories.\n\t\t * \\return A list of shared_ptr of all related plot directories.\n\t\t * Empty, if no related plot directories.\n\t\t */\n\t\tstd::vector<std::shared_ptr<PlotDir>> getRelatedDirs() const;\n\n\t\t/**\n\t\t * \\brief Returns the unique hash-value of the plot directory.\n\t\t * It can be used to compare different miner instances.\n\t\t * \\return A SHA1-hash represented as a string.\n\t\t */\n\t\tconst std::string& getHash() const;\n\n\t\t/**\n\t\t * \\brief Resets the list of all plot files and searches the directory again for them.\n\t\t * The unique hash value and the total size is also recalculated.\n\t\t */\n\t\tvoid rescan();\n\n\tprivate:\n\t\t/**\n\t\t * \\brief Adds a plotfile to the internal list of plotfiles, if it is a valid plotfile.\n\t\t * If the path is a directory, the function gets called recursively for every plotfile\n\t\t * inside the plot directory.\n\t\t * \\param fileOrPath The path to the plotfile or plot directory.\n\t\t * \\return true, if all plot files could be added.\n\t\t */\n\t\tbool addPlotLocation(const std::string& fileOrPath);\n\n\t\t/**\n\t\t * \\brief Adds a single plot file to the internal list of plotfiles, if it is a valid plotfile.\n\t\t * The size of the plotfile is added to the total size of the plot directory. Also \n\t\t * \\param file The file, that needs to be added.\n\t\t * \\return A shared_ptr that points to the internal created \\class PlotFile\n\t\t * If there is an error while creation, a nullptr will be returned instead.\n\t\t */\n\t\tstd::shared_ptr<PlotFile> addPlotFile(const Poco::File& file);\n\n\t\t/**\n\t\t * \\brief Calculates the unique hash value of all plot files inside the internal plotfiles list.\n\t\t */\n\t\tvoid recalculateHash();\n\n\t\tstd::string path_;\n\t\tType type_;\n\t\tPoco::UInt64 size_;\n\t\tPlotList plotfiles_;\n\t\tstd::vector<std::shared_ptr<PlotDir>> relatedDirs_;\n\t\tstd::string hash_;\n\t};\n}\n"
  },
  {
    "path": "src/plots/PlotGenerator.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"PlotGenerator.hpp\"\n#include \"Declarations.hpp\"\n#include \"shabal/MinerShabal.hpp\"\n#include \"mining/Miner.hpp\"\n#include \"PlotVerifier.hpp\"\n#include \"MinerUtil.hpp\"\n#include <fstream>\n#include <random>\n#include \"webserver/MinerServer.hpp\"\n#include <future>\n#include <thread>\n\nPoco::UInt64 Burst::PlotGenerator::generateAndCheck(Poco::UInt64 account, Poco::UInt64 nonce, const Miner& miner)\n{\n\tchar final[32];\n\tchar gendata[16 + Settings::plotSize];\n\n\tauto xv = reinterpret_cast<char*>(&account);\n\n\tfor (auto j = 0u; j <= 7; ++j)\n\t\tgendata[Settings::plotSize + j] = xv[7 - j];\n\n\txv = reinterpret_cast<char*>(&nonce);\n\n\tfor (auto j = 0u; j <= 7; ++j)\n\t\tgendata[Settings::plotSize + 8 + j] = xv[7 - j];\n\n\tfor (auto i = Settings::plotSize; i > 0; i -= Settings::hashSize)\n\t{\n\t\tShabal256Sse2 x;\n\n\t\tauto len = Settings::plotSize + 16 - i;\n\n\t\tif (len > Settings::scoopPerPlot)\n\t\t\tlen = Settings::scoopPerPlot;\n\n\t\tx.update(&gendata[i], len);\n\t\tx.close(&gendata[i - Settings::hashSize]);\n\t}\n\n\tShabal256Sse2 x;\n\tx.update(&gendata[0], 16 + Settings::plotSize);\n\tx.close(&final[0]);\n\n\t// XOR with final\n\tfor (size_t i = 0; i < Settings::plotSize; i++)\n\t\tgendata[i] ^= final[i % Settings::hashSize];\n\n\tif (miner.isPoC2())\n\t\tconvertToPoC2(gendata);\n\n\tstd::array<uint8_t, 32> target{};\n\tPoco::UInt64 result;\n\n\tconst auto generationSignature = miner.getGensig();\n\tconst auto scoop = miner.getScoopNum();\n\tconst auto basetarget = miner.getBaseTarget();\n\n\tShabal256Sse2 y;\n\ty.update(generationSignature.data(), Settings::hashSize);\n\ty.update(&gendata[scoop * Settings::scoopSize], Settings::scoopSize);\n\ty.close(target.data());\n\n\tmemcpy(&result, target.data(), sizeof(Poco::UInt64));\n\n\treturn result / basetarget;\n}\n\n\ndouble Burst::PlotGenerator::checkPlotfileIntegrity(const std::string& plotPath, Miner& miner, MinerServer& server)\n{\n\tconst auto account = Poco::NumberParser::parseUnsigned64(getAccountIdFromPlotFile(plotPath));\n\tconst auto startNonce = Poco::NumberParser::parseUnsigned64(getStartNonceFromPlotFile(plotPath));\n\tconst auto nonceCount = Poco::NumberParser::parseUnsigned64(getNonceCountFromPlotFile(plotPath));\n\tconst auto staggerSize = Poco::NumberParser::parseUnsigned64(getStaggerSizeFromPlotFile(plotPath));\n\n\t//set up random number generator\n\tstd::random_device rd;\n\tstd::mt19937 gen(rd());\n\tstd::uniform_int_distribution<Poco::UInt64> randInt(0, nonceCount);\n\n\tlog_system(MinerLogger::general, \"Validating the integrity of file \" + plotPath + \" ...\");\n\n\tconst auto checkNonces = 32ull; //number of nonces to check\n\tconst auto checkScoops = 32ull; //number of scoops to check per nonce\n\tconst auto scoopSize = Settings::scoopSize;\n\tconst auto scoopStep = Settings::scoopPerPlot / checkScoops;\n\tconst auto nonceStep = (nonceCount / checkNonces);\n\n\t// drawing random numbers to decide which scoops/nonces to check\n\tstd::vector<Poco::UInt64> scoops(checkScoops + 1);\n\tstd::vector<Poco::UInt64> nonces(checkNonces + 1);\n\tfor (Poco::UInt64 i = 0; i < (checkScoops + 1); i++) scoops[i] = randInt(gen) % scoopStep;\n\tfor (Poco::UInt64 i = 0; i < (checkNonces + 1); i++) nonces[i] = randInt(gen) % nonceStep;\n\n\t// reading the nonces from the plot file in a parallel thread\n\tstd::vector<char> readNonce(16 + scoopSize * checkNonces * checkScoops);\n\n\tstd::thread nonceReader([&]\n\t{\n\t\tconst auto nonceScoopOffset = staggerSize * scoopSize;\n\t\tfor (auto scoopInterval = 0ull; scoopInterval < checkScoops; scoopInterval++)\n\t\t{\n\t\t\twhile (miner.isProcessing()) Poco::Thread::sleep(1000);\n\n\t\t\tauto scoop = scoopInterval * scoopStep + scoops[scoopInterval];\n\t\t\tif (scoop >= Settings::scoopPerPlot) scoop = Settings::scoopPerPlot - 1;\n\n\t\t\tstd::ifstream plotFile(plotPath, std::ifstream::in | std::ifstream::binary);\n\n\t\t\tfor (auto nonceInterval = 0ull; nonceInterval < checkNonces; nonceInterval++)\n\t\t\t{\n\t\t\t\tauto nonce = startNonce + nonceInterval * nonceStep + nonces[nonceInterval];\n\t\t\t\tif (nonce >= startNonce + nonceCount) nonce = startNonce + nonceCount - 1;\n\t\t\t\tconst auto nonceStaggerOffset = ((nonce - startNonce) / staggerSize) * Settings::plotSize * staggerSize + ((nonce -\n\t\t\t\t\tstartNonce) % staggerSize) * scoopSize;\n\t\t\t\tplotFile.seekg(nonceStaggerOffset + scoop * nonceScoopOffset);\n\t\t\t\tplotFile.read(readNonce.data() + nonceInterval * scoopSize + (checkNonces * scoopInterval * scoopSize), scoopSize);\n\t\t\t}\n\t\t\tplotFile.close();\n\t\t}\n\t});\n\n\t//Generating the Nonces to compare the scoops with what we have read from the file\n\tstd::array<std::vector<char>, checkNonces> genData;\n\n\tfor (auto nonceInterval = 0ull; nonceInterval < checkNonces; nonceInterval++)\n\t{\n\t\tauto nonce = startNonce + nonceInterval * nonceStep + nonces[nonceInterval];\n\t\tif (nonce >= startNonce + nonceCount) nonce = startNonce + nonceCount - 1;\n\t\tgenData[nonceInterval] = generateSse2(account, nonce);\n\t\tif (miner.isPoC2())\n\t\t\tconvertToPoC2(genData[nonceInterval].data());\n\t}\n\n\t//waiting for read thread to finish\n\tnonceReader.join();\n\n\t//Comparing the read nonces with the generated ones\n\tauto totalIntegrity = 0.0;\n\tauto noncesChecked = 0;\n\n\tfor (auto nonceInterval = 0ull; nonceInterval < checkNonces; nonceInterval++)\n\t{\n\t\tauto nonce = startNonce + nonceInterval * nonceStep + nonces[nonceInterval];\n\t\tif (nonce >= startNonce + nonceCount) nonce = startNonce + nonceCount - 1;\n\t\tauto scoopsIntact = 0ull;\n\t\tauto scoopsChecked = 0ull;\n\n\t\tfor (auto scoopInterval = 0ull; scoopInterval < checkScoops; scoopInterval++)\n\t\t{\n\t\t\tauto scoop = scoopInterval * scoopStep + scoops[scoopInterval];\n\t\t\tif (scoop >= Settings::scoopPerPlot) scoop = Settings::scoopPerPlot - 1;\n\t\t\tconst auto scoopPos = scoop * scoopSize;\n\t\t\tconst auto nonceScoopPos = nonceInterval * scoopSize + (checkNonces*scoopInterval*scoopSize);\n\t\t\tauto bytes = 0;\n\t\t\tfor (auto i = 0ull; i < scoopSize; i++)\n\t\t\t\tif (genData[nonceInterval][scoopPos + i] == readNonce[nonceScoopPos + i]) bytes++;\n\t\t\tif (bytes == 64)\n\t\t\t\tscoopsIntact++;\n\t\t\tscoopsChecked++;\n\t\t}\n\t\tconst auto intact = 100.0 * scoopsIntact / scoopsChecked;\n\t\t//log_information(MinerLogger::general, \"Nonce %s: %s% Integrity.\", std::to_string(nonce), std::to_string(intact));\n\t\ttotalIntegrity += intact;\n\t\tnoncesChecked++;\n\t}\n\n\tif(totalIntegrity / noncesChecked < 100.0)\n\t\tlog_error(MinerLogger::general, \"Total Integrity of %s: %0.3f%%\", plotPath, totalIntegrity / noncesChecked);\n\telse\n\t\tlog_success(MinerLogger::general, \"Total Integrity of %s: %0.3f%%\", plotPath, totalIntegrity / noncesChecked);\n\n\tconst auto plotId = getAccountIdFromPlotFile(plotPath) + \"_\" + getStartNonceFromPlotFile(plotPath) + \"_\" + getNonceCountFromPlotFile(plotPath) + \"_\" + getStaggerSizeFromPlotFile(plotPath);\n\n\t//response to websockets\n\tPoco::JSON::Object json;\n\tjson.set(\"type\", \"plotcheck-result\");\n\tjson.set(\"plotID\", plotId);\n\tjson.set(\"plotIntegrity\", std::to_string(totalIntegrity / noncesChecked));\n\n\tserver.sendToWebsockets(json);\n\n\treturn totalIntegrity / noncesChecked;\n}\n\nstd::vector<char> Burst::PlotGenerator::generateSse2(const Poco::UInt64 account, const Poco::UInt64 startNonce)\n{\n\tconst auto gendata = generate<Shabal256Sse2, PlotGeneratorOperations1<Shabal256Sse2>>(account, startNonce);\n\treturn gendata[0];\n}\n\nstd::array<std::vector<char>, Burst::Shabal256Avx::HashSize> Burst::PlotGenerator::generateAvx(const Poco::UInt64 account, const Poco::UInt64 startNonce)\n{\n\treturn generate<Shabal256Avx, PlotGeneratorOperations4<Shabal256Avx>>(account, startNonce);\n}\n\nstd::array<std::vector<char>, Burst::Shabal256Sse4::HashSize> Burst::PlotGenerator::generateSse4(const Poco::UInt64 account, const Poco::UInt64 startNonce)\n{\n\treturn generate<Shabal256Sse4, PlotGeneratorOperations4<Shabal256Sse4>>(account, startNonce);\n}\n\nstd::array<std::vector<char>, Burst::Shabal256Avx2::HashSize> Burst::PlotGenerator::generateAvx2(const Poco::UInt64 account, const Poco::UInt64 startNonce)\n{\n\treturn generate<Shabal256Avx2, PlotGeneratorOperations8<Shabal256Avx2>>(account, startNonce);\n}\n\nPoco::UInt64 Burst::PlotGenerator::calculateDeadlineSse2(std::vector<char>& gendata,\n\tGensigData& generationSignature, const Poco::UInt64 scoop, const Poco::UInt64 baseTarget)\n{\n\tstd::array<std::vector<char>, 1> container = {gendata};\n\treturn calculateDeadline<Shabal256Sse2, PlotGeneratorOperations1<Shabal256Sse2>>(container, generationSignature, scoop, baseTarget)[0];\n}\n\nstd::array<Poco::UInt64, Burst::Shabal256Avx::HashSize> Burst::PlotGenerator::\n\tcalculateDeadlineAvx(std::array<std::vector<char>, Shabal256Avx::HashSize>& gendatas,\n\t\tGensigData& generationSignature, const Poco::UInt64 scoop, const Poco::UInt64 baseTarget)\n{\n\treturn calculateDeadline<Shabal256Avx, PlotGeneratorOperations4<Shabal256Avx>>(gendatas, generationSignature, scoop, baseTarget);\n}\n\nstd::array<Poco::UInt64, Burst::Shabal256Sse4::HashSize> Burst::PlotGenerator::\n\tcalculateDeadlineSse4(std::array<std::vector<char>, Shabal256Sse4::HashSize>& gendatas,\n\t\tGensigData& generationSignature, const Poco::UInt64 scoop, const Poco::UInt64 baseTarget)\n{\n\treturn calculateDeadline<Shabal256Sse4, PlotGeneratorOperations4<Shabal256Sse4>>(gendatas, generationSignature, scoop, baseTarget);\n}\n\nstd::array<Poco::UInt64, Burst::Shabal256Avx2::HashSize> Burst::PlotGenerator::\n\tcalculateDeadlineAvx2(std::array<std::vector<char>, Shabal256Avx2::HashSize>& gendatas,\n\t\tGensigData& generationSignature, const Poco::UInt64 scoop, const Poco::UInt64 baseTarget)\n{\n\treturn calculateDeadline<Shabal256Avx2, PlotGeneratorOperations8<Shabal256Avx2>>(gendatas, generationSignature, scoop, baseTarget);\n}\n\nvoid Burst::PlotGenerator::convertToPoC2(char* gendata)\n{\n\tstd::array<char, Settings::hashSize> buffer{};\n\tauto indexMirror = Settings::hashSize - Settings::scoopSize;\n\n\tfor (size_t i = 0; i < Settings::plotSize / 2; i += Settings::scoopSize)\n\t{\n\t\tconst auto scoop = &gendata[i + Settings::hashSize];\n\t\tconst auto mirrorScoop = &gendata[indexMirror + Settings::hashSize];\n\n\t\tmemcpy(buffer.data(), scoop, Settings::hashSize);\n\t\tmemcpy(scoop, mirrorScoop, Settings::hashSize);\n\t\tmemcpy(mirrorScoop, buffer.data(), Settings::hashSize);\n\n\t\tindexMirror -= Settings::scoopSize;\n\t}\n}\n"
  },
  {
    "path": "src/plots/PlotGenerator.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <Poco/Types.h>\n#include <mutex>\n#include <vector>\n#include <condition_variable>\n#include \"Declarations.hpp\"\n#include \"shabal/MinerShabal.hpp\"\n#include <future>\n#include <cstring>\n\nnamespace Burst\n{\n\tclass Miner;\n\tclass MinerServer;\n\n\tclass PlotGenerator\n\t{\n\tpublic:\n\t\tstatic Poco::UInt64 generateAndCheck(Poco::UInt64 account, Poco::UInt64 nonce, const Miner& miner);\n\t\tstatic double checkPlotfileIntegrity(const std::string& plotPath, Miner& miner, MinerServer& server);\n\n\t\tstatic std::vector<char> generateSse2(Poco::UInt64 account, Poco::UInt64 startNonce);\n\t\tstatic std::array<std::vector<char>, Shabal256Avx::HashSize> generateAvx(Poco::UInt64 account, Poco::UInt64 startNonce);\n\t\tstatic std::array<std::vector<char>, Shabal256Sse4::HashSize> generateSse4(Poco::UInt64 account, Poco::UInt64 startNonce);\n\t\tstatic std::array<std::vector<char>, Shabal256Avx2::HashSize> generateAvx2(Poco::UInt64 account, Poco::UInt64 startNonce);\n\n\t\tstatic Poco::UInt64 calculateDeadlineSse2(std::vector<char>& gendata,\n\t\t\tGensigData& generationSignature, Poco::UInt64 scoop, Poco::UInt64 baseTarget);\n\n\t\tstatic std::array<Poco::UInt64, Shabal256Avx::HashSize> calculateDeadlineAvx(\n\t\t\tstd::array<std::vector<char>, Shabal256Avx::HashSize>& gendatas,\n\t\t\tGensigData& generationSignature, Poco::UInt64 scoop, Poco::UInt64 baseTarget);\n\n\t\tstatic std::array<Poco::UInt64, Shabal256Sse4::HashSize> calculateDeadlineSse4(\n\t\t\tstd::array<std::vector<char>, Shabal256Sse4::HashSize>& gendatas,\n\t\t\tGensigData& generationSignature, Poco::UInt64 scoop, Poco::UInt64 baseTarget);\n\n\t\tstatic std::array<Poco::UInt64, Shabal256Avx2::HashSize> calculateDeadlineAvx2(\n\t\t\tstd::array<std::vector<char>, Shabal256Avx2::HashSize>& gendatas,\n\t\t\tGensigData& generationSignature, Poco::UInt64 scoop, Poco::UInt64 baseTarget);\n\n\tprivate:\n\t\ttemplate <typename TShabal, typename TOperations>\n\t\tstatic std::array<std::vector<char>, TShabal::HashSize> generate(const Poco::UInt64 account, const Poco::UInt64 startNonce)\n\t\t{\n\t\t\tstd::array<std::array<char, 32>, TShabal::HashSize> finals{};\n\t\t\tstd::array<std::vector<char>, TShabal::HashSize> gendatas{};\n\n\t\t\tfor (auto& gendata : gendatas)\n\t\t\t\tgendata.resize(16 + Settings::plotSize);\n\n\t\t\tauto xv = reinterpret_cast<const char*>(&account);\n\n\t\t\tfor (auto& gendata : gendatas)\n\t\t\t\tfor (auto j = 0u; j <= 7; ++j)\n\t\t\t\t\tgendata[Settings::plotSize + j] = xv[7 - j];\n\n\t\t\tauto nonce = startNonce;\n\n\t\t\tfor (auto& gendata : gendatas)\n\t\t\t{\n\t\t\t\txv = reinterpret_cast<char*>(&nonce);\n\t\t\t\t\n\t\t\t\tfor (auto j = 0u; j <= 7; ++j)\n\t\t\t\t\tgendata[Settings::plotSize + 8 + j] = xv[7 - j];\n\n\t\t\t\t++nonce;\n\t\t\t}\n\n\t\t\tstd::array<unsigned char*, TShabal::HashSize> gendataUpdatePtr{};\n\t\t\tstd::array<unsigned char*, TShabal::HashSize> gendataClosePtr{};\n\n\t\t\tfor (auto i = Settings::plotSize; i > 0; i -= Settings::hashSize)\n\t\t\t{\n\t\t\t\tTShabal x;\n\n\t\t\t\tauto len = Settings::plotSize + 16 - i;\n\n\t\t\t\tif (len > Settings::scoopPerPlot)\n\t\t\t\t\tlen = Settings::scoopPerPlot;\n\n\t\t\t\tfor (size_t j = 0; j < TShabal::HashSize; ++j)\n\t\t\t\t{\n\t\t\t\t\tgendataUpdatePtr[j] = reinterpret_cast<unsigned char*>(gendatas[j].data() + i);\n\t\t\t\t\tgendataClosePtr[j] = reinterpret_cast<unsigned char*>(gendatas[j].data() + i - Settings::hashSize);\n\t\t\t\t}\n\n\t\t\t\tTOperations::update(x, gendataUpdatePtr, len);\n\t\t\t\tTOperations::close(x, gendataClosePtr);\n\t\t\t}\n\n\t\t\tTShabal x;\n\n\t\t\tfor (size_t i = 0; i < TShabal::HashSize; ++i)\n\t\t\t{\n\t\t\t\tgendataUpdatePtr[i] = reinterpret_cast<unsigned char*>(gendatas[i].data());\n\t\t\t\tgendataClosePtr[i] = reinterpret_cast<unsigned char*>(&finals[i][0]);\n\t\t\t}\n\n\t\t\tTOperations::update(x, gendataUpdatePtr, 16 + Settings::plotSize);\n\t\t\tTOperations::close(x, gendataClosePtr);\n\n\t\t\t// XOR with final\n\t\t\tfor (size_t i = 0; i < TShabal::HashSize; ++i)\n\t\t\t\tfor (size_t j = 0; j < Settings::plotSize; j++)\n\t\t\t\t\tgendatas[i][j] ^= finals[i][j % Settings::hashSize];\n\n\t\t\treturn std::move(gendatas);\n\t\t}\n\n\t\ttemplate <typename TShabal, typename TOperations, typename TContainer>\n\t\tstatic std::array<Poco::UInt64, TShabal::HashSize> calculateDeadline(TContainer& container,\n\t\t\tGensigData& generationSignature, const Poco::UInt64 scoop, const Poco::UInt64 baseTarget)\n\t\t{\n\t\t\tstd::array<std::array<uint8_t, 32>, TShabal::HashSize> targets{};\n\t\t\tstd::array<Poco::UInt64, TShabal::HashSize> results{};\n\n\t\t\tstd::array<char*, TShabal::HashSize> gensigPtr{};\n\t\t\tstd::array<char*, TShabal::HashSize> updatePtr{};\n\t\t\tstd::array<char*, TShabal::HashSize> closePtr{};\n\n\t\t\tfor (size_t i = 0; i < TShabal::HashSize; ++i)\n\t\t\t{\n\t\t\t\tgensigPtr[i] = reinterpret_cast<char*>(generationSignature.data());\n\t\t\t\tupdatePtr[i] = &container[i].at(scoop * Settings::scoopSize);\n\t\t\t\tclosePtr[i] = reinterpret_cast<char*>(targets[i].data());\n\t\t\t}\n\n\t\t\tTShabal x;\n\t\t\tTOperations::update(x, gensigPtr, Settings::hashSize);\n\t\t\tTOperations::update(x, updatePtr, Settings::scoopSize);\n\t\t\tTOperations::close(x, closePtr);\n\t\t\t\n\t\t\tstd::array<Poco::UInt64, TShabal::HashSize> deadlines{};\n\n\t\t\tfor (size_t i = 0; i < TShabal::HashSize; ++i)\n\t\t\t{\n\t\t\t\tmemcpy(&deadlines[i], targets[i].data(), sizeof(Poco::UInt64));\n\t\t\t\tdeadlines[i] /= baseTarget;\n\t\t\t}\n\n\t\t\treturn deadlines;\n\t\t}\n\n\t\tstatic void convertToPoC2(char* gendata);\n\n\t\ttemplate <typename TContainer>\n\t\tstatic void convertToPoC2(TContainer& container)\n\t\t{\n\t\t\tstd::vector<std::thread> workers;\n\n\t\t\tfor (auto& gendata : container)\n\t\t\t{\n\t\t\t\tworkers.emplace_back([&]()\n\t\t\t\t{\n\t\t\t\t\tconvertToPoC2(gendata);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfor (auto& worker : workers)\n\t\t\t\tworker.join();\n\t\t}\n\t};\n\n\ttemplate <typename TShabal>\n\tstruct PlotGeneratorOperations1\n\t{\n\t\ttemplate <typename TContainer>\n\t\tstatic void update(TShabal& shabal, const TContainer& container, const Poco::UInt64 length)\n\t\t{\n\t\t\tshabal.update(container[0], length);\n\t\t}\n\n\t\ttemplate <typename TContainer>\n\t\tstatic void close(TShabal& shabal, const TContainer& container)\n\t\t{\n\t\t\tshabal.close(container[0]);\n\t\t}\n\t};\n\n\ttemplate <typename TShabal>\n\tstruct PlotGeneratorOperations4\n\t{\n\t\ttemplate <typename TContainer>\n\t\tstatic void update(TShabal& shabal, const TContainer& container, const Poco::UInt64 length)\n\t\t{\n\t\t\tshabal.update(container[0], container[1], container[2], container[3], length);\n\t\t}\n\n\t\ttemplate <typename TContainer>\n\t\tstatic void close(TShabal& shabal, const TContainer& container)\n\t\t{\n\t\t\tshabal.close(container[0], container[1], container[2], container[3]);\n\t\t}\n\t};\n\n\ttemplate <typename TShabal>\n\tstruct PlotGeneratorOperations8\n\t{\n\t\ttemplate <typename TContainer>\n\t\tstatic void update(TShabal& shabal, const TContainer& container, const Poco::UInt64 length)\n\t\t{\n\t\t\tshabal.update(container[0], container[1], container[2], container[3],\n\t\t\t\tcontainer[4], container[5], container[6], container[7], length);\n\t\t}\n\n\t\ttemplate <typename TContainer>\n\t\tstatic void close(TShabal& shabal, const TContainer& container)\n\t\t{\n\t\t\tshabal.close(container[0], container[1], container[2], container[3],\n\t\t\t\tcontainer[4], container[5], container[6], container[7]);\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "src/plots/PlotReader.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"PlotReader.hpp\"\n#include \"MinerUtil.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include \"mining/MinerConfig.hpp\"\n#include <fstream>\n#include <utility>\n#include \"mining/Miner.hpp\"\n#include <Poco/NotificationQueue.h>\n#include \"PlotVerifier.hpp\"\n#include <Poco/Timestamp.h>\n#include \"logging/Output.hpp\"\n#include \"Plot.hpp\"\n#include <Poco/FileStream.h>\n\nBurst::GlobalBufferSize Burst::PlotReader::globalBufferSize;\n\nvoid Burst::GlobalBufferSize::setMax(const Poco::UInt64 max)\n{\n\tchunkQueue.wakeUpAll();\n\n\tif (max > 0)\n\t{\n\t\tif (getMax() == max)\n\t\t\treturn;\n\n\t\tif (memoryPool_ != nullptr)\n\t\t\tmemoryPool_.reset();\n\n\t\tconst auto chunks = MinerConfig::getConfig().getBufferChunkCount();\n\t\tauto chunkSize = max / chunks;\n\n\t\tmemoryPool_ = std::make_unique<Poco::MemoryPool>(chunkSize, 0, chunks);\n\t\tmax_ = max;\n\t}\n}\n\nvoid* Burst::GlobalBufferSize::reserve()\n{\n\t// unlimited memory\n\t//if (MinerConfig::getConfig().getMaxBufferSizeRaw() == 0)\n\t//\treturn true;\n\n\ttry\n\t{\n\t\treturn memoryPool_->get();\n\t}\n\tcatch (...)\n\t{\n\t\treturn nullptr;\n\t}\n}\n\nvoid Burst::GlobalBufferSize::free(void* memory)\n{\n\t// unlimited memory\n\t//if (MinerConfig::getConfig().getMaxBufferSizeRaw() == 0)\n\t//\treturn true;\n\n\tmemoryPool_->release(memory);\n}\n\nPoco::UInt64 Burst::GlobalBufferSize::getSize() const\n{\n\tif (memoryPool_ == nullptr)\n\t\treturn 0;\n\n\treturn memoryPool_->blockSize() * memoryPool_->allocated();\n}\n\nPoco::UInt64 Burst::GlobalBufferSize::getMax() const\n{\n\treturn max_;\n}\n\nBurst::PlotReader::PlotReader(MinerData& data, std::shared_ptr<PlotReadProgress> progressRead,\n                              std::shared_ptr<PlotReadProgress> progressVerify,\n                              Poco::NotificationQueue& verificationQueue, Poco::NotificationQueue& plotReadQueue)\n\t: Task(\"PlotReader\"), data_(data), progressRead_{std::move(progressRead)}, progressVerify_{std::move(progressVerify)},\n\t  verificationQueue_{&verificationQueue},\n\t  plotReadQueue_(&plotReadQueue)\n{\n}\n\nvoid Burst::PlotReader::runTask()\n{\n\tScoopData* memoryMirror = nullptr;\n\n\twhile (!isCancelled())\n\t{\n\t\ttry\n\t\t{\n\t\t\tPoco::Notification::Ptr notification(plotReadQueue_->waitDequeueNotification());\n\t\t\tPlotReadNotification::Ptr plotReadNotification;\n\n\t\t\tif (notification)\n\t\t\t\tplotReadNotification = notification.cast<PlotReadNotification>();\n\t\t\telse\n\t\t\t\tbreak;\n\n\t\t\t// only process the current block\n\t\t\tif (data_.getCurrentBlockheight() != plotReadNotification->blockheight)\n\t\t\t\tcontinue;\n\n\t\t\tauto poc2 = false;\n\n\t\t\tif (MinerConfig::getConfig().getPoc2StartBlock() > 0)\n\t\t\t\tpoc2 = MinerConfig::getConfig().getPoc2StartBlock() <= plotReadNotification->blockheight;\n\n\t\t\tPoco::Timestamp timeStartDir;\n\n\t\t\t// check, if the incoming plot-read-notification is for the current round\n\t\t\tauto currentBlock = plotReadNotification->blockheight == data_.getCurrentBlockheight();\n\t\t\tauto& plotList = plotReadNotification->plotList;\n\n\t\t\t// put in all related plot files\n\t\t\tfor (const auto& relatedPlotList : plotReadNotification->relatedPlotLists)\n\t\t\t\tfor (const auto& relatedPlotFile : relatedPlotList.second)\n\t\t\t\t\tplotList.emplace_back(relatedPlotFile);\n\n\t\t\tfor (auto plotFileIter = plotList.begin(); plotFileIter != plotList.end() && !isCancelled() && currentBlock; ++plotFileIter)\n\t\t\t{\n\t\t\t\tauto& plotFile = **plotFileIter;\n\t\t\t\tconst auto startPos = plotFile.getStartPos();\n\t\t\t\tstd::string filePath;\n\t\t\t\tif (startPos > 0) {\n\t\t\t\t\tfilePath = plotFile.getDevicePath();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfilePath = plotFile.getPath();\n\t\t\t\t}\n\t\t\t\tLowLevelFileStream inputStream{filePath};\n\t\t\t\tPlotReadProgressGuard progressGuard{progressRead_, plotFile.getNonces(), plotReadNotification->blockheight};\n\t\t\t\tconst auto progressGuardVerify = std::make_shared<PlotReadProgressGuard>(\n\t\t\t\t\tprogressVerify_, plotFile.getNonces(), plotReadNotification->blockheight);\n\n\t\t\t\tPoco::Timestamp timeStartFile;\n\n\t\t\t\tif (!isCancelled() && inputStream)\n\t\t\t\t{\n\t\t\t\t\tif (plotReadNotification->wakeUpCall)\n\t\t\t\t\t{\n\t\t\t\t\t\t// its just a wake up call for the HDD, simply read the first byte\n\t\t\t\t\t\tchar dummyByte;\n\n\t\t\t\t\t\tif (inputStream.read(&dummyByte, sizeof dummyByte))\n\t\t\t\t\t\t\tlog_debug(MinerLogger::plotReader, \"Woke up the HDD %s\", plotReadNotification->dir);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tlog_error(MinerLogger::plotReader, \"Could not wake up HDD %s\", plotReadNotification->dir);\n\n\t\t\t\t\t\t// ... and then jump to the next notification, no need to search for deadlines\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst auto maxBufferSize = MinerConfig::getConfig().getMaxBufferSizeRaw();\n\t\t\t\t\tauto chunkBytes = MinerConfig::getConfig().getMaxBufferSize() / MinerConfig::getConfig().getBufferChunkCount();\n\n\t\t\t\t\t// unlimited buffer size\n\t\t\t\t\tif (maxBufferSize == 0)\n\t\t\t\t\t\tchunkBytes = plotFile.getStaggerScoopBytes();\n\n\t\t\t\t\tconst auto noncesPerChunk = std::min(chunkBytes / Settings::scoopSize, plotFile.getStaggerSize());\n\t\t\t\t\tauto nonce = 0ull;\n\n\t\t\t\t\twhile (nonce < plotFile.getNonces() && currentBlock && !isCancelled())\n\t\t\t\t\t{\n\t\t\t\t\t\tconst auto startNonce = nonce;\n\t\t\t\t\t\tauto readNonces = noncesPerChunk;\n\t\t\t\t\t\tconst auto staggerBegin = startNonce / plotFile.getStaggerSize();\n\t\t\t\t\t\tconst auto staggerEnd = (startNonce + readNonces) / plotFile.getStaggerSize();\n\n\t\t\t\t\t\tif (staggerBegin != staggerEnd)\n\t\t\t\t\t\t\treadNonces = plotFile.getStaggerSize() - startNonce % plotFile.getStaggerSize();\n\n\t\t\t\t\t\tconst auto memoryToAcquire = std::min(readNonces * Settings::scoopSize, chunkBytes);\n\t\t\t\t\t\tScoopData* memory = nullptr;\n\n\t\t\t\t\t\twhile (!isCancelled() && memory == nullptr)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmemory = reinterpret_cast<ScoopData*>(globalBufferSize.reserve());\n\n\t\t\t\t\t\t\tif (memory == nullptr)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tstd::this_thread::sleep_for(std::chrono::milliseconds{38});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (poc2 && !plotFile.isPoC(2))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\twhile (!isCancelled() && memoryMirror == nullptr)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tmemoryMirror = reinterpret_cast<ScoopData*>(globalBufferSize.reserve());\n\n\t\t\t\t\t\t\t\t\tif (memoryMirror == nullptr)\n\t\t\t\t\t\t\t\t\t\tstd::this_thread::sleep_for(std::chrono::milliseconds{38});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// if the reader is cancelled, jump out of the loop\n\t\t\t\t\t\tif (isCancelled())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// but first give free the allocated memory\n\t\t\t\t\t\t\tif (memory != nullptr)\n\t\t\t\t\t\t\t\tglobalBufferSize.free(memory);\n\n\t\t\t\t\t\t\tif (memoryMirror != nullptr)\n\t\t\t\t\t\t\t\tglobalBufferSize.free(memoryMirror);\n\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (memory != nullptr && currentBlock)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst auto chunkOffset = startNonce % plotFile.getStaggerSize() * Settings::scoopSize;\n\t\t\t\t\t\t\tconst auto staggerBlockOffset = staggerBegin * plotFile.getStaggerBytes();\n\t\t\t\t\t\t\tconst auto staggerScoopOffset = plotReadNotification->scoopNum * plotFile.getStaggerScoopBytes();\n\n\t\t\t\t\t\t\tVerifyNotification::Ptr verification(new VerifyNotification{});\n\t\t\t\t\t\t\tverification->accountId = plotFile.getAccountId();\n\t\t\t\t\t\t\tverification->nonceStart = plotFile.getNonceStart();\n\t\t\t\t\t\t\tverification->block = plotReadNotification->blockheight;\n\t\t\t\t\t\t\tverification->inputPath = plotFile.getPath();\n\t\t\t\t\t\t\tverification->gensig = plotReadNotification->gensig;\n\t\t\t\t\t\t\tverification->nonceRead = startNonce;\n\t\t\t\t\t\t\tverification->baseTarget = plotReadNotification->baseTarget;\n\t\t\t\t\t\t\tverification->nonces = readNonces;\n\t\t\t\t\t\t\tverification->buffer = memory;\n\t\t\t\t\t\t\tverification->progress = progressGuardVerify;\n\n\t\t\t\t\t\t\tconst auto offset = startPos + staggerBlockOffset + staggerScoopOffset + chunkOffset;\n\n\t\t\t\t\t\t\tif (!inputStream.seekg(offset))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlog_error(MinerLogger::plotReader, \"Could not set the read position of '%s' to %Lu (nonce %Lu)\",\n\t\t\t\t\t\t\t\t\tplotFile.getPath(), offset, offset / Settings::plotSize);\n\t\t\t\t\t\t\t\tglobalBufferSize.free(memory);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!inputStream.read(reinterpret_cast<char*>(verification->buffer), memoryToAcquire))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlog_error(MinerLogger::plotReader,\n\t\t\t\t\t\t\t\t\t\"Could not read %Lu bytes (%Lu nonces) of '%s' at position %Lu (mirror nonce), file size is %Lu\",\n\t\t\t\t\t\t\t\t\tmemoryToAcquire, memoryToAcquire / Settings::plotSize, plotFile.getPath(), offset, plotFile.getSize());\n\t\t\t\t\t\t\t\tglobalBufferSize.free(memory);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (memoryMirror != nullptr)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tconst auto staggerScoopOffsetMirror = (4095 - plotReadNotification->scoopNum) * plotFile.getStaggerScoopBytes();\n\t\t\t\t\t\t\t\tconst auto offsetMirror = startPos + staggerBlockOffset + staggerScoopOffsetMirror + chunkOffset;\n\n\t\t\t\t\t\t\t\tif (!inputStream.seekg(offsetMirror))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tlog_error(MinerLogger::plotReader, \"Could not set read position of %s to %Lu (mirror nonce %Lu)\",\n\t\t\t\t\t\t\t\t\t\tplotFile.getPath(), offsetMirror, offsetMirror / Settings::plotSize);\n\t\t\t\t\t\t\t\t\tglobalBufferSize.free(memoryMirror);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (!inputStream.read(reinterpret_cast<char*>(memoryMirror), memoryToAcquire))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tlog_error(MinerLogger::plotReader,\n\t\t\t\t\t\t\t\t\t\t\"Could not read %Lu bytes (%Lu nonces) of '%s' at position %Lu (mirror nonce), file size is %Lu\",\n\t\t\t\t\t\t\t\t\t\tmemoryToAcquire, memoryToAcquire / Settings::plotSize, plotFile.getPath(), offsetMirror, plotFile.getSize());\n\t\t\t\t\t\t\t\t\tglobalBufferSize.free(memoryMirror);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfor (size_t i = 0; i < readNonces; ++i)\n\t\t\t\t\t\t\t\t\tmemcpy(&verification->buffer[i][32], &memoryMirror[i][32], 32);\n\n\t\t\t\t\t\t\t\tglobalBufferSize.free(memoryMirror);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tverificationQueue_->enqueueNotification(verification);\n\n\t\t\t\t\t\t\t// check, if the incoming plot-read-notification is for the current round\n\t\t\t\t\t\t\tcurrentBlock = plotReadNotification->blockheight == data_.getCurrentBlockheight();\n\t\t\t\t\t\t\tnonce += readNonces;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// if the memory was acquired, but it was not the right block, give it free\n\t\t\t\t\t\telse if (memory != nullptr)\n\t\t\t\t\t\t\tglobalBufferSize.free(memory);\n\t\t\t\t\t\t// this should never happen.. no memory allocated, not cancelled, wrong block\n\t\t\t\t\t\telse;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// check, if the incoming plot-read-notification is for the current round\n\t\t\t\tcurrentBlock = plotReadNotification->blockheight == data_.getCurrentBlockheight();\n\n\t\t\t\tif (!isCancelled() && currentBlock)\n\t\t\t\t{\n\t\t\t\t\tconst auto fileReadDiff = timeStartFile.elapsed();\n\t\t\t\t\tconst auto fileReadDiffSeconds = static_cast<float>(fileReadDiff) / 1000 / 1000;\n\t\t\t\t\tconst Poco::Timespan span{fileReadDiff};\n\n\t\t\t\t\tconst auto plotListSize = plotReadNotification->plotList.size();\n\n\t\t\t\t\tif (plotListSize > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tdata_.getBlockData()->setProgress(\n\t\t\t\t\t\t\tplotReadNotification->dir,\n\t\t\t\t\t\t\tstatic_cast<float>(std::distance(plotReadNotification->plotList.begin(), plotFileIter) + 1) / plotListSize\n\t\t\t\t\t\t\t* 100.f,\n\t\t\t\t\t\t\tplotReadNotification->blockheight\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst auto nonceBytes = static_cast<double>(plotFile.getNonces() * Settings::scoopSize);\n\t\t\t\t\tconst auto bytesPerSeconds = nonceBytes / fileReadDiffSeconds;\n\n\t\t\t\t\tlog_information_if(MinerLogger::plotReader, MinerLogger::hasOutput(PlotDone), \"%s (%s) read in %ss (~%s/s)\",\n\t\t\t\t\t\tplotFile.getPath(),\n\t\t\t\t\t\tmemToString(plotFile.getSize(), 2),\n\t\t\t\t\t\tPoco::DateTimeFormatter::format(span, \"%s.%i\"),\n\t\t\t\t\t\tmemToString(static_cast<Poco::UInt64>(bytesPerSeconds), 2));\n\t\t\t\t}\n\n\t\t\t\t// if it was cancelled, we push the current plot dir back in the queue again\n\t\t\t\tif (isCancelled())\n\t\t\t\t\tplotReadQueue_->enqueueNotification(plotReadNotification);\n\t\t\t}\n\n\t\t\tif (plotReadNotification->wakeUpCall)\n\t\t\t\tcontinue;\n\n\t\t\tdata_.getBlockData()->setProgress(plotReadNotification->dir, 100.f, plotReadNotification->blockheight);\n\n\t\t\tconst auto dirReadDiff = timeStartDir.elapsed();\n\t\t\tconst auto dirReadDiffSeconds = static_cast<float>(dirReadDiff) / 1000 / 1000;\n\t\t\tconst Poco::Timespan span{dirReadDiff};\n\n\t\t\tPoco::UInt64 totalSizeBytes = 0u;\n\n\t\t\tfor (const auto& plot : plotReadNotification->plotList)\n\t\t\t\ttotalSizeBytes += plot->getSize();\n\n\t\t\tif (plotReadNotification->type == PlotDir::Type::Sequential && totalSizeBytes > 0 && currentBlock)\n\t\t\t{\n\t\t\t\tconst auto sumNonces = totalSizeBytes / Settings::plotSize;\n\t\t\t\tconst auto sumNoncesBytes = static_cast<float>(sumNonces * Settings::scoopSize);\n\t\t\t\tconst auto bytesPerSecond = sumNoncesBytes / dirReadDiffSeconds;\n\n\t\t\t\tstd::stringstream sstr;\n\n\t\t\t\tsstr << plotReadNotification->dir;\n\n\t\t\t\tfor (const auto& relatedPlotList : plotReadNotification->relatedPlotLists)\n\t\t\t\t\tsstr << \" + \" << relatedPlotList.first;\n\n\t\t\t\tlog_information_if(MinerLogger::plotReader, MinerLogger::hasOutput(DirDone),\n\t\t\t\t\t\"Dir %s read in %ss (~%s/s), %z %s (%s)\",\n\t\t\t\t\tsstr.str(),\n\t\t\t\t\tPoco::DateTimeFormatter::format(span, \"%s.%i\"),\n\t\t\t\t\tmemToString(static_cast<Poco::UInt64>(bytesPerSecond), 2),\n\t\t\t\t\tplotReadNotification->plotList.size(),\n\t\t\t\t\tplotReadNotification->plotList.size() == 1 ? std::string(\"file\") : std::string(\"files\"),\n\t\t\t\t\tmemToString(totalSizeBytes, 2));\n\t\t\t}\n\t\t}\n\t\tcatch (Poco::Exception& exc)\n\t\t{\n\t\t\tlog_fatal(MinerLogger::plotReader, \"A plotreader just crashed while reading!\");\n\t\t\tlog_exception(MinerLogger::plotReader, exc);\n\t\t}\n\t\tcatch (std::exception& exc)\n\t\t{\n\t\t\tlog_fatal(MinerLogger::plotReader, \"A plotreader just crashed while reading!\\n\"\n\t\t\t\t\"\\tReason: %s\", std::string(exc.what()));\n\t\t}\n\t}\n}\n\nvoid Burst::PlotReadProgress::reset(Poco::UInt64 blockheight, uintmax_t max)\n{\n\tstd::lock_guard<std::mutex> guard(mutex_);\n\tprogress_ = 0;\n\tblockheight_ = blockheight;\n\tmax_ = max;\n}\n\nvoid Burst::PlotReadProgress::add(uintmax_t value, Poco::UInt64 blockheight)\n{\n\t{\n\t\tstd::lock_guard<std::mutex> guard(mutex_);\n\n\t\tif (blockheight != blockheight_)\n\t\t\treturn;\n\n\t\tprogress_ += value;\n\t}\n\n\tfireProgressChanged();\n}\n\nbool Burst::PlotReadProgress::isReady() const\n{\n\tstd::lock_guard<std::mutex> guard(mutex_);\n\treturn progress_ >= max_;\n}\n\nuintmax_t Burst::PlotReadProgress::getValue() const\n{\n\tstd::lock_guard<std::mutex> guard(mutex_);\n\treturn progress_;\n}\n\nfloat Burst::PlotReadProgress::getProgress() const\n{\n\tstd::lock_guard<std::mutex> guard(mutex_);\n\n\tif (max_ == 0.f)\n\t\treturn 0.f;\n\n\treturn progress_ * 1.f / max_ * 100;\n}\n\nvoid Burst::PlotReadProgress::fireProgressChanged()\n{\n\tauto progress = getProgress();\n\tprogressChanged.notify(this, progress);\n}\n\nBurst::PlotReadProgressGuard::PlotReadProgressGuard(std::shared_ptr<PlotReadProgress> progress, const Poco::UInt64 nonces,\n\tconst Poco::UInt64 blockheight)\n\t: progress_(std::move(progress)), nonces_(nonces), blockheight_(blockheight)\n{\n}\n\nBurst::PlotReadProgressGuard::~PlotReadProgressGuard()\n{\n\tprogress_->add(nonces_ * Settings::plotSize, blockheight_);\n}\n"
  },
  {
    "path": "src/plots/PlotReader.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <string>\n#include <vector>\n#include <memory>\n#include <thread>\n#include <mutex>\n#include \"Declarations.hpp\"\n#include <Poco/Task.h>\n#include <atomic>\n#include <Poco/Notification.h>\n#include \"mining/MinerConfig.hpp\"\n#include \"Plot.hpp\"\n#include <Poco/NotificationQueue.h>\n#include <Poco/MemoryPool.h>\n\nnamespace Poco\n{\n\tclass NotificationQueue;\n}\n\nnamespace Burst\n{\n\tclass MinerData;\n\tclass PlotReadProgress;\n\n\tclass GlobalBufferSize\n\t{\n\tpublic:\n\t\tvoid setMax(Poco::UInt64 max);\n\t\tvoid* reserve();\n\t\tvoid free(void* memory);\n\t\t\n\t\tPoco::UInt64 getSize() const;\n\t\tPoco::UInt64 getMax() const;\n\n\t\tPoco::NotificationQueue chunkQueue;\n\n\tprivate:\n\t\tPoco::Event reserveEvent_;\n\t\tPoco::UInt64 max_;\n\t\tstd::unique_ptr<Poco::MemoryPool> memoryPool_;\n\t};\n\n\tstruct PlotReadNotification : Poco::Notification\n\t{\n\t\ttypedef Poco::AutoPtr<PlotReadNotification> Ptr;\n\t\tstd::string dir;\n\t\tstd::vector<std::shared_ptr<PlotFile>> plotList;\n\t\tPoco::UInt64 scoopNum = 0;\n\t\tGensigData gensig;\n\t\tPoco::UInt64 blockheight = 0;\n\t\tPoco::UInt64 baseTarget = 0;\n\t\tstd::vector<std::pair<std::string, std::vector<std::shared_ptr<PlotFile>>>> relatedPlotLists;\n\t\tPlotDir::Type type = PlotDir::Type::Sequential;\n\t\tbool wakeUpCall = false;\n\t};\n\n\tclass PlotReader : public Poco::Task\n\t{\n\tpublic:\n\t\tPlotReader(MinerData& data, std::shared_ptr<PlotReadProgress> progressRead,\n\t\t\tstd::shared_ptr<PlotReadProgress> progressVerify,\n\t\t\tPoco::NotificationQueue& verificationQueue, Poco::NotificationQueue& plotReadQueue);\n\t\t~PlotReader() override = default;\n\n\t\tvoid runTask() override;\n\n\t\tstatic GlobalBufferSize globalBufferSize;\n\n\tprivate:\n\t\tMinerData& data_;\n\t\tstd::shared_ptr<PlotReadProgress> progressRead_, progressVerify_;\n\t\tPoco::NotificationQueue* verificationQueue_;\n\t\tPoco::NotificationQueue* plotReadQueue_;\n\t};\n\n\tclass PlotReadProgress\n\t{\n\tpublic:\n\t\tvoid reset(Poco::UInt64 blockheight, uintmax_t max);\n\t\tvoid add(uintmax_t value, Poco::UInt64 blockheight);\n\t\tbool isReady() const;\n\t\tuintmax_t getValue() const;\n\t\tfloat getProgress() const;\n\n\t\tPoco::BasicEvent<float> progressChanged;\n\n\tprivate:\n\t\tuintmax_t progress_ = 0, max_ = 0;\n\t\tPoco::UInt64 blockheight_ = 0;\n\t\tmutable std::mutex mutex_;\n\n\t\tvoid fireProgressChanged();\n\t};\n\n\tclass PlotReadProgressGuard\n\t{\n\tpublic:\n\t\tPlotReadProgressGuard(std::shared_ptr<PlotReadProgress> progress, Poco::UInt64 nonces, Poco::UInt64 blockheight);\n\t\t~PlotReadProgressGuard();\n\n\tprivate:\n\t\tstd::shared_ptr<PlotReadProgress> progress_;\n\t\tPoco::UInt64 nonces_, blockheight_;\n\t};\n}\n"
  },
  {
    "path": "src/plots/PlotSizes.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"PlotSizes.hpp\"\n#include \"logging/MinerLogger.hpp\"\n\nstd::map<Poco::Net::IPAddress, Burst::PlotSizes::HistoricalPlotSize> Burst::PlotSizes::sizes_;\nPoco::Mutex Burst::PlotSizes::mutex_;\n\nvoid Burst::PlotSizes::set(const Poco::Net::IPAddress& ip, const Poco::UInt64 size, const bool local)\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\tHistoricalPlotSize historicalSize;\n\thistoricalSize.size = size;\n\thistoricalSize.age = 0;\n\thistoricalSize.local = local;\n\n\tsizes_[ip] = historicalSize;\n}\n\nPoco::UInt64 Burst::PlotSizes::get(const Poco::Net::IPAddress& ip)\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\tconst auto iter = sizes_.find(ip);\n\n\tif (iter != sizes_.end())\n\t\treturn (*iter).second.size;\n\n\treturn 0;\n}\n\nPoco::UInt64 Burst::PlotSizes::getTotal(const Type type, const Poco::UInt64 maxAge) \n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\tPoco::UInt64 sum = 0;\n\n\tfor (auto& size : sizes_)\n\t{\n\t\tif (maxAge == 0 || size.second.age <= maxAge)\n\t\t{\n\t\t\tif (type == Type::Local && size.second.local)\n\t\t\t\tsum += size.second.size;\n\t\t\telse if (type == Type::Remote && !size.second.local)\n\t\t\t\tsum += size.second.size;\n\t\t\telse if (type == Type::Combined)\n\t\t\t\tsum += size.second.size;\n\t\t}\n\t}\n\n\treturn sum / 1024 / 1024 / 1024; //returns total plotsize in GB\n}\n\nPoco::UInt64 Burst::PlotSizes::getTotalBytes(const Type type, const Poco::UInt64 maxAge)\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\tPoco::UInt64 sum = 0;\n\n\tfor (auto& size : sizes_)\n\t{\n\t\tif (maxAge == 0 || size.second.age <= maxAge)\n\t\t{\n\t\t\tif (type == Type::Local && size.second.local)\n\t\t\t\tsum += size.second.size;\n\t\t\telse if (type == Type::Remote && !size.second.local)\n\t\t\t\tsum += size.second.size;\n\t\t\telse if (type == Type::Combined)\n\t\t\t\tsum += size.second.size;\n\t\t}\n\t}\n\n\treturn sum;\n}\n\nvoid Burst::PlotSizes::nextRound()\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{mutex_};\n\n\tfor (auto& size : sizes_)\n\t\tsize.second.age++;\n}\n\nvoid Burst::PlotSizes::refresh(const Poco::Net::IPAddress& ip)\n{\n\tconst auto iter = sizes_.find(ip);\n\n\tif (iter != sizes_.end())\n\t\titer->second.age = 0;\n}\n"
  },
  {
    "path": "src/plots/PlotSizes.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <map>\n#include <Poco/Mutex.h>\n#include <Poco/Net/IPAddress.h>\n\nnamespace Burst\n{\n\tclass PlotSizes\n\t{\n\tpublic:\n\t\tenum class Type\n\t\t{\n\t\t\tLocal,\n\t\t\tRemote,\n\t\t\tCombined\n\t\t};\n\n\tpublic:\n\t\t~PlotSizes() = delete;\n\n\t\t/**\n\t\t * \\brief Sets or adds the size of all plot files of a miner.\n\t\t * \\param ip The id of the miner.\n\t\t * \\param size The size of all plot files.\n\t\t * \\param local True, if the plot sizes belongs to the local computer.\n\t\t */\n\t\tstatic void set(const Poco::Net::IPAddress& ip, Poco::UInt64 size, bool local);\n\n\t\t/**\n\t\t * \\brief Gets the sum size of all plot files of one miner in the cluster.\n\t\t * \\param ip The id of the miner.\n\t\t * \\return The amount of plot size in GB (0 if the miner is not in the cluster).\n\t\t */\n\t\tstatic Poco::UInt64 get(const Poco::Net::IPAddress& ip);\n\n\t\t/**\n\t\t * \\brief Gets the sum size of all plot files from all miners in the cluster.\n\t\t * \\param type Filters the size.\n\t\t * \\param maxAge Only count sizes that were updated in the last maxAge rounds.\n\t\t * If 0, all sizes are summed up.\n\t\t * \\return The total amount of plot size in GB.\n\t\t */\n\t\tstatic Poco::UInt64 getTotal(Type type, Poco::UInt64 maxAge = 10);\n\t\tstatic Poco::UInt64 getTotalBytes(Type type, Poco::UInt64 maxAge = 10);\n\n\t\t/**\n\t\t * \\brief Adds one round to all plots sizes.\n\t\t * This is useful in combination with getTotal().\n\t\t */\n\t\tstatic void nextRound();\n\n\t\t/**\n\t\t * \\brief Resets the age of a the plots size of a miner.\n\t\t * \\param ip The id of the miner.\n\t\t */\n\t\tstatic void refresh(const Poco::Net::IPAddress& ip);\n\n\tprivate:\n\t\tstruct HistoricalPlotSize\n\t\t{\n\t\t\tPoco::UInt64 size = 0;\n\t\t\tPoco::UInt64 age = 0;\n\t\t\tbool local = false;\n\t\t};\n\n\t\tstatic Poco::Mutex mutex_;\n\t\tstatic std::map<Poco::Net::IPAddress, HistoricalPlotSize> sizes_;\n\t};\n}\n"
  },
  {
    "path": "src/plots/PlotVerifier.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"PlotVerifier.hpp\"\n"
  },
  {
    "path": "src/plots/PlotVerifier.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <Poco/Task.h>\n#include \"Declarations.hpp\"\n#include <Poco/AutoPtr.h>\n#include <Poco/Notification.h>\n#include <Poco/NotificationQueue.h>\n#include \"shabal/MinerShabal.hpp\"\n#include \"mining/Miner.hpp\"\n#include \"logging/Message.hpp\"\n#include \"logging/MinerLogger.hpp\"\n#include \"PlotReader.hpp\"\n#include \"gpu/gpu_shell.hpp\"\n#include \"gpu/algorithm/gpu_algorithm_atomic.hpp\"\n#include \"libShabal.h\"\n\nnamespace Burst\n{\n\tclass PlotReadProgressGuard;\n\n\tstruct VerifyNotification : Poco::Notification\n\t{\n\t\ttypedef Poco::AutoPtr<VerifyNotification> Ptr;\n\n\t\tScoopData* buffer = nullptr;\n\t\tPoco::UInt64 accountId = 0;\n\t\tPoco::UInt64 nonceRead = 0;\n\t\tPoco::UInt64 nonceStart = 0;\n\t\tstd::string inputPath = \"\";\n\t\tPoco::UInt64 block = 0;\n\t\tGensigData gensig;\n\t\tPoco::UInt64 baseTarget = 0;\n\t\tPoco::UInt64 nonces = 0;\n\t\tstd::shared_ptr<PlotReadProgressGuard> progress;\n\t};\n\t\n\tusing DeadlineTuple = std::pair<Poco::UInt64, Poco::UInt64>;\n\tusing SubmitFunction = std::function<void(Poco::UInt64, Poco::UInt64, Poco::UInt64, Poco::UInt64, std::string, bool)>;\n\n\ttemplate <typename TVerificationAlgorithm>\n\tclass PlotVerifier : public Poco::Task\n\t{\n\tpublic:\n\t\tPlotVerifier(MinerData& data, Poco::NotificationQueue& queue, SubmitFunction submitFunction);\n\t\t~PlotVerifier() override;\n\t\tvoid runTask() override;\n\t\t\n\tprivate:\n\t\tMinerData* data_;\n\t\tPoco::NotificationQueue* queue_;\n\t\tSubmitFunction submitFunction_;\n\t};\n\n\ttemplate <typename TVerificationAlgorithm>\n\tPlotVerifier<TVerificationAlgorithm>::PlotVerifier(MinerData& data, Poco::NotificationQueue& queue, SubmitFunction submitFunction)\n\t\t: Task(\"PlotVerifier\"), data_{&data}, queue_{&queue}, submitFunction_{submitFunction}\n\t{\n\t}\n\n\ttemplate <typename TVerificationAlgorithm>\n\tPlotVerifier<TVerificationAlgorithm>::~PlotVerifier()\n\t{\n\t}\n\n\ttemplate <typename TVerificationAlgorithm>\n\tvoid PlotVerifier<TVerificationAlgorithm>::runTask()\n\t{\n\t\tvoid* stream = nullptr;\n\t\t\n\t\tif (!TVerificationAlgorithm::initStream(&stream))\n\t\t{\n\t\t\tlog_critical(MinerLogger::plotVerifier, \"Could not create a verification stream!\\n\"\n\t\t\t\t\"Shutting down the verifier...\");\n\t\t\treturn;\n\t\t}\n\n\t\twhile (!isCancelled())\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tPoco::Notification::Ptr notification(queue_->waitDequeueNotification());\n\t\t\t\tVerifyNotification::Ptr verifyNotification;\n\n\t\t\t\tif (notification)\n\t\t\t\t\tverifyNotification = notification.cast<VerifyNotification>();\n\t\t\t\telse\n\t\t\t\t\tbreak;\n\n\t\t\t\tconst auto stopFunction = [this, &verifyNotification]()\n\t\t\t\t{\n\t\t\t\t\treturn isCancelled() || verifyNotification->block != data_->getCurrentBlockheight();\n\t\t\t\t};\n\n\t\t\t\tauto bestResult = TVerificationAlgorithm::run(verifyNotification->buffer, verifyNotification->nonces,\n\t\t\t\t                                              verifyNotification->nonceRead, verifyNotification->nonceStart,\n\t\t\t\t                                              verifyNotification->baseTarget, verifyNotification->gensig,\n\t\t\t\t                                              stopFunction, stream);\n\n\t\t\t\tif (bestResult.first != 0 && bestResult.second != 0)\n\t\t\t\t{\n\t\t\t\t\tsubmitFunction_(bestResult.first,\n\t\t\t\t\t                verifyNotification->accountId,\n\t\t\t\t\t                bestResult.second,\n\t\t\t\t\t                verifyNotification->block,\n\t\t\t\t\t                verifyNotification->inputPath,\n\t\t\t\t\t                true);\n\t\t\t\t}\n\n\t\t\t\tPlotReader::globalBufferSize.free(verifyNotification->buffer);\n\t\t\t}\n\t\t\tcatch (Poco::Exception& exc)\n\t\t\t{\n\t\t\t\tlog_error(MinerLogger::plotVerifier, \"One of the plot verifiers just crashed! It will recover now.\\n\"\n\t\t\t\t\t\"\\tReason: %s\", exc.displayText());\n\t\t\t\tlog_exception(MinerLogger::plotVerifier, exc);\n\t\t\t}\n\t\t\tcatch (std::exception& exc)\n\t\t\t{\n\t\t\t\tlog_error(MinerLogger::plotVerifier, \"One of the plot verifiers just crashed! It will recover now.\\n\"\n\t\t\t\t\t\"\\tReason:\\t%s\", std::string(exc.what()));\n\t\t\t}\n\t\t\tcatch (...)\n\t\t\t{\n\t\t\t\tlog_error(MinerLogger::plotVerifier, \"One of the plot verifiers just crashed by an unknown reason! It will recover now.\");\n\t\t\t}\n\t\t}\n\n\t\tlog_debug(MinerLogger::plotVerifier, \"Verifier stopped\");\n\t}\n\n\ttemplate <typename TShabal>\n\tstruct PlotVerifierOperations1\n\t{\n\t\tstatic void update(TShabal& shabal, const ScoopData* buffer, const size_t offset, const size_t size)\n\t\t{\n\t\t\tshabal.update(0 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 0),\n\t\t\t              Settings::scoopSize);\n\t\t}\n\n\t\ttemplate <typename TContainer>\n\t\tstatic void close(TShabal& shabal, TContainer& targets, const size_t offset, const size_t size)\n\t\t{\n\t\t\tshabal.close(0 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[0].data()));\n\t\t}\n\t};\n\n\ttemplate <typename TShabal>\n\tstruct PlotVerifierOperations4\n\t{\n\t\tstatic void update(TShabal& shabal, const ScoopData* buffer, const size_t offset, const size_t size)\n\t\t{\n\t\t\tshabal.update(0 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 0),\n\t\t\t              1 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 1),\n\t\t\t              2 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 2),\n\t\t\t              3 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 3),\n\t\t\t              Settings::scoopSize);\n\t\t}\n\n\t\ttemplate <typename TContainer>\n\t\tstatic void close(TShabal& shabal, TContainer& targets, const size_t offset, const size_t size)\n\t\t{\n\t\t\tshabal.close(0 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[0].data()),\n\t\t\t             1 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[1].data()),\n\t\t\t             2 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[2].data()),\n\t\t\t             3 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[3].data()));\n\t\t}\n\t};\n\n\n\ttemplate <typename TShabal>\n\tstruct PlotVerifierOperations8\n\t{\n\t\tstatic void update(TShabal& shabal, const ScoopData* buffer, const size_t offset, const size_t size)\n\t\t{\n\t\t\tshabal.update(0 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 0),\n\t\t\t              1 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 1),\n\t\t\t              2 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 2),\n\t\t\t              3 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 3),\n\t\t\t              4 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 4),\n\t\t\t              5 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 5),\n\t\t\t              6 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 6),\n\t\t\t              7 + offset >= size ? nullptr : reinterpret_cast<const unsigned char*>(buffer + offset + 7),\n\t\t\t              Settings::scoopSize);\n\t\t}\n\n\t\ttemplate <typename TContainer>\n\t\tstatic void close(TShabal& shabal, TContainer& targets, const size_t offset, const size_t size)\n\t\t{\n\t\t\tshabal.close(0 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[0].data()),\n\t\t\t             1 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[1].data()),\n\t\t\t             2 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[2].data()),\n\t\t\t             3 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[3].data()),\n\t\t\t             4 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[4].data()),\n\t\t\t             5 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[5].data()),\n\t\t\t             6 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[6].data()),\n\t\t\t             7 + offset >= size ? nullptr : reinterpret_cast<unsigned char*>(targets[7].data()));\n\t\t}\n\t};\n\n\ttemplate <typename TShabal, typename TShabalOperations>\n\tstruct PlotVerifierAlgorithmCpu\n\t{\n\t\tstatic bool initStream(void** stream)\n\t\t{\n            shabal_init();\n\t\t\treturn true;\n\t\t}\n\n\t\tstatic DeadlineTuple run(ScoopData* buffer, const size_t size, const Poco::UInt64 nonceRead,\n\t\t                         const Poco::UInt64 nonceStart, const Poco::UInt64 baseTarget, const GensigData& gensig,\n\t\t                         const std::function<bool()>& stop, void* stream)\n\t\t{\n            uint64_t deadline = std::numeric_limits<uint64_t>::max();\n            uint64_t offset = 0;\n            std::vector<uint8_t> scoops;\n            for (size_t i = 0; i < buffer->size(); i++) { // Compile scoops into one big array\n                scoops.insert(scoops.end(), &buffer[i][0], &buffer[i][Settings::scoopSize]);\n            }\n            shabal_findBestDeadlineDirect(reinterpret_cast<const char*>(scoops.data()), buffer->size(), reinterpret_cast<const char*>(gensig.data()), &deadline, &offset);\n            return {nonceStart + nonceRead + offset, deadline};\n\t\t}\n\t};\n\n\n\ttemplate <typename TGpu, typename TAlgorithm>\n\tstruct PlotVerifierAlgorithm_gpu\n\t{\n\t\tstatic bool initStream(void** stream)\n\t\t{\n\t\t\treturn TGpu::initStream(stream);\n\t\t}\n\n\t\tstatic DeadlineTuple run(ScoopData* buffer, size_t size, Poco::UInt64 nonceRead, Poco::UInt64 nonceStart,\n\t\t                         Poco::UInt64 baseTarget, const GensigData& gensig, std::function<bool()> stop, void* stream)\n\t\t{\n\t\t\tDeadlineTuple bestDeadline{0, 0};\n\t\t\tTGpu::template run<TAlgorithm>(buffer, size, gensig, nonceStart + nonceRead, baseTarget, stream, bestDeadline);\n\t\t\treturn bestDeadline;\n\t\t}\n\t};\n\n\tusing PlotVerifierOperationSse2 = PlotVerifierOperations1<Shabal256Sse2>;\n\tusing PlotVerifierOperationSse4 = PlotVerifierOperations4<Shabal256Sse4>;\n\tusing PlotVerifierOperationAvx = PlotVerifierOperations4<Shabal256Avx>;\n\tusing PlotVerifierOperationAvx2 = PlotVerifierOperations8<Shabal256Avx2>;\n\n\tusing PlotVerifierAlgorithmSse2 = PlotVerifierAlgorithmCpu<Shabal256Sse2, PlotVerifierOperationSse2>;\n\tusing PlotVerifierAlgorithmSse4 = PlotVerifierAlgorithmCpu<Shabal256Sse4, PlotVerifierOperationSse4>;\n\tusing PlotVerifierAlgorithmAvx = PlotVerifierAlgorithmCpu<Shabal256Avx, PlotVerifierOperationAvx>;\n\tusing PlotVerifierAlgorithmAvx2 = PlotVerifierAlgorithmCpu<Shabal256Avx2, PlotVerifierOperationAvx2>;\n\n\tusing PlotVerifierSse2 = PlotVerifier<PlotVerifierAlgorithmSse2>;\n\tusing PlotVerifierSse4 = PlotVerifier<PlotVerifierAlgorithmSse4>;\n\tusing PlotVerifierAvx = PlotVerifier<PlotVerifierAlgorithmAvx>;\n\tusing PlotVerifierAvx2 = PlotVerifier<PlotVerifierAlgorithmAvx2>;\n\n\tusing PlotVerifierAlgorithmCuda = PlotVerifierAlgorithm_gpu<GpuCuda, GpuAlgorithmAtomic>;\n\tusing PlotVerifierAlgorithmOpencl = PlotVerifierAlgorithm_gpu<GpuOpenCl, GpuAlgorithmAtomic>;\n\n\tusing PlotVerifierCuda = PlotVerifier<PlotVerifierAlgorithmCuda>;\n\tusing PlotVerifierOpencl = PlotVerifier<PlotVerifierAlgorithmOpencl>;\n}\n\n"
  },
  {
    "path": "src/plots/libShabal.h",
    "content": "#include <cstdarg>\n#include <cstdint>\n#include <cstdlib>\n\nextern \"C\" {\n\nuint64_t shabal_findBestDeadline(const char *scoops, uint64_t nonce_count, const char *gensig);\n\nvoid shabal_findBestDeadlineDirect(const char *scoops,\n                                   uint64_t nonce_count,\n                                   const char *gensig,\n                                   uint64_t *best_deadline,\n                                   uint64_t *best_offset);\n\nvoid shabal_init();\n\n} // extern \"C\"\n"
  },
  {
    "path": "src/resources.rc",
    "content": "MAINICON ICON DISCARDABLE \"../resources/public/favicon.ico\""
  },
  {
    "path": "src/shabal/MinerShabal.cpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"MinerShabal.hpp\"\n"
  },
  {
    "path": "src/shabal/MinerShabal.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <memory>\n\n#include \"shabal/impl/mshabal_avx2_impl.hpp\"\n#include \"shabal/impl/mshabal_avx_impl.hpp\"\n#include \"shabal/impl/mshabal_sse4_impl.hpp\"\n#include \"shabal/impl/sphlib_impl.hpp\"\n#include <Poco/ByteOrder.h>\n\nnamespace Burst\n{\n\ttemplate <typename TAlgorithm>\n\tclass Shabal256Shell\n\t{\n\tpublic:\n\t\tstatic constexpr size_t HashSize = TAlgorithm::HashSize;\n\n\t\tShabal256Shell()\n\t\t{\n\t\t\tTAlgorithm::init(context_);\n\t\t}\n\n\t\ttemplate <typename ...Args>\n\t\tvoid update(Args&&... args)\n\t\t{\n\t\t\tTAlgorithm::update(context_, std::forward<Args&&>(args)...);\n\t\t}\n\n\t\tvoid update(Poco::UInt64 singleValue)\n\t\t{\n\t\t\tauto result = Poco::ByteOrder::flipBytes(singleValue);\n\t\t\tupdate(&result, sizeof(Poco::UInt64));\n\t\t}\n\n\t\ttemplate <typename ...Args>\n\t\tvoid close(Args&&... args)\n\t\t{\n\t\t\tTAlgorithm::close(context_, std::forward<Args&&>(args)...);\n\t\t}\n\n\tprivate:\n\t\ttypename TAlgorithm::context_t context_;\n\t};\n\n\tusing Shabal256Avx2 = Shabal256Shell<MshabalAvx2Impl>;\n\tusing Shabal256Avx = Shabal256Shell<MshabalAvxImpl>;\n\tusing Shabal256Sse4 = Shabal256Shell<MshabalSse4Impl>;\n\tusing Shabal256Sse2 = Shabal256Shell<SphlibImpl>;\n}\n"
  },
  {
    "path": "src/shabal/cuda/Shabal.cu",
    "content": "/* $Id: shabal.c 175 2010-05-07 16:03:20Z tp $ */\n/*\n* Shabal implementation.\n*\n* ==========================(LICENSE BEGIN)============================\n*\n* Copyright (c) 2007-2010  Projet RNRT SAPHIR\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 NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*\n* ===========================(LICENSE END)=============================\n*\n* @author            Thomas Pornin <thomas.pornin@cryptolog.com>\n* @cuda author\t\t Creepsky      <creepsky@gmail.com>\n* \n*/\n\n#include \"shabal/sphlib/sph_shabal.h\"\n#include \"Shabal.hpp\"\n#include <string>\n#include <thrust/device_ptr.h>\n#include <thrust/extrema.h>\n\nusing namespace Burst;\n\n#define SPH_C32(x)    ((sph_u32)(x ## U))\n#define C32   SPH_C32\n\n#define sM    16\n\n#define C32   SPH_C32\n#define T32   SPH_T32\n\n#define O1   13\n#define O2    9\n#define O3    6\n\n/*\n* We copy the state into local variables, so that the compiler knows\n* that it can optimize them at will.\n*/\n\n/* BEGIN -- automatically generated code. */\n\n#define DECL_STATE   \\\n\tsph_u32 A00, A01, A02, A03, A04, A05, A06, A07, \\\n\t        A08, A09, A0A, A0B; \\\n\tsph_u32 B0, B1, B2, B3, B4, B5, B6, B7, \\\n\t        B8, B9, BA, BB, BC, BD, BE, BF; \\\n\tsph_u32 C0, C1, C2, C3, C4, C5, C6, C7, \\\n\t        C8, C9, CA, CB, CC, CD, CE, CF; \\\n\tsph_u32 M0, M1, M2, M3, M4, M5, M6, M7, \\\n\t        M8, M9, MA, MB, MC, MD, ME, MF; \\\n\tsph_u32 Wlow, Whigh;\n\n#define READ_STATE(state)   do { \\\n\t\tA00 = (state)->A[0]; \\\n\t\tA01 = (state)->A[1]; \\\n\t\tA02 = (state)->A[2]; \\\n\t\tA03 = (state)->A[3]; \\\n\t\tA04 = (state)->A[4]; \\\n\t\tA05 = (state)->A[5]; \\\n\t\tA06 = (state)->A[6]; \\\n\t\tA07 = (state)->A[7]; \\\n\t\tA08 = (state)->A[8]; \\\n\t\tA09 = (state)->A[9]; \\\n\t\tA0A = (state)->A[10]; \\\n\t\tA0B = (state)->A[11]; \\\n\t\tB0 = (state)->B[0]; \\\n\t\tB1 = (state)->B[1]; \\\n\t\tB2 = (state)->B[2]; \\\n\t\tB3 = (state)->B[3]; \\\n\t\tB4 = (state)->B[4]; \\\n\t\tB5 = (state)->B[5]; \\\n\t\tB6 = (state)->B[6]; \\\n\t\tB7 = (state)->B[7]; \\\n\t\tB8 = (state)->B[8]; \\\n\t\tB9 = (state)->B[9]; \\\n\t\tBA = (state)->B[10]; \\\n\t\tBB = (state)->B[11]; \\\n\t\tBC = (state)->B[12]; \\\n\t\tBD = (state)->B[13]; \\\n\t\tBE = (state)->B[14]; \\\n\t\tBF = (state)->B[15]; \\\n\t\tC0 = (state)->C[0]; \\\n\t\tC1 = (state)->C[1]; \\\n\t\tC2 = (state)->C[2]; \\\n\t\tC3 = (state)->C[3]; \\\n\t\tC4 = (state)->C[4]; \\\n\t\tC5 = (state)->C[5]; \\\n\t\tC6 = (state)->C[6]; \\\n\t\tC7 = (state)->C[7]; \\\n\t\tC8 = (state)->C[8]; \\\n\t\tC9 = (state)->C[9]; \\\n\t\tCA = (state)->C[10]; \\\n\t\tCB = (state)->C[11]; \\\n\t\tCC = (state)->C[12]; \\\n\t\tCD = (state)->C[13]; \\\n\t\tCE = (state)->C[14]; \\\n\t\tCF = (state)->C[15]; \\\n\t\tWlow = (state)->Wlow; \\\n\t\tWhigh = (state)->Whigh; \\\n\t} while (0)\n\n#define WRITE_STATE(state)   do { \\\n\t\t(state)->A[0] = A00; \\\n\t\t(state)->A[1] = A01; \\\n\t\t(state)->A[2] = A02; \\\n\t\t(state)->A[3] = A03; \\\n\t\t(state)->A[4] = A04; \\\n\t\t(state)->A[5] = A05; \\\n\t\t(state)->A[6] = A06; \\\n\t\t(state)->A[7] = A07; \\\n\t\t(state)->A[8] = A08; \\\n\t\t(state)->A[9] = A09; \\\n\t\t(state)->A[10] = A0A; \\\n\t\t(state)->A[11] = A0B; \\\n\t\t(state)->B[0] = B0; \\\n\t\t(state)->B[1] = B1; \\\n\t\t(state)->B[2] = B2; \\\n\t\t(state)->B[3] = B3; \\\n\t\t(state)->B[4] = B4; \\\n\t\t(state)->B[5] = B5; \\\n\t\t(state)->B[6] = B6; \\\n\t\t(state)->B[7] = B7; \\\n\t\t(state)->B[8] = B8; \\\n\t\t(state)->B[9] = B9; \\\n\t\t(state)->B[10] = BA; \\\n\t\t(state)->B[11] = BB; \\\n\t\t(state)->B[12] = BC; \\\n\t\t(state)->B[13] = BD; \\\n\t\t(state)->B[14] = BE; \\\n\t\t(state)->B[15] = BF; \\\n\t\t(state)->C[0] = C0; \\\n\t\t(state)->C[1] = C1; \\\n\t\t(state)->C[2] = C2; \\\n\t\t(state)->C[3] = C3; \\\n\t\t(state)->C[4] = C4; \\\n\t\t(state)->C[5] = C5; \\\n\t\t(state)->C[6] = C6; \\\n\t\t(state)->C[7] = C7; \\\n\t\t(state)->C[8] = C8; \\\n\t\t(state)->C[9] = C9; \\\n\t\t(state)->C[10] = CA; \\\n\t\t(state)->C[11] = CB; \\\n\t\t(state)->C[12] = CC; \\\n\t\t(state)->C[13] = CD; \\\n\t\t(state)->C[14] = CE; \\\n\t\t(state)->C[15] = CF; \\\n\t\t(state)->Wlow = Wlow; \\\n\t\t(state)->Whigh = Whigh; \\\n\t} while (0)\n\n#define DECODE_BLOCK   do { \\\n\t\tM0 = cuda_sph_dec32le_aligned(buf + 0); \\\n\t\tM1 = cuda_sph_dec32le_aligned(buf + 4); \\\n\t\tM2 = cuda_sph_dec32le_aligned(buf + 8); \\\n\t\tM3 = cuda_sph_dec32le_aligned(buf + 12); \\\n\t\tM4 = cuda_sph_dec32le_aligned(buf + 16); \\\n\t\tM5 = cuda_sph_dec32le_aligned(buf + 20); \\\n\t\tM6 = cuda_sph_dec32le_aligned(buf + 24); \\\n\t\tM7 = cuda_sph_dec32le_aligned(buf + 28); \\\n\t\tM8 = cuda_sph_dec32le_aligned(buf + 32); \\\n\t\tM9 = cuda_sph_dec32le_aligned(buf + 36); \\\n\t\tMA = cuda_sph_dec32le_aligned(buf + 40); \\\n\t\tMB = cuda_sph_dec32le_aligned(buf + 44); \\\n\t\tMC = cuda_sph_dec32le_aligned(buf + 48); \\\n\t\tMD = cuda_sph_dec32le_aligned(buf + 52); \\\n\t\tME = cuda_sph_dec32le_aligned(buf + 56); \\\n\t\tMF = cuda_sph_dec32le_aligned(buf + 60); \\\n\t} while (0)\n\n#define INPUT_BLOCK_ADD   do { \\\n\t\tB0 = T32(B0 + M0); \\\n\t\tB1 = T32(B1 + M1); \\\n\t\tB2 = T32(B2 + M2); \\\n\t\tB3 = T32(B3 + M3); \\\n\t\tB4 = T32(B4 + M4); \\\n\t\tB5 = T32(B5 + M5); \\\n\t\tB6 = T32(B6 + M6); \\\n\t\tB7 = T32(B7 + M7); \\\n\t\tB8 = T32(B8 + M8); \\\n\t\tB9 = T32(B9 + M9); \\\n\t\tBA = T32(BA + MA); \\\n\t\tBB = T32(BB + MB); \\\n\t\tBC = T32(BC + MC); \\\n\t\tBD = T32(BD + MD); \\\n\t\tBE = T32(BE + ME); \\\n\t\tBF = T32(BF + MF); \\\n\t} while (0)\n\n#define INPUT_BLOCK_SUB   do { \\\n\t\tC0 = T32(C0 - M0); \\\n\t\tC1 = T32(C1 - M1); \\\n\t\tC2 = T32(C2 - M2); \\\n\t\tC3 = T32(C3 - M3); \\\n\t\tC4 = T32(C4 - M4); \\\n\t\tC5 = T32(C5 - M5); \\\n\t\tC6 = T32(C6 - M6); \\\n\t\tC7 = T32(C7 - M7); \\\n\t\tC8 = T32(C8 - M8); \\\n\t\tC9 = T32(C9 - M9); \\\n\t\tCA = T32(CA - MA); \\\n\t\tCB = T32(CB - MB); \\\n\t\tCC = T32(CC - MC); \\\n\t\tCD = T32(CD - MD); \\\n\t\tCE = T32(CE - ME); \\\n\t\tCF = T32(CF - MF); \\\n\t} while (0)\n\n#define XOR_W   do { \\\n\t\tA00 ^= Wlow; \\\n\t\tA01 ^= Whigh; \\\n\t} while (0)\n\n#define SWAP(v1, v2)   do { \\\n\t\tsph_u32 tmp = (v1); \\\n\t\t(v1) = (v2); \\\n\t\t(v2) = tmp; \\\n\t} while (0)\n\n#define SWAP_BC   do { \\\n\t\tSWAP(B0, C0); \\\n\t\tSWAP(B1, C1); \\\n\t\tSWAP(B2, C2); \\\n\t\tSWAP(B3, C3); \\\n\t\tSWAP(B4, C4); \\\n\t\tSWAP(B5, C5); \\\n\t\tSWAP(B6, C6); \\\n\t\tSWAP(B7, C7); \\\n\t\tSWAP(B8, C8); \\\n\t\tSWAP(B9, C9); \\\n\t\tSWAP(BA, CA); \\\n\t\tSWAP(BB, CB); \\\n\t\tSWAP(BC, CC); \\\n\t\tSWAP(BD, CD); \\\n\t\tSWAP(BE, CE); \\\n\t\tSWAP(BF, CF); \\\n\t} while (0)\n\n#define PERM_ELT(xa0, xa1, xb0, xb1, xb2, xb3, xc, xm)   do { \\\n\t\txa0 = T32((xa0 \\\n\t\t\t^ (((xa1 << 15) | (xa1 >> 17)) * 5U) \\\n\t\t\t^ xc) * 3U) \\\n\t\t\t^ xb1 ^ (xb2 & ~xb3) ^ xm; \\\n\t\txb0 = T32(~(((xb0 << 1) | (xb0 >> 31)) ^ xa0)); \\\n\t} while (0)\n\n#define PERM_STEP_0   do { \\\n\t\tPERM_ELT(A00, A0B, B0, BD, B9, B6, C8, M0); \\\n\t\tPERM_ELT(A01, A00, B1, BE, BA, B7, C7, M1); \\\n\t\tPERM_ELT(A02, A01, B2, BF, BB, B8, C6, M2); \\\n\t\tPERM_ELT(A03, A02, B3, B0, BC, B9, C5, M3); \\\n\t\tPERM_ELT(A04, A03, B4, B1, BD, BA, C4, M4); \\\n\t\tPERM_ELT(A05, A04, B5, B2, BE, BB, C3, M5); \\\n\t\tPERM_ELT(A06, A05, B6, B3, BF, BC, C2, M6); \\\n\t\tPERM_ELT(A07, A06, B7, B4, B0, BD, C1, M7); \\\n\t\tPERM_ELT(A08, A07, B8, B5, B1, BE, C0, M8); \\\n\t\tPERM_ELT(A09, A08, B9, B6, B2, BF, CF, M9); \\\n\t\tPERM_ELT(A0A, A09, BA, B7, B3, B0, CE, MA); \\\n\t\tPERM_ELT(A0B, A0A, BB, B8, B4, B1, CD, MB); \\\n\t\tPERM_ELT(A00, A0B, BC, B9, B5, B2, CC, MC); \\\n\t\tPERM_ELT(A01, A00, BD, BA, B6, B3, CB, MD); \\\n\t\tPERM_ELT(A02, A01, BE, BB, B7, B4, CA, ME); \\\n\t\tPERM_ELT(A03, A02, BF, BC, B8, B5, C9, MF); \\\n\t} while (0)\n\n#define PERM_STEP_1   do { \\\n\t\tPERM_ELT(A04, A03, B0, BD, B9, B6, C8, M0); \\\n\t\tPERM_ELT(A05, A04, B1, BE, BA, B7, C7, M1); \\\n\t\tPERM_ELT(A06, A05, B2, BF, BB, B8, C6, M2); \\\n\t\tPERM_ELT(A07, A06, B3, B0, BC, B9, C5, M3); \\\n\t\tPERM_ELT(A08, A07, B4, B1, BD, BA, C4, M4); \\\n\t\tPERM_ELT(A09, A08, B5, B2, BE, BB, C3, M5); \\\n\t\tPERM_ELT(A0A, A09, B6, B3, BF, BC, C2, M6); \\\n\t\tPERM_ELT(A0B, A0A, B7, B4, B0, BD, C1, M7); \\\n\t\tPERM_ELT(A00, A0B, B8, B5, B1, BE, C0, M8); \\\n\t\tPERM_ELT(A01, A00, B9, B6, B2, BF, CF, M9); \\\n\t\tPERM_ELT(A02, A01, BA, B7, B3, B0, CE, MA); \\\n\t\tPERM_ELT(A03, A02, BB, B8, B4, B1, CD, MB); \\\n\t\tPERM_ELT(A04, A03, BC, B9, B5, B2, CC, MC); \\\n\t\tPERM_ELT(A05, A04, BD, BA, B6, B3, CB, MD); \\\n\t\tPERM_ELT(A06, A05, BE, BB, B7, B4, CA, ME); \\\n\t\tPERM_ELT(A07, A06, BF, BC, B8, B5, C9, MF); \\\n\t} while (0)\n\n#define PERM_STEP_2   do { \\\n\t\tPERM_ELT(A08, A07, B0, BD, B9, B6, C8, M0); \\\n\t\tPERM_ELT(A09, A08, B1, BE, BA, B7, C7, M1); \\\n\t\tPERM_ELT(A0A, A09, B2, BF, BB, B8, C6, M2); \\\n\t\tPERM_ELT(A0B, A0A, B3, B0, BC, B9, C5, M3); \\\n\t\tPERM_ELT(A00, A0B, B4, B1, BD, BA, C4, M4); \\\n\t\tPERM_ELT(A01, A00, B5, B2, BE, BB, C3, M5); \\\n\t\tPERM_ELT(A02, A01, B6, B3, BF, BC, C2, M6); \\\n\t\tPERM_ELT(A03, A02, B7, B4, B0, BD, C1, M7); \\\n\t\tPERM_ELT(A04, A03, B8, B5, B1, BE, C0, M8); \\\n\t\tPERM_ELT(A05, A04, B9, B6, B2, BF, CF, M9); \\\n\t\tPERM_ELT(A06, A05, BA, B7, B3, B0, CE, MA); \\\n\t\tPERM_ELT(A07, A06, BB, B8, B4, B1, CD, MB); \\\n\t\tPERM_ELT(A08, A07, BC, B9, B5, B2, CC, MC); \\\n\t\tPERM_ELT(A09, A08, BD, BA, B6, B3, CB, MD); \\\n\t\tPERM_ELT(A0A, A09, BE, BB, B7, B4, CA, ME); \\\n\t\tPERM_ELT(A0B, A0A, BF, BC, B8, B5, C9, MF); \\\n\t} while (0)\n\n#define APPLY_P   do { \\\n\t\tB0 = T32(B0 << 17) | (B0 >> 15); \\\n\t\tB1 = T32(B1 << 17) | (B1 >> 15); \\\n\t\tB2 = T32(B2 << 17) | (B2 >> 15); \\\n\t\tB3 = T32(B3 << 17) | (B3 >> 15); \\\n\t\tB4 = T32(B4 << 17) | (B4 >> 15); \\\n\t\tB5 = T32(B5 << 17) | (B5 >> 15); \\\n\t\tB6 = T32(B6 << 17) | (B6 >> 15); \\\n\t\tB7 = T32(B7 << 17) | (B7 >> 15); \\\n\t\tB8 = T32(B8 << 17) | (B8 >> 15); \\\n\t\tB9 = T32(B9 << 17) | (B9 >> 15); \\\n\t\tBA = T32(BA << 17) | (BA >> 15); \\\n\t\tBB = T32(BB << 17) | (BB >> 15); \\\n\t\tBC = T32(BC << 17) | (BC >> 15); \\\n\t\tBD = T32(BD << 17) | (BD >> 15); \\\n\t\tBE = T32(BE << 17) | (BE >> 15); \\\n\t\tBF = T32(BF << 17) | (BF >> 15); \\\n\t\tPERM_STEP_0; \\\n\t\tPERM_STEP_1; \\\n\t\tPERM_STEP_2; \\\n\t\tA0B = T32(A0B + C6); \\\n\t\tA0A = T32(A0A + C5); \\\n\t\tA09 = T32(A09 + C4); \\\n\t\tA08 = T32(A08 + C3); \\\n\t\tA07 = T32(A07 + C2); \\\n\t\tA06 = T32(A06 + C1); \\\n\t\tA05 = T32(A05 + C0); \\\n\t\tA04 = T32(A04 + CF); \\\n\t\tA03 = T32(A03 + CE); \\\n\t\tA02 = T32(A02 + CD); \\\n\t\tA01 = T32(A01 + CC); \\\n\t\tA00 = T32(A00 + CB); \\\n\t\tA0B = T32(A0B + CA); \\\n\t\tA0A = T32(A0A + C9); \\\n\t\tA09 = T32(A09 + C8); \\\n\t\tA08 = T32(A08 + C7); \\\n\t\tA07 = T32(A07 + C6); \\\n\t\tA06 = T32(A06 + C5); \\\n\t\tA05 = T32(A05 + C4); \\\n\t\tA04 = T32(A04 + C3); \\\n\t\tA03 = T32(A03 + C2); \\\n\t\tA02 = T32(A02 + C1); \\\n\t\tA01 = T32(A01 + C0); \\\n\t\tA00 = T32(A00 + CF); \\\n\t\tA0B = T32(A0B + CE); \\\n\t\tA0A = T32(A0A + CD); \\\n\t\tA09 = T32(A09 + CC); \\\n\t\tA08 = T32(A08 + CB); \\\n\t\tA07 = T32(A07 + CA); \\\n\t\tA06 = T32(A06 + C9); \\\n\t\tA05 = T32(A05 + C8); \\\n\t\tA04 = T32(A04 + C7); \\\n\t\tA03 = T32(A03 + C6); \\\n\t\tA02 = T32(A02 + C5); \\\n\t\tA01 = T32(A01 + C4); \\\n\t\tA00 = T32(A00 + C3); \\\n\t} while (0)\n\n#define INCR_W   do { \\\n\t\tif ((Wlow = T32(Wlow + 1)) == 0) \\\n\t\t\tWhigh = T32(Whigh + 1); \\\n\t} while (0)\n\n__constant__\nsph_u32 A_init_256[] = {\nC32(0x52F84552), C32(0xE54B7999), C32(0x2D8EE3EC), C32(0xB9645191),\nC32(0xE0078B86), C32(0xBB7C44C9), C32(0xD2B5C1CA), C32(0xB0D2EB8C),\nC32(0x14CE5A45), C32(0x22AF50DC), C32(0xEFFDBC6B), C32(0xEB21B74A)\n};\n\n__constant__\nsph_u32 B_init_256[] = {\nC32(0xB555C6EE), C32(0x3E710596), C32(0xA72A652F), C32(0x9301515F),\nC32(0xDA28C1FA), C32(0x696FD868), C32(0x9CB6BF72), C32(0x0AFE4002),\nC32(0xA6E03615), C32(0x5138C1D4), C32(0xBE216306), C32(0xB38B8890),\nC32(0x3EA8B96B), C32(0x3299ACE4), C32(0x30924DD4), C32(0x55CB34A5)\n};\n\n__constant__\nsph_u32 C_init_256[] = {\nC32(0xB405F031), C32(0xC4233EBA), C32(0xB3733979), C32(0xC0DD9D55),\nC32(0xC51C28AE), C32(0xA327B8E1), C32(0x56C56167), C32(0xED614433),\nC32(0x88B59D60), C32(0x60E2CEBA), C32(0x758B4B8B), C32(0x83E82A7F),\nC32(0xBC968828), C32(0xE6E00BF7), C32(0xBA839E55), C32(0x9B491C60)\n};\n\n/*\n* Part of this code was automatically generated (the part between\n* the \"BEGIN\" and \"END\" markers).\n*/\n\n__device__\nsph_u32 cuda_sph_dec32le_aligned(const void *src)\n{\n#if SPH_LITTLE_ENDIAN\n\treturn *(const sph_u32 *)src;\n#elif SPH_BIG_ENDIAN\n#if SPH_SPARCV9_GCC && !SPH_NO_ASM\n\tsph_u32 tmp;\n\n\t__asm__ __volatile__ (\"lda [%1]0x88,%0\" : \"=r\" (tmp) : \"r\" (src));\n\treturn tmp;\n\t/*\n\t* Not worth it generally.\n\t*\n\t#elif (SPH_PPC32_GCC || SPH_PPC64_GCC) && !SPH_NO_ASM\n\tsph_u32 tmp;\n\n\t__asm__ __volatile__ (\"lwbrx %0,0,%1\" : \"=r\" (tmp) : \"r\" (src));\n\treturn tmp;\n\t*/\n#else\n\treturn sph_bswap32(*(const sph_u32 *)src);\n#endif\n#else\n\treturn (sph_u32)(((const unsigned char *)src)[0])\n\t\t| ((sph_u32)(((const unsigned char *)src)[1]) << 8)\n\t\t| ((sph_u32)(((const unsigned char *)src)[2]) << 16)\n\t\t| ((sph_u32)(((const unsigned char *)src)[3]) << 24);\n#endif\n}\n\n__device__\nvoid cuda_shabal_init(void *cc, unsigned size)\n{\n\t/*\n\t* We have precomputed initial states for all the supported\n\t* output bit lengths.\n\t*/\n\tsph_u32 *A_init, *B_init, *C_init;\n\tsph_shabal_context *sc;\n\n\tA_init = A_init_256;\n\tB_init = B_init_256;\n\tC_init = C_init_256;\n\n\tsc = (sph_shabal_context *)cc;\n\t\n\tmemcpy(sc->A, A_init, sizeof sc->A);\n\tmemcpy(sc->B, B_init, sizeof sc->B);\n\tmemcpy(sc->C, C_init, sizeof sc->C);\n\n\tsc->Wlow = 1;\n\tsc->Whigh = 0;\n\tsc->ptr = 0;\n}\n\n__device__\nvoid cuda_shabal_core(void *cc, const unsigned char *data, size_t len)\n{\n\tsph_shabal_context *sc;\n\tunsigned char *buf;\n\tsize_t ptr;\n\tDECL_STATE\n\n\tsc = (sph_shabal_context *)cc;\n\tbuf = sc->buf;\n\tptr = sc->ptr;\n\n\t/*\n\t* We do not want to copy the state to local variables if the\n\t* amount of data is less than what is needed to complete the\n\t* current block. Note that it is anyway suboptimal to call\n\t* this method many times for small chunks of data.\n\t*/\n\tif (len < (sizeof sc->buf) - ptr) {\n\t\tmemcpy(buf + ptr, data, len);\n\t\tptr += len;\n\t\tsc->ptr = ptr;\n\t\treturn;\n\t}\n\n\tREAD_STATE(sc);\n\twhile (len > 0) {\n\t\tsize_t clen;\n\n\t\tclen = (sizeof sc->buf) - ptr;\n\t\tif (clen > len)\n\t\t\tclen = len;\n\t\tmemcpy(buf + ptr, data, clen);\n\t\tptr += clen;\n\t\tdata += clen;\n\t\tlen -= clen;\n\t\tif (ptr == sizeof sc->buf) {\n\t\t\tDECODE_BLOCK;\n\t\t\tINPUT_BLOCK_ADD;\n\t\t\tXOR_W;\n\t\t\tAPPLY_P;\n\t\t\tINPUT_BLOCK_SUB;\n\t\t\tSWAP_BC;\n\t\t\tINCR_W;\n\t\t\tptr = 0;\n\t\t}\n\t}\n\tWRITE_STATE(sc);\n\tsc->ptr = ptr;\n}\n\n__device__\nvoid cuda_sph_enc32le_aligned(void *dst, sph_u32 val)\n{\n#if SPH_LITTLE_ENDIAN\n\t*(sph_u32 *)dst = val;\n#elif SPH_BIG_ENDIAN\n\t*(sph_u32 *)dst = sph_bswap32(val);\n#else\n\t((unsigned char *)dst)[0] = val;\n\t((unsigned char *)dst)[1] = (val >> 8);\n\t((unsigned char *)dst)[2] = (val >> 16);\n\t((unsigned char *)dst)[3] = (val >> 24);\n#endif\n}\n\n__device__\nvoid cuda_shabal_close(void *cc, unsigned ub, unsigned n, void *dst)\n{\n\tconst auto size_word = 8;\n\tsph_shabal_context *sc;\n\tunsigned char *buf;\n\tsize_t ptr;\n\tint i;\n\tunsigned z;\n\tunion {\n\t\tunsigned char tmp_out[64];\n\t\tsph_u32 dummy;\n\t} u;\n\tsize_t out_len;\n\tDECL_STATE\n\n\tsc = (sph_shabal_context *)cc;\n\tbuf = sc->buf;\n\tptr = sc->ptr;\n\tz = 0x80 >> n;\n\tbuf[ptr] = ((ub & -z) | z) & 0xFF;\n\tmemset(buf + ptr + 1, 0, (sizeof sc->buf) - (ptr + 1));\n\tREAD_STATE(sc);\n\tDECODE_BLOCK;\n\tINPUT_BLOCK_ADD;\n\tXOR_W;\n\tAPPLY_P;\n\tfor (i = 0; i < 3; i ++) {\n\t\tSWAP_BC;\n\t\tXOR_W;\n\t\tAPPLY_P;\n\t}\n\n\t/*\n\t* We just use our local variables; no need to go through\n\t* the state structure. In order to share some code, we\n\t* emit the relevant words into a temporary buffer, which\n\t* we finally copy into the destination array.\n\t*/\n\tcuda_sph_enc32le_aligned(u.tmp_out + 32, B8);\n\tcuda_sph_enc32le_aligned(u.tmp_out + 36, B9);\n\tcuda_sph_enc32le_aligned(u.tmp_out + 40, BA);\n\tcuda_sph_enc32le_aligned(u.tmp_out + 44, BB);\n\tcuda_sph_enc32le_aligned(u.tmp_out + 48, BC);\n\tcuda_sph_enc32le_aligned(u.tmp_out + 52, BD);\n\tcuda_sph_enc32le_aligned(u.tmp_out + 56, BE);\n\tcuda_sph_enc32le_aligned(u.tmp_out + 60, BF);\n\n\tout_len = size_word << 2;\n\tmemcpy(dst, u.tmp_out + (sizeof u.tmp_out) - out_len, out_len);\n\tcuda_shabal_init(sc, size_word << 5);\n}\n\n__global__\nvoid cuda_calculate_shabal(Burst::ScoopData* buffer, Poco::UInt64* deadlines, Poco::UInt64 len,\n\tconst GensigData* gensig, Poco::UInt64 nonceStart, Poco::UInt64 baseTarget)\n{\n\tint tid = threadIdx.x + blockIdx.x * blockDim.x;\n\n\tsph_shabal256_context context;\n\tcuda_shabal_init(&context, 256);\n\n\t//printf(\"blockIdx.x = %i\\n\", blockIdx.x);\n\t//printf(\"blockIdx.x = %i, threadIdx.x = %i, index = %i\\n\", blockIdx.x, threadIdx.x, i);\n\t\n\tif (tid >= len)\n\t{\n\t\t//printf(\"blockIdx.x = %i, threadIdx.x = %i, index = %i\\n\", blockIdx.x, threadIdx.x, i);\n\t\treturn;\n\t}\n\n\tPoco::UInt8 target[Settings::hashSize];\n\tauto test = buffer[tid];\n\n\tcuda_shabal_core(&context, (const unsigned char *)gensig, Settings::hashSize);\n\tcuda_shabal_core(&context, (const unsigned char *)&test, Settings::scoopSize);\n\tcuda_shabal_close(&context, 0, 0, &target[0]);\n\n\tPoco::UInt64 targetResult = 0;\n\tmemcpy(&targetResult, &target[0], sizeof(Poco::UInt64));\n\n\t//auto buffer_deadline = (Poco::UInt64*)(buffer + tid);\n\t//*buffer_deadline = targetResult / baseTarget;\n\tdeadlines[tid] = targetResult / baseTarget;\n}\n\nvoid cuda_calc_occupancy(int bufferSize, int& gridSize, int& blockSize)\n{\n\tint minGridSize;\n\n\tcudaOccupancyMaxPotentialBlockSize(&minGridSize, &blockSize, (void*)cuda_calculate_shabal, 0, 0);\n\n\tgridSize = (bufferSize + blockSize - 1) / blockSize;\n}\n\nbool cuda_alloc_memory(Poco::UInt64 size, void** mem)\n{\n\tif (size <= 0)\n\t\treturn false;\n\n\treturn cudaMalloc((void**)&*mem, size) == cudaSuccess;\n}\n\nbool cuda_copy_memory(Poco::UInt64 size, const void* from, void* to, MemoryCopyDirection copyDirection)\n{\n\tif (size <= 0)\n\t\treturn false;\n\n\treturn cudaMemcpy(to, from, size, copyDirection == MemoryCopyDirection::ToDevice ? cudaMemcpyHostToDevice : cudaMemcpyDeviceToHost) == cudaSuccess;\n}\n\nbool cuda_free_memory(void* mem)\n{\n\tif (mem == nullptr)\n\t\treturn false;\n\n\treturn cudaFree(mem) == cudaSuccess;\n}\n\nbool cuda_calculate_shabal_host_preallocated(ScoopData* buffer, Poco::UInt64* deadlines, Poco::UInt64 bufferSize, const GensigData* gensig,\n\tPoco::UInt64 nonceStart, Poco::UInt64 baseTarget, std::string& errorString)\n{\n\tauto blockSize = 0;\n\tauto minGridSize = 0;\n\t\n\tcudaOccupancyMaxPotentialBlockSize(&minGridSize, &blockSize, (void*)cuda_calculate_shabal, 0, 0);\n\n\tint gridSize = (bufferSize + blockSize - 1) / blockSize;\n\n\tcuda_calculate_shabal<<<gridSize, blockSize>>>(buffer, deadlines, bufferSize, gensig, nonceStart, baseTarget);\n\t\n\treturn !cuda_get_error(errorString);\n}\n\nbool cuda_reduce_best_deadline(Poco::UInt64* deadlines, size_t size, Poco::UInt64& minDeadline, Poco::UInt64& index, std::string& errorString)\n{\n\tthrust::device_ptr<Poco::UInt64> deadlinesPtr(deadlines);\n\tauto pos = thrust::min_element(deadlinesPtr, deadlinesPtr + size);\n\tindex = thrust::distance(deadlinesPtr, pos);\n\n\tif (!cuda_copy_memory(sizeof(Poco::UInt64), &deadlines[index], &minDeadline, MemoryCopyDirection::ToHost))\n\t\treturn false;\n\n\treturn !cuda_get_error(errorString);\n}\n\nbool cuda_get_error(std::string& errorString)\n{\n\tconst auto err = cudaPeekAtLastError();\n\n\tif (err != cudaSuccess)\n\t{\n\t\terrorString = cudaGetErrorString(err);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nbool cuda_get_devices(std::vector<std::string>& devices)\n{\n\tauto count = 0;\n\n\tif (cudaGetDeviceCount(&count) != cudaSuccess)\n\t\treturn false;\n\n\tdevices.clear();\n\t\n\tfor (auto i = 0; i < count; ++i)\n\t{\n\t\tcudaDeviceProp prop;\n\t\t\n\t\tif (cudaGetDeviceProperties(&prop, i) != cudaSuccess)\n\t\t\tcontinue;\n\n\t\tdevices.emplace_back(prop.name);\n\t}\n\n\treturn true;\n}\n\nbool cuda_set_device(unsigned index)\n{\n\treturn cudaSetDevice(static_cast<int>(index)) == cudaSuccess;\n}\n"
  },
  {
    "path": "src/shabal/cuda/Shabal.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"Declarations.hpp\"\n#include <Poco/Types.h>\n#include \"gpu/gpu_declarations.hpp\"\n#include <string>\n#include <vector>\n\nextern \"C\" void cuda_calc_occupancy(int bufferSize, int& gridSize, int& blockSize);\nextern \"C\" bool cuda_alloc_memory(Poco::UInt64 size,  void** mem);\nextern \"C\" bool cuda_copy_memory(Poco::UInt64 size, const void* from, void* to, Burst::MemoryCopyDirection copyDirection);\nextern \"C\" bool cuda_free_memory(void* mem);\n\nextern \"C\" bool cuda_calculate_shabal_host_preallocated(Burst::ScoopData* buffer, Poco::UInt64* deadlines, Poco::UInt64 bufferSize,\n\tconst Burst::GensigData* gensig,\n\tPoco::UInt64 nonceStart, Poco::UInt64 baseTarget, std::string& errorString);\n\nextern \"C\" bool cuda_reduce_best_deadline(Poco::UInt64* deadlines, size_t size,\n\tPoco::UInt64& minDeadline, Poco::UInt64& index, std::string& errorString);\n\nextern \"C\" bool cuda_get_error(std::string& errorString);\n\nextern \"C\" bool cuda_get_devices(std::vector<std::string>& devices);\nextern \"C\" bool cuda_set_device(unsigned index);\n"
  },
  {
    "path": "src/shabal/impl/mshabal_avx2_impl.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"shabal/mshabal/mshabal.h\"\n\nnamespace Burst\n{\n\tstruct MshabalAvx2Impl\n\t{\n\t\tstatic constexpr size_t HashSize = 8;\n\n\t\tusing context_t = mshabal256_context;\n\n\t\tstatic void init(context_t& context)\n\t\t{\n\t\t\tavx2_mshabal_init(&context, 256);\n\t\t}\n\n\t\tstatic void update(context_t& context, const void* data, size_t length)\n\t\t{\n\t\t\tupdate(context, data, data, data, data, data, data, data, data, length);\n\t\t}\n\n\t\tstatic void update(context_t& context,\n\t\t                   const void* data1, const void* data2, const void* data3, const void* data4,\n\t\t                   const void* data5, const void* data6, const void* data7, const void* data8,\n\t\t                   size_t length)\n\t\t{\n\t\t\tavx2_mshabal(&context, data1, data2, data3, data4, data5, data6, data7, data8, length);\n\t\t}\n\n\t\tstatic void close(context_t& context, void* output)\n\t\t{\n\t\t\tavx2_mshabal_close(&context, 0, 0, 0, 0, 0, 0, 0, 0, 0, output,\n\t\t\t                   nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);\n\t\t}\n\n\t\tstatic void close(context_t& context,\n\t\t                  void* out1, void* out2, void* out3, void* out4,\n\t\t                  void* out5, void* out6, void* out7, void* out8)\n\t\t{\n\t\t\tavx2_mshabal_close(&context, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t                   out1, out2, out3, out4, out5, out6, out7, out8);\n\t\t}\n\t};\n}\n\n#ifndef USE_AVX2\ninline void avx2_mshabal_init(mshabal256_context* sc, unsigned out_size) {}\n\ninline void avx2_mshabal(mshabal256_context* sc, const void* data0, const void* data1, const void* data2, const void* data3,\n                  const void* data4, const void* data5, const void* data6, const void* data7, size_t len) {}\n\ninline void avx2_mshabal_close(mshabal256_context* sc, unsigned ub0, unsigned ub1, unsigned ub2, unsigned ub3, unsigned ub4,\n                        unsigned ub5, unsigned ub6, unsigned ub7, unsigned n, void* dst0, void* dst1, void* dst2,\n                        void* dst3, void* dst4, void* dst5, void* dst6, void* dst7) {}\n#endif\n"
  },
  {
    "path": "src/shabal/impl/mshabal_avx_impl.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"shabal/mshabal/mshabal.h\"\n\nnamespace Burst\n{\n\tstruct MshabalAvxImpl\n\t{\n\t\tstatic constexpr size_t HashSize = 4;\n\n\t\tusing context_t = mshabal_context;\n\n\t\tstatic void init(context_t& context)\n\t\t{\n\t\t\tavx1_mshabal_init(&context, 256);\n\t\t}\n\n\t\tstatic void update(context_t& context, const void* data, size_t length)\n\t\t{\n\t\t\tupdate(context, data, data, data, data, length);\n\t\t}\n\n\t\tstatic void update(context_t& context,\n\t\t                   const void* data1, const void* data2, const void* data3, const void* data4,\n\t\t                   size_t length)\n\t\t{\n\t\t\tavx1_mshabal(&context, data1, data2, data3, data4, length);\n\t\t}\n\n\t\tstatic void close(context_t& context, void* output)\n\t\t{\n\t\t\tavx1_mshabal_close(&context, 0, 0, 0, 0, 0, output, nullptr, nullptr, nullptr);\n\t\t}\n\n\t\tstatic void close(context_t& context,\n\t\t\tvoid* out1, void* out2, void* out3, void* out4)\n\t\t{\n\t\t\tavx1_mshabal_close(&context, 0, 0, 0, 0, 0, out1, out2, out3, out4);\n\t\t}\n\t};\n}\n\n#ifndef USE_AVX\ninline void avx1_mshabal_init(mshabal_context* sc, unsigned out_size) {}\n\ninline void avx1_mshabal(mshabal_context* sc, const void* data0, const void* data1, const void* data2, const void* data3,\n                  size_t len) {}\n\ninline void avx1_mshabal_close(mshabal_context* sc, unsigned ub0, unsigned ub1, unsigned ub2, unsigned ub3, unsigned n,\n                        void* dst0, void* dst1, void* dst2, void* dst3) {}\n#endif\n"
  },
  {
    "path": "src/shabal/impl/mshabal_sse4_impl.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"shabal/mshabal/mshabal.h\"\n\nnamespace Burst\n{\n\tstruct MshabalSse4Impl\n\t{\n\t\tstatic constexpr size_t HashSize = 4;\n\n\t\tusing context_t = mshabal_context;\n\n\t\tstatic void init(context_t& context)\n\t\t{\n\t\t\tsse4_mshabal_init(&context, 256);\n\t\t}\n\n\t\tstatic void update(context_t& context, const void* data, size_t length)\n\t\t{\n\t\t\tupdate(context, data, data, data, data, length);\n\t\t}\n\n\t\tstatic void update(context_t& context,\n\t\t\tconst void* data1, const void* data2, const void* data3, const void* data4,\n\t\t\tsize_t length)\n\t\t{\n\t\t\tsse4_mshabal(&context, data1, data2, data3, data4, length);\n\t\t}\n\n\t\tstatic void close(context_t& context, void* output)\n\t\t{\n\t\t\tsse4_mshabal_close(&context, 0, 0, 0, 0, 0, output, nullptr, nullptr, nullptr);\n\t\t}\n\n\t\tstatic void close(context_t& context,\n\t\t\tvoid* out1, void* out2, void* out3, void* out4)\n\t\t{\n\t\t\tsse4_mshabal_close(&context, 0, 0, 0, 0, 0, out1, out2, out3, out4);\n\t\t}\n\t};\n}\n\n#ifndef USE_SSE4\ninline void sse4_mshabal_init(mshabal_context *sc, unsigned out_size) {}\n\ninline void sse4_mshabal(mshabal_context *sc, const void *data0, const void *data1, const void *data2, const void *data3, size_t len) {}\n\ninline void sse4_mshabal_close(mshabal_context* sc, unsigned ub0, unsigned ub1, unsigned ub2, unsigned ub3, unsigned n,\n                        void* dst0, void* dst1, void* dst2, void* dst3) {}\n#endif\n"
  },
  {
    "path": "src/shabal/impl/sphlib_impl.hpp",
    "content": "// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"shabal/sphlib/sph_shabal.h\"\n\nnamespace Burst\n{\n\tstruct SphlibImpl\n\t{\n\t\tstatic constexpr size_t HashSize = 1;\n\n\t\tusing context_t = sph_shabal256_context;\n\n\t\tstatic void init(context_t& context)\n\t\t{\n\t\t\tsph_shabal256_init(&context);\n\t\t}\n\n\t\tstatic void update(context_t& context, const void* data, size_t length)\n\t\t{\n\t\t\tsph_shabal256(&context, data, length);\n\t\t}\n\n\t\tstatic void close(context_t& context, void* out)\n\t\t{\n\t\t\tsph_shabal256_close(&context, out);\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "src/shabal/mshabal/mshabal.h",
    "content": "/*\n* A parallel implementation of Shabal, for platforms with SSE2.\n*\n* This is the header file for an implementation of the Shabal family\n* of hash functions, designed for maximum parallel speed. It processes\n* up to four instances of Shabal in parallel, using the SSE2 unit.\n* Total bandwidth appear to be up to twice that of a plain 32-bit\n* Shabal implementation.\n*\n* A computation uses a mshabal_context structure. That structure is\n* supposed to be allocated and released by the caller, e.g. as a\n* local or global variable, or on the heap. The structure contents\n* are initialized with mshabal_init(). Once the structure has been\n* initialized, data is input as chunks, with the mshabal() functions.\n* Chunks for the four parallel instances are provided simultaneously\n* and must have the same length. It is allowed not to use some of the\n* instances; the corresponding parameters in mshabal() are then NULL.\n* However, using NULL as a chunk for one of the instances effectively\n* deactivates that instance; this cannot be used to \"skip\" a chunk\n* for one instance.\n*\n* The computation is finalized with mshabal_close(). Some extra message\n* bits (0 to 7) can be input. The outputs of the four parallel instances\n* are written in the provided buffers. There again, NULL can be\n* provided as parameter is the output of one of the instances is not\n* needed.\n*\n* A mshabal_context instance is self-contained and holds no pointer.\n* Thus, it can be cloned (e.g. with memcpy()) or moved (as long as\n* proper alignment is maintained). This implementation uses no state\n* variable beyond the context instance; this, it is thread-safe and\n* reentrant.\n*\n* The Shabal specification defines Shabal with output sizes of 192,\n* 224, 256, 384 and 512 bits. This code accepts all those sizes, as\n* well as any output size which is multiple of 32, between 32 and\n* 512 (inclusive).\n*\n* Parameters are not validated. Thus, undefined behaviour occurs if\n* any of the \"shall\" or \"must\" clauses in this documentation is\n* violated.\n*\n*\n* (c) 2010 SAPHIR project. This software is provided 'as-is', without\n* any epxress or implied warranty. In no event will the authors be held\n* liable for any damages arising from the use of this software.\n*\n* Permission is granted to anyone to use this software for any purpose,\n* including commercial applications, and to alter it and redistribute it\n* freely, subject to no restriction.\n*\n* Technical remarks and questions can be addressed to:\n* <thomas.pornin@cryptolog.com>\n*/\n\n#ifndef MSHABAL_H__\n#define MSHABAL_H__\n\n#include <limits.h>\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n\t/*\n\t* We need an integer type with width 32-bit or more (preferably, with\n\t* a width of exactly 32 bits).\n\t*/\n#if defined __STDC__ && __STDC_VERSION__ >= 199901L\n#include <stdint.h>\n#ifdef UINT32_MAX\n\ttypedef uint32_t mshabal_u32;\n#else\n\ttypedef uint_fast32_t mshabal_u32;\n#endif\n#else\n#if ((UINT_MAX >> 11) >> 11) >= 0x3FF\n\ttypedef unsigned int mshabal_u32;\n\ttypedef unsigned int mshabal256_u32;\n#else\n\ttypedef unsigned long mshabal_u32;\n\ttypedef unsigned long mshabal256_u32;\n#endif\n#endif\n\n#define MSHABAL256_FACTOR 2\n\n\t/*\n\t* The context structure for a Shabal computation. Contents are\n\t* private. Such a structure should be allocated and released by\n\t* the caller, in any memory area.\n\t*/\n\ttypedef struct {\n\t\tunsigned char buf0[64];\n\t\tunsigned char buf1[64];\n\t\tunsigned char buf2[64];\n\t\tunsigned char buf3[64];\n\t\tsize_t ptr;\n\t\tmshabal_u32 state[(12 + 16 + 16) * 4];\n\t\tmshabal_u32 Whigh, Wlow;\n\t\tunsigned out_size;\n\t} mshabal_context;\n\n\t/*\n\t* The context structure for a Shabal computation. Contents are\n\t* private. Such a structure should be allocated and released by\n\t* the caller, in any memory area.\n\t*/\n\ttypedef struct {\n\t\tunsigned char buf0[64];\n\t\tunsigned char buf1[64];\n\t\tunsigned char buf2[64];\n\t\tunsigned char buf3[64];\n\t\tunsigned char buf4[64];\n\t\tunsigned char buf5[64];\n\t\tunsigned char buf6[64];\n\t\tunsigned char buf7[64];\n\t\tsize_t ptr;\n\t\tmshabal256_u32 state[(12 + 16 + 16) * 4 * MSHABAL256_FACTOR];\n\t\tmshabal256_u32 Whigh, Wlow;\n\t\tunsigned out_size;\n\t} mshabal256_context;\n\n\t/*\n\t* Initialize a context structure. The output size must be a multiple\n\t* of 32, between 32 and 512 (inclusive). The output size is expressed\n\t* in bits.\n\t*/\n\tvoid sse4_mshabal_init(mshabal_context *sc, unsigned out_size);\n\n\t/*\n\t* Initialize a context structure. The output size must be a multiple\n\t* of 32, between 32 and 512 (inclusive). The output size is expressed\n\t* in bits.\n\t*/\n\tvoid avx1_mshabal_init(mshabal_context *sc, unsigned out_size);\n\n\t/*\n\t* Initialize a context structure. The output size must be a multiple\n\t* of 32, between 32 and 512 (inclusive). The output size is expressed\n\t* in bits.\n\t*/\n\tvoid avx2_mshabal_init(mshabal256_context *sc, unsigned out_size);\n\n\t/*\n\t* Process some more data bytes; four chunks of data, pointed to by\n\t* data0, data1, data2 and data3, are processed. The four chunks have\n\t* the same length of \"len\" bytes. For efficiency, it is best if data is\n\t* processed by medium-sized chunks, e.g. a few kilobytes at a time.\n\t*\n\t* The \"len\" data bytes shall all be accessible. If \"len\" is zero, this\n\t* this function does nothing and ignores the data* arguments.\n\t* Otherwise, if one of the data* argument is NULL, then the\n\t* corresponding instance is deactivated (the final value obtained from\n\t* that instance is undefined).\n\t*/\n\tvoid sse4_mshabal(mshabal_context *sc, const void *data0, const void *data1, const void *data2, const void *data3, size_t len);\n\n\t/*\n\t* Process some more data bytes; four chunks of data, pointed to by\n\t* data0, data1, data2 and data3, are processed. The four chunks have\n\t* the same length of \"len\" bytes. For efficiency, it is best if data is\n\t* processed by medium-sized chunks, e.g. a few kilobytes at a time.\n\t*\n\t* The \"len\" data bytes shall all be accessible. If \"len\" is zero, this\n\t* this function does nothing and ignores the data* arguments.\n\t* Otherwise, if one of the data* argument is NULL, then the\n\t* corresponding instance is deactivated (the final value obtained from\n\t* that instance is undefined).\n\t*/\n\tvoid avx1_mshabal(mshabal_context *sc, const void *data0, const void *data1, const void *data2, const void *data3, size_t len);\n\n\t/*\n\t* Process some more data bytes; four chunks of data, pointed to by\n\t* data0, data1, data2 and data3, are processed. The four chunks have\n\t* the same length of \"len\" bytes. For efficiency, it is best if data is\n\t* processed by medium-sized chunks, e.g. a few kilobytes at a time.\n\t*\n\t* The \"len\" data bytes shall all be accessible. If \"len\" is zero, this\n\t* this function does nothing and ignores the data* arguments.\n\t* Otherwise, if one of the data* argument is NULL, then the\n\t* corresponding instance is deactivated (the final value obtained from\n\t* that instance is undefined).\n\t*/\n\tvoid avx2_mshabal(mshabal256_context *sc,\n\t\tconst void *data0, const void *data1, const void *data2, const void *data3,\n\t\tconst void *data4, const void *data5, const void *data6, const void *data7,\n\t\tsize_t len);\n\n\t/*\n\t* Terminate the Shabal computation incarnated by the provided context\n\t* structure. \"n\" shall be a value between 0 and 7 (inclusive): this is\n\t* the number of extra bits to extract from ub0, ub1, ub2 and ub3, and\n\t* append at the end of the input message for each of the four parallel\n\t* instances. Bits in \"ub*\" are taken in big-endian format: first bit is\n\t* the one of numerical value 128, second bit has numerical value 64,\n\t* and so on. Other bits in \"ub*\" are ignored. For most applications,\n\t* input messages will consist in sequence of bytes, and the \"ub*\" and\n\t* \"n\" parameters will be zero.\n\t*\n\t* The Shabal output for each of the parallel instances is written out\n\t* in the areas pointed to by, respectively, dst0, dst1, dst2 and dst3.\n\t* These areas shall be wide enough to accomodate the result (result\n\t* size was specified as parameter to mshabal_init()). It is acceptable\n\t* to use NULL for any of those pointers, if the result from the\n\t* corresponding instance is not needed.\n\t*\n\t* After this call, the context structure is invalid. The caller shall\n\t* release it, or reinitialize it with mshabal_init(). The mshabal_close()\n\t* function does NOT imply a hidden call to mshabal_init().\n\t*/\n\tvoid sse4_mshabal_close(mshabal_context *sc, unsigned ub0, unsigned ub1, unsigned ub2, unsigned ub3, unsigned n, void *dst0, void *dst1, void *dst2, void *dst3);\n\n\t/*\n\t* Terminate the Shabal computation incarnated by the provided context\n\t* structure. \"n\" shall be a value between 0 and 7 (inclusive): this is\n\t* the number of extra bits to extract from ub0, ub1, ub2 and ub3, and\n\t* append at the end of the input message for each of the four parallel\n\t* instances. Bits in \"ub*\" are taken in big-endian format: first bit is\n\t* the one of numerical value 128, second bit has numerical value 64,\n\t* and so on. Other bits in \"ub*\" are ignored. For most applications,\n\t* input messages will consist in sequence of bytes, and the \"ub*\" and\n\t* \"n\" parameters will be zero.\n\t*\n\t* The Shabal output for each of the parallel instances is written out\n\t* in the areas pointed to by, respectively, dst0, dst1, dst2 and dst3.\n\t* These areas shall be wide enough to accomodate the result (result\n\t* size was specified as parameter to mshabal_init()). It is acceptable\n\t* to use NULL for any of those pointers, if the result from the\n\t* corresponding instance is not needed.\n\t*\n\t* After this call, the context structure is invalid. The caller shall\n\t* release it, or reinitialize it with mshabal_init(). The mshabal_close()\n\t* function does NOT imply a hidden call to mshabal_init().\n\t*/\n\tvoid avx1_mshabal_close(mshabal_context *sc, unsigned ub0, unsigned ub1, unsigned ub2, unsigned ub3, unsigned n, void *dst0, void *dst1, void *dst2, void *dst3);\n\n\t/*\n\t* Terminate the Shabal computation incarnated by the provided context\n\t* structure. \"n\" shall be a value between 0 and 7 (inclusive): this is\n\t* the number of extra bits to extract from ub0, ub1, ub2 and ub3, and\n\t* append at the end of the input message for each of the four parallel\n\t* instances. Bits in \"ub*\" are taken in big-endian format: first bit is\n\t* the one of numerical value 128, second bit has numerical value 64,\n\t* and so on. Other bits in \"ub*\" are ignored. For most applications,\n\t* input messages will consist in sequence of bytes, and the \"ub*\" and\n\t* \"n\" parameters will be zero.\n\t*\n\t* The Shabal output for each of the parallel instances is written out\n\t* in the areas pointed to by, respectively, dst0, dst1, dst2 and dst3.\n\t* These areas shall be wide enough to accomodate the result (result\n\t* size was specified as parameter to mshabal256_init()). It is acceptable\n\t* to use NULL for any of those pointers, if the result from the\n\t* corresponding instance is not needed.\n\t*\n\t* After this call, the context structure is invalid. The caller shall\n\t* release it, or reinitialize it with mshabal256_init(). The mshabal256_close()\n\t* function does NOT imply a hidden call to mshabal256_init().\n\t*/\n\tvoid avx2_mshabal_close(mshabal256_context *sc,\n\t\tunsigned ub0, unsigned ub1, unsigned ub2, unsigned ub3,\n\t\tunsigned ub4, unsigned ub5, unsigned ub6, unsigned ub7,\n\t\tunsigned n,\n\t\tvoid *dst0, void *dst1, void *dst2, void *dst3,\n\t\tvoid *dst4, void *dst5, void *dst6, void *dst7);\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif"
  },
  {
    "path": "src/shabal/mshabal/mshabal_avx1.cpp",
    "content": "/*\n* Parallel implementation of Shabal, using the SSE2 unit. This code\n* compiles and runs on x86 architectures, in 32-bit or 64-bit mode,\n* which possess a SSE2-compatible SIMD unit.\n*\n*\n* (c) 2010 SAPHIR project. This software is provided 'as-is', without\n* any epxress or implied warranty. In no event will the authors be held\n* liable for any damages arising from the use of this software.\n*\n* Permission is granted to anyone to use this software for any purpose,\n* including commercial applications, and to alter it and redistribute it\n* freely, subject to no restriction.\n*\n* Technical remarks and questions can be addressed to:\n* <thomas.pornin@cryptolog.com>\n*/\n\n#include <stddef.h>\n#include <string.h>\n#include <emmintrin.h>\n\n#include \"mshabal.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef _MSC_VER\n#pragma warning (disable: 4146)\n#endif\n\n\ttypedef mshabal_u32 u32;\n\n#define C32(x)         ((u32)x ## UL)\n#define T32(x)         ((x) & C32(0xFFFFFFFF))\n#define ROTL32(x, n)   T32(((x) << (n)) | ((x) >> (32 - (n))))\n\n\tstatic void\n\t\tavx1_mshabal_compress(mshabal_context *sc,\n\t\t\tconst unsigned char *buf0, const unsigned char *buf1,\n\t\t\tconst unsigned char *buf2, const unsigned char *buf3,\n\t\t\tsize_t num)\n\t{\n\t\tunion {\n\t\t\tu32 words[64];\n\t\t\t__m128i data[16];\n\t\t} u;\n\t\tsize_t j;\n\t\t__m128i A[12], B[16], C[16];\n\t\t__m128i one;\n\n\t\tfor (j = 0; j < 12; j++)\n\t\t\tA[j] = _mm_loadu_si128((__m128i *)sc->state + j);\n\t\tfor (j = 0; j < 16; j++) {\n\t\t\tB[j] = _mm_loadu_si128((__m128i *)sc->state + j + 12);\n\t\t\tC[j] = _mm_loadu_si128((__m128i *)sc->state + j + 28);\n\t\t}\n\t\tone = _mm_set1_epi32(C32(0xFFFFFFFF));\n\n#define M(i)   _mm_load_si128(u.data + (i))\n\n\t\twhile (num-- > 0) {\n\n\t\t\tfor (j = 0; j < 64; j += 4) {\n\t\t\t\tu.words[j + 0] = *(u32 *)(buf0 + j);\n\t\t\t\tu.words[j + 1] = *(u32 *)(buf1 + j);\n\t\t\t\tu.words[j + 2] = *(u32 *)(buf2 + j);\n\t\t\t\tu.words[j + 3] = *(u32 *)(buf3 + j);\n\t\t\t}\n\n\t\t\tfor (j = 0; j < 16; j++)\n\t\t\t\tB[j] = _mm_add_epi32(B[j], M(j));\n\n\t\t\tA[0] = _mm_xor_si128(A[0], _mm_set1_epi32(sc->Wlow));\n\t\t\tA[1] = _mm_xor_si128(A[1], _mm_set1_epi32(sc->Whigh));\n\n\t\t\tfor (j = 0; j < 16; j++)\n\t\t\t\tB[j] = _mm_or_si128(_mm_slli_epi32(B[j], 17),\n\t\t\t\t\t_mm_srli_epi32(B[j], 15));\n\n#define PP(xa0, xa1, xb0, xb1, xb2, xb3, xc, xm)   do { \\\n\t\t__m128i tt; \\\n\t\ttt = _mm_or_si128(_mm_slli_epi32(xa1, 15), \\\n\t\t\t_mm_srli_epi32(xa1, 17)); \\\n\t\ttt = _mm_add_epi32(_mm_slli_epi32(tt, 2), tt); \\\n\t\ttt = _mm_xor_si128(_mm_xor_si128(xa0, tt), xc); \\\n\t\ttt = _mm_add_epi32(_mm_slli_epi32(tt, 1), tt); \\\n\t\ttt = _mm_xor_si128( \\\n\t\t\t_mm_xor_si128(tt, xb1), \\\n\t\t\t_mm_xor_si128(_mm_andnot_si128(xb3, xb2), xm)); \\\n\t\txa0 = tt; \\\n\t\ttt = xb0; \\\n\t\ttt = _mm_or_si128(_mm_slli_epi32(tt, 1), \\\n\t\t\t_mm_srli_epi32(tt, 31)); \\\n\t\txb0 = _mm_xor_si128(tt, _mm_xor_si128(xa0, one)); \\\n            \t} while (0)\n\n\t\t\tPP(A[0x0], A[0xB], B[0x0], B[0xD], B[0x9], B[0x6], C[0x8], M(0x0));\n\t\t\tPP(A[0x1], A[0x0], B[0x1], B[0xE], B[0xA], B[0x7], C[0x7], M(0x1));\n\t\t\tPP(A[0x2], A[0x1], B[0x2], B[0xF], B[0xB], B[0x8], C[0x6], M(0x2));\n\t\t\tPP(A[0x3], A[0x2], B[0x3], B[0x0], B[0xC], B[0x9], C[0x5], M(0x3));\n\t\t\tPP(A[0x4], A[0x3], B[0x4], B[0x1], B[0xD], B[0xA], C[0x4], M(0x4));\n\t\t\tPP(A[0x5], A[0x4], B[0x5], B[0x2], B[0xE], B[0xB], C[0x3], M(0x5));\n\t\t\tPP(A[0x6], A[0x5], B[0x6], B[0x3], B[0xF], B[0xC], C[0x2], M(0x6));\n\t\t\tPP(A[0x7], A[0x6], B[0x7], B[0x4], B[0x0], B[0xD], C[0x1], M(0x7));\n\t\t\tPP(A[0x8], A[0x7], B[0x8], B[0x5], B[0x1], B[0xE], C[0x0], M(0x8));\n\t\t\tPP(A[0x9], A[0x8], B[0x9], B[0x6], B[0x2], B[0xF], C[0xF], M(0x9));\n\t\t\tPP(A[0xA], A[0x9], B[0xA], B[0x7], B[0x3], B[0x0], C[0xE], M(0xA));\n\t\t\tPP(A[0xB], A[0xA], B[0xB], B[0x8], B[0x4], B[0x1], C[0xD], M(0xB));\n\t\t\tPP(A[0x0], A[0xB], B[0xC], B[0x9], B[0x5], B[0x2], C[0xC], M(0xC));\n\t\t\tPP(A[0x1], A[0x0], B[0xD], B[0xA], B[0x6], B[0x3], C[0xB], M(0xD));\n\t\t\tPP(A[0x2], A[0x1], B[0xE], B[0xB], B[0x7], B[0x4], C[0xA], M(0xE));\n\t\t\tPP(A[0x3], A[0x2], B[0xF], B[0xC], B[0x8], B[0x5], C[0x9], M(0xF));\n\n\t\t\tPP(A[0x4], A[0x3], B[0x0], B[0xD], B[0x9], B[0x6], C[0x8], M(0x0));\n\t\t\tPP(A[0x5], A[0x4], B[0x1], B[0xE], B[0xA], B[0x7], C[0x7], M(0x1));\n\t\t\tPP(A[0x6], A[0x5], B[0x2], B[0xF], B[0xB], B[0x8], C[0x6], M(0x2));\n\t\t\tPP(A[0x7], A[0x6], B[0x3], B[0x0], B[0xC], B[0x9], C[0x5], M(0x3));\n\t\t\tPP(A[0x8], A[0x7], B[0x4], B[0x1], B[0xD], B[0xA], C[0x4], M(0x4));\n\t\t\tPP(A[0x9], A[0x8], B[0x5], B[0x2], B[0xE], B[0xB], C[0x3], M(0x5));\n\t\t\tPP(A[0xA], A[0x9], B[0x6], B[0x3], B[0xF], B[0xC], C[0x2], M(0x6));\n\t\t\tPP(A[0xB], A[0xA], B[0x7], B[0x4], B[0x0], B[0xD], C[0x1], M(0x7));\n\t\t\tPP(A[0x0], A[0xB], B[0x8], B[0x5], B[0x1], B[0xE], C[0x0], M(0x8));\n\t\t\tPP(A[0x1], A[0x0], B[0x9], B[0x6], B[0x2], B[0xF], C[0xF], M(0x9));\n\t\t\tPP(A[0x2], A[0x1], B[0xA], B[0x7], B[0x3], B[0x0], C[0xE], M(0xA));\n\t\t\tPP(A[0x3], A[0x2], B[0xB], B[0x8], B[0x4], B[0x1], C[0xD], M(0xB));\n\t\t\tPP(A[0x4], A[0x3], B[0xC], B[0x9], B[0x5], B[0x2], C[0xC], M(0xC));\n\t\t\tPP(A[0x5], A[0x4], B[0xD], B[0xA], B[0x6], B[0x3], C[0xB], M(0xD));\n\t\t\tPP(A[0x6], A[0x5], B[0xE], B[0xB], B[0x7], B[0x4], C[0xA], M(0xE));\n\t\t\tPP(A[0x7], A[0x6], B[0xF], B[0xC], B[0x8], B[0x5], C[0x9], M(0xF));\n\n\t\t\tPP(A[0x8], A[0x7], B[0x0], B[0xD], B[0x9], B[0x6], C[0x8], M(0x0));\n\t\t\tPP(A[0x9], A[0x8], B[0x1], B[0xE], B[0xA], B[0x7], C[0x7], M(0x1));\n\t\t\tPP(A[0xA], A[0x9], B[0x2], B[0xF], B[0xB], B[0x8], C[0x6], M(0x2));\n\t\t\tPP(A[0xB], A[0xA], B[0x3], B[0x0], B[0xC], B[0x9], C[0x5], M(0x3));\n\t\t\tPP(A[0x0], A[0xB], B[0x4], B[0x1], B[0xD], B[0xA], C[0x4], M(0x4));\n\t\t\tPP(A[0x1], A[0x0], B[0x5], B[0x2], B[0xE], B[0xB], C[0x3], M(0x5));\n\t\t\tPP(A[0x2], A[0x1], B[0x6], B[0x3], B[0xF], B[0xC], C[0x2], M(0x6));\n\t\t\tPP(A[0x3], A[0x2], B[0x7], B[0x4], B[0x0], B[0xD], C[0x1], M(0x7));\n\t\t\tPP(A[0x4], A[0x3], B[0x8], B[0x5], B[0x1], B[0xE], C[0x0], M(0x8));\n\t\t\tPP(A[0x5], A[0x4], B[0x9], B[0x6], B[0x2], B[0xF], C[0xF], M(0x9));\n\t\t\tPP(A[0x6], A[0x5], B[0xA], B[0x7], B[0x3], B[0x0], C[0xE], M(0xA));\n\t\t\tPP(A[0x7], A[0x6], B[0xB], B[0x8], B[0x4], B[0x1], C[0xD], M(0xB));\n\t\t\tPP(A[0x8], A[0x7], B[0xC], B[0x9], B[0x5], B[0x2], C[0xC], M(0xC));\n\t\t\tPP(A[0x9], A[0x8], B[0xD], B[0xA], B[0x6], B[0x3], C[0xB], M(0xD));\n\t\t\tPP(A[0xA], A[0x9], B[0xE], B[0xB], B[0x7], B[0x4], C[0xA], M(0xE));\n\t\t\tPP(A[0xB], A[0xA], B[0xF], B[0xC], B[0x8], B[0x5], C[0x9], M(0xF));\n\n\t\t\tA[0xB] = _mm_add_epi32(A[0xB], C[0x6]);\n\t\t\tA[0xA] = _mm_add_epi32(A[0xA], C[0x5]);\n\t\t\tA[0x9] = _mm_add_epi32(A[0x9], C[0x4]);\n\t\t\tA[0x8] = _mm_add_epi32(A[0x8], C[0x3]);\n\t\t\tA[0x7] = _mm_add_epi32(A[0x7], C[0x2]);\n\t\t\tA[0x6] = _mm_add_epi32(A[0x6], C[0x1]);\n\t\t\tA[0x5] = _mm_add_epi32(A[0x5], C[0x0]);\n\t\t\tA[0x4] = _mm_add_epi32(A[0x4], C[0xF]);\n\t\t\tA[0x3] = _mm_add_epi32(A[0x3], C[0xE]);\n\t\t\tA[0x2] = _mm_add_epi32(A[0x2], C[0xD]);\n\t\t\tA[0x1] = _mm_add_epi32(A[0x1], C[0xC]);\n\t\t\tA[0x0] = _mm_add_epi32(A[0x0], C[0xB]);\n\t\t\tA[0xB] = _mm_add_epi32(A[0xB], C[0xA]);\n\t\t\tA[0xA] = _mm_add_epi32(A[0xA], C[0x9]);\n\t\t\tA[0x9] = _mm_add_epi32(A[0x9], C[0x8]);\n\t\t\tA[0x8] = _mm_add_epi32(A[0x8], C[0x7]);\n\t\t\tA[0x7] = _mm_add_epi32(A[0x7], C[0x6]);\n\t\t\tA[0x6] = _mm_add_epi32(A[0x6], C[0x5]);\n\t\t\tA[0x5] = _mm_add_epi32(A[0x5], C[0x4]);\n\t\t\tA[0x4] = _mm_add_epi32(A[0x4], C[0x3]);\n\t\t\tA[0x3] = _mm_add_epi32(A[0x3], C[0x2]);\n\t\t\tA[0x2] = _mm_add_epi32(A[0x2], C[0x1]);\n\t\t\tA[0x1] = _mm_add_epi32(A[0x1], C[0x0]);\n\t\t\tA[0x0] = _mm_add_epi32(A[0x0], C[0xF]);\n\t\t\tA[0xB] = _mm_add_epi32(A[0xB], C[0xE]);\n\t\t\tA[0xA] = _mm_add_epi32(A[0xA], C[0xD]);\n\t\t\tA[0x9] = _mm_add_epi32(A[0x9], C[0xC]);\n\t\t\tA[0x8] = _mm_add_epi32(A[0x8], C[0xB]);\n\t\t\tA[0x7] = _mm_add_epi32(A[0x7], C[0xA]);\n\t\t\tA[0x6] = _mm_add_epi32(A[0x6], C[0x9]);\n\t\t\tA[0x5] = _mm_add_epi32(A[0x5], C[0x8]);\n\t\t\tA[0x4] = _mm_add_epi32(A[0x4], C[0x7]);\n\t\t\tA[0x3] = _mm_add_epi32(A[0x3], C[0x6]);\n\t\t\tA[0x2] = _mm_add_epi32(A[0x2], C[0x5]);\n\t\t\tA[0x1] = _mm_add_epi32(A[0x1], C[0x4]);\n\t\t\tA[0x0] = _mm_add_epi32(A[0x0], C[0x3]);\n\n#define SWAP_AND_SUB(xb, xc, xm)   do { \\\n\t\t__m128i tmp; \\\n\t\ttmp = xb; \\\n\t\txb = _mm_sub_epi32(xc, xm); \\\n\t\txc = tmp; \\\n            \t} while (0)\n\n\t\t\tSWAP_AND_SUB(B[0x0], C[0x0], M(0x0));\n\t\t\tSWAP_AND_SUB(B[0x1], C[0x1], M(0x1));\n\t\t\tSWAP_AND_SUB(B[0x2], C[0x2], M(0x2));\n\t\t\tSWAP_AND_SUB(B[0x3], C[0x3], M(0x3));\n\t\t\tSWAP_AND_SUB(B[0x4], C[0x4], M(0x4));\n\t\t\tSWAP_AND_SUB(B[0x5], C[0x5], M(0x5));\n\t\t\tSWAP_AND_SUB(B[0x6], C[0x6], M(0x6));\n\t\t\tSWAP_AND_SUB(B[0x7], C[0x7], M(0x7));\n\t\t\tSWAP_AND_SUB(B[0x8], C[0x8], M(0x8));\n\t\t\tSWAP_AND_SUB(B[0x9], C[0x9], M(0x9));\n\t\t\tSWAP_AND_SUB(B[0xA], C[0xA], M(0xA));\n\t\t\tSWAP_AND_SUB(B[0xB], C[0xB], M(0xB));\n\t\t\tSWAP_AND_SUB(B[0xC], C[0xC], M(0xC));\n\t\t\tSWAP_AND_SUB(B[0xD], C[0xD], M(0xD));\n\t\t\tSWAP_AND_SUB(B[0xE], C[0xE], M(0xE));\n\t\t\tSWAP_AND_SUB(B[0xF], C[0xF], M(0xF));\n\n\t\t\tbuf0 += 64;\n\t\t\tbuf1 += 64;\n\t\t\tbuf2 += 64;\n\t\t\tbuf3 += 64;\n\t\t\tif (++sc->Wlow == 0)\n\t\t\t\tsc->Whigh++;\n\n\t\t}\n\n\t\tfor (j = 0; j < 12; j++)\n\t\t\t_mm_storeu_si128((__m128i *)sc->state + j, A[j]);\n\t\tfor (j = 0; j < 16; j++) {\n\t\t\t_mm_storeu_si128((__m128i *)sc->state + j + 12, B[j]);\n\t\t\t_mm_storeu_si128((__m128i *)sc->state + j + 28, C[j]);\n\t\t}\n\n#undef M\n\t}\n\n\t/* see shabal_small.h */\n\tvoid\n\t\tavx1_mshabal_init(mshabal_context *sc, unsigned out_size)\n\t{\n\t\tunsigned u;\n\n\t\tfor (u = 0; u < 176; u++)\n\t\t\tsc->state[u] = 0;\n\t\tmemset(sc->buf0, 0, sizeof sc->buf0);\n\t\tmemset(sc->buf1, 0, sizeof sc->buf1);\n\t\tmemset(sc->buf2, 0, sizeof sc->buf2);\n\t\tmemset(sc->buf3, 0, sizeof sc->buf3);\n\t\tfor (u = 0; u < 16; u++) {\n\t\t\tsc->buf0[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf0[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf1[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf1[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf2[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf2[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf3[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf3[4 * u + 1] = (out_size + u) >> 8;\n\t\t}\n\t\tsc->Whigh = sc->Wlow = C32(0xFFFFFFFF);\n\t\tavx1_mshabal_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, 1);\n\t\tfor (u = 0; u < 16; u++) {\n\t\t\tsc->buf0[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf0[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf1[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf1[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf2[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf2[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf3[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf3[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t}\n\t\tavx1_mshabal_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, 1);\n\t\tsc->ptr = 0;\n\t\tsc->out_size = out_size;\n\t}\n\n\t/* see shabal_small.h */\n\tvoid\n\t\tavx1_mshabal(mshabal_context *sc, const void *data0, const void *data1,\n\t\t\tconst void *data2, const void *data3, size_t len)\n\t{\n\t\tsize_t ptr, num;\n\n\t\tif (data0 == NULL) {\n\t\t\tif (data1 == NULL) {\n\t\t\t\tif (data2 == NULL) {\n\t\t\t\t\tif (data3 == NULL) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tdata0 = data3;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdata0 = data2;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdata0 = data1;\n\t\t\t}\n\t\t}\n\t\tif (data1 == NULL)\n\t\t\tdata1 = data0;\n\t\tif (data2 == NULL)\n\t\t\tdata2 = data0;\n\t\tif (data3 == NULL)\n\t\t\tdata3 = data0;\n\n\t\tptr = sc->ptr;\n\t\tif (ptr != 0) {\n\t\t\tsize_t clen;\n\n\t\t\tclen = (sizeof sc->buf0 - ptr);\n\t\t\tif (clen > len) {\n\t\t\t\tmemcpy(sc->buf0 + ptr, data0, len);\n\t\t\t\tmemcpy(sc->buf1 + ptr, data1, len);\n\t\t\t\tmemcpy(sc->buf2 + ptr, data2, len);\n\t\t\t\tmemcpy(sc->buf3 + ptr, data3, len);\n\t\t\t\tsc->ptr = ptr + len;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmemcpy(sc->buf0 + ptr, data0, clen);\n\t\t\t\tmemcpy(sc->buf1 + ptr, data1, clen);\n\t\t\t\tmemcpy(sc->buf2 + ptr, data2, clen);\n\t\t\t\tmemcpy(sc->buf3 + ptr, data3, clen);\n\t\t\t\tavx1_mshabal_compress(sc,\n\t\t\t\t\tsc->buf0, sc->buf1, sc->buf2, sc->buf3, 1);\n\t\t\t\tdata0 = (const unsigned char *)data0 + clen;\n\t\t\t\tdata1 = (const unsigned char *)data1 + clen;\n\t\t\t\tdata2 = (const unsigned char *)data2 + clen;\n\t\t\t\tdata3 = (const unsigned char *)data3 + clen;\n\t\t\t\tlen -= clen;\n\t\t\t}\n\t\t}\n\n\t\tnum = len >> 6;\n\t\tif (num != 0) {\n\t\t\tavx1_mshabal_compress(sc, (unsigned char*)data0, (unsigned char*)data1, (unsigned char*)data2, (unsigned char*)data3, num);\n\t\t\tdata0 = (const unsigned char *)data0 + (num << 6);\n\t\t\tdata1 = (const unsigned char *)data1 + (num << 6);\n\t\t\tdata2 = (const unsigned char *)data2 + (num << 6);\n\t\t\tdata3 = (const unsigned char *)data3 + (num << 6);\n\t\t}\n\t\tlen &= (size_t)63;\n\t\tmemcpy(sc->buf0, data0, len);\n\t\tmemcpy(sc->buf1, data1, len);\n\t\tmemcpy(sc->buf2, data2, len);\n\t\tmemcpy(sc->buf3, data3, len);\n\t\tsc->ptr = len;\n\t}\n\n\t/* see shabal_small.h */\n\tvoid\n\t\tavx1_mshabal_close(mshabal_context *sc,\n\t\t\tunsigned ub0, unsigned ub1, unsigned ub2, unsigned ub3, unsigned n,\n\t\t\tvoid *dst0, void *dst1, void *dst2, void *dst3)\n\t{\n\t\tsize_t ptr, off;\n\t\tunsigned z, out_size_w32;\n\n\t\tz = 0x80 >> n;\n\t\tptr = sc->ptr;\n\t\tsc->buf0[ptr] = (ub0 & -z) | z;\n\t\tsc->buf1[ptr] = (ub1 & -z) | z;\n\t\tsc->buf2[ptr] = (ub2 & -z) | z;\n\t\tsc->buf3[ptr] = (ub3 & -z) | z;\n\t\tptr++;\n\t\tmemset(sc->buf0 + ptr, 0, (sizeof sc->buf0) - ptr);\n\t\tmemset(sc->buf1 + ptr, 0, (sizeof sc->buf1) - ptr);\n\t\tmemset(sc->buf2 + ptr, 0, (sizeof sc->buf2) - ptr);\n\t\tmemset(sc->buf3 + ptr, 0, (sizeof sc->buf3) - ptr);\n\t\tfor (z = 0; z < 4; z++) {\n\t\t\tavx1_mshabal_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, 1);\n\t\t\tif (sc->Wlow-- == 0)\n\t\t\t\tsc->Whigh--;\n\t\t}\n\t\tout_size_w32 = sc->out_size >> 5;\n\t\toff = 4 * (28 + (16 - out_size_w32));\n\t\tif (dst0 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst0;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + (z << 2) + 0];\n\t\t}\n\t\tif (dst1 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst1;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + (z << 2) + 1];\n\t\t}\n\t\tif (dst2 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst2;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + (z << 2) + 2];\n\t\t}\n\t\tif (dst3 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst3;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + (z << 2) + 3];\n\t\t}\n\t}\n\n#ifdef  __cplusplus\n}\n#endif"
  },
  {
    "path": "src/shabal/mshabal/mshabal_avx2.cpp",
    "content": "/*\n* Parallel implementation of Shabal, using the SSE2 unit. This code\n* compiles and runs on x86 architectures, in 32-bit or 64-bit mode,\n* which possess a SSE2-compatible SIMD unit.\n*\n*\n* (c) 2010 SAPHIR project. This software is provided 'as-is', without\n* any epxress or implied warranty. In no event will the authors be held\n* liable for any damages arising from the use of this software.\n*\n* Permission is granted to anyone to use this software for any purpose,\n* including commercial applications, and to alter it and redistribute it\n* freely, subject to no restriction.\n*\n* Technical remarks and questions can be addressed to:\n* <thomas.pornin@cryptolog.com>\n*/\n\n#include <stddef.h>\n#include <string.h>\n#include <immintrin.h>\n\n#include \"mshabal.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef _MSC_VER\n#pragma warning (disable: 4146)\n#endif\n\n\ttypedef mshabal256_u32 u32;\n\n#define C32(x)         ((u32)x ## UL)\n#define T32(x)         ((x) & C32(0xFFFFFFFF))\n#define ROTL32(x, n)   T32(((x) << (n)) | ((x) >> (32 - (n))))\n\n\tstatic void\n\t\tmshabal256_compress(mshabal256_context *sc,\n\t\t\tconst unsigned char *buf0, const unsigned char *buf1,\n\t\t\tconst unsigned char *buf2, const unsigned char *buf3,\n\t\t\tconst unsigned char *buf4, const unsigned char *buf5,\n\t\t\tconst unsigned char *buf6, const unsigned char *buf7,\n\t\t\tsize_t num)\n\t{\n\t\tunion {\n\t\t\tu32 words[64 * MSHABAL256_FACTOR];\n\t\t\t__m256i data[16];\n\t\t} u;\n\t\tsize_t j;\n\t\t__m256i A[12], B[16], C[16];\n\t\t__m256i one;\n\n\t\tfor (j = 0; j < 12; j++)\n\t\t\tA[j] = _mm256_loadu_si256((__m256i *)sc->state + j);\n\t\tfor (j = 0; j < 16; j++) {\n\t\t\tB[j] = _mm256_loadu_si256((__m256i *)sc->state + j + 12);\n\t\t\tC[j] = _mm256_loadu_si256((__m256i *)sc->state + j + 28);\n\t\t}\n\t\tone = _mm256_set1_epi32(C32(0xFFFFFFFF));\n\n#define M(i)   _mm256_load_si256(u.data + (i))\n\n\t\twhile (num-- > 0) {\n\n\t\t\tfor (j = 0; j < 64 * MSHABAL256_FACTOR; j += 4 * MSHABAL256_FACTOR) {\n\t\t\t\tsize_t o = j / MSHABAL256_FACTOR;\n\t\t\t\tu.words[j + 0] = *(u32 *)(buf0 + o);\n\t\t\t\tu.words[j + 1] = *(u32 *)(buf1 + o);\n\t\t\t\tu.words[j + 2] = *(u32 *)(buf2 + o);\n\t\t\t\tu.words[j + 3] = *(u32 *)(buf3 + o);\n\t\t\t\tu.words[j + 4] = *(u32 *)(buf4 + o);\n\t\t\t\tu.words[j + 5] = *(u32 *)(buf5 + o);\n\t\t\t\tu.words[j + 6] = *(u32 *)(buf6 + o);\n\t\t\t\tu.words[j + 7] = *(u32 *)(buf7 + o);\n\t\t\t}\n\n\t\t\tfor (j = 0; j < 16; j++)\n\t\t\t\tB[j] = _mm256_add_epi32(B[j], M(j));\n\n\t\t\tA[0] = _mm256_xor_si256(A[0], _mm256_set1_epi32(sc->Wlow));\n\t\t\tA[1] = _mm256_xor_si256(A[1], _mm256_set1_epi32(sc->Whigh));\n\n\t\t\tfor (j = 0; j < 16; j++)\n\t\t\t\tB[j] = _mm256_or_si256(_mm256_slli_epi32(B[j], 17),\n\t\t\t\t\t_mm256_srli_epi32(B[j], 15));\n\n#define PP(xa0, xa1, xb0, xb1, xb2, xb3, xc, xm)   do { \\\n    __m256i tt; \\\n    tt = _mm256_or_si256(_mm256_slli_epi32(xa1, 15), \\\n      _mm256_srli_epi32(xa1, 17)); \\\n    tt = _mm256_add_epi32(_mm256_slli_epi32(tt, 2), tt); \\\n    tt = _mm256_xor_si256(_mm256_xor_si256(xa0, tt), xc); \\\n    tt = _mm256_add_epi32(_mm256_slli_epi32(tt, 1), tt); \\\n    tt = _mm256_xor_si256(\\\n      _mm256_xor_si256(tt, xb1), \\\n      _mm256_xor_si256(_mm256_andnot_si256(xb3, xb2), xm)); \\\n    xa0 = tt; \\\n    tt = xb0; \\\n    tt = _mm256_or_si256(_mm256_slli_epi32(tt, 1), \\\n      _mm256_srli_epi32(tt, 31)); \\\n    xb0 = _mm256_xor_si256(tt, _mm256_xor_si256(xa0, one)); \\\n        } while (0)\n\n\t\t\tPP(A[0x0], A[0xB], B[0x0], B[0xD], B[0x9], B[0x6], C[0x8], M(0x0));\n\t\t\tPP(A[0x1], A[0x0], B[0x1], B[0xE], B[0xA], B[0x7], C[0x7], M(0x1));\n\t\t\tPP(A[0x2], A[0x1], B[0x2], B[0xF], B[0xB], B[0x8], C[0x6], M(0x2));\n\t\t\tPP(A[0x3], A[0x2], B[0x3], B[0x0], B[0xC], B[0x9], C[0x5], M(0x3));\n\t\t\tPP(A[0x4], A[0x3], B[0x4], B[0x1], B[0xD], B[0xA], C[0x4], M(0x4));\n\t\t\tPP(A[0x5], A[0x4], B[0x5], B[0x2], B[0xE], B[0xB], C[0x3], M(0x5));\n\t\t\tPP(A[0x6], A[0x5], B[0x6], B[0x3], B[0xF], B[0xC], C[0x2], M(0x6));\n\t\t\tPP(A[0x7], A[0x6], B[0x7], B[0x4], B[0x0], B[0xD], C[0x1], M(0x7));\n\t\t\tPP(A[0x8], A[0x7], B[0x8], B[0x5], B[0x1], B[0xE], C[0x0], M(0x8));\n\t\t\tPP(A[0x9], A[0x8], B[0x9], B[0x6], B[0x2], B[0xF], C[0xF], M(0x9));\n\t\t\tPP(A[0xA], A[0x9], B[0xA], B[0x7], B[0x3], B[0x0], C[0xE], M(0xA));\n\t\t\tPP(A[0xB], A[0xA], B[0xB], B[0x8], B[0x4], B[0x1], C[0xD], M(0xB));\n\t\t\tPP(A[0x0], A[0xB], B[0xC], B[0x9], B[0x5], B[0x2], C[0xC], M(0xC));\n\t\t\tPP(A[0x1], A[0x0], B[0xD], B[0xA], B[0x6], B[0x3], C[0xB], M(0xD));\n\t\t\tPP(A[0x2], A[0x1], B[0xE], B[0xB], B[0x7], B[0x4], C[0xA], M(0xE));\n\t\t\tPP(A[0x3], A[0x2], B[0xF], B[0xC], B[0x8], B[0x5], C[0x9], M(0xF));\n\n\t\t\tPP(A[0x4], A[0x3], B[0x0], B[0xD], B[0x9], B[0x6], C[0x8], M(0x0));\n\t\t\tPP(A[0x5], A[0x4], B[0x1], B[0xE], B[0xA], B[0x7], C[0x7], M(0x1));\n\t\t\tPP(A[0x6], A[0x5], B[0x2], B[0xF], B[0xB], B[0x8], C[0x6], M(0x2));\n\t\t\tPP(A[0x7], A[0x6], B[0x3], B[0x0], B[0xC], B[0x9], C[0x5], M(0x3));\n\t\t\tPP(A[0x8], A[0x7], B[0x4], B[0x1], B[0xD], B[0xA], C[0x4], M(0x4));\n\t\t\tPP(A[0x9], A[0x8], B[0x5], B[0x2], B[0xE], B[0xB], C[0x3], M(0x5));\n\t\t\tPP(A[0xA], A[0x9], B[0x6], B[0x3], B[0xF], B[0xC], C[0x2], M(0x6));\n\t\t\tPP(A[0xB], A[0xA], B[0x7], B[0x4], B[0x0], B[0xD], C[0x1], M(0x7));\n\t\t\tPP(A[0x0], A[0xB], B[0x8], B[0x5], B[0x1], B[0xE], C[0x0], M(0x8));\n\t\t\tPP(A[0x1], A[0x0], B[0x9], B[0x6], B[0x2], B[0xF], C[0xF], M(0x9));\n\t\t\tPP(A[0x2], A[0x1], B[0xA], B[0x7], B[0x3], B[0x0], C[0xE], M(0xA));\n\t\t\tPP(A[0x3], A[0x2], B[0xB], B[0x8], B[0x4], B[0x1], C[0xD], M(0xB));\n\t\t\tPP(A[0x4], A[0x3], B[0xC], B[0x9], B[0x5], B[0x2], C[0xC], M(0xC));\n\t\t\tPP(A[0x5], A[0x4], B[0xD], B[0xA], B[0x6], B[0x3], C[0xB], M(0xD));\n\t\t\tPP(A[0x6], A[0x5], B[0xE], B[0xB], B[0x7], B[0x4], C[0xA], M(0xE));\n\t\t\tPP(A[0x7], A[0x6], B[0xF], B[0xC], B[0x8], B[0x5], C[0x9], M(0xF));\n\n\t\t\tPP(A[0x8], A[0x7], B[0x0], B[0xD], B[0x9], B[0x6], C[0x8], M(0x0));\n\t\t\tPP(A[0x9], A[0x8], B[0x1], B[0xE], B[0xA], B[0x7], C[0x7], M(0x1));\n\t\t\tPP(A[0xA], A[0x9], B[0x2], B[0xF], B[0xB], B[0x8], C[0x6], M(0x2));\n\t\t\tPP(A[0xB], A[0xA], B[0x3], B[0x0], B[0xC], B[0x9], C[0x5], M(0x3));\n\t\t\tPP(A[0x0], A[0xB], B[0x4], B[0x1], B[0xD], B[0xA], C[0x4], M(0x4));\n\t\t\tPP(A[0x1], A[0x0], B[0x5], B[0x2], B[0xE], B[0xB], C[0x3], M(0x5));\n\t\t\tPP(A[0x2], A[0x1], B[0x6], B[0x3], B[0xF], B[0xC], C[0x2], M(0x6));\n\t\t\tPP(A[0x3], A[0x2], B[0x7], B[0x4], B[0x0], B[0xD], C[0x1], M(0x7));\n\t\t\tPP(A[0x4], A[0x3], B[0x8], B[0x5], B[0x1], B[0xE], C[0x0], M(0x8));\n\t\t\tPP(A[0x5], A[0x4], B[0x9], B[0x6], B[0x2], B[0xF], C[0xF], M(0x9));\n\t\t\tPP(A[0x6], A[0x5], B[0xA], B[0x7], B[0x3], B[0x0], C[0xE], M(0xA));\n\t\t\tPP(A[0x7], A[0x6], B[0xB], B[0x8], B[0x4], B[0x1], C[0xD], M(0xB));\n\t\t\tPP(A[0x8], A[0x7], B[0xC], B[0x9], B[0x5], B[0x2], C[0xC], M(0xC));\n\t\t\tPP(A[0x9], A[0x8], B[0xD], B[0xA], B[0x6], B[0x3], C[0xB], M(0xD));\n\t\t\tPP(A[0xA], A[0x9], B[0xE], B[0xB], B[0x7], B[0x4], C[0xA], M(0xE));\n\t\t\tPP(A[0xB], A[0xA], B[0xF], B[0xC], B[0x8], B[0x5], C[0x9], M(0xF));\n\n\t\t\tA[0xB] = _mm256_add_epi32(A[0xB], C[0x6]);\n\t\t\tA[0xA] = _mm256_add_epi32(A[0xA], C[0x5]);\n\t\t\tA[0x9] = _mm256_add_epi32(A[0x9], C[0x4]);\n\t\t\tA[0x8] = _mm256_add_epi32(A[0x8], C[0x3]);\n\t\t\tA[0x7] = _mm256_add_epi32(A[0x7], C[0x2]);\n\t\t\tA[0x6] = _mm256_add_epi32(A[0x6], C[0x1]);\n\t\t\tA[0x5] = _mm256_add_epi32(A[0x5], C[0x0]);\n\t\t\tA[0x4] = _mm256_add_epi32(A[0x4], C[0xF]);\n\t\t\tA[0x3] = _mm256_add_epi32(A[0x3], C[0xE]);\n\t\t\tA[0x2] = _mm256_add_epi32(A[0x2], C[0xD]);\n\t\t\tA[0x1] = _mm256_add_epi32(A[0x1], C[0xC]);\n\t\t\tA[0x0] = _mm256_add_epi32(A[0x0], C[0xB]);\n\t\t\tA[0xB] = _mm256_add_epi32(A[0xB], C[0xA]);\n\t\t\tA[0xA] = _mm256_add_epi32(A[0xA], C[0x9]);\n\t\t\tA[0x9] = _mm256_add_epi32(A[0x9], C[0x8]);\n\t\t\tA[0x8] = _mm256_add_epi32(A[0x8], C[0x7]);\n\t\t\tA[0x7] = _mm256_add_epi32(A[0x7], C[0x6]);\n\t\t\tA[0x6] = _mm256_add_epi32(A[0x6], C[0x5]);\n\t\t\tA[0x5] = _mm256_add_epi32(A[0x5], C[0x4]);\n\t\t\tA[0x4] = _mm256_add_epi32(A[0x4], C[0x3]);\n\t\t\tA[0x3] = _mm256_add_epi32(A[0x3], C[0x2]);\n\t\t\tA[0x2] = _mm256_add_epi32(A[0x2], C[0x1]);\n\t\t\tA[0x1] = _mm256_add_epi32(A[0x1], C[0x0]);\n\t\t\tA[0x0] = _mm256_add_epi32(A[0x0], C[0xF]);\n\t\t\tA[0xB] = _mm256_add_epi32(A[0xB], C[0xE]);\n\t\t\tA[0xA] = _mm256_add_epi32(A[0xA], C[0xD]);\n\t\t\tA[0x9] = _mm256_add_epi32(A[0x9], C[0xC]);\n\t\t\tA[0x8] = _mm256_add_epi32(A[0x8], C[0xB]);\n\t\t\tA[0x7] = _mm256_add_epi32(A[0x7], C[0xA]);\n\t\t\tA[0x6] = _mm256_add_epi32(A[0x6], C[0x9]);\n\t\t\tA[0x5] = _mm256_add_epi32(A[0x5], C[0x8]);\n\t\t\tA[0x4] = _mm256_add_epi32(A[0x4], C[0x7]);\n\t\t\tA[0x3] = _mm256_add_epi32(A[0x3], C[0x6]);\n\t\t\tA[0x2] = _mm256_add_epi32(A[0x2], C[0x5]);\n\t\t\tA[0x1] = _mm256_add_epi32(A[0x1], C[0x4]);\n\t\t\tA[0x0] = _mm256_add_epi32(A[0x0], C[0x3]);\n\n#define SWAP_AND_SUB(xb, xc, xm)   do { \\\n    __m256i tmp; \\\n    tmp = xb; \\\n    xb = _mm256_sub_epi32(xc, xm); \\\n    xc = tmp; \\\n        } while (0)\n\n\t\t\tSWAP_AND_SUB(B[0x0], C[0x0], M(0x0));\n\t\t\tSWAP_AND_SUB(B[0x1], C[0x1], M(0x1));\n\t\t\tSWAP_AND_SUB(B[0x2], C[0x2], M(0x2));\n\t\t\tSWAP_AND_SUB(B[0x3], C[0x3], M(0x3));\n\t\t\tSWAP_AND_SUB(B[0x4], C[0x4], M(0x4));\n\t\t\tSWAP_AND_SUB(B[0x5], C[0x5], M(0x5));\n\t\t\tSWAP_AND_SUB(B[0x6], C[0x6], M(0x6));\n\t\t\tSWAP_AND_SUB(B[0x7], C[0x7], M(0x7));\n\t\t\tSWAP_AND_SUB(B[0x8], C[0x8], M(0x8));\n\t\t\tSWAP_AND_SUB(B[0x9], C[0x9], M(0x9));\n\t\t\tSWAP_AND_SUB(B[0xA], C[0xA], M(0xA));\n\t\t\tSWAP_AND_SUB(B[0xB], C[0xB], M(0xB));\n\t\t\tSWAP_AND_SUB(B[0xC], C[0xC], M(0xC));\n\t\t\tSWAP_AND_SUB(B[0xD], C[0xD], M(0xD));\n\t\t\tSWAP_AND_SUB(B[0xE], C[0xE], M(0xE));\n\t\t\tSWAP_AND_SUB(B[0xF], C[0xF], M(0xF));\n\n\t\t\tbuf0 += 64;\n\t\t\tbuf1 += 64;\n\t\t\tbuf2 += 64;\n\t\t\tbuf3 += 64;\n\t\t\tbuf4 += 64;\n\t\t\tbuf5 += 64;\n\t\t\tbuf6 += 64;\n\t\t\tbuf7 += 64;\n\t\t\tif (++sc->Wlow == 0)\n\t\t\t\tsc->Whigh++;\n\n\t\t}\n\n\t\tfor (j = 0; j < 12; j++)\n\t\t\t_mm256_storeu_si256((__m256i *)sc->state + j, A[j]);\n\t\tfor (j = 0; j < 16; j++) {\n\t\t\t_mm256_storeu_si256((__m256i *)sc->state + j + 12, B[j]);\n\t\t\t_mm256_storeu_si256((__m256i *)sc->state + j + 28, C[j]);\n\t\t}\n\n#undef M\n\t}\n\n\t/* see shabal_small.h */\n\tvoid\n\t\tavx2_mshabal_init(mshabal256_context *sc, unsigned out_size)\n\t{\n\t\tunsigned u;\n\n\t\tfor (u = 0; u < (12 + 16 + 16) * 4 * MSHABAL256_FACTOR; u++)\n\t\t\tsc->state[u] = 0;\n\t\tmemset(sc->buf0, 0, sizeof sc->buf0);\n\t\tmemset(sc->buf1, 0, sizeof sc->buf1);\n\t\tmemset(sc->buf2, 0, sizeof sc->buf2);\n\t\tmemset(sc->buf3, 0, sizeof sc->buf3);\n\t\tmemset(sc->buf4, 0, sizeof sc->buf4);\n\t\tmemset(sc->buf5, 0, sizeof sc->buf5);\n\t\tmemset(sc->buf6, 0, sizeof sc->buf6);\n\t\tmemset(sc->buf7, 0, sizeof sc->buf7);\n\t\tfor (u = 0; u < 16; u++) {\n\t\t\tsc->buf0[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf0[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf1[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf1[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf2[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf2[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf3[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf3[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf4[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf4[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf5[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf5[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf6[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf6[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf7[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf7[4 * u + 1] = (out_size + u) >> 8;\n\t\t}\n\t\tsc->Whigh = sc->Wlow = C32(0xFFFFFFFF);\n\t\tmshabal256_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, sc->buf4, sc->buf5, sc->buf6, sc->buf7, 1);\n\t\tfor (u = 0; u < 16; u++) {\n\t\t\tsc->buf0[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf0[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf1[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf1[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf2[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf2[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf3[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf3[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf4[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf4[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf5[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf5[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf6[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf6[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf7[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf7[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t}\n\t\tmshabal256_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, sc->buf4, sc->buf5, sc->buf6, sc->buf7, 1);\n\t\tsc->ptr = 0;\n\t\tsc->out_size = out_size;\n\t}\n\n\t/* see shabal_small.h */\n\tvoid\n\t\tavx2_mshabal(mshabal256_context *sc,\n\t\t\tconst void *data0, const void *data1, const void *data2, const void *data3,\n\t\t\tconst void *data4, const void *data5, const void *data6, const void *data7,\n\t\t\tsize_t len)\n\t{\n\t\tsize_t ptr, num;\n\n\t\tif (data0 == NULL) {\n\t\t\tif (data1 == NULL) {\n\t\t\t\tif (data2 == NULL) {\n\t\t\t\t\tif (data3 == NULL) {\n\t\t\t\t\t\tif (data4 == NULL) {\n\t\t\t\t\t\t\tif (data5 == NULL) {\n\t\t\t\t\t\t\t\tif (data6 == NULL) {\n\t\t\t\t\t\t\t\t\tif (data7 == NULL) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tdata0 = data7;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tdata0 = data6;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tdata0 = data5;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tdata0 = data4;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tdata0 = data3;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdata0 = data2;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdata0 = data1;\n\t\t\t}\n\t\t}\n\t\t//else {\n\t\t//  data0 = data0;\n\t\t//}\n\n\t\tif (data1 == NULL)\n\t\t\tdata1 = data0;\n\t\tif (data2 == NULL)\n\t\t\tdata2 = data0;\n\t\tif (data3 == NULL)\n\t\t\tdata3 = data0;\n\t\tif (data4 == NULL)\n\t\t\tdata4 = data0;\n\t\tif (data5 == NULL)\n\t\t\tdata5 = data0;\n\t\tif (data6 == NULL)\n\t\t\tdata6 = data0;\n\t\tif (data7 == NULL)\n\t\t\tdata7 = data0;\n\n\t\tptr = sc->ptr;\n\t\tif (ptr != 0) {\n\t\t\tsize_t clen;\n\n\t\t\tclen = (sizeof sc->buf0 - ptr);\n\t\t\tif (clen > len) {\n\t\t\t\tmemcpy(sc->buf0 + ptr, data0, len);\n\t\t\t\tmemcpy(sc->buf1 + ptr, data1, len);\n\t\t\t\tmemcpy(sc->buf2 + ptr, data2, len);\n\t\t\t\tmemcpy(sc->buf3 + ptr, data3, len);\n\t\t\t\tmemcpy(sc->buf4 + ptr, data4, len);\n\t\t\t\tmemcpy(sc->buf5 + ptr, data5, len);\n\t\t\t\tmemcpy(sc->buf6 + ptr, data6, len);\n\t\t\t\tmemcpy(sc->buf7 + ptr, data7, len);\n\t\t\t\tsc->ptr = ptr + len;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmemcpy(sc->buf0 + ptr, data0, clen);\n\t\t\t\tmemcpy(sc->buf1 + ptr, data1, clen);\n\t\t\t\tmemcpy(sc->buf2 + ptr, data2, clen);\n\t\t\t\tmemcpy(sc->buf3 + ptr, data3, clen);\n\t\t\t\tmemcpy(sc->buf4 + ptr, data4, clen);\n\t\t\t\tmemcpy(sc->buf5 + ptr, data5, clen);\n\t\t\t\tmemcpy(sc->buf6 + ptr, data6, clen);\n\t\t\t\tmemcpy(sc->buf7 + ptr, data7, clen);\n\t\t\t\tmshabal256_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, sc->buf4, sc->buf5, sc->buf6, sc->buf7, 1);\n\t\t\t\tdata0 = (const unsigned char *)data0 + clen;\n\t\t\t\tdata1 = (const unsigned char *)data1 + clen;\n\t\t\t\tdata2 = (const unsigned char *)data2 + clen;\n\t\t\t\tdata3 = (const unsigned char *)data3 + clen;\n\t\t\t\tdata4 = (const unsigned char *)data4 + clen;\n\t\t\t\tdata5 = (const unsigned char *)data5 + clen;\n\t\t\t\tdata6 = (const unsigned char *)data6 + clen;\n\t\t\t\tdata7 = (const unsigned char *)data7 + clen;\n\t\t\t\tlen -= clen;\n\t\t\t}\n\t\t}\n\n\t\tnum = len >> 6;\n\t\tif (num != 0) {\n\t\t\tmshabal256_compress(sc,\n\t\t\t\t(const unsigned char *)data0,\n\t\t\t\t(const unsigned char *)data1,\n\t\t\t\t(const unsigned char *)data2,\n\t\t\t\t(const unsigned char *)data3,\n\t\t\t\t(const unsigned char *)data4,\n\t\t\t\t(const unsigned char *)data5,\n\t\t\t\t(const unsigned char *)data6,\n\t\t\t\t(const unsigned char *)data7,\n\t\t\t\tnum);\n\t\t\tdata0 = (const unsigned char *)data0 + (num << 6);\n\t\t\tdata1 = (const unsigned char *)data1 + (num << 6);\n\t\t\tdata2 = (const unsigned char *)data2 + (num << 6);\n\t\t\tdata3 = (const unsigned char *)data3 + (num << 6);\n\t\t\tdata4 = (const unsigned char *)data4 + (num << 6);\n\t\t\tdata5 = (const unsigned char *)data5 + (num << 6);\n\t\t\tdata6 = (const unsigned char *)data6 + (num << 6);\n\t\t\tdata7 = (const unsigned char *)data7 + (num << 6);\n\t\t}\n\t\tlen &= (size_t)63;\n\t\tmemcpy(sc->buf0, data0, len);\n\t\tmemcpy(sc->buf1, data1, len);\n\t\tmemcpy(sc->buf2, data2, len);\n\t\tmemcpy(sc->buf3, data3, len);\n\t\tmemcpy(sc->buf4, data4, len);\n\t\tmemcpy(sc->buf5, data5, len);\n\t\tmemcpy(sc->buf6, data6, len);\n\t\tmemcpy(sc->buf7, data7, len);\n\t\tsc->ptr = len;\n\t}\n\n\t/* see shabal_small.h */\n\tvoid\n\t\tavx2_mshabal_close(mshabal256_context *sc,\n\t\t\tunsigned ub0, unsigned ub1, unsigned ub2, unsigned ub3,\n\t\t\tunsigned ub4, unsigned ub5, unsigned ub6, unsigned ub7,\n\t\t\tunsigned n,\n\t\t\tvoid *dst0, void *dst1, void *dst2, void *dst3,\n\t\t\tvoid *dst4, void *dst5, void *dst6, void *dst7)\n\t{\n\t\tsize_t ptr, off;\n\t\tunsigned z, out_size_w32;\n\n\t\tz = 0x80 >> n;\n\t\tptr = sc->ptr;\n\t\tsc->buf0[ptr] = (ub0 & -z) | z;\n\t\tsc->buf1[ptr] = (ub1 & -z) | z;\n\t\tsc->buf2[ptr] = (ub2 & -z) | z;\n\t\tsc->buf3[ptr] = (ub3 & -z) | z;\n\t\tsc->buf4[ptr] = (ub4 & -z) | z;\n\t\tsc->buf5[ptr] = (ub5 & -z) | z;\n\t\tsc->buf6[ptr] = (ub6 & -z) | z;\n\t\tsc->buf7[ptr] = (ub7 & -z) | z;\n\t\tptr++;\n\t\tmemset(sc->buf0 + ptr, 0, (sizeof sc->buf0) - ptr);\n\t\tmemset(sc->buf1 + ptr, 0, (sizeof sc->buf1) - ptr);\n\t\tmemset(sc->buf2 + ptr, 0, (sizeof sc->buf2) - ptr);\n\t\tmemset(sc->buf3 + ptr, 0, (sizeof sc->buf3) - ptr);\n\t\tmemset(sc->buf4 + ptr, 0, (sizeof sc->buf4) - ptr);\n\t\tmemset(sc->buf5 + ptr, 0, (sizeof sc->buf5) - ptr);\n\t\tmemset(sc->buf6 + ptr, 0, (sizeof sc->buf6) - ptr);\n\t\tmemset(sc->buf7 + ptr, 0, (sizeof sc->buf7) - ptr);\n\t\tfor (z = 0; z < 4; z++) {\n\t\t\tmshabal256_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, sc->buf4, sc->buf5, sc->buf6, sc->buf7, 1);\n\t\t\tif (sc->Wlow-- == 0)\n\t\t\t\tsc->Whigh--;\n\t\t}\n\t\tout_size_w32 = sc->out_size >> 5;\n\t\toff = MSHABAL256_FACTOR * 4 * (28 + (16 - out_size_w32));\n\t\tif (dst0 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst0;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + MSHABAL256_FACTOR * (z << 2) + 0];\n\t\t}\n\t\tif (dst1 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst1;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + MSHABAL256_FACTOR * (z << 2) + 1];\n\t\t}\n\t\tif (dst2 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst2;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + MSHABAL256_FACTOR * (z << 2) + 2];\n\t\t}\n\t\tif (dst3 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst3;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + MSHABAL256_FACTOR * (z << 2) + 3];\n\t\t}\n\t\tif (dst4 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst4;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + MSHABAL256_FACTOR * (z << 2) + 4];\n\t\t}\n\t\tif (dst5 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst5;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + MSHABAL256_FACTOR * (z << 2) + 5];\n\t\t}\n\t\tif (dst6 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst6;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + MSHABAL256_FACTOR * (z << 2) + 6];\n\t\t}\n\t\tif (dst7 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst7;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + MSHABAL256_FACTOR * (z << 2) + 7];\n\t\t}\n\t}\n\n#ifdef  __cplusplus\n}\n#endif"
  },
  {
    "path": "src/shabal/mshabal/mshabal_sse4.cpp",
    "content": "/*\n* Parallel implementation of Shabal, using the SSE2 unit. This code\n* compiles and runs on x86 architectures, in 32-bit or 64-bit mode,\n* which possess a SSE2-compatible SIMD unit.\n*\n*\n* (c) 2010 SAPHIR project. This software is provided 'as-is', without\n* any epxress or implied warranty. In no event will the authors be held\n* liable for any damages arising from the use of this software.\n*\n* Permission is granted to anyone to use this software for any purpose,\n* including commercial applications, and to alter it and redistribute it\n* freely, subject to no restriction.\n*\n* Technical remarks and questions can be addressed to:\n* <thomas.pornin@cryptolog.com>\n*/\n\n#include <stddef.h>\n#include <string.h>\n#include <emmintrin.h>\n\n#include \"mshabal.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef _MSC_VER\n#pragma warning (disable: 4146)\n#endif\n\n\ttypedef mshabal_u32 u32;\n\n#define C32(x)         ((u32)x ## UL)\n#define T32(x)         ((x) & C32(0xFFFFFFFF))\n#define ROTL32(x, n)   T32(((x) << (n)) | ((x) >> (32 - (n))))\n\n\tstatic void\n\t\tsse4_mshabal_compress(mshabal_context *sc,\n\t\t\tconst unsigned char *buf0, const unsigned char *buf1,\n\t\t\tconst unsigned char *buf2, const unsigned char *buf3,\n\t\t\tsize_t num)\n\t{\n\t\tunion {\n\t\t\tu32 words[64];\n\t\t\t__m128i data[16];\n\t\t} u;\n\t\tsize_t j;\n\t\t__m128i A[12], B[16], C[16];\n\t\t__m128i one;\n\n\t\tfor (j = 0; j < 12; j++)\n\t\t\tA[j] = _mm_loadu_si128((__m128i *)sc->state + j);\n\t\tfor (j = 0; j < 16; j++) {\n\t\t\tB[j] = _mm_loadu_si128((__m128i *)sc->state + j + 12);\n\t\t\tC[j] = _mm_loadu_si128((__m128i *)sc->state + j + 28);\n\t\t}\n\t\tone = _mm_set1_epi32(C32(0xFFFFFFFF));\n\n#define M(i)   _mm_load_si128(u.data + (i))\n\n\t\twhile (num-- > 0) {\n\n\t\t\tfor (j = 0; j < 64; j += 4) {\n\t\t\t\tu.words[j + 0] = *(u32 *)(buf0 + j);\n\t\t\t\tu.words[j + 1] = *(u32 *)(buf1 + j);\n\t\t\t\tu.words[j + 2] = *(u32 *)(buf2 + j);\n\t\t\t\tu.words[j + 3] = *(u32 *)(buf3 + j);\n\t\t\t}\n\n\t\t\tfor (j = 0; j < 16; j++)\n\t\t\t\tB[j] = _mm_add_epi32(B[j], M(j));\n\n\t\t\tA[0] = _mm_xor_si128(A[0], _mm_set1_epi32(sc->Wlow));\n\t\t\tA[1] = _mm_xor_si128(A[1], _mm_set1_epi32(sc->Whigh));\n\n\t\t\tfor (j = 0; j < 16; j++)\n\t\t\t\tB[j] = _mm_or_si128(_mm_slli_epi32(B[j], 17),\n\t\t\t\t\t_mm_srli_epi32(B[j], 15));\n\n#define PP(xa0, xa1, xb0, xb1, xb2, xb3, xc, xm)   do { \\\n\t\t__m128i tt; \\\n\t\ttt = _mm_or_si128(_mm_slli_epi32(xa1, 15), \\\n\t\t\t_mm_srli_epi32(xa1, 17)); \\\n\t\ttt = _mm_add_epi32(_mm_slli_epi32(tt, 2), tt); \\\n\t\ttt = _mm_xor_si128(_mm_xor_si128(xa0, tt), xc); \\\n\t\ttt = _mm_add_epi32(_mm_slli_epi32(tt, 1), tt); \\\n\t\ttt = _mm_xor_si128( \\\n\t\t\t_mm_xor_si128(tt, xb1), \\\n\t\t\t_mm_xor_si128(_mm_andnot_si128(xb3, xb2), xm)); \\\n\t\txa0 = tt; \\\n\t\ttt = xb0; \\\n\t\ttt = _mm_or_si128(_mm_slli_epi32(tt, 1), \\\n\t\t\t_mm_srli_epi32(tt, 31)); \\\n\t\txb0 = _mm_xor_si128(tt, _mm_xor_si128(xa0, one)); \\\n            \t} while (0)\n\n\t\t\tPP(A[0x0], A[0xB], B[0x0], B[0xD], B[0x9], B[0x6], C[0x8], M(0x0));\n\t\t\tPP(A[0x1], A[0x0], B[0x1], B[0xE], B[0xA], B[0x7], C[0x7], M(0x1));\n\t\t\tPP(A[0x2], A[0x1], B[0x2], B[0xF], B[0xB], B[0x8], C[0x6], M(0x2));\n\t\t\tPP(A[0x3], A[0x2], B[0x3], B[0x0], B[0xC], B[0x9], C[0x5], M(0x3));\n\t\t\tPP(A[0x4], A[0x3], B[0x4], B[0x1], B[0xD], B[0xA], C[0x4], M(0x4));\n\t\t\tPP(A[0x5], A[0x4], B[0x5], B[0x2], B[0xE], B[0xB], C[0x3], M(0x5));\n\t\t\tPP(A[0x6], A[0x5], B[0x6], B[0x3], B[0xF], B[0xC], C[0x2], M(0x6));\n\t\t\tPP(A[0x7], A[0x6], B[0x7], B[0x4], B[0x0], B[0xD], C[0x1], M(0x7));\n\t\t\tPP(A[0x8], A[0x7], B[0x8], B[0x5], B[0x1], B[0xE], C[0x0], M(0x8));\n\t\t\tPP(A[0x9], A[0x8], B[0x9], B[0x6], B[0x2], B[0xF], C[0xF], M(0x9));\n\t\t\tPP(A[0xA], A[0x9], B[0xA], B[0x7], B[0x3], B[0x0], C[0xE], M(0xA));\n\t\t\tPP(A[0xB], A[0xA], B[0xB], B[0x8], B[0x4], B[0x1], C[0xD], M(0xB));\n\t\t\tPP(A[0x0], A[0xB], B[0xC], B[0x9], B[0x5], B[0x2], C[0xC], M(0xC));\n\t\t\tPP(A[0x1], A[0x0], B[0xD], B[0xA], B[0x6], B[0x3], C[0xB], M(0xD));\n\t\t\tPP(A[0x2], A[0x1], B[0xE], B[0xB], B[0x7], B[0x4], C[0xA], M(0xE));\n\t\t\tPP(A[0x3], A[0x2], B[0xF], B[0xC], B[0x8], B[0x5], C[0x9], M(0xF));\n\n\t\t\tPP(A[0x4], A[0x3], B[0x0], B[0xD], B[0x9], B[0x6], C[0x8], M(0x0));\n\t\t\tPP(A[0x5], A[0x4], B[0x1], B[0xE], B[0xA], B[0x7], C[0x7], M(0x1));\n\t\t\tPP(A[0x6], A[0x5], B[0x2], B[0xF], B[0xB], B[0x8], C[0x6], M(0x2));\n\t\t\tPP(A[0x7], A[0x6], B[0x3], B[0x0], B[0xC], B[0x9], C[0x5], M(0x3));\n\t\t\tPP(A[0x8], A[0x7], B[0x4], B[0x1], B[0xD], B[0xA], C[0x4], M(0x4));\n\t\t\tPP(A[0x9], A[0x8], B[0x5], B[0x2], B[0xE], B[0xB], C[0x3], M(0x5));\n\t\t\tPP(A[0xA], A[0x9], B[0x6], B[0x3], B[0xF], B[0xC], C[0x2], M(0x6));\n\t\t\tPP(A[0xB], A[0xA], B[0x7], B[0x4], B[0x0], B[0xD], C[0x1], M(0x7));\n\t\t\tPP(A[0x0], A[0xB], B[0x8], B[0x5], B[0x1], B[0xE], C[0x0], M(0x8));\n\t\t\tPP(A[0x1], A[0x0], B[0x9], B[0x6], B[0x2], B[0xF], C[0xF], M(0x9));\n\t\t\tPP(A[0x2], A[0x1], B[0xA], B[0x7], B[0x3], B[0x0], C[0xE], M(0xA));\n\t\t\tPP(A[0x3], A[0x2], B[0xB], B[0x8], B[0x4], B[0x1], C[0xD], M(0xB));\n\t\t\tPP(A[0x4], A[0x3], B[0xC], B[0x9], B[0x5], B[0x2], C[0xC], M(0xC));\n\t\t\tPP(A[0x5], A[0x4], B[0xD], B[0xA], B[0x6], B[0x3], C[0xB], M(0xD));\n\t\t\tPP(A[0x6], A[0x5], B[0xE], B[0xB], B[0x7], B[0x4], C[0xA], M(0xE));\n\t\t\tPP(A[0x7], A[0x6], B[0xF], B[0xC], B[0x8], B[0x5], C[0x9], M(0xF));\n\n\t\t\tPP(A[0x8], A[0x7], B[0x0], B[0xD], B[0x9], B[0x6], C[0x8], M(0x0));\n\t\t\tPP(A[0x9], A[0x8], B[0x1], B[0xE], B[0xA], B[0x7], C[0x7], M(0x1));\n\t\t\tPP(A[0xA], A[0x9], B[0x2], B[0xF], B[0xB], B[0x8], C[0x6], M(0x2));\n\t\t\tPP(A[0xB], A[0xA], B[0x3], B[0x0], B[0xC], B[0x9], C[0x5], M(0x3));\n\t\t\tPP(A[0x0], A[0xB], B[0x4], B[0x1], B[0xD], B[0xA], C[0x4], M(0x4));\n\t\t\tPP(A[0x1], A[0x0], B[0x5], B[0x2], B[0xE], B[0xB], C[0x3], M(0x5));\n\t\t\tPP(A[0x2], A[0x1], B[0x6], B[0x3], B[0xF], B[0xC], C[0x2], M(0x6));\n\t\t\tPP(A[0x3], A[0x2], B[0x7], B[0x4], B[0x0], B[0xD], C[0x1], M(0x7));\n\t\t\tPP(A[0x4], A[0x3], B[0x8], B[0x5], B[0x1], B[0xE], C[0x0], M(0x8));\n\t\t\tPP(A[0x5], A[0x4], B[0x9], B[0x6], B[0x2], B[0xF], C[0xF], M(0x9));\n\t\t\tPP(A[0x6], A[0x5], B[0xA], B[0x7], B[0x3], B[0x0], C[0xE], M(0xA));\n\t\t\tPP(A[0x7], A[0x6], B[0xB], B[0x8], B[0x4], B[0x1], C[0xD], M(0xB));\n\t\t\tPP(A[0x8], A[0x7], B[0xC], B[0x9], B[0x5], B[0x2], C[0xC], M(0xC));\n\t\t\tPP(A[0x9], A[0x8], B[0xD], B[0xA], B[0x6], B[0x3], C[0xB], M(0xD));\n\t\t\tPP(A[0xA], A[0x9], B[0xE], B[0xB], B[0x7], B[0x4], C[0xA], M(0xE));\n\t\t\tPP(A[0xB], A[0xA], B[0xF], B[0xC], B[0x8], B[0x5], C[0x9], M(0xF));\n\n\t\t\tA[0xB] = _mm_add_epi32(A[0xB], C[0x6]);\n\t\t\tA[0xA] = _mm_add_epi32(A[0xA], C[0x5]);\n\t\t\tA[0x9] = _mm_add_epi32(A[0x9], C[0x4]);\n\t\t\tA[0x8] = _mm_add_epi32(A[0x8], C[0x3]);\n\t\t\tA[0x7] = _mm_add_epi32(A[0x7], C[0x2]);\n\t\t\tA[0x6] = _mm_add_epi32(A[0x6], C[0x1]);\n\t\t\tA[0x5] = _mm_add_epi32(A[0x5], C[0x0]);\n\t\t\tA[0x4] = _mm_add_epi32(A[0x4], C[0xF]);\n\t\t\tA[0x3] = _mm_add_epi32(A[0x3], C[0xE]);\n\t\t\tA[0x2] = _mm_add_epi32(A[0x2], C[0xD]);\n\t\t\tA[0x1] = _mm_add_epi32(A[0x1], C[0xC]);\n\t\t\tA[0x0] = _mm_add_epi32(A[0x0], C[0xB]);\n\t\t\tA[0xB] = _mm_add_epi32(A[0xB], C[0xA]);\n\t\t\tA[0xA] = _mm_add_epi32(A[0xA], C[0x9]);\n\t\t\tA[0x9] = _mm_add_epi32(A[0x9], C[0x8]);\n\t\t\tA[0x8] = _mm_add_epi32(A[0x8], C[0x7]);\n\t\t\tA[0x7] = _mm_add_epi32(A[0x7], C[0x6]);\n\t\t\tA[0x6] = _mm_add_epi32(A[0x6], C[0x5]);\n\t\t\tA[0x5] = _mm_add_epi32(A[0x5], C[0x4]);\n\t\t\tA[0x4] = _mm_add_epi32(A[0x4], C[0x3]);\n\t\t\tA[0x3] = _mm_add_epi32(A[0x3], C[0x2]);\n\t\t\tA[0x2] = _mm_add_epi32(A[0x2], C[0x1]);\n\t\t\tA[0x1] = _mm_add_epi32(A[0x1], C[0x0]);\n\t\t\tA[0x0] = _mm_add_epi32(A[0x0], C[0xF]);\n\t\t\tA[0xB] = _mm_add_epi32(A[0xB], C[0xE]);\n\t\t\tA[0xA] = _mm_add_epi32(A[0xA], C[0xD]);\n\t\t\tA[0x9] = _mm_add_epi32(A[0x9], C[0xC]);\n\t\t\tA[0x8] = _mm_add_epi32(A[0x8], C[0xB]);\n\t\t\tA[0x7] = _mm_add_epi32(A[0x7], C[0xA]);\n\t\t\tA[0x6] = _mm_add_epi32(A[0x6], C[0x9]);\n\t\t\tA[0x5] = _mm_add_epi32(A[0x5], C[0x8]);\n\t\t\tA[0x4] = _mm_add_epi32(A[0x4], C[0x7]);\n\t\t\tA[0x3] = _mm_add_epi32(A[0x3], C[0x6]);\n\t\t\tA[0x2] = _mm_add_epi32(A[0x2], C[0x5]);\n\t\t\tA[0x1] = _mm_add_epi32(A[0x1], C[0x4]);\n\t\t\tA[0x0] = _mm_add_epi32(A[0x0], C[0x3]);\n\n#define SWAP_AND_SUB(xb, xc, xm)   do { \\\n\t\t__m128i tmp; \\\n\t\ttmp = xb; \\\n\t\txb = _mm_sub_epi32(xc, xm); \\\n\t\txc = tmp; \\\n            \t} while (0)\n\n\t\t\tSWAP_AND_SUB(B[0x0], C[0x0], M(0x0));\n\t\t\tSWAP_AND_SUB(B[0x1], C[0x1], M(0x1));\n\t\t\tSWAP_AND_SUB(B[0x2], C[0x2], M(0x2));\n\t\t\tSWAP_AND_SUB(B[0x3], C[0x3], M(0x3));\n\t\t\tSWAP_AND_SUB(B[0x4], C[0x4], M(0x4));\n\t\t\tSWAP_AND_SUB(B[0x5], C[0x5], M(0x5));\n\t\t\tSWAP_AND_SUB(B[0x6], C[0x6], M(0x6));\n\t\t\tSWAP_AND_SUB(B[0x7], C[0x7], M(0x7));\n\t\t\tSWAP_AND_SUB(B[0x8], C[0x8], M(0x8));\n\t\t\tSWAP_AND_SUB(B[0x9], C[0x9], M(0x9));\n\t\t\tSWAP_AND_SUB(B[0xA], C[0xA], M(0xA));\n\t\t\tSWAP_AND_SUB(B[0xB], C[0xB], M(0xB));\n\t\t\tSWAP_AND_SUB(B[0xC], C[0xC], M(0xC));\n\t\t\tSWAP_AND_SUB(B[0xD], C[0xD], M(0xD));\n\t\t\tSWAP_AND_SUB(B[0xE], C[0xE], M(0xE));\n\t\t\tSWAP_AND_SUB(B[0xF], C[0xF], M(0xF));\n\n\t\t\tbuf0 += 64;\n\t\t\tbuf1 += 64;\n\t\t\tbuf2 += 64;\n\t\t\tbuf3 += 64;\n\t\t\tif (++sc->Wlow == 0)\n\t\t\t\tsc->Whigh++;\n\n\t\t}\n\n\t\tfor (j = 0; j < 12; j++)\n\t\t\t_mm_storeu_si128((__m128i *)sc->state + j, A[j]);\n\t\tfor (j = 0; j < 16; j++) {\n\t\t\t_mm_storeu_si128((__m128i *)sc->state + j + 12, B[j]);\n\t\t\t_mm_storeu_si128((__m128i *)sc->state + j + 28, C[j]);\n\t\t}\n\n#undef M\n\t}\n\n\t/* see shabal_small.h */\n\tvoid\n\t\tsse4_mshabal_init(mshabal_context *sc, unsigned out_size)\n\t{\n\t\tunsigned u;\n\n\t\tfor (u = 0; u < 176; u++)\n\t\t\tsc->state[u] = 0;\n\t\tmemset(sc->buf0, 0, sizeof sc->buf0);\n\t\tmemset(sc->buf1, 0, sizeof sc->buf1);\n\t\tmemset(sc->buf2, 0, sizeof sc->buf2);\n\t\tmemset(sc->buf3, 0, sizeof sc->buf3);\n\t\tfor (u = 0; u < 16; u++) {\n\t\t\tsc->buf0[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf0[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf1[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf1[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf2[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf2[4 * u + 1] = (out_size + u) >> 8;\n\t\t\tsc->buf3[4 * u + 0] = (out_size + u);\n\t\t\tsc->buf3[4 * u + 1] = (out_size + u) >> 8;\n\t\t}\n\t\tsc->Whigh = sc->Wlow = C32(0xFFFFFFFF);\n\t\tsse4_mshabal_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, 1);\n\t\tfor (u = 0; u < 16; u++) {\n\t\t\tsc->buf0[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf0[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf1[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf1[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf2[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf2[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t\tsc->buf3[4 * u + 0] = (out_size + u + 16);\n\t\t\tsc->buf3[4 * u + 1] = (out_size + u + 16) >> 8;\n\t\t}\n\t\tsse4_mshabal_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, 1);\n\t\tsc->ptr = 0;\n\t\tsc->out_size = out_size;\n\t}\n\n\t/* see shabal_small.h */\n\tvoid\n\t\tsse4_mshabal(mshabal_context *sc, const void *data0, const void *data1,\n\t\t\tconst void *data2, const void *data3, size_t len)\n\t{\n\t\tsize_t ptr, num;\n\n\t\tif (data0 == NULL) {\n\t\t\tif (data1 == NULL) {\n\t\t\t\tif (data2 == NULL) {\n\t\t\t\t\tif (data3 == NULL) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tdata0 = data3;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdata0 = data2;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdata0 = data1;\n\t\t\t}\n\t\t}\n\t\tif (data1 == NULL)\n\t\t\tdata1 = data0;\n\t\tif (data2 == NULL)\n\t\t\tdata2 = data0;\n\t\tif (data3 == NULL)\n\t\t\tdata3 = data0;\n\n\t\tptr = sc->ptr;\n\t\tif (ptr != 0) {\n\t\t\tsize_t clen;\n\n\t\t\tclen = (sizeof sc->buf0 - ptr);\n\t\t\tif (clen > len) {\n\t\t\t\tmemcpy(sc->buf0 + ptr, data0, len);\n\t\t\t\tmemcpy(sc->buf1 + ptr, data1, len);\n\t\t\t\tmemcpy(sc->buf2 + ptr, data2, len);\n\t\t\t\tmemcpy(sc->buf3 + ptr, data3, len);\n\t\t\t\tsc->ptr = ptr + len;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmemcpy(sc->buf0 + ptr, data0, clen);\n\t\t\t\tmemcpy(sc->buf1 + ptr, data1, clen);\n\t\t\t\tmemcpy(sc->buf2 + ptr, data2, clen);\n\t\t\t\tmemcpy(sc->buf3 + ptr, data3, clen);\n\t\t\t\tsse4_mshabal_compress(sc,\n\t\t\t\t\tsc->buf0, sc->buf1, sc->buf2, sc->buf3, 1);\n\t\t\t\tdata0 = (const unsigned char *)data0 + clen;\n\t\t\t\tdata1 = (const unsigned char *)data1 + clen;\n\t\t\t\tdata2 = (const unsigned char *)data2 + clen;\n\t\t\t\tdata3 = (const unsigned char *)data3 + clen;\n\t\t\t\tlen -= clen;\n\t\t\t}\n\t\t}\n\n\t\tnum = len >> 6;\n\t\tif (num != 0) {\n\t\t\tsse4_mshabal_compress(sc, (const unsigned char*)data0, (const unsigned char*)data1, (const unsigned char*)data2, (const unsigned char*)data3, num);\n\t\t\tdata0 = (const unsigned char *)data0 + (num << 6);\n\t\t\tdata1 = (const unsigned char *)data1 + (num << 6);\n\t\t\tdata2 = (const unsigned char *)data2 + (num << 6);\n\t\t\tdata3 = (const unsigned char *)data3 + (num << 6);\n\t\t}\n\t\tlen &= (size_t)63;\n\t\tmemcpy(sc->buf0, data0, len);\n\t\tmemcpy(sc->buf1, data1, len);\n\t\tmemcpy(sc->buf2, data2, len);\n\t\tmemcpy(sc->buf3, data3, len);\n\t\tsc->ptr = len;\n\t}\n\n\t/* see shabal_small.h */\n\tvoid\n\t\tsse4_mshabal_close(mshabal_context *sc,\n\t\t\tunsigned ub0, unsigned ub1, unsigned ub2, unsigned ub3, unsigned n,\n\t\t\tvoid *dst0, void *dst1, void *dst2, void *dst3)\n\t{\n\t\tsize_t ptr, off;\n\t\tunsigned z, out_size_w32;\n\n\t\tz = 0x80 >> n;\n\t\tptr = sc->ptr;\n\t\tsc->buf0[ptr] = (ub0 & -z) | z;\n\t\tsc->buf1[ptr] = (ub1 & -z) | z;\n\t\tsc->buf2[ptr] = (ub2 & -z) | z;\n\t\tsc->buf3[ptr] = (ub3 & -z) | z;\n\t\tptr++;\n\t\tmemset(sc->buf0 + ptr, 0, (sizeof sc->buf0) - ptr);\n\t\tmemset(sc->buf1 + ptr, 0, (sizeof sc->buf1) - ptr);\n\t\tmemset(sc->buf2 + ptr, 0, (sizeof sc->buf2) - ptr);\n\t\tmemset(sc->buf3 + ptr, 0, (sizeof sc->buf3) - ptr);\n\t\tfor (z = 0; z < 4; z++) {\n\t\t\tsse4_mshabal_compress(sc, sc->buf0, sc->buf1, sc->buf2, sc->buf3, 1);\n\t\t\tif (sc->Wlow-- == 0)\n\t\t\t\tsc->Whigh--;\n\t\t}\n\t\tout_size_w32 = sc->out_size >> 5;\n\t\toff = 4 * (28 + (16 - out_size_w32));\n\t\tif (dst0 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst0;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + (z << 2) + 0];\n\t\t}\n\t\tif (dst1 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst1;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + (z << 2) + 1];\n\t\t}\n\t\tif (dst2 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst2;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + (z << 2) + 2];\n\t\t}\n\t\tif (dst3 != NULL) {\n\t\t\tu32 *out;\n\n\t\t\tout = (u32*)dst3;\n\t\t\tfor (z = 0; z < out_size_w32; z++)\n\t\t\t\tout[z] = sc->state[off + (z << 2) + 3];\n\t\t}\n\t}\n\n#ifdef  __cplusplus\n}\n#endif"
  },
  {
    "path": "src/shabal/opencl/mining.cl",
    "content": "/*\n* The MIT License (MIT)\n*\n* Copyright (c) 2016 by luxe - https://github.com/de-luxe - BURST-LUXE-RED2-G6JW-H4HG5\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy of this software\n* and associated documentation files (the \"Software\"), to deal in the Software without restriction,\n* including without limitation the rights to use, copy, modify, merge, publish, distribute,\n* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software\n* is furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in all copies\n* or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*\n*/\n\n// the source code for this file by luxe can be found here:\n// https://github.com/de-luxe/burstcoin-jminer/blob/master/src/main/java/burstcoin/jminer/core/checker/util/calcdeadlines.cl\n\ntypedef unsigned int sph_u32;\n\n#define SPH_C32(x)    ((sph_u32)(x ## U))\n#define SPH_T32(x) ((uint)(x))\n#define SPH_ROTL32(x, n) rotate(as_uint(x), as_uint(n))\n#define SPH_ROTR32(x, n)   SPH_ROTL32(x, (32 - (n)))\n\n#define SPH_C64(x)    ((sph_u64)(x ## UL))\n#define SPH_T64(x) (as_ulong(x))\n#define SPH_ROTL64(x, n) rotate(as_ulong(x), (n) & 0xFFFFFFFFFFFFFFFFUL)\n#define SPH_ROTR64(x, n)   SPH_ROTL64(x, (64 - (n)))\n\n/* $Id: shabal.c 175 2010-05-07 16:03:20Z tp $ */\n/*\n* Shabal implementation.\n*\n* ==========================(LICENSE BEGIN)============================\n*\n* Copyright (c) 2007-2010  Projet RNRT SAPHIR\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 NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*\n* ===========================(LICENSE END)=============================\n*\n* @author   Thomas Pornin <thomas.pornin@cryptolog.com>\n*/\n\n/*\n* Part of this code was automatically generated (the part between\n* the \"BEGIN\" and \"END\" markers).\n*/\n\n#define sM    16\n\n#define C32   SPH_C32\n#define T32   SPH_T32\n\n#define O1   13\n#define O2    9\n#define O3    6\n\n/*\n* We copy the state into local variables, so that the compiler knows\n* that it can optimize them at will.\n*/\n\n/* BEGIN -- automatically generated code. */\n\n#define INPUT_BLOCK_ADD   do { \\\n\t\tB0 = T32(B0 + M0); \\\n\t\tB1 = T32(B1 + M1); \\\n\t\tB2 = T32(B2 + M2); \\\n\t\tB3 = T32(B3 + M3); \\\n\t\tB4 = T32(B4 + M4); \\\n\t\tB5 = T32(B5 + M5); \\\n\t\tB6 = T32(B6 + M6); \\\n\t\tB7 = T32(B7 + M7); \\\n\t\tB8 = T32(B8 + M8); \\\n\t\tB9 = T32(B9 + M9); \\\n\t\tBA = T32(BA + MA); \\\n\t\tBB = T32(BB + MB); \\\n\t\tBC = T32(BC + MC); \\\n\t\tBD = T32(BD + MD); \\\n\t\tBE = T32(BE + ME); \\\n\t\tBF = T32(BF + MF); \\\n\t} while (0)\n\n#define INPUT_BLOCK_SUB   do { \\\n\t\tC0 = T32(C0 - M0); \\\n\t\tC1 = T32(C1 - M1); \\\n\t\tC2 = T32(C2 - M2); \\\n\t\tC3 = T32(C3 - M3); \\\n\t\tC4 = T32(C4 - M4); \\\n\t\tC5 = T32(C5 - M5); \\\n\t\tC6 = T32(C6 - M6); \\\n\t\tC7 = T32(C7 - M7); \\\n\t\tC8 = T32(C8 - M8); \\\n\t\tC9 = T32(C9 - M9); \\\n\t\tCA = T32(CA - MA); \\\n\t\tCB = T32(CB - MB); \\\n\t\tCC = T32(CC - MC); \\\n\t\tCD = T32(CD - MD); \\\n\t\tCE = T32(CE - ME); \\\n\t\tCF = T32(CF - MF); \\\n\t} while (0)\n\n#define XOR_W   do { \\\n\t\tA00 ^= Wlow; \\\n\t\tA01 ^= Whigh; \\\n\t} while (0)\n\n#define SWAP(v1, v2)   do { \\\n\t\tsph_u32 tmp = (v1); \\\n\t\t(v1) = (v2); \\\n\t\t(v2) = tmp; \\\n\t} while (0)\n\n#define SWAP_BC   do { \\\n\t\tSWAP(B0, C0); \\\n\t\tSWAP(B1, C1); \\\n\t\tSWAP(B2, C2); \\\n\t\tSWAP(B3, C3); \\\n\t\tSWAP(B4, C4); \\\n\t\tSWAP(B5, C5); \\\n\t\tSWAP(B6, C6); \\\n\t\tSWAP(B7, C7); \\\n\t\tSWAP(B8, C8); \\\n\t\tSWAP(B9, C9); \\\n\t\tSWAP(BA, CA); \\\n\t\tSWAP(BB, CB); \\\n\t\tSWAP(BC, CC); \\\n\t\tSWAP(BD, CD); \\\n\t\tSWAP(BE, CE); \\\n\t\tSWAP(BF, CF); \\\n\t} while (0)\n\n#define PERM_ELT(xa0, xa1, xb0, xb1, xb2, xb3, xc, xm)   do { \\\n\t\txa0 = T32((xa0 \\\n\t\t\t^ (((xa1 << 15) | (xa1 >> 17)) * 5U) \\\n\t\t\t^ xc) * 3U) \\\n\t\t\t^ xb1 ^ (xb2 & ~xb3) ^ xm; \\\n\t\txb0 = T32(~(((xb0 << 1) | (xb0 >> 31)) ^ xa0)); \\\n\t} while (0)\n\n#define PERM_STEP_0   do { \\\n\t\tPERM_ELT(A00, A0B, B0, BD, B9, B6, C8, M0); \\\n\t\tPERM_ELT(A01, A00, B1, BE, BA, B7, C7, M1); \\\n\t\tPERM_ELT(A02, A01, B2, BF, BB, B8, C6, M2); \\\n\t\tPERM_ELT(A03, A02, B3, B0, BC, B9, C5, M3); \\\n\t\tPERM_ELT(A04, A03, B4, B1, BD, BA, C4, M4); \\\n\t\tPERM_ELT(A05, A04, B5, B2, BE, BB, C3, M5); \\\n\t\tPERM_ELT(A06, A05, B6, B3, BF, BC, C2, M6); \\\n\t\tPERM_ELT(A07, A06, B7, B4, B0, BD, C1, M7); \\\n\t\tPERM_ELT(A08, A07, B8, B5, B1, BE, C0, M8); \\\n\t\tPERM_ELT(A09, A08, B9, B6, B2, BF, CF, M9); \\\n\t\tPERM_ELT(A0A, A09, BA, B7, B3, B0, CE, MA); \\\n\t\tPERM_ELT(A0B, A0A, BB, B8, B4, B1, CD, MB); \\\n\t\tPERM_ELT(A00, A0B, BC, B9, B5, B2, CC, MC); \\\n\t\tPERM_ELT(A01, A00, BD, BA, B6, B3, CB, MD); \\\n\t\tPERM_ELT(A02, A01, BE, BB, B7, B4, CA, ME); \\\n\t\tPERM_ELT(A03, A02, BF, BC, B8, B5, C9, MF); \\\n\t} while (0)\n\n#define PERM_STEP_1   do { \\\n\t\tPERM_ELT(A04, A03, B0, BD, B9, B6, C8, M0); \\\n\t\tPERM_ELT(A05, A04, B1, BE, BA, B7, C7, M1); \\\n\t\tPERM_ELT(A06, A05, B2, BF, BB, B8, C6, M2); \\\n\t\tPERM_ELT(A07, A06, B3, B0, BC, B9, C5, M3); \\\n\t\tPERM_ELT(A08, A07, B4, B1, BD, BA, C4, M4); \\\n\t\tPERM_ELT(A09, A08, B5, B2, BE, BB, C3, M5); \\\n\t\tPERM_ELT(A0A, A09, B6, B3, BF, BC, C2, M6); \\\n\t\tPERM_ELT(A0B, A0A, B7, B4, B0, BD, C1, M7); \\\n\t\tPERM_ELT(A00, A0B, B8, B5, B1, BE, C0, M8); \\\n\t\tPERM_ELT(A01, A00, B9, B6, B2, BF, CF, M9); \\\n\t\tPERM_ELT(A02, A01, BA, B7, B3, B0, CE, MA); \\\n\t\tPERM_ELT(A03, A02, BB, B8, B4, B1, CD, MB); \\\n\t\tPERM_ELT(A04, A03, BC, B9, B5, B2, CC, MC); \\\n\t\tPERM_ELT(A05, A04, BD, BA, B6, B3, CB, MD); \\\n\t\tPERM_ELT(A06, A05, BE, BB, B7, B4, CA, ME); \\\n\t\tPERM_ELT(A07, A06, BF, BC, B8, B5, C9, MF); \\\n\t} while (0)\n\n#define PERM_STEP_2   do { \\\n\t\tPERM_ELT(A08, A07, B0, BD, B9, B6, C8, M0); \\\n\t\tPERM_ELT(A09, A08, B1, BE, BA, B7, C7, M1); \\\n\t\tPERM_ELT(A0A, A09, B2, BF, BB, B8, C6, M2); \\\n\t\tPERM_ELT(A0B, A0A, B3, B0, BC, B9, C5, M3); \\\n\t\tPERM_ELT(A00, A0B, B4, B1, BD, BA, C4, M4); \\\n\t\tPERM_ELT(A01, A00, B5, B2, BE, BB, C3, M5); \\\n\t\tPERM_ELT(A02, A01, B6, B3, BF, BC, C2, M6); \\\n\t\tPERM_ELT(A03, A02, B7, B4, B0, BD, C1, M7); \\\n\t\tPERM_ELT(A04, A03, B8, B5, B1, BE, C0, M8); \\\n\t\tPERM_ELT(A05, A04, B9, B6, B2, BF, CF, M9); \\\n\t\tPERM_ELT(A06, A05, BA, B7, B3, B0, CE, MA); \\\n\t\tPERM_ELT(A07, A06, BB, B8, B4, B1, CD, MB); \\\n\t\tPERM_ELT(A08, A07, BC, B9, B5, B2, CC, MC); \\\n\t\tPERM_ELT(A09, A08, BD, BA, B6, B3, CB, MD); \\\n\t\tPERM_ELT(A0A, A09, BE, BB, B7, B4, CA, ME); \\\n\t\tPERM_ELT(A0B, A0A, BF, BC, B8, B5, C9, MF); \\\n\t} while (0)\n\n#define APPLY_P   do { \\\n\t\tB0 = T32(B0 << 17) | (B0 >> 15); \\\n\t\tB1 = T32(B1 << 17) | (B1 >> 15); \\\n\t\tB2 = T32(B2 << 17) | (B2 >> 15); \\\n\t\tB3 = T32(B3 << 17) | (B3 >> 15); \\\n\t\tB4 = T32(B4 << 17) | (B4 >> 15); \\\n\t\tB5 = T32(B5 << 17) | (B5 >> 15); \\\n\t\tB6 = T32(B6 << 17) | (B6 >> 15); \\\n\t\tB7 = T32(B7 << 17) | (B7 >> 15); \\\n\t\tB8 = T32(B8 << 17) | (B8 >> 15); \\\n\t\tB9 = T32(B9 << 17) | (B9 >> 15); \\\n\t\tBA = T32(BA << 17) | (BA >> 15); \\\n\t\tBB = T32(BB << 17) | (BB >> 15); \\\n\t\tBC = T32(BC << 17) | (BC >> 15); \\\n\t\tBD = T32(BD << 17) | (BD >> 15); \\\n\t\tBE = T32(BE << 17) | (BE >> 15); \\\n\t\tBF = T32(BF << 17) | (BF >> 15); \\\n\t\tPERM_STEP_0; \\\n\t\tPERM_STEP_1; \\\n\t\tPERM_STEP_2; \\\n\t\tA0B = T32(A0B + C6); \\\n\t\tA0A = T32(A0A + C5); \\\n\t\tA09 = T32(A09 + C4); \\\n\t\tA08 = T32(A08 + C3); \\\n\t\tA07 = T32(A07 + C2); \\\n\t\tA06 = T32(A06 + C1); \\\n\t\tA05 = T32(A05 + C0); \\\n\t\tA04 = T32(A04 + CF); \\\n\t\tA03 = T32(A03 + CE); \\\n\t\tA02 = T32(A02 + CD); \\\n\t\tA01 = T32(A01 + CC); \\\n\t\tA00 = T32(A00 + CB); \\\n\t\tA0B = T32(A0B + CA); \\\n\t\tA0A = T32(A0A + C9); \\\n\t\tA09 = T32(A09 + C8); \\\n\t\tA08 = T32(A08 + C7); \\\n\t\tA07 = T32(A07 + C6); \\\n\t\tA06 = T32(A06 + C5); \\\n\t\tA05 = T32(A05 + C4); \\\n\t\tA04 = T32(A04 + C3); \\\n\t\tA03 = T32(A03 + C2); \\\n\t\tA02 = T32(A02 + C1); \\\n\t\tA01 = T32(A01 + C0); \\\n\t\tA00 = T32(A00 + CF); \\\n\t\tA0B = T32(A0B + CE); \\\n\t\tA0A = T32(A0A + CD); \\\n\t\tA09 = T32(A09 + CC); \\\n\t\tA08 = T32(A08 + CB); \\\n\t\tA07 = T32(A07 + CA); \\\n\t\tA06 = T32(A06 + C9); \\\n\t\tA05 = T32(A05 + C8); \\\n\t\tA04 = T32(A04 + C7); \\\n\t\tA03 = T32(A03 + C6); \\\n\t\tA02 = T32(A02 + C5); \\\n\t\tA01 = T32(A01 + C4); \\\n\t\tA00 = T32(A00 + C3); \\\n\t} while (0)\n\n#define INCR_W   do { \\\n\t\tif ((Wlow = T32(Wlow + 1)) == 0) \\\n\t\t\tWhigh = T32(Whigh + 1); \\\n\t} while (0)\n\n__constant static const sph_u32 A_init_192[] = {\n\tC32(0xFD749ED4), C32(0xB798E530), C32(0x33904B6F), C32(0x46BDA85E),\n\tC32(0x076934B4), C32(0x454B4058), C32(0x77F74527), C32(0xFB4CF465),\n\tC32(0x62931DA9), C32(0xE778C8DB), C32(0x22B3998E), C32(0xAC15CFB9)\n};\n\n__constant static const sph_u32 B_init_192[] = {\n\tC32(0x58BCBAC4), C32(0xEC47A08E), C32(0xAEE933B2), C32(0xDFCBC824),\n\tC32(0xA7944804), C32(0xBF65BDB0), C32(0x5A9D4502), C32(0x59979AF7),\n\tC32(0xC5CEA54E), C32(0x4B6B8150), C32(0x16E71909), C32(0x7D632319),\n\tC32(0x930573A0), C32(0xF34C63D1), C32(0xCAF914B4), C32(0xFDD6612C)\n};\n\n__constant static const sph_u32 C_init_192[] = {\n\tC32(0x61550878), C32(0x89EF2B75), C32(0xA1660C46), C32(0x7EF3855B),\n\tC32(0x7297B58C), C32(0x1BC67793), C32(0x7FB1C723), C32(0xB66FC640),\n\tC32(0x1A48B71C), C32(0xF0976D17), C32(0x088CE80A), C32(0xA454EDF3),\n\tC32(0x1C096BF4), C32(0xAC76224B), C32(0x5215781C), C32(0xCD5D2669)\n};\n\n__constant static const sph_u32 A_init_224[] = {\n\tC32(0xA5201467), C32(0xA9B8D94A), C32(0xD4CED997), C32(0x68379D7B),\n\tC32(0xA7FC73BA), C32(0xF1A2546B), C32(0x606782BF), C32(0xE0BCFD0F),\n\tC32(0x2F25374E), C32(0x069A149F), C32(0x5E2DFF25), C32(0xFAECF061)\n};\n\n__constant static const sph_u32 B_init_224[] = {\n\tC32(0xEC9905D8), C32(0xF21850CF), C32(0xC0A746C8), C32(0x21DAD498),\n\tC32(0x35156EEB), C32(0x088C97F2), C32(0x26303E40), C32(0x8A2D4FB5),\n\tC32(0xFEEE44B6), C32(0x8A1E9573), C32(0x7B81111A), C32(0xCBC139F0),\n\tC32(0xA3513861), C32(0x1D2C362E), C32(0x918C580E), C32(0xB58E1B9C)\n};\n\n__constant static const sph_u32 C_init_224[] = {\n\tC32(0xE4B573A1), C32(0x4C1A0880), C32(0x1E907C51), C32(0x04807EFD),\n\tC32(0x3AD8CDE5), C32(0x16B21302), C32(0x02512C53), C32(0x2204CB18),\n\tC32(0x99405F2D), C32(0xE5B648A1), C32(0x70AB1D43), C32(0xA10C25C2),\n\tC32(0x16F1AC05), C32(0x38BBEB56), C32(0x9B01DC60), C32(0xB1096D83)\n};\n\n__constant static const sph_u32 A_init_256[] = {\n\tC32(0x52F84552), C32(0xE54B7999), C32(0x2D8EE3EC), C32(0xB9645191),\n\tC32(0xE0078B86), C32(0xBB7C44C9), C32(0xD2B5C1CA), C32(0xB0D2EB8C),\n\tC32(0x14CE5A45), C32(0x22AF50DC), C32(0xEFFDBC6B), C32(0xEB21B74A)\n};\n\n__constant static const sph_u32 B_init_256[] = {\n\tC32(0xB555C6EE), C32(0x3E710596), C32(0xA72A652F), C32(0x9301515F),\n\tC32(0xDA28C1FA), C32(0x696FD868), C32(0x9CB6BF72), C32(0x0AFE4002),\n\tC32(0xA6E03615), C32(0x5138C1D4), C32(0xBE216306), C32(0xB38B8890),\n\tC32(0x3EA8B96B), C32(0x3299ACE4), C32(0x30924DD4), C32(0x55CB34A5)\n};\n\n__constant static const sph_u32 C_init_256[] = {\n\tC32(0xB405F031), C32(0xC4233EBA), C32(0xB3733979), C32(0xC0DD9D55),\n\tC32(0xC51C28AE), C32(0xA327B8E1), C32(0x56C56167), C32(0xED614433),\n\tC32(0x88B59D60), C32(0x60E2CEBA), C32(0x758B4B8B), C32(0x83E82A7F),\n\tC32(0xBC968828), C32(0xE6E00BF7), C32(0xBA839E55), C32(0x9B491C60)\n};\n\n__constant static const sph_u32 A_init_384[] = {\n\tC32(0xC8FCA331), C32(0xE55C504E), C32(0x003EBF26), C32(0xBB6B8D83),\n\tC32(0x7B0448C1), C32(0x41B82789), C32(0x0A7C9601), C32(0x8D659CFF),\n\tC32(0xB6E2673E), C32(0xCA54C77B), C32(0x1460FD7E), C32(0x3FCB8F2D)\n};\n\n__constant static const sph_u32 B_init_384[] = {\n\tC32(0x527291FC), C32(0x2A16455F), C32(0x78E627E5), C32(0x944F169F),\n\tC32(0x1CA6F016), C32(0xA854EA25), C32(0x8DB98ABE), C32(0xF2C62641),\n\tC32(0x30117DCB), C32(0xCF5C4309), C32(0x93711A25), C32(0xF9F671B8),\n\tC32(0xB01D2116), C32(0x333F4B89), C32(0xB285D165), C32(0x86829B36)\n};\n\n__constant static const sph_u32 C_init_384[] = {\n\tC32(0xF764B11A), C32(0x76172146), C32(0xCEF6934D), C32(0xC6D28399),\n\tC32(0xFE095F61), C32(0x5E6018B4), C32(0x5048ECF5), C32(0x51353261),\n\tC32(0x6E6E36DC), C32(0x63130DAD), C32(0xA9C69BD6), C32(0x1E90EA0C),\n\tC32(0x7C35073B), C32(0x28D95E6D), C32(0xAA340E0D), C32(0xCB3DEE70)\n};\n\n__constant static const sph_u32 A_init_512[] = {\n\tC32(0x20728DFD), C32(0x46C0BD53), C32(0xE782B699), C32(0x55304632),\n\tC32(0x71B4EF90), C32(0x0EA9E82C), C32(0xDBB930F1), C32(0xFAD06B8B),\n\tC32(0xBE0CAE40), C32(0x8BD14410), C32(0x76D2ADAC), C32(0x28ACAB7F)\n};\n\n__constant static const sph_u32 B_init_512[] = {\n\tC32(0xC1099CB7), C32(0x07B385F3), C32(0xE7442C26), C32(0xCC8AD640),\n\tC32(0xEB6F56C7), C32(0x1EA81AA9), C32(0x73B9D314), C32(0x1DE85D08),\n\tC32(0x48910A5A), C32(0x893B22DB), C32(0xC5A0DF44), C32(0xBBC4324E),\n\tC32(0x72D2F240), C32(0x75941D99), C32(0x6D8BDE82), C32(0xA1A7502B)\n};\n\n__constant static const sph_u32 C_init_512[] = {\n\tC32(0xD9BF68D1), C32(0x58BAD750), C32(0x56028CB2), C32(0x8134F359),\n\tC32(0xB5D469D8), C32(0x941A8CC2), C32(0x418B2A6E), C32(0x04052780),\n\tC32(0x7F07D787), C32(0x5194358F), C32(0x3C60D665), C32(0xBE97D79A),\n\tC32(0x950C3434), C32(0xAED9A06D), C32(0x2537DC8D), C32(0x7CDB5969)\n};\n\n/* END -- automatically generated code. */\n\n#define HASH_SIZE\t\t\t32\n#define HASHES_PER_SCOOP\t2\n#define SCOOP_SIZE\t\t\t(HASHES_PER_SCOOP * HASH_SIZE)\n#define SCOOPS_PER_PLOT\t\t4096\n#define PLOT_SIZE\t\t\t(SCOOPS_PER_PLOT * SCOOP_SIZE)\n#define HASH_CAP\t\t\t4096\n#define GEN_SIZE\t\t\t(PLOT_SIZE + 16)\n\n__kernel void calculate_deadlines(__global unsigned char* gen_sig, __global unsigned char* plot_data, __global unsigned long* deadlines,\n\tunsigned long nonces, unsigned long baseTarget) {\n\tint gid = get_global_id(0);\n\n\tif (gid >= nonces)\n\t\treturn;\n\n\tsph_u32 A00 = A_init_256[0], A01 = A_init_256[1], A02 = A_init_256[2], A03 = A_init_256[3], A04 = A_init_256[4], A05 = A_init_256[5], A06 = A_init_256[6], A07 = A_init_256[7],\n\t\tA08 = A_init_256[8], A09 = A_init_256[9], A0A = A_init_256[10], A0B = A_init_256[11];\n\tsph_u32 B0 = B_init_256[0], B1 = B_init_256[1], B2 = B_init_256[2], B3 = B_init_256[3], B4 = B_init_256[4], B5 = B_init_256[5], B6 = B_init_256[6], B7 = B_init_256[7],\n\t\tB8 = B_init_256[8], B9 = B_init_256[9], BA = B_init_256[10], BB = B_init_256[11], BC = B_init_256[12], BD = B_init_256[13], BE = B_init_256[14], BF = B_init_256[15];\n\tsph_u32 C0 = C_init_256[0], C1 = C_init_256[1], C2 = C_init_256[2], C3 = C_init_256[3], C4 = C_init_256[4], C5 = C_init_256[5], C6 = C_init_256[6], C7 = C_init_256[7],\n\t\tC8 = C_init_256[8], C9 = C_init_256[9], CA = C_init_256[10], CB = C_init_256[11], CC = C_init_256[12], CD = C_init_256[13], CE = C_init_256[14], CF = C_init_256[15];\n\tsph_u32 M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, MA, MB, MC, MD, ME, MF;\n\tsph_u32 Wlow = 1, Whigh = 0;\n\n\tM0 = ((__global unsigned int*)gen_sig)[0];\n\tM1 = ((__global unsigned int*)gen_sig)[1];\n\tM2 = ((__global unsigned int*)gen_sig)[2];\n\tM3 = ((__global unsigned int*)gen_sig)[3];\n\tM4 = ((__global unsigned int*)gen_sig)[4];\n\tM5 = ((__global unsigned int*)gen_sig)[5];\n\tM6 = ((__global unsigned int*)gen_sig)[6];\n\tM7 = ((__global unsigned int*)gen_sig)[7];\n\n\tM8 = ((__global unsigned int*)plot_data)[gid * 16];\n\tM9 = ((__global unsigned int*)plot_data)[gid * 16 + 1];\n\tMA = ((__global unsigned int*)plot_data)[gid * 16 + 2];\n\tMB = ((__global unsigned int*)plot_data)[gid * 16 + 3];\n\tMC = ((__global unsigned int*)plot_data)[gid * 16 + 4];\n\tMD = ((__global unsigned int*)plot_data)[gid * 16 + 5];\n\tME = ((__global unsigned int*)plot_data)[gid * 16 + 6];\n\tMF = ((__global unsigned int*)plot_data)[gid * 16 + 7];\n\n\tINPUT_BLOCK_ADD;\n\tXOR_W;\n\tAPPLY_P;\n\tINPUT_BLOCK_SUB;\n\tSWAP_BC;\n\tINCR_W;\n\n\tM0 = ((__global unsigned int*)plot_data)[gid * 16 + 8];\n\tM1 = ((__global unsigned int*)plot_data)[gid * 16 + 9];\n\tM2 = ((__global unsigned int*)plot_data)[gid * 16 + 10];\n\tM3 = ((__global unsigned int*)plot_data)[gid * 16 + 11];\n\tM4 = ((__global unsigned int*)plot_data)[gid * 16 + 12];\n\tM5 = ((__global unsigned int*)plot_data)[gid * 16 + 13];\n\tM6 = ((__global unsigned int*)plot_data)[gid * 16 + 14];\n\tM7 = ((__global unsigned int*)plot_data)[gid * 16 + 15];\n\n\tM8 = 0x80;\n\tM9 = MA = MB = MC = MD = ME = MF = 0;\n\tINPUT_BLOCK_ADD;\n\tXOR_W;\n\tAPPLY_P;\n\n\tfor (unsigned i = 0; i < 3; i++) {\n\t\tSWAP_BC;\n\t\tXOR_W;\n\t\tAPPLY_P;\n\t}\n\n\tunsigned int out[2];\n\tout[0] = B8;\n\tout[1] = B9;\n\n\tdeadlines[gid] = *((unsigned long*)out) / baseTarget;\n}\n\n// changed type of parameter best from unsigned int to unsigned long, so we can also save the deadline without truncating it\n__kernel void reduce_best(__global unsigned long* deadlines, unsigned int length, __local unsigned int* best_pos, __local unsigned long* best_deadline, __global unsigned long* best) {\n\tint gid = get_global_id(0);\n\tint gsize = get_global_size(0);\n\n\tunsigned int bpos = 0;\n\tunsigned long bdeadline = 0xFFFFFFFFFFFFFFFFL;\n\tfor (int i = gid; i < length; i += gsize) {\n\t\tunsigned long d = deadlines[i];\n\t\tif (d < bdeadline) {\n\t\t\tbpos = i;\n\t\t\tbdeadline = d;\n\t\t}\n\t}\n\n\tint lid = get_local_id(0);\n\tint lsize = get_local_size(0);\n\n\tbest_pos[lid] = bpos;\n\tbest_deadline[lid] = bdeadline;\n\tbarrier(CLK_LOCAL_MEM_FENCE);\n\n\tfor (int offset = lsize / 2; offset > 0; offset >>= 1) {\n\t\tif (lid < offset) {\n\t\t\tif (best_deadline[lid + offset] < best_deadline[lid]) {\n\t\t\t\tbest_pos[lid] = best_pos[lid + offset];\n\t\t\t\tbest_deadline[lid] = best_deadline[lid + offset];\n\t\t\t}\n\t\t}\n\t\tbarrier(CLK_LOCAL_MEM_FENCE);\n\t}\n\n\tif (lid == 0) {\n\t\t// original: best[get_group_id(0)] = best_pos[0];\n\t\t// we save a group of {index=>deadline} instead of only the index\n\t\tbest[get_group_id(0) * 2 + 0] = best_pos[0];\n\t\t// the best deadline\n\t\tbest[get_group_id(0) * 2 + 1] = best_deadline[0];\n\t}\n}\n"
  },
  {
    "path": "src/shabal/sphlib/sph_shabal.cpp",
    "content": "/* $Id: shabal.c 175 2010-05-07 16:03:20Z tp $ */\n/*\n * Shabal implementation.\n *\n * ==========================(LICENSE BEGIN)============================\n *\n * Copyright (c) 2007-2010  Projet RNRT SAPHIR\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 NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n * ===========================(LICENSE END)=============================\n *\n * @author   Thomas Pornin <thomas.pornin@cryptolog.com>\n */\n\n#include <stddef.h>\n#include <string.h>\n\n#include \"sph_shabal.h\"\n\n#ifdef _MSC_VER\n#pragma warning (disable: 4146)\n#endif\n\n/*\n * Part of this code was automatically generated (the part between\n * the \"BEGIN\" and \"END\" markers).\n */\n\n#define sM    16\n\n#define C32   SPH_C32\n#define T32   SPH_T32\n\n#define O1   13\n#define O2    9\n#define O3    6\n\n/*\n * We copy the state into local variables, so that the compiler knows\n * that it can optimize them at will.\n */\n\n/* BEGIN -- automatically generated code. */\n\n#define DECL_STATE   \\\n\tsph_u32 A00, A01, A02, A03, A04, A05, A06, A07, \\\n\t        A08, A09, A0A, A0B; \\\n\tsph_u32 B0, B1, B2, B3, B4, B5, B6, B7, \\\n\t        B8, B9, BA, BB, BC, BD, BE, BF; \\\n\tsph_u32 C0, C1, C2, C3, C4, C5, C6, C7, \\\n\t        C8, C9, CA, CB, CC, CD, CE, CF; \\\n\tsph_u32 M0, M1, M2, M3, M4, M5, M6, M7, \\\n\t        M8, M9, MA, MB, MC, MD, ME, MF; \\\n\tsph_u32 Wlow, Whigh;\n\n#define READ_STATE(state)   do { \\\n\t\tA00 = (state)->A[0]; \\\n\t\tA01 = (state)->A[1]; \\\n\t\tA02 = (state)->A[2]; \\\n\t\tA03 = (state)->A[3]; \\\n\t\tA04 = (state)->A[4]; \\\n\t\tA05 = (state)->A[5]; \\\n\t\tA06 = (state)->A[6]; \\\n\t\tA07 = (state)->A[7]; \\\n\t\tA08 = (state)->A[8]; \\\n\t\tA09 = (state)->A[9]; \\\n\t\tA0A = (state)->A[10]; \\\n\t\tA0B = (state)->A[11]; \\\n\t\tB0 = (state)->B[0]; \\\n\t\tB1 = (state)->B[1]; \\\n\t\tB2 = (state)->B[2]; \\\n\t\tB3 = (state)->B[3]; \\\n\t\tB4 = (state)->B[4]; \\\n\t\tB5 = (state)->B[5]; \\\n\t\tB6 = (state)->B[6]; \\\n\t\tB7 = (state)->B[7]; \\\n\t\tB8 = (state)->B[8]; \\\n\t\tB9 = (state)->B[9]; \\\n\t\tBA = (state)->B[10]; \\\n\t\tBB = (state)->B[11]; \\\n\t\tBC = (state)->B[12]; \\\n\t\tBD = (state)->B[13]; \\\n\t\tBE = (state)->B[14]; \\\n\t\tBF = (state)->B[15]; \\\n\t\tC0 = (state)->C[0]; \\\n\t\tC1 = (state)->C[1]; \\\n\t\tC2 = (state)->C[2]; \\\n\t\tC3 = (state)->C[3]; \\\n\t\tC4 = (state)->C[4]; \\\n\t\tC5 = (state)->C[5]; \\\n\t\tC6 = (state)->C[6]; \\\n\t\tC7 = (state)->C[7]; \\\n\t\tC8 = (state)->C[8]; \\\n\t\tC9 = (state)->C[9]; \\\n\t\tCA = (state)->C[10]; \\\n\t\tCB = (state)->C[11]; \\\n\t\tCC = (state)->C[12]; \\\n\t\tCD = (state)->C[13]; \\\n\t\tCE = (state)->C[14]; \\\n\t\tCF = (state)->C[15]; \\\n\t\tWlow = (state)->Wlow; \\\n\t\tWhigh = (state)->Whigh; \\\n\t} while (0)\n\n#define WRITE_STATE(state)   do { \\\n\t\t(state)->A[0] = A00; \\\n\t\t(state)->A[1] = A01; \\\n\t\t(state)->A[2] = A02; \\\n\t\t(state)->A[3] = A03; \\\n\t\t(state)->A[4] = A04; \\\n\t\t(state)->A[5] = A05; \\\n\t\t(state)->A[6] = A06; \\\n\t\t(state)->A[7] = A07; \\\n\t\t(state)->A[8] = A08; \\\n\t\t(state)->A[9] = A09; \\\n\t\t(state)->A[10] = A0A; \\\n\t\t(state)->A[11] = A0B; \\\n\t\t(state)->B[0] = B0; \\\n\t\t(state)->B[1] = B1; \\\n\t\t(state)->B[2] = B2; \\\n\t\t(state)->B[3] = B3; \\\n\t\t(state)->B[4] = B4; \\\n\t\t(state)->B[5] = B5; \\\n\t\t(state)->B[6] = B6; \\\n\t\t(state)->B[7] = B7; \\\n\t\t(state)->B[8] = B8; \\\n\t\t(state)->B[9] = B9; \\\n\t\t(state)->B[10] = BA; \\\n\t\t(state)->B[11] = BB; \\\n\t\t(state)->B[12] = BC; \\\n\t\t(state)->B[13] = BD; \\\n\t\t(state)->B[14] = BE; \\\n\t\t(state)->B[15] = BF; \\\n\t\t(state)->C[0] = C0; \\\n\t\t(state)->C[1] = C1; \\\n\t\t(state)->C[2] = C2; \\\n\t\t(state)->C[3] = C3; \\\n\t\t(state)->C[4] = C4; \\\n\t\t(state)->C[5] = C5; \\\n\t\t(state)->C[6] = C6; \\\n\t\t(state)->C[7] = C7; \\\n\t\t(state)->C[8] = C8; \\\n\t\t(state)->C[9] = C9; \\\n\t\t(state)->C[10] = CA; \\\n\t\t(state)->C[11] = CB; \\\n\t\t(state)->C[12] = CC; \\\n\t\t(state)->C[13] = CD; \\\n\t\t(state)->C[14] = CE; \\\n\t\t(state)->C[15] = CF; \\\n\t\t(state)->Wlow = Wlow; \\\n\t\t(state)->Whigh = Whigh; \\\n\t} while (0)\n\n#define DECODE_BLOCK   do { \\\n\t\tM0 = sph_dec32le_aligned(buf + 0); \\\n\t\tM1 = sph_dec32le_aligned(buf + 4); \\\n\t\tM2 = sph_dec32le_aligned(buf + 8); \\\n\t\tM3 = sph_dec32le_aligned(buf + 12); \\\n\t\tM4 = sph_dec32le_aligned(buf + 16); \\\n\t\tM5 = sph_dec32le_aligned(buf + 20); \\\n\t\tM6 = sph_dec32le_aligned(buf + 24); \\\n\t\tM7 = sph_dec32le_aligned(buf + 28); \\\n\t\tM8 = sph_dec32le_aligned(buf + 32); \\\n\t\tM9 = sph_dec32le_aligned(buf + 36); \\\n\t\tMA = sph_dec32le_aligned(buf + 40); \\\n\t\tMB = sph_dec32le_aligned(buf + 44); \\\n\t\tMC = sph_dec32le_aligned(buf + 48); \\\n\t\tMD = sph_dec32le_aligned(buf + 52); \\\n\t\tME = sph_dec32le_aligned(buf + 56); \\\n\t\tMF = sph_dec32le_aligned(buf + 60); \\\n\t} while (0)\n\n#define INPUT_BLOCK_ADD   do { \\\n\t\tB0 = T32(B0 + M0); \\\n\t\tB1 = T32(B1 + M1); \\\n\t\tB2 = T32(B2 + M2); \\\n\t\tB3 = T32(B3 + M3); \\\n\t\tB4 = T32(B4 + M4); \\\n\t\tB5 = T32(B5 + M5); \\\n\t\tB6 = T32(B6 + M6); \\\n\t\tB7 = T32(B7 + M7); \\\n\t\tB8 = T32(B8 + M8); \\\n\t\tB9 = T32(B9 + M9); \\\n\t\tBA = T32(BA + MA); \\\n\t\tBB = T32(BB + MB); \\\n\t\tBC = T32(BC + MC); \\\n\t\tBD = T32(BD + MD); \\\n\t\tBE = T32(BE + ME); \\\n\t\tBF = T32(BF + MF); \\\n\t} while (0)\n\n#define INPUT_BLOCK_SUB   do { \\\n\t\tC0 = T32(C0 - M0); \\\n\t\tC1 = T32(C1 - M1); \\\n\t\tC2 = T32(C2 - M2); \\\n\t\tC3 = T32(C3 - M3); \\\n\t\tC4 = T32(C4 - M4); \\\n\t\tC5 = T32(C5 - M5); \\\n\t\tC6 = T32(C6 - M6); \\\n\t\tC7 = T32(C7 - M7); \\\n\t\tC8 = T32(C8 - M8); \\\n\t\tC9 = T32(C9 - M9); \\\n\t\tCA = T32(CA - MA); \\\n\t\tCB = T32(CB - MB); \\\n\t\tCC = T32(CC - MC); \\\n\t\tCD = T32(CD - MD); \\\n\t\tCE = T32(CE - ME); \\\n\t\tCF = T32(CF - MF); \\\n\t} while (0)\n\n#define XOR_W   do { \\\n\t\tA00 ^= Wlow; \\\n\t\tA01 ^= Whigh; \\\n\t} while (0)\n\n#define SWAP(v1, v2)   do { \\\n\t\tsph_u32 tmp = (v1); \\\n\t\t(v1) = (v2); \\\n\t\t(v2) = tmp; \\\n\t} while (0)\n\n#define SWAP_BC   do { \\\n\t\tSWAP(B0, C0); \\\n\t\tSWAP(B1, C1); \\\n\t\tSWAP(B2, C2); \\\n\t\tSWAP(B3, C3); \\\n\t\tSWAP(B4, C4); \\\n\t\tSWAP(B5, C5); \\\n\t\tSWAP(B6, C6); \\\n\t\tSWAP(B7, C7); \\\n\t\tSWAP(B8, C8); \\\n\t\tSWAP(B9, C9); \\\n\t\tSWAP(BA, CA); \\\n\t\tSWAP(BB, CB); \\\n\t\tSWAP(BC, CC); \\\n\t\tSWAP(BD, CD); \\\n\t\tSWAP(BE, CE); \\\n\t\tSWAP(BF, CF); \\\n\t} while (0)\n\n#define PERM_ELT(xa0, xa1, xb0, xb1, xb2, xb3, xc, xm)   do { \\\n\t\txa0 = T32((xa0 \\\n\t\t\t^ (((xa1 << 15) | (xa1 >> 17)) * 5U) \\\n\t\t\t^ xc) * 3U) \\\n\t\t\t^ xb1 ^ (xb2 & ~xb3) ^ xm; \\\n\t\txb0 = T32(~(((xb0 << 1) | (xb0 >> 31)) ^ xa0)); \\\n\t} while (0)\n\n#define PERM_STEP_0   do { \\\n\t\tPERM_ELT(A00, A0B, B0, BD, B9, B6, C8, M0); \\\n\t\tPERM_ELT(A01, A00, B1, BE, BA, B7, C7, M1); \\\n\t\tPERM_ELT(A02, A01, B2, BF, BB, B8, C6, M2); \\\n\t\tPERM_ELT(A03, A02, B3, B0, BC, B9, C5, M3); \\\n\t\tPERM_ELT(A04, A03, B4, B1, BD, BA, C4, M4); \\\n\t\tPERM_ELT(A05, A04, B5, B2, BE, BB, C3, M5); \\\n\t\tPERM_ELT(A06, A05, B6, B3, BF, BC, C2, M6); \\\n\t\tPERM_ELT(A07, A06, B7, B4, B0, BD, C1, M7); \\\n\t\tPERM_ELT(A08, A07, B8, B5, B1, BE, C0, M8); \\\n\t\tPERM_ELT(A09, A08, B9, B6, B2, BF, CF, M9); \\\n\t\tPERM_ELT(A0A, A09, BA, B7, B3, B0, CE, MA); \\\n\t\tPERM_ELT(A0B, A0A, BB, B8, B4, B1, CD, MB); \\\n\t\tPERM_ELT(A00, A0B, BC, B9, B5, B2, CC, MC); \\\n\t\tPERM_ELT(A01, A00, BD, BA, B6, B3, CB, MD); \\\n\t\tPERM_ELT(A02, A01, BE, BB, B7, B4, CA, ME); \\\n\t\tPERM_ELT(A03, A02, BF, BC, B8, B5, C9, MF); \\\n\t} while (0)\n\n#define PERM_STEP_1   do { \\\n\t\tPERM_ELT(A04, A03, B0, BD, B9, B6, C8, M0); \\\n\t\tPERM_ELT(A05, A04, B1, BE, BA, B7, C7, M1); \\\n\t\tPERM_ELT(A06, A05, B2, BF, BB, B8, C6, M2); \\\n\t\tPERM_ELT(A07, A06, B3, B0, BC, B9, C5, M3); \\\n\t\tPERM_ELT(A08, A07, B4, B1, BD, BA, C4, M4); \\\n\t\tPERM_ELT(A09, A08, B5, B2, BE, BB, C3, M5); \\\n\t\tPERM_ELT(A0A, A09, B6, B3, BF, BC, C2, M6); \\\n\t\tPERM_ELT(A0B, A0A, B7, B4, B0, BD, C1, M7); \\\n\t\tPERM_ELT(A00, A0B, B8, B5, B1, BE, C0, M8); \\\n\t\tPERM_ELT(A01, A00, B9, B6, B2, BF, CF, M9); \\\n\t\tPERM_ELT(A02, A01, BA, B7, B3, B0, CE, MA); \\\n\t\tPERM_ELT(A03, A02, BB, B8, B4, B1, CD, MB); \\\n\t\tPERM_ELT(A04, A03, BC, B9, B5, B2, CC, MC); \\\n\t\tPERM_ELT(A05, A04, BD, BA, B6, B3, CB, MD); \\\n\t\tPERM_ELT(A06, A05, BE, BB, B7, B4, CA, ME); \\\n\t\tPERM_ELT(A07, A06, BF, BC, B8, B5, C9, MF); \\\n\t} while (0)\n\n#define PERM_STEP_2   do { \\\n\t\tPERM_ELT(A08, A07, B0, BD, B9, B6, C8, M0); \\\n\t\tPERM_ELT(A09, A08, B1, BE, BA, B7, C7, M1); \\\n\t\tPERM_ELT(A0A, A09, B2, BF, BB, B8, C6, M2); \\\n\t\tPERM_ELT(A0B, A0A, B3, B0, BC, B9, C5, M3); \\\n\t\tPERM_ELT(A00, A0B, B4, B1, BD, BA, C4, M4); \\\n\t\tPERM_ELT(A01, A00, B5, B2, BE, BB, C3, M5); \\\n\t\tPERM_ELT(A02, A01, B6, B3, BF, BC, C2, M6); \\\n\t\tPERM_ELT(A03, A02, B7, B4, B0, BD, C1, M7); \\\n\t\tPERM_ELT(A04, A03, B8, B5, B1, BE, C0, M8); \\\n\t\tPERM_ELT(A05, A04, B9, B6, B2, BF, CF, M9); \\\n\t\tPERM_ELT(A06, A05, BA, B7, B3, B0, CE, MA); \\\n\t\tPERM_ELT(A07, A06, BB, B8, B4, B1, CD, MB); \\\n\t\tPERM_ELT(A08, A07, BC, B9, B5, B2, CC, MC); \\\n\t\tPERM_ELT(A09, A08, BD, BA, B6, B3, CB, MD); \\\n\t\tPERM_ELT(A0A, A09, BE, BB, B7, B4, CA, ME); \\\n\t\tPERM_ELT(A0B, A0A, BF, BC, B8, B5, C9, MF); \\\n\t} while (0)\n\n#define APPLY_P   do { \\\n\t\tB0 = T32(B0 << 17) | (B0 >> 15); \\\n\t\tB1 = T32(B1 << 17) | (B1 >> 15); \\\n\t\tB2 = T32(B2 << 17) | (B2 >> 15); \\\n\t\tB3 = T32(B3 << 17) | (B3 >> 15); \\\n\t\tB4 = T32(B4 << 17) | (B4 >> 15); \\\n\t\tB5 = T32(B5 << 17) | (B5 >> 15); \\\n\t\tB6 = T32(B6 << 17) | (B6 >> 15); \\\n\t\tB7 = T32(B7 << 17) | (B7 >> 15); \\\n\t\tB8 = T32(B8 << 17) | (B8 >> 15); \\\n\t\tB9 = T32(B9 << 17) | (B9 >> 15); \\\n\t\tBA = T32(BA << 17) | (BA >> 15); \\\n\t\tBB = T32(BB << 17) | (BB >> 15); \\\n\t\tBC = T32(BC << 17) | (BC >> 15); \\\n\t\tBD = T32(BD << 17) | (BD >> 15); \\\n\t\tBE = T32(BE << 17) | (BE >> 15); \\\n\t\tBF = T32(BF << 17) | (BF >> 15); \\\n\t\tPERM_STEP_0; \\\n\t\tPERM_STEP_1; \\\n\t\tPERM_STEP_2; \\\n\t\tA0B = T32(A0B + C6); \\\n\t\tA0A = T32(A0A + C5); \\\n\t\tA09 = T32(A09 + C4); \\\n\t\tA08 = T32(A08 + C3); \\\n\t\tA07 = T32(A07 + C2); \\\n\t\tA06 = T32(A06 + C1); \\\n\t\tA05 = T32(A05 + C0); \\\n\t\tA04 = T32(A04 + CF); \\\n\t\tA03 = T32(A03 + CE); \\\n\t\tA02 = T32(A02 + CD); \\\n\t\tA01 = T32(A01 + CC); \\\n\t\tA00 = T32(A00 + CB); \\\n\t\tA0B = T32(A0B + CA); \\\n\t\tA0A = T32(A0A + C9); \\\n\t\tA09 = T32(A09 + C8); \\\n\t\tA08 = T32(A08 + C7); \\\n\t\tA07 = T32(A07 + C6); \\\n\t\tA06 = T32(A06 + C5); \\\n\t\tA05 = T32(A05 + C4); \\\n\t\tA04 = T32(A04 + C3); \\\n\t\tA03 = T32(A03 + C2); \\\n\t\tA02 = T32(A02 + C1); \\\n\t\tA01 = T32(A01 + C0); \\\n\t\tA00 = T32(A00 + CF); \\\n\t\tA0B = T32(A0B + CE); \\\n\t\tA0A = T32(A0A + CD); \\\n\t\tA09 = T32(A09 + CC); \\\n\t\tA08 = T32(A08 + CB); \\\n\t\tA07 = T32(A07 + CA); \\\n\t\tA06 = T32(A06 + C9); \\\n\t\tA05 = T32(A05 + C8); \\\n\t\tA04 = T32(A04 + C7); \\\n\t\tA03 = T32(A03 + C6); \\\n\t\tA02 = T32(A02 + C5); \\\n\t\tA01 = T32(A01 + C4); \\\n\t\tA00 = T32(A00 + C3); \\\n\t} while (0)\n\n#define INCR_W   do { \\\n\t\tif ((Wlow = T32(Wlow + 1)) == 0) \\\n\t\t\tWhigh = T32(Whigh + 1); \\\n\t} while (0)\n\nstatic const sph_u32 A_init_192[] = {\n\tC32(0xFD749ED4), C32(0xB798E530), C32(0x33904B6F), C32(0x46BDA85E),\n\tC32(0x076934B4), C32(0x454B4058), C32(0x77F74527), C32(0xFB4CF465),\n\tC32(0x62931DA9), C32(0xE778C8DB), C32(0x22B3998E), C32(0xAC15CFB9)\n};\n\nstatic const sph_u32 B_init_192[] = {\n\tC32(0x58BCBAC4), C32(0xEC47A08E), C32(0xAEE933B2), C32(0xDFCBC824),\n\tC32(0xA7944804), C32(0xBF65BDB0), C32(0x5A9D4502), C32(0x59979AF7),\n\tC32(0xC5CEA54E), C32(0x4B6B8150), C32(0x16E71909), C32(0x7D632319),\n\tC32(0x930573A0), C32(0xF34C63D1), C32(0xCAF914B4), C32(0xFDD6612C)\n};\n\nstatic const sph_u32 C_init_192[] = {\n\tC32(0x61550878), C32(0x89EF2B75), C32(0xA1660C46), C32(0x7EF3855B),\n\tC32(0x7297B58C), C32(0x1BC67793), C32(0x7FB1C723), C32(0xB66FC640),\n\tC32(0x1A48B71C), C32(0xF0976D17), C32(0x088CE80A), C32(0xA454EDF3),\n\tC32(0x1C096BF4), C32(0xAC76224B), C32(0x5215781C), C32(0xCD5D2669)\n};\n\nstatic const sph_u32 A_init_224[] = {\n\tC32(0xA5201467), C32(0xA9B8D94A), C32(0xD4CED997), C32(0x68379D7B),\n\tC32(0xA7FC73BA), C32(0xF1A2546B), C32(0x606782BF), C32(0xE0BCFD0F),\n\tC32(0x2F25374E), C32(0x069A149F), C32(0x5E2DFF25), C32(0xFAECF061)\n};\n\nstatic const sph_u32 B_init_224[] = {\n\tC32(0xEC9905D8), C32(0xF21850CF), C32(0xC0A746C8), C32(0x21DAD498),\n\tC32(0x35156EEB), C32(0x088C97F2), C32(0x26303E40), C32(0x8A2D4FB5),\n\tC32(0xFEEE44B6), C32(0x8A1E9573), C32(0x7B81111A), C32(0xCBC139F0),\n\tC32(0xA3513861), C32(0x1D2C362E), C32(0x918C580E), C32(0xB58E1B9C)\n};\n\nstatic const sph_u32 C_init_224[] = {\n\tC32(0xE4B573A1), C32(0x4C1A0880), C32(0x1E907C51), C32(0x04807EFD),\n\tC32(0x3AD8CDE5), C32(0x16B21302), C32(0x02512C53), C32(0x2204CB18),\n\tC32(0x99405F2D), C32(0xE5B648A1), C32(0x70AB1D43), C32(0xA10C25C2),\n\tC32(0x16F1AC05), C32(0x38BBEB56), C32(0x9B01DC60), C32(0xB1096D83)\n};\n\nstatic const sph_u32 A_init_256[] = {\n\tC32(0x52F84552), C32(0xE54B7999), C32(0x2D8EE3EC), C32(0xB9645191),\n\tC32(0xE0078B86), C32(0xBB7C44C9), C32(0xD2B5C1CA), C32(0xB0D2EB8C),\n\tC32(0x14CE5A45), C32(0x22AF50DC), C32(0xEFFDBC6B), C32(0xEB21B74A)\n};\n\nstatic const sph_u32 B_init_256[] = {\n\tC32(0xB555C6EE), C32(0x3E710596), C32(0xA72A652F), C32(0x9301515F),\n\tC32(0xDA28C1FA), C32(0x696FD868), C32(0x9CB6BF72), C32(0x0AFE4002),\n\tC32(0xA6E03615), C32(0x5138C1D4), C32(0xBE216306), C32(0xB38B8890),\n\tC32(0x3EA8B96B), C32(0x3299ACE4), C32(0x30924DD4), C32(0x55CB34A5)\n};\n\nstatic const sph_u32 C_init_256[] = {\n\tC32(0xB405F031), C32(0xC4233EBA), C32(0xB3733979), C32(0xC0DD9D55),\n\tC32(0xC51C28AE), C32(0xA327B8E1), C32(0x56C56167), C32(0xED614433),\n\tC32(0x88B59D60), C32(0x60E2CEBA), C32(0x758B4B8B), C32(0x83E82A7F),\n\tC32(0xBC968828), C32(0xE6E00BF7), C32(0xBA839E55), C32(0x9B491C60)\n};\n\nstatic const sph_u32 A_init_384[] = {\n\tC32(0xC8FCA331), C32(0xE55C504E), C32(0x003EBF26), C32(0xBB6B8D83),\n\tC32(0x7B0448C1), C32(0x41B82789), C32(0x0A7C9601), C32(0x8D659CFF),\n\tC32(0xB6E2673E), C32(0xCA54C77B), C32(0x1460FD7E), C32(0x3FCB8F2D)\n};\n\nstatic const sph_u32 B_init_384[] = {\n\tC32(0x527291FC), C32(0x2A16455F), C32(0x78E627E5), C32(0x944F169F),\n\tC32(0x1CA6F016), C32(0xA854EA25), C32(0x8DB98ABE), C32(0xF2C62641),\n\tC32(0x30117DCB), C32(0xCF5C4309), C32(0x93711A25), C32(0xF9F671B8),\n\tC32(0xB01D2116), C32(0x333F4B89), C32(0xB285D165), C32(0x86829B36)\n};\n\nstatic const sph_u32 C_init_384[] = {\n\tC32(0xF764B11A), C32(0x76172146), C32(0xCEF6934D), C32(0xC6D28399),\n\tC32(0xFE095F61), C32(0x5E6018B4), C32(0x5048ECF5), C32(0x51353261),\n\tC32(0x6E6E36DC), C32(0x63130DAD), C32(0xA9C69BD6), C32(0x1E90EA0C),\n\tC32(0x7C35073B), C32(0x28D95E6D), C32(0xAA340E0D), C32(0xCB3DEE70)\n};\n\nstatic const sph_u32 A_init_512[] = {\n\tC32(0x20728DFD), C32(0x46C0BD53), C32(0xE782B699), C32(0x55304632),\n\tC32(0x71B4EF90), C32(0x0EA9E82C), C32(0xDBB930F1), C32(0xFAD06B8B),\n\tC32(0xBE0CAE40), C32(0x8BD14410), C32(0x76D2ADAC), C32(0x28ACAB7F)\n};\n\nstatic const sph_u32 B_init_512[] = {\n\tC32(0xC1099CB7), C32(0x07B385F3), C32(0xE7442C26), C32(0xCC8AD640),\n\tC32(0xEB6F56C7), C32(0x1EA81AA9), C32(0x73B9D314), C32(0x1DE85D08),\n\tC32(0x48910A5A), C32(0x893B22DB), C32(0xC5A0DF44), C32(0xBBC4324E),\n\tC32(0x72D2F240), C32(0x75941D99), C32(0x6D8BDE82), C32(0xA1A7502B)\n};\n\nstatic const sph_u32 C_init_512[] = {\n\tC32(0xD9BF68D1), C32(0x58BAD750), C32(0x56028CB2), C32(0x8134F359),\n\tC32(0xB5D469D8), C32(0x941A8CC2), C32(0x418B2A6E), C32(0x04052780),\n\tC32(0x7F07D787), C32(0x5194358F), C32(0x3C60D665), C32(0xBE97D79A),\n\tC32(0x950C3434), C32(0xAED9A06D), C32(0x2537DC8D), C32(0x7CDB5969)\n};\n\n/* END -- automatically generated code. */\n\nvoid shabal_init(void *cc, unsigned size)\n{\n\t/*\n\t * We have precomputed initial states for all the supported\n\t * output bit lengths.\n\t */\n\tconst sph_u32 *A_init, *B_init, *C_init;\n\tsph_shabal_context *sc;\n\n\tswitch (size) {\n\tcase 192:\n\t\tA_init = A_init_192;\n\t\tB_init = B_init_192;\n\t\tC_init = C_init_192;\n\t\tbreak;\n\tcase 224:\n\t\tA_init = A_init_224;\n\t\tB_init = B_init_224;\n\t\tC_init = C_init_224;\n\t\tbreak;\n\tcase 256:\n\t\tA_init = A_init_256;\n\t\tB_init = B_init_256;\n\t\tC_init = C_init_256;\n\t\tbreak;\n\tcase 384:\n\t\tA_init = A_init_384;\n\t\tB_init = B_init_384;\n\t\tC_init = C_init_384;\n\t\tbreak;\n\tcase 512:\n\t\tA_init = A_init_512;\n\t\tB_init = B_init_512;\n\t\tC_init = C_init_512;\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n\tsc = (sph_shabal_context *)cc;\n\tmemcpy(sc->A, A_init, sizeof sc->A);\n\tmemcpy(sc->B, B_init, sizeof sc->B);\n\tmemcpy(sc->C, C_init, sizeof sc->C);\n\tsc->Wlow = 1;\n\tsc->Whigh = 0;\n\tsc->ptr = 0;\n}\n\nvoid shabal_core(void *cc, const unsigned char *data, size_t len)\n{\n\tsph_shabal_context *sc;\n\tunsigned char *buf;\n\tsize_t ptr;\n\tDECL_STATE\n\n\tsc = (sph_shabal_context *)cc;\n\tbuf = sc->buf;\n\tptr = sc->ptr;\n\n\t/*\n\t * We do not want to copy the state to local variables if the\n\t * amount of data is less than what is needed to complete the\n\t * current block. Note that it is anyway suboptimal to call\n\t * this method many times for small chunks of data.\n\t */\n\tif (len < (sizeof sc->buf) - ptr) {\n\t\tmemcpy(buf + ptr, data, len);\n\t\tptr += len;\n\t\tsc->ptr = ptr;\n\t\treturn;\n\t}\n\n\tREAD_STATE(sc);\n\twhile (len > 0) {\n\t\tsize_t clen;\n\n\t\tclen = (sizeof sc->buf) - ptr;\n\t\tif (clen > len)\n\t\t\tclen = len;\n\t\tmemcpy(buf + ptr, data, clen);\n\t\tptr += clen;\n\t\tdata += clen;\n\t\tlen -= clen;\n\t\tif (ptr == sizeof sc->buf) {\n\t\t\tDECODE_BLOCK;\n\t\t\tINPUT_BLOCK_ADD;\n\t\t\tXOR_W;\n\t\t\tAPPLY_P;\n\t\t\tINPUT_BLOCK_SUB;\n\t\t\tSWAP_BC;\n\t\t\tINCR_W;\n\t\t\tptr = 0;\n\t\t}\n\t}\n\tWRITE_STATE(sc);\n\tsc->ptr = ptr;\n}\n\nstatic void\nshabal_close(void *cc, unsigned ub, unsigned n, void *dst, unsigned size_words)\n{\n\tsph_shabal_context *sc;\n\tunsigned char *buf;\n\tsize_t ptr;\n\tint i;\n\tunsigned z;\n\tunion {\n\t\tunsigned char tmp_out[64];\n\t\tsph_u32 dummy;\n\t} u;\n\tsize_t out_len;\n\tDECL_STATE\n\n\tsc = (sph_shabal_context *)cc;\n\tbuf = sc->buf;\n\tptr = sc->ptr;\n\tz = 0x80 >> n;\n\tbuf[ptr] = ((ub & -z) | z) & 0xFF;\n\tmemset(buf + ptr + 1, 0, (sizeof sc->buf) - (ptr + 1));\n\tREAD_STATE(sc);\n\tDECODE_BLOCK;\n\tINPUT_BLOCK_ADD;\n\tXOR_W;\n\tAPPLY_P;\n\tfor (i = 0; i < 3; i ++) {\n\t\tSWAP_BC;\n\t\tXOR_W;\n\t\tAPPLY_P;\n\t}\n\n\t/*\n\t * We just use our local variables; no need to go through\n\t * the state structure. In order to share some code, we\n\t * emit the relevant words into a temporary buffer, which\n\t * we finally copy into the destination array.\n\t */\n\tswitch (size_words) {\n\tcase 16:\n\t\tsph_enc32le_aligned(u.tmp_out +  0, B0);\n\t\tsph_enc32le_aligned(u.tmp_out +  4, B1);\n\t\tsph_enc32le_aligned(u.tmp_out +  8, B2);\n\t\tsph_enc32le_aligned(u.tmp_out + 12, B3);\n\t\t/* fall through */\n\tcase 12:\n\t\tsph_enc32le_aligned(u.tmp_out + 16, B4);\n\t\tsph_enc32le_aligned(u.tmp_out + 20, B5);\n\t\tsph_enc32le_aligned(u.tmp_out + 24, B6);\n\t\tsph_enc32le_aligned(u.tmp_out + 28, B7);\n\t\t/* fall through */\n\tcase 8:\n\t\tsph_enc32le_aligned(u.tmp_out + 32, B8);\n\t\t/* fall through */\n\tcase 7:\n\t\tsph_enc32le_aligned(u.tmp_out + 36, B9);\n\t\t/* fall through */\n\tcase 6:\n\t\tsph_enc32le_aligned(u.tmp_out + 40, BA);\n\t\tsph_enc32le_aligned(u.tmp_out + 44, BB);\n\t\tsph_enc32le_aligned(u.tmp_out + 48, BC);\n\t\tsph_enc32le_aligned(u.tmp_out + 52, BD);\n\t\tsph_enc32le_aligned(u.tmp_out + 56, BE);\n\t\tsph_enc32le_aligned(u.tmp_out + 60, BF);\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n\tout_len = size_words << 2;\n\tmemcpy(dst, u.tmp_out + (sizeof u.tmp_out) - out_len, out_len);\n\tshabal_init(sc, size_words << 5);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal192_init(void *cc)\n{\n\tshabal_init(cc, 192);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal192(void *cc, const void *data, size_t len)\n{\n\tshabal_core(cc, (const unsigned char *)data, len);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal192_close(void *cc, void *dst)\n{\n\tshabal_close(cc, 0, 0, dst, 6);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal192_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)\n{\n\tshabal_close(cc, ub, n, dst, 6);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal224_init(void *cc)\n{\n\tshabal_init(cc, 224);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal224(void *cc, const void *data, size_t len)\n{\n\tshabal_core(cc, (const unsigned char *)data, len);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal224_close(void *cc, void *dst)\n{\n\tshabal_close(cc, 0, 0, dst, 7);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal224_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)\n{\n\tshabal_close(cc, ub, n, dst, 7);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal256_init(void *cc)\n{\n\tshabal_init(cc, 256);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal256(void *cc, const void *data, size_t len)\n{\n\tshabal_core(cc, (const unsigned char *)data, len);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal256_close(void *cc, void *dst)\n{\n\tshabal_close(cc, 0, 0, dst, 8);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)\n{\n\tshabal_close(cc, ub, n, dst, 8);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal384_init(void *cc)\n{\n\tshabal_init(cc, 384);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal384(void *cc, const void *data, size_t len)\n{\n\tshabal_core(cc, (const unsigned char *)data, len);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal384_close(void *cc, void *dst)\n{\n\tshabal_close(cc, 0, 0, dst, 12);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal384_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)\n{\n\tshabal_close(cc, ub, n, dst, 12);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal512_init(void *cc)\n{\n\tshabal_init(cc, 512);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal512(void *cc, const void *data, size_t len)\n{\n\tshabal_core(cc, (const unsigned char *)data, len);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal512_close(void *cc, void *dst)\n{\n\tshabal_close(cc, 0, 0, dst, 16);\n}\n\n/* see sph_shabal.h */\nvoid\nsph_shabal512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)\n{\n\tshabal_close(cc, ub, n, dst, 16);\n}\n"
  },
  {
    "path": "src/shabal/sphlib/sph_shabal.h",
    "content": "/* $Id: sph_shabal.h 175 2010-05-07 16:03:20Z tp $ */\n/**\n * Shabal interface. Shabal is a family of functions which differ by\n * their output size; this implementation defines Shabal for output\n * sizes 192, 224, 256, 384 and 512 bits.\n *\n * ==========================(LICENSE BEGIN)============================\n *\n * Copyright (c) 2007-2010  Projet RNRT SAPHIR\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 NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n * ===========================(LICENSE END)=============================\n *\n * @file     sph_shabal.h\n * @author   Thomas Pornin <thomas.pornin@cryptolog.com>\n */\n\n#ifndef SPH_SHABAL_H__\n#define SPH_SHABAL_H__\n\n#include <stddef.h>\n#include \"sph_types.h\"\n\n/**\n * Output size (in bits) for Shabal-192.\n */\n#define SPH_SIZE_shabal192   192\n\n/**\n * Output size (in bits) for Shabal-224.\n */\n#define SPH_SIZE_shabal224   224\n\n/**\n * Output size (in bits) for Shabal-256.\n */\n#define SPH_SIZE_shabal256   256\n\n/**\n * Output size (in bits) for Shabal-384.\n */\n#define SPH_SIZE_shabal384   384\n\n/**\n * Output size (in bits) for Shabal-512.\n */\n#define SPH_SIZE_shabal512   512\n\n/**\n * This structure is a context for Shabal computations: it contains the\n * intermediate values and some data from the last entered block. Once\n * a Shabal computation has been performed, the context can be reused for\n * another computation.\n *\n * The contents of this structure are private. A running Shabal computation\n * can be cloned by copying the context (e.g. with a simple\n * <code>memcpy()</code>).\n */\ntypedef struct {\n#ifndef DOXYGEN_IGNORE\n\tunsigned char buf[64];    /* first field, for alignment */\n\tsize_t ptr;\n\tsph_u32 A[12], B[16], C[16];\n\tsph_u32 Whigh, Wlow;\n#endif\n} sph_shabal_context;\n\n/**\n * Type for a Shabal-192 context (identical to the common context).\n */\ntypedef sph_shabal_context sph_shabal192_context;\n\n/**\n * Type for a Shabal-224 context (identical to the common context).\n */\ntypedef sph_shabal_context sph_shabal224_context;\n\n/**\n * Type for a Shabal-256 context (identical to the common context).\n */\ntypedef sph_shabal_context sph_shabal256_context;\n\n/**\n * Type for a Shabal-384 context (identical to the common context).\n */\ntypedef sph_shabal_context sph_shabal384_context;\n\n/**\n * Type for a Shabal-512 context (identical to the common context).\n */\ntypedef sph_shabal_context sph_shabal512_context;\n\n/**\n * Initialize a Shabal-192 context. This process performs no memory allocation.\n *\n * @param cc   the Shabal-192 context (pointer to a\n *             <code>sph_shabal192_context</code>)\n */\nvoid sph_shabal192_init(void *cc);\n\n/**\n * Process some data bytes. It is acceptable that <code>len</code> is zero\n * (in which case this function does nothing).\n *\n * @param cc     the Shabal-192 context\n * @param data   the input data\n * @param len    the input data length (in bytes)\n */\nvoid sph_shabal192(void *cc, const void *data, size_t len);\n\n/**\n * Terminate the current Shabal-192 computation and output the result into\n * the provided buffer. The destination buffer must be wide enough to\n * accomodate the result (24 bytes). The context is automatically\n * reinitialized.\n *\n * @param cc    the Shabal-192 context\n * @param dst   the destination buffer\n */\nvoid sph_shabal192_close(void *cc, void *dst);\n\n/**\n * Add a few additional bits (0 to 7) to the current computation, then\n * terminate it and output the result in the provided buffer, which must\n * be wide enough to accomodate the result (24 bytes). If bit number i\n * in <code>ub</code> has value 2^i, then the extra bits are those\n * numbered 7 downto 8-n (this is the big-endian convention at the byte\n * level). The context is automatically reinitialized.\n *\n * @param cc    the Shabal-192 context\n * @param ub    the extra bits\n * @param n     the number of extra bits (0 to 7)\n * @param dst   the destination buffer\n */\nvoid sph_shabal192_addbits_and_close(\n\tvoid *cc, unsigned ub, unsigned n, void *dst);\n\n/**\n * Initialize a Shabal-224 context. This process performs no memory allocation.\n *\n * @param cc   the Shabal-224 context (pointer to a\n *             <code>sph_shabal224_context</code>)\n */\nvoid sph_shabal224_init(void *cc);\n\n/**\n * Process some data bytes. It is acceptable that <code>len</code> is zero\n * (in which case this function does nothing).\n *\n * @param cc     the Shabal-224 context\n * @param data   the input data\n * @param len    the input data length (in bytes)\n */\nvoid sph_shabal224(void *cc, const void *data, size_t len);\n\n/**\n * Terminate the current Shabal-224 computation and output the result into\n * the provided buffer. The destination buffer must be wide enough to\n * accomodate the result (28 bytes). The context is automatically\n * reinitialized.\n *\n * @param cc    the Shabal-224 context\n * @param dst   the destination buffer\n */\nvoid sph_shabal224_close(void *cc, void *dst);\n\n/**\n * Add a few additional bits (0 to 7) to the current computation, then\n * terminate it and output the result in the provided buffer, which must\n * be wide enough to accomodate the result (28 bytes). If bit number i\n * in <code>ub</code> has value 2^i, then the extra bits are those\n * numbered 7 downto 8-n (this is the big-endian convention at the byte\n * level). The context is automatically reinitialized.\n *\n * @param cc    the Shabal-224 context\n * @param ub    the extra bits\n * @param n     the number of extra bits (0 to 7)\n * @param dst   the destination buffer\n */\nvoid sph_shabal224_addbits_and_close(\n\tvoid *cc, unsigned ub, unsigned n, void *dst);\n\n/**\n * Initialize a Shabal-256 context. This process performs no memory allocation.\n *\n * @param cc   the Shabal-256 context (pointer to a\n *             <code>sph_shabal256_context</code>)\n */\nvoid sph_shabal256_init(void *cc);\n\n/**\n * Process some data bytes. It is acceptable that <code>len</code> is zero\n * (in which case this function does nothing).\n *\n * @param cc     the Shabal-256 context\n * @param data   the input data\n * @param len    the input data length (in bytes)\n */\nvoid sph_shabal256(void *cc, const void *data, size_t len);\n\n/**\n * Terminate the current Shabal-256 computation and output the result into\n * the provided buffer. The destination buffer must be wide enough to\n * accomodate the result (32 bytes). The context is automatically\n * reinitialized.\n *\n * @param cc    the Shabal-256 context\n * @param dst   the destination buffer\n */\nvoid sph_shabal256_close(void *cc, void *dst);\n\n/**\n * Add a few additional bits (0 to 7) to the current computation, then\n * terminate it and output the result in the provided buffer, which must\n * be wide enough to accomodate the result (32 bytes). If bit number i\n * in <code>ub</code> has value 2^i, then the extra bits are those\n * numbered 7 downto 8-n (this is the big-endian convention at the byte\n * level). The context is automatically reinitialized.\n *\n * @param cc    the Shabal-256 context\n * @param ub    the extra bits\n * @param n     the number of extra bits (0 to 7)\n * @param dst   the destination buffer\n */\nvoid sph_shabal256_addbits_and_close(\n\tvoid *cc, unsigned ub, unsigned n, void *dst);\n\n/**\n * Initialize a Shabal-384 context. This process performs no memory allocation.\n *\n * @param cc   the Shabal-384 context (pointer to a\n *             <code>sph_shabal384_context</code>)\n */\nvoid sph_shabal384_init(void *cc);\n\n/**\n * Process some data bytes. It is acceptable that <code>len</code> is zero\n * (in which case this function does nothing).\n *\n * @param cc     the Shabal-384 context\n * @param data   the input data\n * @param len    the input data length (in bytes)\n */\nvoid sph_shabal384(void *cc, const void *data, size_t len);\n\n/**\n * Terminate the current Shabal-384 computation and output the result into\n * the provided buffer. The destination buffer must be wide enough to\n * accomodate the result (48 bytes). The context is automatically\n * reinitialized.\n *\n * @param cc    the Shabal-384 context\n * @param dst   the destination buffer\n */\nvoid sph_shabal384_close(void *cc, void *dst);\n\n/**\n * Add a few additional bits (0 to 7) to the current computation, then\n * terminate it and output the result in the provided buffer, which must\n * be wide enough to accomodate the result (48 bytes). If bit number i\n * in <code>ub</code> has value 2^i, then the extra bits are those\n * numbered 7 downto 8-n (this is the big-endian convention at the byte\n * level). The context is automatically reinitialized.\n *\n * @param cc    the Shabal-384 context\n * @param ub    the extra bits\n * @param n     the number of extra bits (0 to 7)\n * @param dst   the destination buffer\n */\nvoid sph_shabal384_addbits_and_close(\n\tvoid *cc, unsigned ub, unsigned n, void *dst);\n\n/**\n * Initialize a Shabal-512 context. This process performs no memory allocation.\n *\n * @param cc   the Shabal-512 context (pointer to a\n *             <code>sph_shabal512_context</code>)\n */\nvoid sph_shabal512_init(void *cc);\n\n/**\n * Process some data bytes. It is acceptable that <code>len</code> is zero\n * (in which case this function does nothing).\n *\n * @param cc     the Shabal-512 context\n * @param data   the input data\n * @param len    the input data length (in bytes)\n */\nvoid sph_shabal512(void *cc, const void *data, size_t len);\n\n/**\n * Terminate the current Shabal-512 computation and output the result into\n * the provided buffer. The destination buffer must be wide enough to\n * accomodate the result (64 bytes). The context is automatically\n * reinitialized.\n *\n * @param cc    the Shabal-512 context\n * @param dst   the destination buffer\n */\nvoid sph_shabal512_close(void *cc, void *dst);\n\n/**\n * Add a few additional bits (0 to 7) to the current computation, then\n * terminate it and output the result in the provided buffer, which must\n * be wide enough to accomodate the result (64 bytes). If bit number i\n * in <code>ub</code> has value 2^i, then the extra bits are those\n * numbered 7 downto 8-n (this is the big-endian convention at the byte\n * level). The context is automatically reinitialized.\n *\n * @param cc    the Shabal-512 context\n * @param ub    the extra bits\n * @param n     the number of extra bits (0 to 7)\n * @param dst   the destination buffer\n */\nvoid sph_shabal512_addbits_and_close(\n\tvoid *cc, unsigned ub, unsigned n, void *dst);\n\n#endif\n"
  },
  {
    "path": "src/shabal/sphlib/sph_types.h",
    "content": "/* $Id: sph_types.h 260 2011-07-21 01:02:38Z tp $ */\n/**\n * Basic type definitions.\n *\n * This header file defines the generic integer types that will be used\n * for the implementation of hash functions; it also contains helper\n * functions which encode and decode multi-byte integer values, using\n * either little-endian or big-endian conventions.\n *\n * This file contains a compile-time test on the size of a byte\n * (the <code>unsigned char</code> C type). If bytes are not octets,\n * i.e. if they do not have a size of exactly 8 bits, then compilation\n * is aborted. Architectures where bytes are not octets are relatively\n * rare, even in the embedded devices market. We forbid non-octet bytes\n * because there is no clear convention on how octet streams are encoded\n * on such systems.\n *\n * ==========================(LICENSE BEGIN)============================\n *\n * Copyright (c) 2007-2010  Projet RNRT SAPHIR\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 NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n * ===========================(LICENSE END)=============================\n *\n * @file     sph_types.h\n * @author   Thomas Pornin <thomas.pornin@cryptolog.com>\n */\n\n#ifndef SPH_TYPES_H__\n#define SPH_TYPES_H__\n\n#include <limits.h>\n\n/*\n * All our I/O functions are defined over octet streams. We do not know\n * how to handle input data if bytes are not octets.\n */\n#if CHAR_BIT != 8\n#error This code requires 8-bit bytes\n#endif\n\n/* ============= BEGIN documentation block for Doxygen ============ */\n\n#ifdef DOXYGEN_IGNORE\n\n/** @mainpage sphlib C code documentation\n *\n * @section overview Overview\n *\n * <code>sphlib</code> is a library which contains implementations of\n * various cryptographic hash functions. These pages have been generated\n * with <a href=\"http://www.doxygen.org/index.html\">doxygen</a> and\n * document the API for the C implementations.\n *\n * The API is described in appropriate header files, which are available\n * in the \"Files\" section. Each hash function family has its own header,\n * whose name begins with <code>\"sph_\"</code> and contains the family\n * name. For instance, the API for the RIPEMD hash functions is available\n * in the header file <code>sph_ripemd.h</code>.\n *\n * @section principles API structure and conventions\n *\n * @subsection io Input/output conventions\n *\n * In all generality, hash functions operate over strings of bits.\n * Individual bits are rarely encountered in C programming or actual\n * communication protocols; most protocols converge on the ubiquitous\n * \"octet\" which is a group of eight bits. Data is thus expressed as a\n * stream of octets. The C programming language contains the notion of a\n * \"byte\", which is a data unit managed under the type <code>\"unsigned\n * char\"</code>. The C standard prescribes that a byte should hold at\n * least eight bits, but possibly more. Most modern architectures, even\n * in the embedded world, feature eight-bit bytes, i.e. map bytes to\n * octets.\n *\n * Nevertheless, for some of the implemented hash functions, an extra\n * API has been added, which allows the input of arbitrary sequences of\n * bits: when the computation is about to be closed, 1 to 7 extra bits\n * can be added. The functions for which this API is implemented include\n * the SHA-2 functions and all SHA-3 candidates.\n *\n * <code>sphlib</code> defines hash function which may hash octet streams,\n * i.e. streams of bits where the number of bits is a multiple of eight.\n * The data input functions in the <code>sphlib</code> API expect data\n * as anonymous pointers (<code>\"const void *\"</code>) with a length\n * (of type <code>\"size_t\"</code>) which gives the input data chunk length\n * in bytes. A byte is assumed to be an octet; the <code>sph_types.h</code>\n * header contains a compile-time test which prevents compilation on\n * architectures where this property is not met.\n *\n * The hash function output is also converted into bytes. All currently\n * implemented hash functions have an output width which is a multiple of\n * eight, and this is likely to remain true for new designs.\n *\n * Most hash functions internally convert input data into 32-bit of 64-bit\n * words, using either little-endian or big-endian conversion. The hash\n * output also often consists of such words, which are encoded into output\n * bytes with a similar endianness convention. Some hash functions have\n * been only loosely specified on that subject; when necessary,\n * <code>sphlib</code> has been tested against published \"reference\"\n * implementations in order to use the same conventions.\n *\n * @subsection shortname Function short name\n *\n * Each implemented hash function has a \"short name\" which is used\n * internally to derive the identifiers for the functions and context\n * structures which the function uses. For instance, MD5 has the short\n * name <code>\"md5\"</code>. Short names are listed in the next section,\n * for the implemented hash functions. In subsequent sections, the\n * short name will be assumed to be <code>\"XXX\"</code>: replace with the\n * actual hash function name to get the C identifier.\n *\n * Note: some functions within the same family share the same core\n * elements, such as update function or context structure. Correspondingly,\n * some of the defined types or functions may actually be macros which\n * transparently evaluate to another type or function name.\n *\n * @subsection context Context structure\n *\n * Each implemented hash fonction has its own context structure, available\n * under the type name <code>\"sph_XXX_context\"</code> for the hash function\n * with short name <code>\"XXX\"</code>. This structure holds all needed\n * state for a running hash computation.\n *\n * The contents of these structures are meant to be opaque, and private\n * to the implementation. However, these contents are specified in the\n * header files so that application code which uses <code>sphlib</code>\n * may access the size of those structures.\n *\n * The caller is responsible for allocating the context structure,\n * whether by dynamic allocation (<code>malloc()</code> or equivalent),\n * static allocation (a global permanent variable), as an automatic\n * variable (\"on the stack\"), or by any other mean which ensures proper\n * structure alignment. <code>sphlib</code> code performs no dynamic\n * allocation by itself.\n *\n * The context must be initialized before use, using the\n * <code>sph_XXX_init()</code> function. This function sets the context\n * state to proper initial values for hashing.\n *\n * Since all state data is contained within the context structure,\n * <code>sphlib</code> is thread-safe and reentrant: several hash\n * computations may be performed in parallel, provided that they do not\n * operate on the same context. Moreover, a running computation can be\n * cloned by copying the context (with a simple <code>memcpy()</code>):\n * the context and its clone are then independant and may be updated\n * with new data and/or closed without interfering with each other.\n * Similarly, a context structure can be moved in memory at will:\n * context structures contain no pointer, in particular no pointer to\n * themselves.\n *\n * @subsection dataio Data input\n *\n * Hashed data is input with the <code>sph_XXX()</code> fonction, which\n * takes as parameters a pointer to the context, a pointer to the data\n * to hash, and the number of data bytes to hash. The context is updated\n * with the new data.\n *\n * Data can be input in one or several calls, with arbitrary input lengths.\n * However, it is best, performance wise, to input data by relatively big\n * chunks (say a few kilobytes), because this allows <code>sphlib</code> to\n * optimize things and avoid internal copying.\n *\n * When all data has been input, the context can be closed with\n * <code>sph_XXX_close()</code>. The hash output is computed and written\n * into the provided buffer. The caller must take care to provide a\n * buffer of appropriate length; e.g., when using SHA-1, the output is\n * a 20-byte word, therefore the output buffer must be at least 20-byte\n * long.\n *\n * For some hash functions, the <code>sph_XXX_addbits_and_close()</code>\n * function can be used instead of <code>sph_XXX_close()</code>. This\n * function can take a few extra <strong>bits</strong> to be added at\n * the end of the input message. This allows hashing messages with a\n * bit length which is not a multiple of 8. The extra bits are provided\n * as an unsigned integer value, and a bit count. The bit count must be\n * between 0 and 7, inclusive. The extra bits are provided as bits 7 to\n * 0 (bits of numerical value 128, 64, 32... downto 0), in that order.\n * For instance, to add three bits of value 1, 1 and 0, the unsigned\n * integer will have value 192 (1*128 + 1*64 + 0*32) and the bit count\n * will be 3.\n *\n * The <code>SPH_SIZE_XXX</code> macro is defined for each hash function;\n * it evaluates to the function output size, expressed in bits. For instance,\n * <code>SPH_SIZE_sha1</code> evaluates to <code>160</code>.\n *\n * When closed, the context is automatically reinitialized and can be\n * immediately used for another computation. It is not necessary to call\n * <code>sph_XXX_init()</code> after a close. Note that\n * <code>sph_XXX_init()</code> can still be called to \"reset\" a context,\n * i.e. forget previously input data, and get back to the initial state.\n *\n * @subsection alignment Data alignment\n *\n * \"Alignment\" is a property of data, which is said to be \"properly\n * aligned\" when its emplacement in memory is such that the data can\n * be optimally read by full words. This depends on the type of access;\n * basically, some hash functions will read data by 32-bit or 64-bit\n * words. <code>sphlib</code> does not mandate such alignment for input\n * data, but using aligned data can substantially improve performance.\n *\n * As a rule, it is best to input data by chunks whose length (in bytes)\n * is a multiple of eight, and which begins at \"generally aligned\"\n * addresses, such as the base address returned by a call to\n * <code>malloc()</code>.\n *\n * @section functions Implemented functions\n *\n * We give here the list of implemented functions. They are grouped by\n * family; to each family corresponds a specific header file. Each\n * individual function has its associated \"short name\". Please refer to\n * the documentation for that header file to get details on the hash\n * function denomination and provenance.\n *\n * Note: the functions marked with a '(64)' in the list below are\n * available only if the C compiler provides an integer type of length\n * 64 bits or more. Such a type is mandatory in the latest C standard\n * (ISO 9899:1999, aka \"C99\") and is present in several older compilers\n * as well, so chances are that such a type is available.\n *\n * - HAVAL family: file <code>sph_haval.h</code>\n *   - HAVAL-128/3 (128-bit, 3 passes): short name: <code>haval128_3</code>\n *   - HAVAL-128/4 (128-bit, 4 passes): short name: <code>haval128_4</code>\n *   - HAVAL-128/5 (128-bit, 5 passes): short name: <code>haval128_5</code>\n *   - HAVAL-160/3 (160-bit, 3 passes): short name: <code>haval160_3</code>\n *   - HAVAL-160/4 (160-bit, 4 passes): short name: <code>haval160_4</code>\n *   - HAVAL-160/5 (160-bit, 5 passes): short name: <code>haval160_5</code>\n *   - HAVAL-192/3 (192-bit, 3 passes): short name: <code>haval192_3</code>\n *   - HAVAL-192/4 (192-bit, 4 passes): short name: <code>haval192_4</code>\n *   - HAVAL-192/5 (192-bit, 5 passes): short name: <code>haval192_5</code>\n *   - HAVAL-224/3 (224-bit, 3 passes): short name: <code>haval224_3</code>\n *   - HAVAL-224/4 (224-bit, 4 passes): short name: <code>haval224_4</code>\n *   - HAVAL-224/5 (224-bit, 5 passes): short name: <code>haval224_5</code>\n *   - HAVAL-256/3 (256-bit, 3 passes): short name: <code>haval256_3</code>\n *   - HAVAL-256/4 (256-bit, 4 passes): short name: <code>haval256_4</code>\n *   - HAVAL-256/5 (256-bit, 5 passes): short name: <code>haval256_5</code>\n * - MD2: file <code>sph_md2.h</code>, short name: <code>md2</code>\n * - MD4: file <code>sph_md4.h</code>, short name: <code>md4</code>\n * - MD5: file <code>sph_md5.h</code>, short name: <code>md5</code>\n * - PANAMA: file <code>sph_panama.h</code>, short name: <code>panama</code>\n * - RadioGatun family: file <code>sph_radiogatun.h</code>\n *   - RadioGatun[32]: short name: <code>radiogatun32</code>\n *   - RadioGatun[64]: short name: <code>radiogatun64</code> (64)\n * - RIPEMD family: file <code>sph_ripemd.h</code>\n *   - RIPEMD: short name: <code>ripemd</code>\n *   - RIPEMD-128: short name: <code>ripemd128</code>\n *   - RIPEMD-160: short name: <code>ripemd160</code>\n * - SHA-0: file <code>sph_sha0.h</code>, short name: <code>sha0</code>\n * - SHA-1: file <code>sph_sha1.h</code>, short name: <code>sha1</code>\n * - SHA-2 family, 32-bit hashes: file <code>sph_sha2.h</code>\n *   - SHA-224: short name: <code>sha224</code>\n *   - SHA-256: short name: <code>sha256</code>\n *   - SHA-384: short name: <code>sha384</code> (64)\n *   - SHA-512: short name: <code>sha512</code> (64)\n * - Tiger family: file <code>sph_tiger.h</code>\n *   - Tiger: short name: <code>tiger</code> (64)\n *   - Tiger2: short name: <code>tiger2</code> (64)\n * - WHIRLPOOL family: file <code>sph_whirlpool.h</code>\n *   - WHIRLPOOL-0: short name: <code>whirlpool0</code> (64)\n *   - WHIRLPOOL-1: short name: <code>whirlpool1</code> (64)\n *   - WHIRLPOOL: short name: <code>whirlpool</code> (64)\n *\n * The fourteen second-round SHA-3 candidates are also implemented;\n * when applicable, the implementations follow the \"final\" specifications\n * as published for the third round of the SHA-3 competition (BLAKE,\n * Groestl, JH, Keccak and Skein have been tweaked for third round).\n *\n * - BLAKE family: file <code>sph_blake.h</code>\n *   - BLAKE-224: short name: <code>blake224</code>\n *   - BLAKE-256: short name: <code>blake256</code>\n *   - BLAKE-384: short name: <code>blake384</code>\n *   - BLAKE-512: short name: <code>blake512</code>\n * - BMW (Blue Midnight Wish) family: file <code>sph_bmw.h</code>\n *   - BMW-224: short name: <code>bmw224</code>\n *   - BMW-256: short name: <code>bmw256</code>\n *   - BMW-384: short name: <code>bmw384</code> (64)\n *   - BMW-512: short name: <code>bmw512</code> (64)\n * - CubeHash family: file <code>sph_cubehash.h</code> (specified as\n *   CubeHash16/32 in the CubeHash specification)\n *   - CubeHash-224: short name: <code>cubehash224</code>\n *   - CubeHash-256: short name: <code>cubehash256</code>\n *   - CubeHash-384: short name: <code>cubehash384</code>\n *   - CubeHash-512: short name: <code>cubehash512</code>\n * - ECHO family: file <code>sph_echo.h</code>\n *   - ECHO-224: short name: <code>echo224</code>\n *   - ECHO-256: short name: <code>echo256</code>\n *   - ECHO-384: short name: <code>echo384</code>\n *   - ECHO-512: short name: <code>echo512</code>\n * - Fugue family: file <code>sph_fugue.h</code>\n *   - Fugue-224: short name: <code>fugue224</code>\n *   - Fugue-256: short name: <code>fugue256</code>\n *   - Fugue-384: short name: <code>fugue384</code>\n *   - Fugue-512: short name: <code>fugue512</code>\n * - Groestl family: file <code>sph_groestl.h</code>\n *   - Groestl-224: short name: <code>groestl224</code>\n *   - Groestl-256: short name: <code>groestl256</code>\n *   - Groestl-384: short name: <code>groestl384</code>\n *   - Groestl-512: short name: <code>groestl512</code>\n * - Hamsi family: file <code>sph_hamsi.h</code>\n *   - Hamsi-224: short name: <code>hamsi224</code>\n *   - Hamsi-256: short name: <code>hamsi256</code>\n *   - Hamsi-384: short name: <code>hamsi384</code>\n *   - Hamsi-512: short name: <code>hamsi512</code>\n * - JH family: file <code>sph_jh.h</code>\n *   - JH-224: short name: <code>jh224</code>\n *   - JH-256: short name: <code>jh256</code>\n *   - JH-384: short name: <code>jh384</code>\n *   - JH-512: short name: <code>jh512</code>\n * - Keccak family: file <code>sph_keccak.h</code>\n *   - Keccak-224: short name: <code>keccak224</code>\n *   - Keccak-256: short name: <code>keccak256</code>\n *   - Keccak-384: short name: <code>keccak384</code>\n *   - Keccak-512: short name: <code>keccak512</code>\n * - Luffa family: file <code>sph_luffa.h</code>\n *   - Luffa-224: short name: <code>luffa224</code>\n *   - Luffa-256: short name: <code>luffa256</code>\n *   - Luffa-384: short name: <code>luffa384</code>\n *   - Luffa-512: short name: <code>luffa512</code>\n * - Shabal family: file <code>sph_shabal.h</code>\n *   - Shabal-192: short name: <code>shabal192</code>\n *   - Shabal-224: short name: <code>shabal224</code>\n *   - Shabal-256: short name: <code>shabal256</code>\n *   - Shabal-384: short name: <code>shabal384</code>\n *   - Shabal-512: short name: <code>shabal512</code>\n * - SHAvite-3 family: file <code>sph_shavite.h</code>\n *   - SHAvite-224 (nominally \"SHAvite-3 with 224-bit output\"):\n *     short name: <code>shabal224</code>\n *   - SHAvite-256 (nominally \"SHAvite-3 with 256-bit output\"):\n *     short name: <code>shabal256</code>\n *   - SHAvite-384 (nominally \"SHAvite-3 with 384-bit output\"):\n *     short name: <code>shabal384</code>\n *   - SHAvite-512 (nominally \"SHAvite-3 with 512-bit output\"):\n *     short name: <code>shabal512</code>\n * - SIMD family: file <code>sph_simd.h</code>\n *   - SIMD-224: short name: <code>simd224</code>\n *   - SIMD-256: short name: <code>simd256</code>\n *   - SIMD-384: short name: <code>simd384</code>\n *   - SIMD-512: short name: <code>simd512</code>\n * - Skein family: file <code>sph_skein.h</code>\n *   - Skein-224 (nominally specified as Skein-512-224): short name:\n *     <code>skein224</code> (64)\n *   - Skein-256 (nominally specified as Skein-512-256): short name:\n *     <code>skein256</code> (64)\n *   - Skein-384 (nominally specified as Skein-512-384): short name:\n *     <code>skein384</code> (64)\n *   - Skein-512 (nominally specified as Skein-512-512): short name:\n *     <code>skein512</code> (64)\n *\n * For the second-round SHA-3 candidates, the functions are as specified\n * for round 2, i.e. with the \"tweaks\" that some candidates added\n * between round 1 and round 2. Also, some of the submitted packages for\n * round 2 contained errors, in the specification, reference code, or\n * both. <code>sphlib</code> implements the corrected versions.\n */\n\n/** @hideinitializer\n * Unsigned integer type whose length is at least 32 bits; on most\n * architectures, it will have a width of exactly 32 bits. Unsigned C\n * types implement arithmetics modulo a power of 2; use the\n * <code>SPH_T32()</code> macro to ensure that the value is truncated\n * to exactly 32 bits. Unless otherwise specified, all macros and\n * functions which accept <code>sph_u32</code> values assume that these\n * values fit on 32 bits, i.e. do not exceed 2^32-1, even on architectures\n * where <code>sph_u32</code> is larger than that.\n */\ntypedef __arch_dependant__ sph_u32;\n\n/** @hideinitializer\n * Signed integer type corresponding to <code>sph_u32</code>; it has\n * width 32 bits or more.\n */\ntypedef __arch_dependant__ sph_s32;\n\n/** @hideinitializer\n * Unsigned integer type whose length is at least 64 bits; on most\n * architectures which feature such a type, it will have a width of\n * exactly 64 bits. C99-compliant platform will have this type; it\n * is also defined when the GNU compiler (gcc) is used, and on\n * platforms where <code>unsigned long</code> is large enough. If this\n * type is not available, then some hash functions which depends on\n * a 64-bit type will not be available (most notably SHA-384, SHA-512,\n * Tiger and WHIRLPOOL).\n */\ntypedef __arch_dependant__ sph_u64;\n\n/** @hideinitializer\n * Signed integer type corresponding to <code>sph_u64</code>; it has\n * width 64 bits or more.\n */\ntypedef __arch_dependant__ sph_s64;\n\n/**\n * This macro expands the token <code>x</code> into a suitable\n * constant expression of type <code>sph_u32</code>. Depending on\n * how this type is defined, a suffix such as <code>UL</code> may\n * be appended to the argument.\n *\n * @param x   the token to expand into a suitable constant expression\n */\n#define SPH_C32(x)\n\n/**\n * Truncate a 32-bit value to exactly 32 bits. On most systems, this is\n * a no-op, recognized as such by the compiler.\n *\n * @param x   the value to truncate (of type <code>sph_u32</code>)\n */\n#define SPH_T32(x)\n\n/**\n * Rotate a 32-bit value by a number of bits to the left. The rotate\n * count must reside between 1 and 31. This macro assumes that its\n * first argument fits in 32 bits (no extra bit allowed on machines where\n * <code>sph_u32</code> is wider); both arguments may be evaluated\n * several times.\n *\n * @param x   the value to rotate (of type <code>sph_u32</code>)\n * @param n   the rotation count (between 1 and 31, inclusive)\n */\n#define SPH_ROTL32(x, n)\n\n/**\n * Rotate a 32-bit value by a number of bits to the left. The rotate\n * count must reside between 1 and 31. This macro assumes that its\n * first argument fits in 32 bits (no extra bit allowed on machines where\n * <code>sph_u32</code> is wider); both arguments may be evaluated\n * several times.\n *\n * @param x   the value to rotate (of type <code>sph_u32</code>)\n * @param n   the rotation count (between 1 and 31, inclusive)\n */\n#define SPH_ROTR32(x, n)\n\n/**\n * This macro is defined on systems for which a 64-bit type has been\n * detected, and is used for <code>sph_u64</code>.\n */\n#define SPH_64\n\n/**\n * This macro is defined on systems for the \"native\" integer size is\n * 64 bits (64-bit values fit in one register).\n */\n#define SPH_64_TRUE\n\n/**\n * This macro expands the token <code>x</code> into a suitable\n * constant expression of type <code>sph_u64</code>. Depending on\n * how this type is defined, a suffix such as <code>ULL</code> may\n * be appended to the argument. This macro is defined only if a\n * 64-bit type was detected and used for <code>sph_u64</code>.\n *\n * @param x   the token to expand into a suitable constant expression\n */\n#define SPH_C64(x)\n\n/**\n * Truncate a 64-bit value to exactly 64 bits. On most systems, this is\n * a no-op, recognized as such by the compiler. This macro is defined only\n * if a 64-bit type was detected and used for <code>sph_u64</code>.\n *\n * @param x   the value to truncate (of type <code>sph_u64</code>)\n */\n#define SPH_T64(x)\n\n/**\n * Rotate a 64-bit value by a number of bits to the left. The rotate\n * count must reside between 1 and 63. This macro assumes that its\n * first argument fits in 64 bits (no extra bit allowed on machines where\n * <code>sph_u64</code> is wider); both arguments may be evaluated\n * several times. This macro is defined only if a 64-bit type was detected\n * and used for <code>sph_u64</code>.\n *\n * @param x   the value to rotate (of type <code>sph_u64</code>)\n * @param n   the rotation count (between 1 and 63, inclusive)\n */\n#define SPH_ROTL64(x, n)\n\n/**\n * Rotate a 64-bit value by a number of bits to the left. The rotate\n * count must reside between 1 and 63. This macro assumes that its\n * first argument fits in 64 bits (no extra bit allowed on machines where\n * <code>sph_u64</code> is wider); both arguments may be evaluated\n * several times. This macro is defined only if a 64-bit type was detected\n * and used for <code>sph_u64</code>.\n *\n * @param x   the value to rotate (of type <code>sph_u64</code>)\n * @param n   the rotation count (between 1 and 63, inclusive)\n */\n#define SPH_ROTR64(x, n)\n\n/**\n * This macro evaluates to <code>inline</code> or an equivalent construction,\n * if available on the compilation platform, or to nothing otherwise. This\n * is used to declare inline functions, for which the compiler should\n * endeavour to include the code directly in the caller. Inline functions\n * are typically defined in header files as replacement for macros.\n */\n#define SPH_INLINE\n\n/**\n * This macro is defined if the platform has been detected as using\n * little-endian convention. This implies that the <code>sph_u32</code>\n * type (and the <code>sph_u64</code> type also, if it is defined) has\n * an exact width (i.e. exactly 32-bit, respectively 64-bit).\n */\n#define SPH_LITTLE_ENDIAN\n\n/**\n * This macro is defined if the platform has been detected as using\n * big-endian convention. This implies that the <code>sph_u32</code>\n * type (and the <code>sph_u64</code> type also, if it is defined) has\n * an exact width (i.e. exactly 32-bit, respectively 64-bit).\n */\n#define SPH_BIG_ENDIAN\n\n/**\n * This macro is defined if 32-bit words (and 64-bit words, if defined)\n * can be read from and written to memory efficiently in little-endian\n * convention. This is the case for little-endian platforms, and also\n * for the big-endian platforms which have special little-endian access\n * opcodes (e.g. Ultrasparc).\n */\n#define SPH_LITTLE_FAST\n\n/**\n * This macro is defined if 32-bit words (and 64-bit words, if defined)\n * can be read from and written to memory efficiently in big-endian\n * convention. This is the case for little-endian platforms, and also\n * for the little-endian platforms which have special big-endian access\n * opcodes.\n */\n#define SPH_BIG_FAST\n\n/**\n * On some platforms, this macro is defined to an unsigned integer type\n * into which pointer values may be cast. The resulting value can then\n * be tested for being a multiple of 2, 4 or 8, indicating an aligned\n * pointer for, respectively, 16-bit, 32-bit or 64-bit memory accesses.\n */\n#define SPH_UPTR\n\n/**\n * When defined, this macro indicates that unaligned memory accesses\n * are possible with only a minor penalty, and thus should be prefered\n * over strategies which first copy data to an aligned buffer.\n */\n#define SPH_UNALIGNED\n\n/**\n * Byte-swap a 32-bit word (i.e. <code>0x12345678</code> becomes\n * <code>0x78563412</code>). This is an inline function which resorts\n * to inline assembly on some platforms, for better performance.\n *\n * @param x   the 32-bit value to byte-swap\n * @return  the byte-swapped value\n */\nstatic inline sph_u32 sph_bswap32(sph_u32 x);\n\n/**\n * Byte-swap a 64-bit word. This is an inline function which resorts\n * to inline assembly on some platforms, for better performance. This\n * function is defined only if a suitable 64-bit type was found for\n * <code>sph_u64</code>\n *\n * @param x   the 64-bit value to byte-swap\n * @return  the byte-swapped value\n */\nstatic inline sph_u64 sph_bswap64(sph_u64 x);\n\n/**\n * Decode a 16-bit unsigned value from memory, in little-endian convention\n * (least significant byte comes first).\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline unsigned sph_dec16le(const void *src);\n\n/**\n * Encode a 16-bit unsigned value into memory, in little-endian convention\n * (least significant byte comes first).\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc16le(void *dst, unsigned val);\n\n/**\n * Decode a 16-bit unsigned value from memory, in big-endian convention\n * (most significant byte comes first).\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline unsigned sph_dec16be(const void *src);\n\n/**\n * Encode a 16-bit unsigned value into memory, in big-endian convention\n * (most significant byte comes first).\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc16be(void *dst, unsigned val);\n\n/**\n * Decode a 32-bit unsigned value from memory, in little-endian convention\n * (least significant byte comes first).\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline sph_u32 sph_dec32le(const void *src);\n\n/**\n * Decode a 32-bit unsigned value from memory, in little-endian convention\n * (least significant byte comes first). This function assumes that the\n * source address is suitably aligned for a direct access, if the platform\n * supports such things; it can thus be marginally faster than the generic\n * <code>sph_dec32le()</code> function.\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline sph_u32 sph_dec32le_aligned(const void *src);\n\n/**\n * Encode a 32-bit unsigned value into memory, in little-endian convention\n * (least significant byte comes first).\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc32le(void *dst, sph_u32 val);\n\n/**\n * Encode a 32-bit unsigned value into memory, in little-endian convention\n * (least significant byte comes first). This function assumes that the\n * destination address is suitably aligned for a direct access, if the\n * platform supports such things; it can thus be marginally faster than\n * the generic <code>sph_enc32le()</code> function.\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc32le_aligned(void *dst, sph_u32 val);\n\n/**\n * Decode a 32-bit unsigned value from memory, in big-endian convention\n * (most significant byte comes first).\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline sph_u32 sph_dec32be(const void *src);\n\n/**\n * Decode a 32-bit unsigned value from memory, in big-endian convention\n * (most significant byte comes first). This function assumes that the\n * source address is suitably aligned for a direct access, if the platform\n * supports such things; it can thus be marginally faster than the generic\n * <code>sph_dec32be()</code> function.\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline sph_u32 sph_dec32be_aligned(const void *src);\n\n/**\n * Encode a 32-bit unsigned value into memory, in big-endian convention\n * (most significant byte comes first).\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc32be(void *dst, sph_u32 val);\n\n/**\n * Encode a 32-bit unsigned value into memory, in big-endian convention\n * (most significant byte comes first). This function assumes that the\n * destination address is suitably aligned for a direct access, if the\n * platform supports such things; it can thus be marginally faster than\n * the generic <code>sph_enc32be()</code> function.\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc32be_aligned(void *dst, sph_u32 val);\n\n/**\n * Decode a 64-bit unsigned value from memory, in little-endian convention\n * (least significant byte comes first). This function is defined only\n * if a suitable 64-bit type was detected and used for <code>sph_u64</code>.\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline sph_u64 sph_dec64le(const void *src);\n\n/**\n * Decode a 64-bit unsigned value from memory, in little-endian convention\n * (least significant byte comes first). This function assumes that the\n * source address is suitably aligned for a direct access, if the platform\n * supports such things; it can thus be marginally faster than the generic\n * <code>sph_dec64le()</code> function. This function is defined only\n * if a suitable 64-bit type was detected and used for <code>sph_u64</code>.\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline sph_u64 sph_dec64le_aligned(const void *src);\n\n/**\n * Encode a 64-bit unsigned value into memory, in little-endian convention\n * (least significant byte comes first). This function is defined only\n * if a suitable 64-bit type was detected and used for <code>sph_u64</code>.\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc64le(void *dst, sph_u64 val);\n\n/**\n * Encode a 64-bit unsigned value into memory, in little-endian convention\n * (least significant byte comes first). This function assumes that the\n * destination address is suitably aligned for a direct access, if the\n * platform supports such things; it can thus be marginally faster than\n * the generic <code>sph_enc64le()</code> function. This function is defined\n * only if a suitable 64-bit type was detected and used for\n * <code>sph_u64</code>.\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc64le_aligned(void *dst, sph_u64 val);\n\n/**\n * Decode a 64-bit unsigned value from memory, in big-endian convention\n * (most significant byte comes first). This function is defined only\n * if a suitable 64-bit type was detected and used for <code>sph_u64</code>.\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline sph_u64 sph_dec64be(const void *src);\n\n/**\n * Decode a 64-bit unsigned value from memory, in big-endian convention\n * (most significant byte comes first). This function assumes that the\n * source address is suitably aligned for a direct access, if the platform\n * supports such things; it can thus be marginally faster than the generic\n * <code>sph_dec64be()</code> function. This function is defined only\n * if a suitable 64-bit type was detected and used for <code>sph_u64</code>.\n *\n * @param src   the source address\n * @return  the decoded value\n */\nstatic inline sph_u64 sph_dec64be_aligned(const void *src);\n\n/**\n * Encode a 64-bit unsigned value into memory, in big-endian convention\n * (most significant byte comes first). This function is defined only\n * if a suitable 64-bit type was detected and used for <code>sph_u64</code>.\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc64be(void *dst, sph_u64 val);\n\n/**\n * Encode a 64-bit unsigned value into memory, in big-endian convention\n * (most significant byte comes first). This function assumes that the\n * destination address is suitably aligned for a direct access, if the\n * platform supports such things; it can thus be marginally faster than\n * the generic <code>sph_enc64be()</code> function. This function is defined\n * only if a suitable 64-bit type was detected and used for\n * <code>sph_u64</code>.\n *\n * @param dst   the destination buffer\n * @param val   the value to encode\n */\nstatic inline void sph_enc64be_aligned(void *dst, sph_u64 val);\n\n#endif\n\n/* ============== END documentation block for Doxygen ============= */\n\n#ifndef DOXYGEN_IGNORE\n\n/*\n * We want to define the types \"sph_u32\" and \"sph_u64\" which hold\n * unsigned values of at least, respectively, 32 and 64 bits. These\n * tests should select appropriate types for most platforms. The\n * macro \"SPH_64\" is defined if the 64-bit is supported.\n */\n\n#undef SPH_64\n#undef SPH_64_TRUE\n\n#if defined __STDC__ && __STDC_VERSION__ >= 199901L\n\n/*\n * On C99 implementations, we can use <stdint.h> to get an exact 64-bit\n * type, if any, or otherwise use a wider type (which must exist, for\n * C99 conformance).\n */\n\n#include <stdint.h>\n\n#ifdef UINT32_MAX\ntypedef uint32_t sph_u32;\ntypedef int32_t sph_s32;\n#else\ntypedef uint_fast32_t sph_u32;\ntypedef int_fast32_t sph_s32;\n#endif\n#if !SPH_NO_64\n#ifdef UINT64_MAX\ntypedef Poco::UInt64 sph_u64;\ntypedef int64_t sph_s64;\n#else\ntypedef uint_fast64_t sph_u64;\ntypedef int_fast64_t sph_s64;\n#endif\n#endif\n\n#define SPH_C32(x)    ((sph_u32)(x))\n#if !SPH_NO_64\n#define SPH_C64(x)    ((sph_u64)(x))\n#define SPH_64  1\n#endif\n\n#else\n\n/*\n * On non-C99 systems, we use \"unsigned int\" if it is wide enough,\n * \"unsigned long\" otherwise. This supports all \"reasonable\" architectures.\n * We have to be cautious: pre-C99 preprocessors handle constants\n * differently in '#if' expressions. Hence the shifts to test UINT_MAX.\n */\n\n#if ((UINT_MAX >> 11) >> 11) >= 0x3FF\n\ntypedef unsigned int sph_u32;\ntypedef int sph_s32;\n\n#define SPH_C32(x)    ((sph_u32)(x ## U))\n\n#else\n\ntypedef unsigned long sph_u32;\ntypedef long sph_s32;\n\n#define SPH_C32(x)    ((sph_u32)(x ## UL))\n\n#endif\n\n#if !SPH_NO_64\n\n/*\n * We want a 64-bit type. We use \"unsigned long\" if it is wide enough (as\n * is common on 64-bit architectures such as AMD64, Alpha or Sparcv9),\n * \"unsigned long long\" otherwise, if available. We use ULLONG_MAX to\n * test whether \"unsigned long long\" is available; we also know that\n * gcc features this type, even if the libc header do not know it.\n */\n\n#if ((ULONG_MAX >> 31) >> 31) >= 3\n\ntypedef unsigned long sph_u64;\ntypedef long sph_s64;\n\n#define SPH_C64(x)    ((sph_u64)(x ## UL))\n\n#define SPH_64  1\n\n#elif ((ULLONG_MAX >> 31) >> 31) >= 3 || defined __GNUC__\n\ntypedef unsigned long long sph_u64;\ntypedef long long sph_s64;\n\n#define SPH_C64(x)    ((sph_u64)(x ## ULL))\n\n#define SPH_64  1\n\n#else\n\n/*\n * No 64-bit type...\n */\n\n#endif\n\n#endif\n\n#endif\n\n/*\n * If the \"unsigned long\" type has length 64 bits or more, then this is\n * a \"true\" 64-bit architectures. This is also true with Visual C on\n * amd64, even though the \"long\" type is limited to 32 bits.\n */\n#if SPH_64 && (((ULONG_MAX >> 31) >> 31) >= 3 || defined _M_X64)\n#define SPH_64_TRUE   1\n#endif\n\n/*\n * Implementation note: some processors have specific opcodes to perform\n * a rotation. Recent versions of gcc recognize the expression above and\n * use the relevant opcodes, when appropriate.\n */\n\n#define SPH_T32(x)    ((x) & SPH_C32(0xFFFFFFFF))\n#define SPH_ROTL32(x, n)   SPH_T32(((x) << (n)) | ((x) >> (32 - (n))))\n#define SPH_ROTR32(x, n)   SPH_ROTL32(x, (32 - (n)))\n\n#if SPH_64\n\n#define SPH_T64(x)    ((x) & SPH_C64(0xFFFFFFFFFFFFFFFF))\n#define SPH_ROTL64(x, n)   SPH_T64(((x) << (n)) | ((x) >> (64 - (n))))\n#define SPH_ROTR64(x, n)   SPH_ROTL64(x, (64 - (n)))\n\n#endif\n\n#ifndef DOXYGEN_IGNORE\n/*\n * Define SPH_INLINE to be an \"inline\" qualifier, if available. We define\n * some small macro-like functions which benefit greatly from being inlined.\n */\n#if (defined __STDC__ && __STDC_VERSION__ >= 199901L) || defined __GNUC__\n#define SPH_INLINE inline\n#elif defined _MSC_VER\n#define SPH_INLINE __inline\n#else\n#define SPH_INLINE\n#endif\n#endif\n\n/*\n * We define some macros which qualify the architecture. These macros\n * may be explicit set externally (e.g. as compiler parameters). The\n * code below sets those macros if they are not already defined.\n *\n * Most macros are boolean, thus evaluate to either zero or non-zero.\n * The SPH_UPTR macro is special, in that it evaluates to a C type,\n * or is not defined.\n *\n * SPH_UPTR             if defined: unsigned type to cast pointers into\n *\n * SPH_UNALIGNED        non-zero if unaligned accesses are efficient\n * SPH_LITTLE_ENDIAN    non-zero if architecture is known to be little-endian\n * SPH_BIG_ENDIAN       non-zero if architecture is known to be big-endian\n * SPH_LITTLE_FAST      non-zero if little-endian decoding is fast\n * SPH_BIG_FAST         non-zero if big-endian decoding is fast\n *\n * If SPH_UPTR is defined, then encoding and decoding of 32-bit and 64-bit\n * values will try to be \"smart\". Either SPH_LITTLE_ENDIAN or SPH_BIG_ENDIAN\n * _must_ be non-zero in those situations. The 32-bit and 64-bit types\n * _must_ also have an exact width.\n *\n * SPH_SPARCV9_GCC_32   UltraSPARC-compatible with gcc, 32-bit mode\n * SPH_SPARCV9_GCC_64   UltraSPARC-compatible with gcc, 64-bit mode\n * SPH_SPARCV9_GCC      UltraSPARC-compatible with gcc\n * SPH_I386_GCC         x86-compatible (32-bit) with gcc\n * SPH_I386_MSVC        x86-compatible (32-bit) with Microsoft Visual C\n * SPH_AMD64_GCC        x86-compatible (64-bit) with gcc\n * SPH_AMD64_MSVC       x86-compatible (64-bit) with Microsoft Visual C\n * SPH_PPC32_GCC        PowerPC, 32-bit, with gcc\n * SPH_PPC64_GCC        PowerPC, 64-bit, with gcc\n *\n * TODO: enhance automatic detection, for more architectures and compilers.\n * Endianness is the most important. SPH_UNALIGNED and SPH_UPTR help with\n * some very fast functions (e.g. MD4) when using unaligned input data.\n * The CPU-specific-with-GCC macros are useful only for inline assembly,\n * normally restrained to this header file.\n */\n\n/*\n * 32-bit x86, aka \"i386 compatible\".\n */\n#if defined __i386__ || defined _M_IX86\n\n#define SPH_DETECT_UNALIGNED         1\n#define SPH_DETECT_LITTLE_ENDIAN     1\n#define SPH_DETECT_UPTR              sph_u32\n#ifdef __GNUC__\n#define SPH_DETECT_I386_GCC          1\n#endif\n#ifdef _MSC_VER\n#define SPH_DETECT_I386_MSVC         1\n#endif\n\n/*\n * 64-bit x86, hereafter known as \"amd64\".\n */\n#elif defined __x86_64 || defined _M_X64\n\n#define SPH_DETECT_UNALIGNED         1\n#define SPH_DETECT_LITTLE_ENDIAN     1\n#define SPH_DETECT_UPTR              sph_u64\n#ifdef __GNUC__\n#define SPH_DETECT_AMD64_GCC         1\n#endif\n#ifdef _MSC_VER\n#define SPH_DETECT_AMD64_MSVC        1\n#endif\n\n/*\n * 64-bit Sparc architecture (implies v9).\n */\n#elif ((defined __sparc__ || defined __sparc) && defined __arch64__) \\\n\t|| defined __sparcv9\n\n#define SPH_DETECT_BIG_ENDIAN        1\n#define SPH_DETECT_UPTR              sph_u64\n#ifdef __GNUC__\n#define SPH_DETECT_SPARCV9_GCC_64    1\n#define SPH_DETECT_LITTLE_FAST       1\n#endif\n\n/*\n * 32-bit Sparc.\n */\n#elif (defined __sparc__ || defined __sparc) \\\n\t&& !(defined __sparcv9 || defined __arch64__)\n\n#define SPH_DETECT_BIG_ENDIAN        1\n#define SPH_DETECT_UPTR              sph_u32\n#if defined __GNUC__ && defined __sparc_v9__\n#define SPH_DETECT_SPARCV9_GCC_32    1\n#define SPH_DETECT_LITTLE_FAST       1\n#endif\n\n/*\n * ARM, little-endian.\n */\n#elif defined __arm__ && __ARMEL__\n\n#define SPH_DETECT_LITTLE_ENDIAN     1\n\n/*\n * MIPS, little-endian.\n */\n#elif MIPSEL || _MIPSEL || __MIPSEL || __MIPSEL__\n\n#define SPH_DETECT_LITTLE_ENDIAN     1\n\n/*\n * MIPS, big-endian.\n */\n#elif MIPSEB || _MIPSEB || __MIPSEB || __MIPSEB__\n\n#define SPH_DETECT_BIG_ENDIAN        1\n\n/*\n * PowerPC.\n */\n#elif defined __powerpc__ || defined __POWERPC__ || defined __ppc__ \\\n\t|| defined _ARCH_PPC\n\n/*\n * Note: we do not declare cross-endian access to be \"fast\": even if\n * using inline assembly, implementation should still assume that\n * keeping the decoded word in a temporary is faster than decoding\n * it again.\n */\n#if defined __GNUC__\n#if SPH_64_TRUE\n#define SPH_DETECT_PPC64_GCC         1\n#else\n#define SPH_DETECT_PPC32_GCC         1\n#endif\n#endif\n\n#if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN\n#define SPH_DETECT_BIG_ENDIAN        1\n#elif defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN\n#define SPH_DETECT_LITTLE_ENDIAN     1\n#endif\n\n/*\n * Itanium, 64-bit.\n */\n#elif defined __ia64 || defined __ia64__ \\\n\t|| defined __itanium__ || defined _M_IA64\n\n#if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN\n#define SPH_DETECT_BIG_ENDIAN        1\n#else\n#define SPH_DETECT_LITTLE_ENDIAN     1\n#endif\n#if defined __LP64__ || defined _LP64\n#define SPH_DETECT_UPTR              sph_u64\n#else\n#define SPH_DETECT_UPTR              sph_u32\n#endif\n\n#endif\n\n#if defined SPH_DETECT_SPARCV9_GCC_32 || defined SPH_DETECT_SPARCV9_GCC_64\n#define SPH_DETECT_SPARCV9_GCC       1\n#endif\n\n#if defined SPH_DETECT_UNALIGNED && !defined SPH_UNALIGNED\n#define SPH_UNALIGNED         SPH_DETECT_UNALIGNED\n#endif\n#if defined SPH_DETECT_UPTR && !defined SPH_UPTR\n#define SPH_UPTR              SPH_DETECT_UPTR\n#endif\n#if defined SPH_DETECT_LITTLE_ENDIAN && !defined SPH_LITTLE_ENDIAN\n#define SPH_LITTLE_ENDIAN     SPH_DETECT_LITTLE_ENDIAN\n#endif\n#if defined SPH_DETECT_BIG_ENDIAN && !defined SPH_BIG_ENDIAN\n#define SPH_BIG_ENDIAN        SPH_DETECT_BIG_ENDIAN\n#endif\n#if defined SPH_DETECT_LITTLE_FAST && !defined SPH_LITTLE_FAST\n#define SPH_LITTLE_FAST       SPH_DETECT_LITTLE_FAST\n#endif\n#if defined SPH_DETECT_BIG_FAST && !defined SPH_BIG_FAST\n#define SPH_BIG_FAST    SPH_DETECT_BIG_FAST\n#endif\n#if defined SPH_DETECT_SPARCV9_GCC_32 && !defined SPH_SPARCV9_GCC_32\n#define SPH_SPARCV9_GCC_32    SPH_DETECT_SPARCV9_GCC_32\n#endif\n#if defined SPH_DETECT_SPARCV9_GCC_64 && !defined SPH_SPARCV9_GCC_64\n#define SPH_SPARCV9_GCC_64    SPH_DETECT_SPARCV9_GCC_64\n#endif\n#if defined SPH_DETECT_SPARCV9_GCC && !defined SPH_SPARCV9_GCC\n#define SPH_SPARCV9_GCC       SPH_DETECT_SPARCV9_GCC\n#endif\n#if defined SPH_DETECT_I386_GCC && !defined SPH_I386_GCC\n#define SPH_I386_GCC          SPH_DETECT_I386_GCC\n#endif\n#if defined SPH_DETECT_I386_MSVC && !defined SPH_I386_MSVC\n#define SPH_I386_MSVC         SPH_DETECT_I386_MSVC\n#endif\n#if defined SPH_DETECT_AMD64_GCC && !defined SPH_AMD64_GCC\n#define SPH_AMD64_GCC         SPH_DETECT_AMD64_GCC\n#endif\n#if defined SPH_DETECT_AMD64_MSVC && !defined SPH_AMD64_MSVC\n#define SPH_AMD64_MSVC        SPH_DETECT_AMD64_MSVC\n#endif\n#if defined SPH_DETECT_PPC32_GCC && !defined SPH_PPC32_GCC\n#define SPH_PPC32_GCC         SPH_DETECT_PPC32_GCC\n#endif\n#if defined SPH_DETECT_PPC64_GCC && !defined SPH_PPC64_GCC\n#define SPH_PPC64_GCC         SPH_DETECT_PPC64_GCC\n#endif\n\n#if SPH_LITTLE_ENDIAN && !defined SPH_LITTLE_FAST\n#define SPH_LITTLE_FAST              1\n#endif\n#if SPH_BIG_ENDIAN && !defined SPH_BIG_FAST\n#define SPH_BIG_FAST                 1\n#endif\n\n#if defined SPH_UPTR && !(SPH_LITTLE_ENDIAN || SPH_BIG_ENDIAN)\n#error SPH_UPTR defined, but endianness is not known.\n#endif\n\n#if SPH_I386_GCC && !SPH_NO_ASM\n\n/*\n * On x86 32-bit, with gcc, we use the bswapl opcode to byte-swap 32-bit\n * values.\n */\n\nstatic SPH_INLINE sph_u32\nsph_bswap32(sph_u32 x)\n{\n\t__asm__ __volatile__ (\"bswapl %0\" : \"=r\" (x) : \"0\" (x));\n\treturn x;\n}\n\n#if SPH_64\n\nstatic SPH_INLINE sph_u64\nsph_bswap64(sph_u64 x)\n{\n\treturn ((sph_u64)sph_bswap32((sph_u32)x) << 32)\n\t\t| (sph_u64)sph_bswap32((sph_u32)(x >> 32));\n}\n\n#endif\n\n#elif SPH_AMD64_GCC && !SPH_NO_ASM\n\n/*\n * On x86 64-bit, with gcc, we use the bswapl opcode to byte-swap 32-bit\n * and 64-bit values.\n */\n\nstatic SPH_INLINE sph_u32\nsph_bswap32(sph_u32 x)\n{\n\t__asm__ __volatile__ (\"bswapl %0\" : \"=r\" (x) : \"0\" (x));\n\treturn x;\n}\n\n#if SPH_64\n\nstatic SPH_INLINE sph_u64\nsph_bswap64(sph_u64 x)\n{\n\t__asm__ __volatile__ (\"bswapq %0\" : \"=r\" (x) : \"0\" (x));\n\treturn x;\n}\n\n#endif\n\n/*\n * Disabled code. Apparently, Microsoft Visual C 2005 is smart enough\n * to generate proper opcodes for endianness swapping with the pure C\n * implementation below.\n *\n\n#elif SPH_I386_MSVC && !SPH_NO_ASM\n\nstatic __inline sph_u32 __declspec(naked) __fastcall\nsph_bswap32(sph_u32 x)\n{\n\t__asm {\n\t\tbswap  ecx\n\t\tmov    eax,ecx\n\t\tret\n\t}\n}\n\n#if SPH_64\n\nstatic SPH_INLINE sph_u64\nsph_bswap64(sph_u64 x)\n{\n\treturn ((sph_u64)sph_bswap32((sph_u32)x) << 32)\n\t\t| (sph_u64)sph_bswap32((sph_u32)(x >> 32));\n}\n\n#endif\n\n *\n * [end of disabled code]\n */\n\n#else\n\nstatic SPH_INLINE sph_u32\nsph_bswap32(sph_u32 x)\n{\n\tx = SPH_T32((x << 16) | (x >> 16));\n\tx = ((x & SPH_C32(0xFF00FF00)) >> 8)\n\t\t| ((x & SPH_C32(0x00FF00FF)) << 8);\n\treturn x;\n}\n\n#if SPH_64\n\n/**\n * Byte-swap a 64-bit value.\n *\n * @param x   the input value\n * @return  the byte-swapped value\n */\nstatic SPH_INLINE sph_u64\nsph_bswap64(sph_u64 x)\n{\n\tx = SPH_T64((x << 32) | (x >> 32));\n\tx = ((x & SPH_C64(0xFFFF0000FFFF0000)) >> 16)\n\t\t| ((x & SPH_C64(0x0000FFFF0000FFFF)) << 16);\n\tx = ((x & SPH_C64(0xFF00FF00FF00FF00)) >> 8)\n\t\t| ((x & SPH_C64(0x00FF00FF00FF00FF)) << 8);\n\treturn x;\n}\n\n#endif\n\n#endif\n\n#if SPH_SPARCV9_GCC && !SPH_NO_ASM\n\n/*\n * On UltraSPARC systems, native ordering is big-endian, but it is\n * possible to perform little-endian read accesses by specifying the\n * address space 0x88 (ASI_PRIMARY_LITTLE). Basically, either we use\n * the opcode \"lda [%reg]0x88,%dst\", where %reg is the register which\n * contains the source address and %dst is the destination register,\n * or we use \"lda [%reg+imm]%asi,%dst\", which uses the %asi register\n * to get the address space name. The latter format is better since it\n * combines an addition and the actual access in a single opcode; but\n * it requires the setting (and subsequent resetting) of %asi, which is\n * slow. Some operations (i.e. MD5 compression function) combine many\n * successive little-endian read accesses, which may share the same\n * %asi setting. The macros below contain the appropriate inline\n * assembly.\n */\n\n#define SPH_SPARCV9_SET_ASI   \\\n\tsph_u32 sph_sparcv9_asi; \\\n\t__asm__ __volatile__ ( \\\n\t\t\"rd %%asi,%0\\n\\twr %%g0,0x88,%%asi\" : \"=r\" (sph_sparcv9_asi));\n\n#define SPH_SPARCV9_RESET_ASI  \\\n\t__asm__ __volatile__ (\"wr %%g0,%0,%%asi\" : : \"r\" (sph_sparcv9_asi));\n\n#define SPH_SPARCV9_DEC32LE(base, idx)   ({ \\\n\t\tsph_u32 sph_sparcv9_tmp; \\\n\t\t__asm__ __volatile__ (\"lda [%1+\" #idx \"*4]%%asi,%0\" \\\n\t\t\t: \"=r\" (sph_sparcv9_tmp) : \"r\" (base)); \\\n\t\tsph_sparcv9_tmp; \\\n\t})\n\n#endif\n\nstatic SPH_INLINE void\nsph_enc16be(void *dst, unsigned val)\n{\n\t((unsigned char *)dst)[0] = (val >> 8);\n\t((unsigned char *)dst)[1] = val;\n}\n\nstatic SPH_INLINE unsigned\nsph_dec16be(const void *src)\n{\n\treturn ((unsigned)(((const unsigned char *)src)[0]) << 8)\n\t\t| (unsigned)(((const unsigned char *)src)[1]);\n}\n\nstatic SPH_INLINE void\nsph_enc16le(void *dst, unsigned val)\n{\n\t((unsigned char *)dst)[0] = val;\n\t((unsigned char *)dst)[1] = val >> 8;\n}\n\nstatic SPH_INLINE unsigned\nsph_dec16le(const void *src)\n{\n\treturn (unsigned)(((const unsigned char *)src)[0])\n\t\t| ((unsigned)(((const unsigned char *)src)[1]) << 8);\n}\n\n/**\n * Encode a 32-bit value into the provided buffer (big endian convention).\n *\n * @param dst   the destination buffer\n * @param val   the 32-bit value to encode\n */\nstatic SPH_INLINE void\nsph_enc32be(void *dst, sph_u32 val)\n{\n#if defined SPH_UPTR\n#if SPH_UNALIGNED\n#if SPH_LITTLE_ENDIAN\n\tval = sph_bswap32(val);\n#endif\n\t*(sph_u32 *)dst = val;\n#else\n\tif (((SPH_UPTR)dst & 3) == 0) {\n#if SPH_LITTLE_ENDIAN\n\t\tval = sph_bswap32(val);\n#endif\n\t\t*(sph_u32 *)dst = val;\n\t} else {\n\t\t((unsigned char *)dst)[0] = (val >> 24);\n\t\t((unsigned char *)dst)[1] = (val >> 16);\n\t\t((unsigned char *)dst)[2] = (val >> 8);\n\t\t((unsigned char *)dst)[3] = val;\n\t}\n#endif\n#else\n\t((unsigned char *)dst)[0] = (val >> 24);\n\t((unsigned char *)dst)[1] = (val >> 16);\n\t((unsigned char *)dst)[2] = (val >> 8);\n\t((unsigned char *)dst)[3] = val;\n#endif\n}\n\n/**\n * Encode a 32-bit value into the provided buffer (big endian convention).\n * The destination buffer must be properly aligned.\n *\n * @param dst   the destination buffer (32-bit aligned)\n * @param val   the value to encode\n */\nstatic SPH_INLINE void\nsph_enc32be_aligned(void *dst, sph_u32 val)\n{\n#if SPH_LITTLE_ENDIAN\n\t*(sph_u32 *)dst = sph_bswap32(val);\n#elif SPH_BIG_ENDIAN\n\t*(sph_u32 *)dst = val;\n#else\n\t((unsigned char *)dst)[0] = (val >> 24);\n\t((unsigned char *)dst)[1] = (val >> 16);\n\t((unsigned char *)dst)[2] = (val >> 8);\n\t((unsigned char *)dst)[3] = val;\n#endif\n}\n\n/**\n * Decode a 32-bit value from the provided buffer (big endian convention).\n *\n * @param src   the source buffer\n * @return  the decoded value\n */\nstatic SPH_INLINE sph_u32\nsph_dec32be(const void *src)\n{\n#if defined SPH_UPTR\n#if SPH_UNALIGNED\n#if SPH_LITTLE_ENDIAN\n\treturn sph_bswap32(*(const sph_u32 *)src);\n#else\n\treturn *(const sph_u32 *)src;\n#endif\n#else\n\tif (((SPH_UPTR)src & 3) == 0) {\n#if SPH_LITTLE_ENDIAN\n\t\treturn sph_bswap32(*(const sph_u32 *)src);\n#else\n\t\treturn *(const sph_u32 *)src;\n#endif\n\t} else {\n\t\treturn ((sph_u32)(((const unsigned char *)src)[0]) << 24)\n\t\t\t| ((sph_u32)(((const unsigned char *)src)[1]) << 16)\n\t\t\t| ((sph_u32)(((const unsigned char *)src)[2]) << 8)\n\t\t\t| (sph_u32)(((const unsigned char *)src)[3]);\n\t}\n#endif\n#else\n\treturn ((sph_u32)(((const unsigned char *)src)[0]) << 24)\n\t\t| ((sph_u32)(((const unsigned char *)src)[1]) << 16)\n\t\t| ((sph_u32)(((const unsigned char *)src)[2]) << 8)\n\t\t| (sph_u32)(((const unsigned char *)src)[3]);\n#endif\n}\n\n/**\n * Decode a 32-bit value from the provided buffer (big endian convention).\n * The source buffer must be properly aligned.\n *\n * @param src   the source buffer (32-bit aligned)\n * @return  the decoded value\n */\nstatic SPH_INLINE sph_u32\nsph_dec32be_aligned(const void *src)\n{\n#if SPH_LITTLE_ENDIAN\n\treturn sph_bswap32(*(const sph_u32 *)src);\n#elif SPH_BIG_ENDIAN\n\treturn *(const sph_u32 *)src;\n#else\n\treturn ((sph_u32)(((const unsigned char *)src)[0]) << 24)\n\t\t| ((sph_u32)(((const unsigned char *)src)[1]) << 16)\n\t\t| ((sph_u32)(((const unsigned char *)src)[2]) << 8)\n\t\t| (sph_u32)(((const unsigned char *)src)[3]);\n#endif\n}\n\n/**\n * Encode a 32-bit value into the provided buffer (little endian convention).\n *\n * @param dst   the destination buffer\n * @param val   the 32-bit value to encode\n */\nstatic SPH_INLINE void\nsph_enc32le(void *dst, sph_u32 val)\n{\n#if defined SPH_UPTR\n#if SPH_UNALIGNED\n#if SPH_BIG_ENDIAN\n\tval = sph_bswap32(val);\n#endif\n\t*(sph_u32 *)dst = val;\n#else\n\tif (((SPH_UPTR)dst & 3) == 0) {\n#if SPH_BIG_ENDIAN\n\t\tval = sph_bswap32(val);\n#endif\n\t\t*(sph_u32 *)dst = val;\n\t} else {\n\t\t((unsigned char *)dst)[0] = val;\n\t\t((unsigned char *)dst)[1] = (val >> 8);\n\t\t((unsigned char *)dst)[2] = (val >> 16);\n\t\t((unsigned char *)dst)[3] = (val >> 24);\n\t}\n#endif\n#else\n\t((unsigned char *)dst)[0] = val;\n\t((unsigned char *)dst)[1] = (val >> 8);\n\t((unsigned char *)dst)[2] = (val >> 16);\n\t((unsigned char *)dst)[3] = (val >> 24);\n#endif\n}\n\n/**\n * Encode a 32-bit value into the provided buffer (little endian convention).\n * The destination buffer must be properly aligned.\n *\n * @param dst   the destination buffer (32-bit aligned)\n * @param val   the value to encode\n */\nstatic SPH_INLINE void\nsph_enc32le_aligned(void *dst, sph_u32 val)\n{\n#if SPH_LITTLE_ENDIAN\n\t*(sph_u32 *)dst = val;\n#elif SPH_BIG_ENDIAN\n\t*(sph_u32 *)dst = sph_bswap32(val);\n#else\n\t((unsigned char *)dst)[0] = val;\n\t((unsigned char *)dst)[1] = (val >> 8);\n\t((unsigned char *)dst)[2] = (val >> 16);\n\t((unsigned char *)dst)[3] = (val >> 24);\n#endif\n}\n\n/**\n * Decode a 32-bit value from the provided buffer (little endian convention).\n *\n * @param src   the source buffer\n * @return  the decoded value\n */\nstatic SPH_INLINE sph_u32\nsph_dec32le(const void *src)\n{\n#if defined SPH_UPTR\n#if SPH_UNALIGNED\n#if SPH_BIG_ENDIAN\n\treturn sph_bswap32(*(const sph_u32 *)src);\n#else\n\treturn *(const sph_u32 *)src;\n#endif\n#else\n\tif (((SPH_UPTR)src & 3) == 0) {\n#if SPH_BIG_ENDIAN\n#if SPH_SPARCV9_GCC && !SPH_NO_ASM\n\t\tsph_u32 tmp;\n\n\t\t/*\n\t\t * \"__volatile__\" is needed here because without it,\n\t\t * gcc-3.4.3 miscompiles the code and performs the\n\t\t * access before the test on the address, thus triggering\n\t\t * a bus error...\n\t\t */\n\t\t__asm__ __volatile__ (\n\t\t\t\"lda [%1]0x88,%0\" : \"=r\" (tmp) : \"r\" (src));\n\t\treturn tmp;\n/*\n * On PowerPC, this turns out not to be worth the effort: the inline\n * assembly makes GCC optimizer uncomfortable, which tends to nullify\n * the decoding gains.\n *\n * For most hash functions, using this inline assembly trick changes\n * hashing speed by less than 5% and often _reduces_ it. The biggest\n * gains are for MD4 (+11%) and CubeHash (+30%). For all others, it is\n * less then 10%. The speed gain on CubeHash is probably due to the\n * chronic shortage of registers that CubeHash endures; for the other\n * functions, the generic code appears to be efficient enough already.\n *\n#elif (SPH_PPC32_GCC || SPH_PPC64_GCC) && !SPH_NO_ASM\n\t\tsph_u32 tmp;\n\n\t\t__asm__ __volatile__ (\n\t\t\t\"lwbrx %0,0,%1\" : \"=r\" (tmp) : \"r\" (src));\n\t\treturn tmp;\n */\n#else\n\t\treturn sph_bswap32(*(const sph_u32 *)src);\n#endif\n#else\n\t\treturn *(const sph_u32 *)src;\n#endif\n\t} else {\n\t\treturn (sph_u32)(((const unsigned char *)src)[0])\n\t\t\t| ((sph_u32)(((const unsigned char *)src)[1]) << 8)\n\t\t\t| ((sph_u32)(((const unsigned char *)src)[2]) << 16)\n\t\t\t| ((sph_u32)(((const unsigned char *)src)[3]) << 24);\n\t}\n#endif\n#else\n\treturn (sph_u32)(((const unsigned char *)src)[0])\n\t\t| ((sph_u32)(((const unsigned char *)src)[1]) << 8)\n\t\t| ((sph_u32)(((const unsigned char *)src)[2]) << 16)\n\t\t| ((sph_u32)(((const unsigned char *)src)[3]) << 24);\n#endif\n}\n\n/**\n * Decode a 32-bit value from the provided buffer (little endian convention).\n * The source buffer must be properly aligned.\n *\n * @param src   the source buffer (32-bit aligned)\n * @return  the decoded value\n */\nstatic SPH_INLINE sph_u32\nsph_dec32le_aligned(const void *src)\n{\n#if SPH_LITTLE_ENDIAN\n\treturn *(const sph_u32 *)src;\n#elif SPH_BIG_ENDIAN\n#if SPH_SPARCV9_GCC && !SPH_NO_ASM\n\tsph_u32 tmp;\n\n\t__asm__ __volatile__ (\"lda [%1]0x88,%0\" : \"=r\" (tmp) : \"r\" (src));\n\treturn tmp;\n/*\n * Not worth it generally.\n *\n#elif (SPH_PPC32_GCC || SPH_PPC64_GCC) && !SPH_NO_ASM\n\tsph_u32 tmp;\n\n\t__asm__ __volatile__ (\"lwbrx %0,0,%1\" : \"=r\" (tmp) : \"r\" (src));\n\treturn tmp;\n */\n#else\n\treturn sph_bswap32(*(const sph_u32 *)src);\n#endif\n#else\n\treturn (sph_u32)(((const unsigned char *)src)[0])\n\t\t| ((sph_u32)(((const unsigned char *)src)[1]) << 8)\n\t\t| ((sph_u32)(((const unsigned char *)src)[2]) << 16)\n\t\t| ((sph_u32)(((const unsigned char *)src)[3]) << 24);\n#endif\n}\n\n#if SPH_64\n\n/**\n * Encode a 64-bit value into the provided buffer (big endian convention).\n *\n * @param dst   the destination buffer\n * @param val   the 64-bit value to encode\n */\nstatic SPH_INLINE void\nsph_enc64be(void *dst, sph_u64 val)\n{\n#if defined SPH_UPTR\n#if SPH_UNALIGNED\n#if SPH_LITTLE_ENDIAN\n\tval = sph_bswap64(val);\n#endif\n\t*(sph_u64 *)dst = val;\n#else\n\tif (((SPH_UPTR)dst & 7) == 0) {\n#if SPH_LITTLE_ENDIAN\n\t\tval = sph_bswap64(val);\n#endif\n\t\t*(sph_u64 *)dst = val;\n\t} else {\n\t\t((unsigned char *)dst)[0] = (val >> 56);\n\t\t((unsigned char *)dst)[1] = (val >> 48);\n\t\t((unsigned char *)dst)[2] = (val >> 40);\n\t\t((unsigned char *)dst)[3] = (val >> 32);\n\t\t((unsigned char *)dst)[4] = (val >> 24);\n\t\t((unsigned char *)dst)[5] = (val >> 16);\n\t\t((unsigned char *)dst)[6] = (val >> 8);\n\t\t((unsigned char *)dst)[7] = val;\n\t}\n#endif\n#else\n\t((unsigned char *)dst)[0] = (val >> 56);\n\t((unsigned char *)dst)[1] = (val >> 48);\n\t((unsigned char *)dst)[2] = (val >> 40);\n\t((unsigned char *)dst)[3] = (val >> 32);\n\t((unsigned char *)dst)[4] = (val >> 24);\n\t((unsigned char *)dst)[5] = (val >> 16);\n\t((unsigned char *)dst)[6] = (val >> 8);\n\t((unsigned char *)dst)[7] = val;\n#endif\n}\n\n/**\n * Encode a 64-bit value into the provided buffer (big endian convention).\n * The destination buffer must be properly aligned.\n *\n * @param dst   the destination buffer (64-bit aligned)\n * @param val   the value to encode\n */\nstatic SPH_INLINE void\nsph_enc64be_aligned(void *dst, sph_u64 val)\n{\n#if SPH_LITTLE_ENDIAN\n\t*(sph_u64 *)dst = sph_bswap64(val);\n#elif SPH_BIG_ENDIAN\n\t*(sph_u64 *)dst = val;\n#else\n\t((unsigned char *)dst)[0] = (val >> 56);\n\t((unsigned char *)dst)[1] = (val >> 48);\n\t((unsigned char *)dst)[2] = (val >> 40);\n\t((unsigned char *)dst)[3] = (val >> 32);\n\t((unsigned char *)dst)[4] = (val >> 24);\n\t((unsigned char *)dst)[5] = (val >> 16);\n\t((unsigned char *)dst)[6] = (val >> 8);\n\t((unsigned char *)dst)[7] = val;\n#endif\n}\n\n/**\n * Decode a 64-bit value from the provided buffer (big endian convention).\n *\n * @param src   the source buffer\n * @return  the decoded value\n */\nstatic SPH_INLINE sph_u64\nsph_dec64be(const void *src)\n{\n#if defined SPH_UPTR\n#if SPH_UNALIGNED\n#if SPH_LITTLE_ENDIAN\n\treturn sph_bswap64(*(const sph_u64 *)src);\n#else\n\treturn *(const sph_u64 *)src;\n#endif\n#else\n\tif (((SPH_UPTR)src & 7) == 0) {\n#if SPH_LITTLE_ENDIAN\n\t\treturn sph_bswap64(*(const sph_u64 *)src);\n#else\n\t\treturn *(const sph_u64 *)src;\n#endif\n\t} else {\n\t\treturn ((sph_u64)(((const unsigned char *)src)[0]) << 56)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[1]) << 48)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[2]) << 40)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[3]) << 32)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[4]) << 24)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[5]) << 16)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[6]) << 8)\n\t\t\t| (sph_u64)(((const unsigned char *)src)[7]);\n\t}\n#endif\n#else\n\treturn ((sph_u64)(((const unsigned char *)src)[0]) << 56)\n\t\t| ((sph_u64)(((const unsigned char *)src)[1]) << 48)\n\t\t| ((sph_u64)(((const unsigned char *)src)[2]) << 40)\n\t\t| ((sph_u64)(((const unsigned char *)src)[3]) << 32)\n\t\t| ((sph_u64)(((const unsigned char *)src)[4]) << 24)\n\t\t| ((sph_u64)(((const unsigned char *)src)[5]) << 16)\n\t\t| ((sph_u64)(((const unsigned char *)src)[6]) << 8)\n\t\t| (sph_u64)(((const unsigned char *)src)[7]);\n#endif\n}\n\n/**\n * Decode a 64-bit value from the provided buffer (big endian convention).\n * The source buffer must be properly aligned.\n *\n * @param src   the source buffer (64-bit aligned)\n * @return  the decoded value\n */\nstatic SPH_INLINE sph_u64\nsph_dec64be_aligned(const void *src)\n{\n#if SPH_LITTLE_ENDIAN\n\treturn sph_bswap64(*(const sph_u64 *)src);\n#elif SPH_BIG_ENDIAN\n\treturn *(const sph_u64 *)src;\n#else\n\treturn ((sph_u64)(((const unsigned char *)src)[0]) << 56)\n\t\t| ((sph_u64)(((const unsigned char *)src)[1]) << 48)\n\t\t| ((sph_u64)(((const unsigned char *)src)[2]) << 40)\n\t\t| ((sph_u64)(((const unsigned char *)src)[3]) << 32)\n\t\t| ((sph_u64)(((const unsigned char *)src)[4]) << 24)\n\t\t| ((sph_u64)(((const unsigned char *)src)[5]) << 16)\n\t\t| ((sph_u64)(((const unsigned char *)src)[6]) << 8)\n\t\t| (sph_u64)(((const unsigned char *)src)[7]);\n#endif\n}\n\n/**\n * Encode a 64-bit value into the provided buffer (little endian convention).\n *\n * @param dst   the destination buffer\n * @param val   the 64-bit value to encode\n */\nstatic SPH_INLINE void\nsph_enc64le(void *dst, sph_u64 val)\n{\n#if defined SPH_UPTR\n#if SPH_UNALIGNED\n#if SPH_BIG_ENDIAN\n\tval = sph_bswap64(val);\n#endif\n\t*(sph_u64 *)dst = val;\n#else\n\tif (((SPH_UPTR)dst & 7) == 0) {\n#if SPH_BIG_ENDIAN\n\t\tval = sph_bswap64(val);\n#endif\n\t\t*(sph_u64 *)dst = val;\n\t} else {\n\t\t((unsigned char *)dst)[0] = val;\n\t\t((unsigned char *)dst)[1] = (val >> 8);\n\t\t((unsigned char *)dst)[2] = (val >> 16);\n\t\t((unsigned char *)dst)[3] = (val >> 24);\n\t\t((unsigned char *)dst)[4] = (val >> 32);\n\t\t((unsigned char *)dst)[5] = (val >> 40);\n\t\t((unsigned char *)dst)[6] = (val >> 48);\n\t\t((unsigned char *)dst)[7] = (val >> 56);\n\t}\n#endif\n#else\n\t((unsigned char *)dst)[0] = val;\n\t((unsigned char *)dst)[1] = (val >> 8);\n\t((unsigned char *)dst)[2] = (val >> 16);\n\t((unsigned char *)dst)[3] = (val >> 24);\n\t((unsigned char *)dst)[4] = (val >> 32);\n\t((unsigned char *)dst)[5] = (val >> 40);\n\t((unsigned char *)dst)[6] = (val >> 48);\n\t((unsigned char *)dst)[7] = (val >> 56);\n#endif\n}\n\n/**\n * Encode a 64-bit value into the provided buffer (little endian convention).\n * The destination buffer must be properly aligned.\n *\n * @param dst   the destination buffer (64-bit aligned)\n * @param val   the value to encode\n */\nstatic SPH_INLINE void\nsph_enc64le_aligned(void *dst, sph_u64 val)\n{\n#if SPH_LITTLE_ENDIAN\n\t*(sph_u64 *)dst = val;\n#elif SPH_BIG_ENDIAN\n\t*(sph_u64 *)dst = sph_bswap64(val);\n#else\n\t((unsigned char *)dst)[0] = val;\n\t((unsigned char *)dst)[1] = (val >> 8);\n\t((unsigned char *)dst)[2] = (val >> 16);\n\t((unsigned char *)dst)[3] = (val >> 24);\n\t((unsigned char *)dst)[4] = (val >> 32);\n\t((unsigned char *)dst)[5] = (val >> 40);\n\t((unsigned char *)dst)[6] = (val >> 48);\n\t((unsigned char *)dst)[7] = (val >> 56);\n#endif\n}\n\n/**\n * Decode a 64-bit value from the provided buffer (little endian convention).\n *\n * @param src   the source buffer\n * @return  the decoded value\n */\nstatic SPH_INLINE sph_u64\nsph_dec64le(const void *src)\n{\n#if defined SPH_UPTR\n#if SPH_UNALIGNED\n#if SPH_BIG_ENDIAN\n\treturn sph_bswap64(*(const sph_u64 *)src);\n#else\n\treturn *(const sph_u64 *)src;\n#endif\n#else\n\tif (((SPH_UPTR)src & 7) == 0) {\n#if SPH_BIG_ENDIAN\n#if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM\n\t\tsph_u64 tmp;\n\n\t\t__asm__ __volatile__ (\n\t\t\t\"ldxa [%1]0x88,%0\" : \"=r\" (tmp) : \"r\" (src));\n\t\treturn tmp;\n/*\n * Not worth it generally.\n *\n#elif SPH_PPC32_GCC && !SPH_NO_ASM\n\t\treturn (sph_u64)sph_dec32le_aligned(src)\n\t\t\t| ((sph_u64)sph_dec32le_aligned(\n\t\t\t\t(const char *)src + 4) << 32);\n#elif SPH_PPC64_GCC && !SPH_NO_ASM\n\t\tsph_u64 tmp;\n\n\t\t__asm__ __volatile__ (\n\t\t\t\"ldbrx %0,0,%1\" : \"=r\" (tmp) : \"r\" (src));\n\t\treturn tmp;\n */\n#else\n\t\treturn sph_bswap64(*(const sph_u64 *)src);\n#endif\n#else\n\t\treturn *(const sph_u64 *)src;\n#endif\n\t} else {\n\t\treturn (sph_u64)(((const unsigned char *)src)[0])\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[1]) << 8)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[2]) << 16)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[3]) << 24)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[4]) << 32)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[5]) << 40)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[6]) << 48)\n\t\t\t| ((sph_u64)(((const unsigned char *)src)[7]) << 56);\n\t}\n#endif\n#else\n\treturn (sph_u64)(((const unsigned char *)src)[0])\n\t\t| ((sph_u64)(((const unsigned char *)src)[1]) << 8)\n\t\t| ((sph_u64)(((const unsigned char *)src)[2]) << 16)\n\t\t| ((sph_u64)(((const unsigned char *)src)[3]) << 24)\n\t\t| ((sph_u64)(((const unsigned char *)src)[4]) << 32)\n\t\t| ((sph_u64)(((const unsigned char *)src)[5]) << 40)\n\t\t| ((sph_u64)(((const unsigned char *)src)[6]) << 48)\n\t\t| ((sph_u64)(((const unsigned char *)src)[7]) << 56);\n#endif\n}\n\n/**\n * Decode a 64-bit value from the provided buffer (little endian convention).\n * The source buffer must be properly aligned.\n *\n * @param src   the source buffer (64-bit aligned)\n * @return  the decoded value\n */\nstatic SPH_INLINE sph_u64\nsph_dec64le_aligned(const void *src)\n{\n#if SPH_LITTLE_ENDIAN\n\treturn *(const sph_u64 *)src;\n#elif SPH_BIG_ENDIAN\n#if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM\n\tsph_u64 tmp;\n\n\t__asm__ __volatile__ (\"ldxa [%1]0x88,%0\" : \"=r\" (tmp) : \"r\" (src));\n\treturn tmp;\n/*\n * Not worth it generally.\n *\n#elif SPH_PPC32_GCC && !SPH_NO_ASM\n\treturn (sph_u64)sph_dec32le_aligned(src)\n\t\t| ((sph_u64)sph_dec32le_aligned((const char *)src + 4) << 32);\n#elif SPH_PPC64_GCC && !SPH_NO_ASM\n\tsph_u64 tmp;\n\n\t__asm__ __volatile__ (\"ldbrx %0,0,%1\" : \"=r\" (tmp) : \"r\" (src));\n\treturn tmp;\n */\n#else\n\treturn sph_bswap64(*(const sph_u64 *)src);\n#endif\n#else\n\treturn (sph_u64)(((const unsigned char *)src)[0])\n\t\t| ((sph_u64)(((const unsigned char *)src)[1]) << 8)\n\t\t| ((sph_u64)(((const unsigned char *)src)[2]) << 16)\n\t\t| ((sph_u64)(((const unsigned char *)src)[3]) << 24)\n\t\t| ((sph_u64)(((const unsigned char *)src)[4]) << 32)\n\t\t| ((sph_u64)(((const unsigned char *)src)[5]) << 40)\n\t\t| ((sph_u64)(((const unsigned char *)src)[6]) << 48)\n\t\t| ((sph_u64)(((const unsigned char *)src)[7]) << 56);\n#endif\n}\n\n#endif\n\n#endif /* Doxygen excluded block */\n\n#endif\n"
  },
  {
    "path": "src/wallet/Account.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"Account.hpp\"\n#include <mutex>\n#include <Poco/Mutex.h>\n#include \"Wallet.hpp\"\n//#include \"Wallet.hpp\"\n#include <thread>\n#include \"nxt/nxt_address.h\"\n#include \"logging/Message.hpp\"\n#include \"logging/MinerLogger.hpp\"\n\nBurst::Account::Account()\n\t: Account {0}\n{}\n\nBurst::Account::Account(AccountId id)\n\t: id_{id},\n\t  wallet_{nullptr}\n{}\n\nBurst::Account::Account(const Wallet& wallet, AccountId id, bool fetchAll)\n\t: id_{id},\n\t  wallet_{&wallet}\n{\n\tif (fetchAll)\n\t{\n\t\tgetOrLoadName(true);\n\t\tgetOrLoadRewardRecipient(true);\n\t\tgetOrLoadAccountBlocks(true);\n\t}\n}\n\nvoid Burst::Account::setWallet(const Wallet& wallet)\n{\n\tPoco::Mutex::ScopedLock lock{ mutex_ };\n\twallet_ = &wallet;\n}\n\nBurst::AccountId Burst::Account::getId() const\n{\n\tPoco::Mutex::ScopedLock lock{ mutex_ };\n\treturn id_;\n}\n\ntemplate <typename T>\nstruct DefaultValueHolder\n{\n\tstatic const T value;\n};\n\ntemplate <typename T>\nconst T DefaultValueHolder<T>::value = T();\n\ntemplate <typename T>\nconst T& getHelper(Poco::Nullable<T>& val, const Burst::Wallet* wallet, bool reset, Poco::Mutex& mutex, std::function<bool(T&)> fetchFunction)\n{\n\tPoco::ScopedLockWithUnlock<Poco::Mutex> lock{ mutex };\n\n\tif (wallet != nullptr && !wallet->isActive())\n\t\treturn val.value(DefaultValueHolder<T>::value);\n\n\t// delete cached name if resetflag is set\n\tif (reset && !val.isNull())\n\t\tval.clear();\n\n\t// add name if there is no cached one\n\tif (val.isNull())\n\t{\n\t\t// because the fetching of the name is async\n\t\t// we insert an empty name in the map\n\t\tval = T{};\n\n\t\tlock.unlock();\n\n\t\tT fetchedVal;\n\n\t\tif (fetchFunction(fetchedVal))\n\t\t{\n\t\t\tPoco::Mutex::ScopedLock innerLock{ mutex };\n\t\t\tval = fetchedVal;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tPoco::Mutex::ScopedLock innerLock{ mutex };\n\t\t\tval.clear();\n\t\t}\n\t}\n\n\tPoco::Mutex::ScopedLock innerLock{ mutex };\n\treturn val.value(DefaultValueHolder<T>::value);\n}\n\nconst std::string& Burst::Account::getName() const\n{\n\tPoco::Mutex::ScopedLock lock{ mutex_ };\n\treturn name_.value(DefaultValueHolder<std::string>::value);\n}\n\nBurst::AccountId Burst::Account::getRewardRecipient()\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{ mutex_ };\n\treturn rewardRecipient_.value(DefaultValueHolder<AccountId>::value);\n}\n\nconst std::vector<Burst::Block>& Burst::Account::getBlocks()\n{\n\tPoco::ScopedLock<Poco::Mutex> lock{ mutex_ };\n\treturn blocks_.value(DefaultValueHolder<std::vector<Block>>::value);\n}\n\nPoco::ActiveResult<std::string> Burst::Account::getOrLoadName(bool reset)\n{\n\treturn DataLoader::getInstance().getName(std::make_tuple(std::ref(*this), reset));\n}\n\nPoco::ActiveResult<Burst::AccountId> Burst::Account::getOrLoadRewardRecipient(bool reset)\n{\n\treturn DataLoader::getInstance().getRewardRecipient(std::make_tuple(std::ref(*this), reset));\n}\n\nPoco::ActiveResult<std::vector<Burst::Block>> Burst::Account::getOrLoadAccountBlocks(bool reset)\n{\n\treturn DataLoader::getInstance().getAccountBlocks(std::make_tuple(std::ref(*this), reset));\n}\n\nstd::string Burst::Account::getAddress() const\n{\n\treturn NxtAddress(getId()).to_string();\n}\n\nPoco::JSON::Object::Ptr Burst::Account::toJSON() const\n{\n\tPoco::Mutex::ScopedLock lock{ mutex_ };\n\n\tPoco::JSON::Object::Ptr json(new Poco::JSON::Object);\n\n\tjson->set(\"numeric\", std::to_string(getId()));\n\tjson->set(\"address\", getAddress());\n\n\tauto name = name_.value(\"\");\n\n\tif (!name.empty())\n\t\tjson->set(\"name\", name);\n\n\tauto blocks = blocks_.value({});\n\n\tPoco::JSON::Array::Ptr jsonBlocks(new Poco::JSON::Array);\n\t\n\tfor (auto block : blocks)\n\t\tjsonBlocks->add(block);\n\n\tjson->set(\"blocks\", jsonBlocks);\n\n\treturn json;\n}\n\nBurst::Account::DataLoader::DataLoader()\n\t: getName{this, &DataLoader::runGetName},\n\t  getRewardRecipient{this, &DataLoader::runGetRewardRecipient},\n\t  getAccountBlocks{this, &DataLoader::runGetAccountBlocks}\n{}\n\nBurst::Account::DataLoader::~DataLoader() {}\n\nBurst::Account::DataLoader& Burst::Account::DataLoader::getInstance()\n{\n\tstatic DataLoader dataLoader;\n\treturn dataLoader;\n}\n\nstd::string Burst::Account::DataLoader::runGetName(const AsyncParameter& parameter)\n{\n\tauto& account = std::get<0>(parameter);\n\tconst auto reset = std::get<1>(parameter);\n\n\treturn getHelper<std::string>(account.name_, account.wallet_, reset, account.mutex_, [&account](std::string& name)\n\t{\n\t\treturn account.wallet_->getNameOfAccount(account.id_, name);\n\t});\n}\n\nBurst::AccountId Burst::Account::DataLoader::runGetRewardRecipient(const AsyncParameter& parameter)\n{\n\tauto& account = std::get<0>(parameter);\n\tconst auto reset = std::get<1>(parameter);\n\t\n\treturn getHelper<AccountId>(account.rewardRecipient_, account.wallet_, reset, account.mutex_, [&account](AccountId& rewardRecipient)\n\t{\n\t\treturn account.wallet_->getRewardRecipientOfAccount(account.id_, rewardRecipient);\n\t});\n}\n\nstd::vector<Burst::Block> Burst::Account::DataLoader::runGetAccountBlocks(const AsyncParameter& parameter)\n{\n\tauto& account = std::get<0>(parameter);\n\tconst auto reset = std::get<1>(parameter);\n\t\n\treturn getHelper<std::vector<Block>>(account.blocks_, account.wallet_, reset, account.mutex_, [&account](std::vector<Block>& blocks)\n\t{\n\t\treturn account.wallet_->getAccountBlocks(account.id_, blocks);\n\t});\n}\n\nstd::shared_ptr<Burst::Account> Burst::Accounts::getAccount(AccountId id, const Wallet& wallet, bool persistent)\n{\n\tPoco::FastMutex::ScopedLock lock{ mutex_ };\n\n\tauto iter = accounts_.find(id);\n\n\t// if the account is not in the cache, we have to fetch him\n\tif (iter == accounts_.end())\n\t{\n\t\tauto account = std::make_shared<Account>(wallet, id, persistent);\n\n\t\t// save the account in the cache if wanted\n\t\tif (persistent)\n\t\t{\n\t\t\taccounts_.emplace(id, account);\n\t\t\tlog_debug(MinerLogger::general, \"Cached accounts: %z\", accounts_.size());\n\t\t}\n\n\t\treturn account;\n\t}\n\n\t// account is in the cache already\n\treturn accounts_[id];\n}\n\nbool Burst::Accounts::isLoaded(AccountId id) const\n{\n\tPoco::FastMutex::ScopedLock lock{ mutex_ };\n\treturn accounts_.find(id) != accounts_.end();\n}\n\nstd::vector<std::shared_ptr<Burst::Account>> Burst::Accounts::getAccounts() const\n{\n\tPoco::FastMutex::ScopedLock lock{ mutex_ };\n\n\tstd::vector<std::shared_ptr<Account>> accounts;\n\n\tfor (auto& account : accounts_)\n\t\taccounts.emplace_back(account.second);\n\n\treturn accounts;\n}\n"
  },
  {
    "path": "src/wallet/Account.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include \"mining/Deadline.hpp\"\n#include <Poco/Nullable.h>\n#include <unordered_map>\n#include <Poco/Activity.h>\n#include <Poco/ActiveMethod.h>\n#include <Poco/JSON/Object.h>\n#include <vector>\n#include <Poco/ActiveDispatcher.h>\n\nnamespace Burst\n{\n\tclass Wallet;\n\n\tusing Block = Poco::UInt64;\n\n\tclass Account\n\t{\n\tpublic:\n\t\tAccount();\n\t\tAccount(AccountId id);\n\t\tAccount(const Wallet& wallet, AccountId id, bool fetchAll = false);\n\n\t\tvoid setWallet(const Wallet& wallet);\n\n\t\tAccountId getId() const;\n\t\tconst std::string& getName() const;\n\t\tstd::string getAddress() const;\n\t\tAccountId getRewardRecipient();\n\t\tconst std::vector<Block>& getBlocks();\n\n\t\tPoco::ActiveResult<std::string> getOrLoadName(bool reset = false);\n\t\tPoco::ActiveResult<AccountId> getOrLoadRewardRecipient(bool reset = false);\n\t\tPoco::ActiveResult<std::vector<Block>> getOrLoadAccountBlocks(bool reset = false);\n\n\t\tPoco::JSON::Object::Ptr toJSON() const;\n\t\t\n\tprivate:\n\t\tclass DataLoader : public Poco::ActiveDispatcher\n\t\t{\n\t\tpublic:\n\t\t\tDataLoader();\n\t\t\t~DataLoader() override;\n\n\t\t\tstatic DataLoader& getInstance();\n\n\t\t\tusing AsyncParameter = std::tuple<Account&, bool>;\n\n\t\t\tPoco::ActiveMethod<std::string, AsyncParameter, DataLoader, Poco::ActiveStarter<ActiveDispatcher>> getName;\n\t\t\tPoco::ActiveMethod<AccountId, AsyncParameter, DataLoader, Poco::ActiveStarter<ActiveDispatcher>> getRewardRecipient;\n\t\t\tPoco::ActiveMethod<std::vector<Block>, AsyncParameter, DataLoader, Poco::ActiveStarter<ActiveDispatcher>> getAccountBlocks;\n\n\t\tprivate:\n\t\t\tstd::string runGetName(const AsyncParameter& parameter);\n\t\t\tAccountId runGetRewardRecipient(const AsyncParameter& parameter);\n\t\t\tstd::vector<Block> runGetAccountBlocks(const AsyncParameter& parameter);\n\t\t};\n\n\tprivate:\n\t\tAccountId id_;\n\t\tPoco::Nullable<std::string> name_;\n\t\tPoco::Nullable<AccountId> rewardRecipient_;\n\t\tPoco::Nullable<std::vector<Block>> blocks_;\n\t\tconst Wallet* wallet_;\n\t\tmutable Poco::Mutex mutex_;\n\t};\n\n\tclass Accounts\n\t{\n\tpublic:\n\t\tstd::shared_ptr<Account> getAccount(AccountId id, const Wallet& wallet, bool persistent);\n\t\tbool isLoaded(AccountId id) const;\n\t\tstd::vector<std::shared_ptr<Account>> getAccounts() const;\n\n\tprivate:\n\t\tstd::unordered_map<AccountId, std::shared_ptr<Account>> accounts_;\n\t\tmutable Poco::FastMutex mutex_;\n\t};\n}\n"
  },
  {
    "path": "src/wallet/Wallet.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"Wallet.hpp\"\n#include \"MinerUtil.hpp\"\n#include <Poco/Net/HTTPClientSession.h>\n#include \"mining/MinerConfig.hpp\"\n#include \"network/Request.hpp\"\n#include <Poco/Net/HTTPRequest.h>\n#include <Poco/JSON/Parser.h>\n#include <cassert>\n#include <Poco/NestedDiagnosticContext.h>\n#include \"logging/MinerLogger.hpp\"\n#include \"Account.hpp\"\n#include <thread>\n\nusing namespace Poco::Net;\n\nBurst::Wallet::Wallet()\n{}\n\nBurst::Wallet::Wallet(const Url& url)\n\t: url_(url)\n{\n\tpoco_ndc(Wallet(const Url& url));\n}\n\nBurst::Wallet::~Wallet()\n{}\n\nbool Burst::Wallet::getWinnerOfBlock(Poco::UInt64 block, AccountId& winnerId) const\n{\n\tpoco_ndc(Wallet::getWinnerOfBlock);\n\twinnerId = 0;\n\n\tif (!isActive())\n\t\treturn false;\n\n\tPoco::JSON::Object::Ptr json;\n\n\tPoco::URI uri;\n\turi.setPath(\"/burst\");\n\turi.addQueryParameter(\"requestType\", \"getBlock\");\n\turi.addQueryParameter(\"height\", std::to_string(block));\n\n\tif (sendWalletRequest(uri, json))\n\t{\n\t\tif (json->has(\"generator\"))\n\t\t{\n            winnerId = json->get(\"generator\").convert<Poco::UInt64>();\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tlog_debug(MinerLogger::wallet, \"Could not get last winner!\");\n\treturn false;\n}\n\nbool Burst::Wallet::getNameOfAccount(AccountId account, std::string& name) const\n{\n\tpoco_ndc(Wallet::getNameOfAccount);\n\tPoco::JSON::Object::Ptr json;\n\tname = \"\";\n\n\tif (!isActive())\n\t\treturn false;\n\n\tPoco::URI uri;\n\turi.setPath(\"/burst\");\n\turi.addQueryParameter(\"requestType\", \"getAccount\");\n\turi.addQueryParameter(\"account\", std::to_string(account));\n\n\tif (sendWalletRequest(uri, json))\n\t{\n\t\tif (json->has(\"name\"))\n\t\t{\n\t\t\tname = json->get(\"name\").convert<std::string>();\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tlog_debug(MinerLogger::wallet, \"Could not get name of account!\");\n\treturn false;\n}\n\nbool Burst::Wallet::getRewardRecipientOfAccount(AccountId account, AccountId& rewardRecipient) const\n{\n\tpoco_ndc(Wallet::getRewardRecipientOfAccount);\n\tPoco::JSON::Object::Ptr json;\n\trewardRecipient = 0;\n\n\tif (!isActive())\n\t\treturn false;\n\n\tPoco::URI uri;\n\turi.setPath(\"/burst\");\n\turi.addQueryParameter(\"requestType\", \"getRewardRecipient\");\n\turi.addQueryParameter(\"account\", std::to_string(account));\n\n\tif (sendWalletRequest(uri, json))\n\t{\n\t\tif (json->has(\"rewardRecipient\"))\n\t\t{\n            rewardRecipient = static_cast<Poco::UInt64>(json->get(\"rewardRecipient\"));\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tlog_debug(MinerLogger::wallet, \"Could not get name of account!\");\n\treturn false;\n}\n\nbool Burst::Wallet::getLastBlock(Poco::UInt64& block) const\n{\n\tpoco_ndc(Wallet::getLastBlock);\n\tPoco::JSON::Object::Ptr json;\n\tblock = 0;\n\n\tif (!isActive())\n\t\treturn false;\n\n\tPoco::URI uri;\n\turi.setPath(\"/burst\");\n\turi.addQueryParameter(\"requestType\", \"getBlock\");\n\n\tif (sendWalletRequest(uri, json))\n\t{\n\t\tif (json->has(\"height\"))\n\t\t{\n            block = static_cast<Poco::UInt64>(json->get(\"height\"));\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tlog_debug(MinerLogger::wallet, \"Could not get last blockheight!\");\n\treturn false;\n}\n\nvoid Burst::Wallet::getAccount(AccountId id, Account& account) const\n{\n\t// TODO REWORK\n\t//if (!url_.empty())\n\t\t//account = {*this, id};\n}\n\nbool Burst::Wallet::getAccountBlocks(AccountId id, std::vector<Block>& blocks) const\n{\n\tPoco::JSON::Object::Ptr json;\n\tblocks.clear();\n\n\tif (!isActive())\n\t\treturn false;\n\n\tPoco::URI uri;\n\turi.setPath(\"/burst\");\n\turi.addQueryParameter(\"requestType\", \"getAccountBlockIds\");\n\turi.addQueryParameter(\"account\", std::to_string(id));\n\n\tif (sendWalletRequest(uri, json))\n\t{\n\t\tif (json->has(\"blockIds\"))\n\t\t{\n\t\t\tauto blockIds = json->getArray(\"blockIds\");\n\n\t\t\tfor (auto block : *blockIds)\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tblocks.emplace_back(block.convert<Poco::UInt64>());\n\t\t\t\t}\n\t\t\t\tcatch (...)\n\t\t\t\t{\n\t\t\t\t\tlog_debug(MinerLogger::wallet,\n\t\t\t\t\t\t\"Could not convert block-id to number!\\n\"\n\t\t\t\t\t\t\"\\tvalue: %s\", block.toString());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tlog_debug(MinerLogger::wallet, \"Could not get account blocks!\");\n\treturn false;\n}\n\nbool Burst::Wallet::isActive() const\n{\n\treturn !url_.empty();\n}\n\nbool Burst::Wallet::sendWalletRequest(const Poco::URI& uri, Poco::JSON::Object::Ptr& json) const\n{\n\tpoco_ndc(Wallet::sendWalletRequest);\n\n\tif (!isActive())\n\t\treturn false;\n\n\tHTTPRequest request{ HTTPRequest::HTTP_GET, uri.getPathAndQuery(), HTTPRequest::HTTP_1_1};\n\trequest.setKeepAlive(false);\n\t\t\n\tRequest req{ url_.createSession() };\n\tauto resp = req.send(request);\n\tstd::string data;\n\n\tfor (auto i = 0u; i < MinerConfig::getConfig().getWalletRequestTries(); ++i)\n\t{\n\t\tif (resp.receive(data))\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tPoco::JSON::Parser parser;\n\t\t\t\tjson = parser.parse(data).extract<Poco::JSON::Object::Ptr>();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcatch (Poco::Exception&)\n\t\t\t{\n\t\t\t\tlog_error(MinerLogger::wallet, \"Got invalid json response from wallet!\\n\\tURI: %s\", uri.getPathAndQuery());\n\t\t\t\tlog_file_only(MinerLogger::wallet, Poco::Message::PRIO_ERROR, TextType::Error, \"Got invalid json response from wallet!\\n%s\", data);\n\t\t\t\tlog_current_stackframe(MinerLogger::wallet);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tstd::this_thread::sleep_for(std::chrono::seconds(MinerConfig::getConfig().getWalletRequestRetryWaitTime()));\n\t}\n\n\tlog_error(MinerLogger::wallet, \"Got no response for wallet request '%s'\", uri.toString());\n\n\treturn false;\n}\n"
  },
  {
    "path": "src/wallet/Wallet.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <memory>\n#include <Poco/JSON/Object.h>\n#include \"Declarations.hpp\"\n#include \"network/Url.hpp\"\n\nnamespace Poco\n{\n\tclass URI;\n\n\tnamespace Net\n\t{\n\t\tclass HTTPClientSession;\n\t}\n}\n\nnamespace Burst\n{\n\tclass Account;\n\tclass Url;\n\n\tusing Block = Poco::UInt64;\n\n\tclass Wallet\n\t{\n\tpublic:\n\t\tWallet();\n\t\tWallet(const Url& url);\n\t\tWallet(const Wallet& rhs) = delete;\n\t\tWallet(Wallet&& rhs) = default;\n\t\t~Wallet();\n\n\t\tbool getWinnerOfBlock(Poco::UInt64 block, AccountId& winnerId) const;\n\t\tbool getNameOfAccount(AccountId account, std::string& name) const;\n\t\tbool getRewardRecipientOfAccount(AccountId account, AccountId& rewardRecipient) const;\n\t\tbool getLastBlock(Poco::UInt64& block) const;\n\t\tvoid getAccount(AccountId id, Account& account) const;\n\t\tbool getAccountBlocks(AccountId id, std::vector<Block>& blocks) const;\n\n\t\tbool isActive() const;\n\n\t\tWallet& operator=(const Wallet& rhs) = delete;\n\t\tWallet& operator=(Wallet&& rhs) = default;\n\n\tprivate:\n\t\tbool sendWalletRequest(const Poco::URI& uri, Poco::JSON::Object::Ptr& json) const;\n\t\tUrl url_;\n\t};\n}\n"
  },
  {
    "path": "src/webserver/MinerServer.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"MinerServer.hpp\"\n#include <memory>\n#include <Poco/Net/HTTPServer.h>\n#include \"MinerUtil.hpp\"\n#include <Poco/Net/HTTPServerRequest.h>\n#include <Poco/Net/HTTPRequestHandler.h>\n#include \"RequestHandler.hpp\"\n#include <Poco/JSON/Object.h>\n#include <Poco/File.h>\n#include \"logging/MinerLogger.hpp\"\n#include <Poco/URI.h>\n#include \"mining/Miner.hpp\"\n#include \"mining/MinerConfig.hpp\"\n#include <Poco/Path.h>\n#include <Poco/NestedDiagnosticContext.h>\n#include <Poco/String.h>\n#include <Poco/Delegate.h>\n#include <Poco/Exception.h>\n#include <Poco/Net/SecureServerSocket.h>\n\nusing namespace Poco;\nusing namespace Net;\n\nBurst::MinerServer::MinerServer(Miner& miner)\n\t: miner_{&miner},\n\t  minerData_(nullptr),\n\t  port_{0}\n{\n\tauto ip = MinerConfig::getConfig().getServerUrl().getCanonical();\n\tauto port = std::to_string(MinerConfig::getConfig().getServerUrl().getPort());\n\n\tvariables_.variables.emplace(std::make_pair(\"title\", []() { return Settings::project.nameAndVersion; }));\n\tvariables_.variables.emplace(std::make_pair(\"ip\", [ip]() { return ip; }));\n\tvariables_.variables.emplace(std::make_pair(\"port\", [port]() { return port; }));\n\tvariables_.variables.emplace(std::make_pair(\"nullDeadline\", []() { return deadlineFormat(0); }));\n}\n\nBurst::MinerServer::~MinerServer()\n{\n\tif (minerData_ != nullptr)\n\t\tminerData_->blockDataChangedEvent -= Poco::delegate(this, &MinerServer::onMinerDataChangeEvent);\n}\n\nvoid Burst::MinerServer::run(uint16_t port)\n{\n\tpoco_ndc(MinerServer::run);\n\t\n\tport_ = port;\n\n\tstd::unique_ptr<ServerSocket> socket;\n\n\tif (MinerConfig::getConfig().getServerCertificatePath().empty())\n\t\tsocket = std::make_unique<ServerSocket>();\n\telse\n\t\tsocket = std::make_unique<SecureServerSocket>();\n\n\ttry\n\t{\n\t\tsocket->bind(port_, true);\n\t\tsocket->listen();\n\t}\n\tcatch (Exception& exc)\n\t{\n\t\tlog_fatal(MinerLogger::server, \"Error while creating local http server on port %hu!\", port_);\n\t\tlog_exception(MinerLogger::server, exc);\n\t\treturn;\n\t}\n\n\tauto params = new HTTPServerParams;\n\n\tparams->setMaxQueued(MinerConfig::getConfig().getMaxConnectionsQueued());\n\tparams->setMaxThreads(MinerConfig::getConfig().getMaxConnectionsActive());\n\tparams->setServerName(Settings::project.name);\n\tparams->setSoftwareVersion(Settings::project.nameAndVersion);\n\n\tthreadPool_.addCapacity(MinerConfig::getConfig().getMaxConnectionsActive());\n\n\tif (server_ != nullptr)\n\t\tserver_->stopAll(true);\n\n\tserver_ = std::make_unique<HTTPServer>(new RequestFactory{*this}, threadPool_, *socket, params);\n\n\tif (server_ != nullptr)\n\t{\n\t\ttry\n\t\t{\n\t\t\tserver_->start();\n\t\t}\n\t\tcatch (Poco::Exception& exc)\n\t\t{\n\t\t\tlog_fatal(MinerLogger::server, \"Could not start local server: %s\", exc.displayText());\n\t\t\tlog_current_stackframe(MinerLogger::server);\n\t\t}\n\t}\n}\n\nvoid Burst::MinerServer::stop()\n{\n\tpoco_ndc(MinerServer::stop);\n\t\n\tif (server_ != nullptr)\n\t{\n\t\tserver_->stopAll(true);\n\t\tthreadPool_.stopAll();\n\t}\n}\n\nvoid Burst::MinerServer::connectToMinerData(MinerData& minerData)\n{\n\tpoco_ndc(MinerServer::connectToMinerData);\n\n\ttry\n\t{\n\t\tminerData_ = &minerData;\n\t\tminerData_->blockDataChangedEvent += delegate(this, &MinerServer::onMinerDataChangeEvent);\n\t}\n\tcatch (const Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not connect to the block data change event: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::MinerServer::sendToWebsockets(std::string& data)\n{\n\tpoco_ndc(MinerServer::sendToWebsockets);\n\tScopedLock<Mutex> lock{mutex_};\n\ttry\n\t{\n\t\tnewDataEvent(this, data);\n\t}\n\tcatch (const Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not set to websockets: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::MinerServer::sendToWebsockets(const JSON::Object& json)\n{\n\tpoco_ndc(MinerServer::sendToWebsockets);\n\n\ttry\n\t{\n\t\tstd::stringstream sstream;\n\t\tjson.stringify(sstream);\n\t\tauto jsonString = sstream.str();\n\t\tsendToWebsockets(jsonString);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not set to websockets: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::MinerServer::onMinerDataChangeEvent(const void* sender, const Poco::JSON::Object& data)\n{\n\tpoco_ndc(MinerServer::onMinerDataChangeEvent);\n\n\ttry\n\t{\n\t\tauto send = true;\n\n\t\t// pre-filter progress\n\t\tif (data.has(\"type\") &&\n\t\t\tdata.get(\"type\") == \"progress\")\n\t\t{\n\t\t\tconst auto progressRead = data.get(\"value\").extract<float>();\n\t\t\tconst auto progressVerification = data.get(\"valueVerification\").extract<float>();\n\n\t\t\tsend = static_cast<int>(progressRead) != static_cast<int>(progressRead_) ||\n\t\t\t\tstatic_cast<int>(progressVerification) != static_cast<int>(progressVerification_);\n\t\t\t\n\t\t\tprogressRead_ = progressRead;\n\t\t\tprogressVerification_ = progressVerification;\n\t\t}\n\n\t\tif (send)\n\t\t\tsendToWebsockets(data);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not change the progress: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nBurst::MinerServer::RequestFactory::RequestFactory(MinerServer& server)\n\t: server_{&server}\n{}\n\nHTTPRequestHandler* Burst::MinerServer::RequestFactory::createRequestHandler(const HTTPServerRequest& request)\n{\n\tusing RequestHandler::LambdaRequestHandler;\n\tusing ReqT = HTTPServerRequest;\n\tusing ResT = HTTPServerResponse;\n\n\tpoco_ndc(MinerServer::RequestFactory::createRequestHandler);\n\n\tif (request.find(\"Upgrade\") != request.end() && icompare(request[\"Upgrade\"], \"websocket\") == 0)\n\t\treturn new RequestHandler::WebsocketRequestHandler(*server_, *server_->minerData_);\n\n\tconst auto demoMiner = MinerConfig::getConfig().getWorkerName() == \"demo\";\n\n\t//std::stringstream sstream;\n\t//sstream << \"Request: \" << request.getURI() << std::endl;\n\t//sstream << \"Ip: \" << request.clientAddress().toString() << std::endl;\n\t//sstream << \"Method: \" << request.getMethod() << std::endl;\n\t//\n\t//for (const auto& header : request)\n\t//\tsstream << header.first << ':' << header.second << std::endl;\n\n\t//log_debug(MinerLogger::server, \"Request: %s\", request.getURI());\n\t//log_file_only(MinerLogger::server, Poco::Message::PRIO_INFORMATION, TextType::Information, sstream.str());\n\n\ttry\n\t{\n\t\tusing namespace Net;\n\n\t\tURI uri{request.getURI()};\n\t\tstd::vector<std::string> pathSegments;\n\n\t\turi.getPathSegments(pathSegments);\n\n\t\t// root\n\t\tif (pathSegments.empty())\n\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t{\n\t\t\t\tauto variables = server_->variables_ + TemplateVariables({\n\t\t\t\t\t{\"includes\", []() { return std::string(\"<script src='js/block.js'></script>\"); }}\n\t\t\t\t});\n\t\t\t\tRequestHandler::loadSecuredTemplate(req, res, \"index.html\", \"block.html\", variables);\n\t\t\t});\n\n\t\t// plotfiles\n\t\tif (pathSegments.front() == \"plotfiles\")\n\t\t{\n\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t{\n\t\t\t\tauto variables = server_->variables_ + TemplateVariables({\n\t\t\t\t\t{\n\t\t\t\t\t\t\"includes\", []()\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto jsonPlotDirs = createJsonPlotDirs();\n\n\t\t\t\t\t\t\tstd::stringstream sstr;\n\t\t\t\t\t\t\tjsonPlotDirs.stringify(sstr);\n\n\t\t\t\t\t\t\tstd::stringstream sstrContent;\n\t\t\t\t\t\t\tsstrContent << \"<script src='js/plotfiles.js'></script>\";\n\t\t\t\t\t\t\tsstrContent << std::endl;\n\t\t\t\t\t\t\tsstrContent << \"<script>var plotdirs = \" << sstr.str() << \";</script>\";\n\t\t\t\t\t\t\treturn sstrContent.str();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tRequestHandler::loadSecuredTemplate(req, res, \"index.html\", \"plotfiles.html\", variables);\n\t\t\t});\n\t\t}\n\n\t\t// shutdown everything\n\t\t//if (path_segments.front() == \"shutdown\")\n\t\t//\treturn new LambdaRequestHandler([&](req_t& req, res_t& res)\n\t\t//\t{\n\t\t//\t\tRequestHandler::shutdown(req, res, *server_->miner_, *server_);\n\t\t//\t});\n\n\t\t// restart\n\t\tif (pathSegments.front() == \"restart\" && !demoMiner)\n\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t{\n\t\t\t\tRequestHandler::restart(req, res, *server_->miner_, *server_);\n\t\t\t});\n\n\t\t// rescan plot files\n\t\tif (pathSegments.front() == \"rescanPlotfiles\" && !demoMiner)\n\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t{\n\t\t\t\tRequestHandler::rescanPlotfiles(req, res, *server_->miner_);\n\t\t\t});\n\n\t\t// show/change settings\n\t\tif (pathSegments.front() == \"settings\")\n\t\t{\n\t\t\t// no body -> show\n\t\t\tif (pathSegments.size() == 1)\n\t\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t\t{\n\t\t\t\t\tauto variables = server_->variables_ + TemplateVariables({\n\t\t\t\t\t\t{\"includes\", []() { return std::string(\"<script src='js/settings.js'></script>\"); }}\n\t\t\t\t\t});\n\t\t\t\t\tRequestHandler::loadSecuredTemplate(req, res, \"index.html\", \"settings.html\", variables);\n\t\t\t\t});\n\n\t\t\t// with body -> change\n\t\t\tif (pathSegments.size() > 1 && !demoMiner)\n\t\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t\t{\n\t\t\t\t\tRequestHandler::changeSettings(req, res, *server_->miner_);\n\t\t\t\t});\n\t\t}\n\n\t\t// check plot file\n\t\tif (pathSegments.front() == \"checkPlotFile\" && !demoMiner)\n\t\t\tif (pathSegments.size() > 1)\n\t\t\t{\n\t\t\t\tif (pathSegments[1] == \"all\")\n\t\t\t\t{\n\t\t\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t\t\t{\n\t\t\t\t\t\tRequestHandler::checkAllPlotfiles(req, res, *server_->miner_, *server_);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tusing Poco::replace;\n\t\t\t\tstd::string plotPath;\n\t\t\t\tURI::decode(replace(request.getURI(), \"/\" + pathSegments[0] + \"/\", plotPath), plotPath, false);\n\t\t\t\treturn new LambdaRequestHandler([&, pPath = move(plotPath)](ReqT& req, ResT& res)\n\t\t\t\t{\n\t\t\t\t\tRequestHandler::checkPlotfile(req, res, *server_->miner_, *server_, pPath);\n\t\t\t\t});\n\t\t\t}\n\n\n\t\t// show/change plot files\n\t\tif (pathSegments.front() == \"plotdir\" && !demoMiner)\n\t\t\tif (pathSegments.size() > 1)\n\t\t\t\treturn new LambdaRequestHandler([&, remove = pathSegments[1] == \"remove\"](ReqT& req, ResT& res)\n\t\t\t\t{\n\t\t\t\t\tRequestHandler::changePlotDirs(req, res, *server_, remove);\n\t\t\t\t});\n\n\t\tif (pathSegments.front() == \"login\")\n\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t{\n\t\t\t\tif (req.getMethod() == \"POST\")\n\t\t\t\t{\n\t\t\t\t\tif (RequestHandler::checkCredentials(req, res))\n\t\t\t\t\t\treturn RequestHandler::redirect(req, res, \"/\");\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tauto variables = server_->variables_ + TemplateVariables({{\"includes\", []() { return std::string(); }}});\n\t\t\t\t\tRequestHandler::loadTemplate(req, res, \"index.html\", \"login.html\", variables);\n\t\t\t\t}\n\t\t\t});\n\n\t\tif (pathSegments.front() == \"logout\")\n\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res) { RequestHandler::logout(req, res); });\n\n\t\t// forward function\n\t\tif (pathSegments.front() == \"burst\")\n\t\t{\n\t\t\tstatic const std::string getMiningInfo = \"requestType=getMiningInfo\";\n\t\t\tstatic const std::string submitNonce = \"requestType=submitNonce\";\n\n\t\t\t// send back local mining infos\n\t\t\tif (uri.getQuery().compare(0, getMiningInfo.size(), getMiningInfo) == 0)\n\t\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t\t{\n\t\t\t\t\tRequestHandler::miningInfo(req, res, *server_->miner_);\n\t\t\t\t});\n\n\t\t\t// forward nonce with combined capacity\n\t\t\tif (uri.getQuery().compare(0, submitNonce.size(), submitNonce) == 0)\n\t\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t\t{\n\t\t\t\t\tRequestHandler::submitNonce(req, res, *server_, *server_->miner_);\n\t\t\t\t});\n\n\t\t\t// just forward whatever the request is to the wallet\n\t\t\t// why wallet? because the only requests to a pool are getMiningInfo and submitNonce and we handled them already\n\t\t\treturn new LambdaRequestHandler([&](ReqT& req, ResT& res)\n\t\t\t{\n\t\t\t\tRequestHandler::forward(req, res, HostType::Wallet);\n\t\t\t});\n\t\t}\n\n\t\tPath path{\"public\"};\n\t\tpath.append(uri.getPath());\n\n\t\tif (File{path}.exists())\n\t\t\treturn new LambdaRequestHandler(RequestHandler::loadAsset);\n\n\t\treturn new LambdaRequestHandler(RequestHandler::notFound);\n\t}\n\tcatch (...)\n\t{\n\t\treturn new LambdaRequestHandler(RequestHandler::badRequest);\n\t}\n}\n"
  },
  {
    "path": "src/webserver/MinerServer.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <memory>\n#include <Poco/Net/HTTPRequestHandlerFactory.h>\n#include \"RequestHandler.hpp\"\n\nnamespace Poco\n{\n\tclass Notification;\n\n\tnamespace Net\n\t{\n\t\tclass HTTPServer;\n\t\tclass WebSocket;\n\t}\n\n\tnamespace JSON\n\t{\n\t\tclass Object;\n\t}\n}\n\nnamespace Burst\n{\n\tclass Miner;\n\tstruct BlockDataChangedNotification;\n\tclass MinerData;\n\n\tclass MinerServer\n\t{\n\tpublic:\n\t\texplicit MinerServer(Miner& miner);\n\t\t~MinerServer();\n\t\t\n\t\tvoid run(uint16_t port = 9999);\n\t\tvoid stop();\n\t\t\n\t\tvoid connectToMinerData(MinerData& minerData);\n\t\tvoid sendToWebsockets(std::string& data);\n\t\tvoid sendToWebsockets(const Poco::JSON::Object& json);\n\n\t\tPoco::BasicEvent<std::string> newDataEvent;\n\n\tprivate:\n\t\tvoid onMinerDataChangeEvent(const void* sender, const Poco::JSON::Object& data);\n\n\t\tMiner* miner_;\n\t\tMinerData* minerData_;\n\t\tuint16_t port_;\n\t\tstd::unique_ptr<Poco::Net::HTTPServer> server_;\n\t\tPoco::Mutex mutex_;\n\t\tTemplateVariables variables_;\n\t\tPoco::ThreadPool threadPool_;\n\t\tfloat progressRead_ = 0.f, progressVerification_ = 0.f;\n\n\t\tstruct RequestFactory : Poco::Net::HTTPRequestHandlerFactory\n\t\t{\n\t\t\texplicit RequestFactory(MinerServer& server);\n\n\t\t\tMinerServer* server_;\n\t\t\tPoco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request) override;\n\t\t};\n\t};\n}\n"
  },
  {
    "path": "src/webserver/RequestHandler.cpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#include \"RequestHandler.hpp\"\n#include <Poco/Net/WebSocket.h>\n#include <Poco/Net/HTTPResponse.h>\n#include <Poco/Net/HTTPServerRequest.h>\n#include <Poco/Net/HTTPServerResponse.h>\n#include <Poco/FileStream.h>\n#include \"logging/MinerLogger.hpp\"\n#include \"MinerUtil.hpp\"\n#include <Poco/JSON/Object.h>\n#include \"MinerServer.hpp\"\n#include \"mining/Miner.hpp\"\n#include <Poco/NestedDiagnosticContext.h>\n#include \"network/Request.hpp\"\n#include \"mining/MinerConfig.hpp\"\n#include \"plots/PlotSizes.hpp\"\n#include <Poco/Logger.h>\n#include <Poco/Base64Decoder.h>\n#include <Poco/StreamCopier.h>\n#include <Poco/StringTokenizer.h>\n#include <Poco/Net/HTMLForm.h>\n#include \"plots/PlotGenerator.hpp\"\n#include <regex>\n#include <utility>\n#include <Poco/Net/NetException.h>\n#include <Poco/Delegate.h>\n#include \"plots/Plot.hpp\"\n#include <Poco/Net/HTTPRequest.h>\n\nconst std::string cookieUserName = \"creepminer-webserver-user\";\nconst std::string cookiePassName = \"creepminer-webserver-pass\";\n\nBurst::TemplateVariables::TemplateVariables(std::unordered_map<std::string, Variable> variables)\n\t: variables(std::move(variables))\n{}\n\nvoid Burst::TemplateVariables::inject(std::string& source) const\n{\n\tfor (const auto& var : variables)\n\t\tPoco::replaceInPlace(source, \"%\" + var.first + \"%\", var.second());\n}\n\nBurst::TemplateVariables Burst::TemplateVariables::operator+(const TemplateVariables& rhs)\n{\n\tTemplateVariables combined(rhs.variables);\n\tcombined.variables.insert(variables.begin(), variables.end());\n\treturn combined;\n}\n\nBurst::RequestHandler::LambdaRequestHandler::LambdaRequestHandler(Lambda lambda)\n\t: lambda_(std::move(lambda))\n{}\n\nvoid Burst::RequestHandler::LambdaRequestHandler::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)\n{\n\tpoco_ndc(LambdaRequestHandler::handleRequest);\n\n\ttry\n\t{\n\t\tlambda_(request, response);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not execute lambda: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nBurst::RequestHandler::WebsocketRequestHandler::WebsocketRequestHandler(MinerServer& server, MinerData& data)\n\t: server_{server}, data_{data}\n{\n\tpoco_ndc(WebsocketRequestHandler::WebSocketRequestHandler);\n\n\ttry\n\t{\n\t\tserver_.newDataEvent += Poco::delegate(this, &WebsocketRequestHandler::onNewData);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not connect to server_.newDataEvent: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nBurst::RequestHandler::WebsocketRequestHandler::~WebsocketRequestHandler()\n{\n\tpoco_ndc(WebsocketRequestHandler::~WebsocketRequestHandler);\n\n\ttry\n\t{\n\t\tserver_.newDataEvent -= Poco::delegate(this, &WebsocketRequestHandler::onNewData);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not disconnect to server_.newDataEvent: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::RequestHandler::WebsocketRequestHandler::handleRequest(Poco::Net::HTTPServerRequest& request,\n\tPoco::Net::HTTPServerResponse& response)\n{\n\tusing namespace Poco;\n\tusing namespace Net;\n\n\ttry\n\t{\n\t\tWebSocket ws(request, response);\n\n\t\ttry\n\t\t{\n\t\t\t// send the config\n\t\t\tstd::stringstream sstream;\n\t\t\tcreateJsonConfig().stringify(sstream);\n\t\t\tconst auto configString = sstream.str();\n\t\t\tws.sendFrame(configString.data(), static_cast<int>(configString.size()));\n\n\t\t\t// send the plot dir data\n\t\t\tsstream.str(\"\");\n\t\t\tcreateJsonPlotDirsRescan().stringify(sstream);\n\t\t\tconst auto plotDirString = sstream.str();\n\t\t\tws.sendFrame(plotDirString.data(), static_cast<int>(plotDirString.size()));\n\n\t\t\tdata_.getBlockData()->forEntries([&](const JSON::Object& json)\n\t\t\t{\n\t\t\t\tsstream.str(\"\");\n\t\t\t\tJSON::Stringifier::condense(json, sstream);\n\t\t\t\tconst auto jsonString = sstream.str();\n\t\t\t\tws.sendFrame(jsonString.data(), static_cast<int>(jsonString.size()));\n\t\t\t\treturn true;\n\t\t\t});\n\t\t}\n\t\tcatch (Exception& exc)\n\t\t{\n\t\t\tlog_exception(MinerLogger::server, exc);\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tchar buffer[1024];\n\t\tint flags = 0;\n\t\tauto close = false;\n\t\tws.setReceiveTimeout(Timespan{1, 0}); // 1 s\n\t\tconst auto sleepTime = std::chrono::milliseconds{10};\n\n\t\tconst auto send = [&]()\n\t\t{\n\t\t\tif (!close)\n\t\t\t{\n\t\t\t\tstd::lock_guard<std::mutex> lock(mutex_);\n\t\t\t\tif (!queue_.empty())\n\t\t\t\t{\n\t\t\t\t\tauto data = queue_.front();\n\t\t\t\t\tqueue_.pop_front();\n\t\t\t\t\tconst auto s = ws.sendFrame(data.data(), static_cast<int>(data.size()));\n\t\t\t\t\tif (s != static_cast<int>(data.size()))\n\t\t\t\t\t\tlog_warning(MinerLogger::server, \"Could not fully send: %s\", data);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tdo\n\t\t{\n\t\t\tif (ws.available() == 0)\n\t\t\t{\n\t\t\t\tsend();\n\t\t\t\tstd::this_thread::sleep_for(sleepTime);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\ttry\n\t\t\t{\n\t\t\t\tclose = ws.receiveFrame(buffer, sizeof buffer, flags) == 0;\n\t\t\t}\n\t\t\tcatch (TimeoutException&)\n\t\t\t{\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t\tcatch (Exception& exc)\n\t\t\t{\n\t\t\t\tlog_exception(MinerLogger::server, exc);\n\t\t\t\tclose = true;\n\t\t\t}\n\n\t\t\tsend();\n\t\t}\n\t\twhile (!close && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);\n\t\tws.shutdown();\n\t}\n\tcatch (WebSocketException& exc)\n\t{\n\t\tlog_exception(MinerLogger::server, exc);\n\t}\n}\n\nvoid Burst::RequestHandler::WebsocketRequestHandler::onNewData(std::string& data)\n{\n\tstd::lock_guard<std::mutex> lock(mutex_);\n\n\tpoco_ndc(WebsocketRequestHandler::onNewData);\n\n\ttry\n\t{\n\t\tqueue_.emplace_back(data);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not enqueue new data for websockets: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::RequestHandler::loadTemplate(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\tconst std::string& templatePage, const std::string& contentPage, TemplateVariables& variables)\n{\n\tPoco::FileInputStream fileIndex, fileContent;\n\tstd::string output;\n\n\t// open the index page \n\ttry\n\t{\n\t\t// open the template file \n\t\tfileIndex.open(\"public/\" + templatePage, std::ios::in);\n\t\t// read the content of the file and load it into a string \n\t\toutput = std::string{ std::istreambuf_iterator<char>{fileIndex},{} };\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not open public/index.html!\");\n\t\tlog_exception(MinerLogger::server, exc);\n\n\t\tif (fileIndex)\n\t\t\tfileIndex.close();\n\n\t\treturn notFound(request, response);\n\t}\n\n\t// open the embedded page \n\ttry\n\t{\n\t\t// load it into a string \n\t\tfileContent.open(\"public/\" + contentPage, std::ios::in);\n\t\tstd::string strContent(std::istreambuf_iterator<char>{fileContent}, {});\n\n\t\t// replace variables inside it \n\t\tTemplateVariables contentFramework;\n\t\tcontentFramework.variables.emplace(\"content\", [&strContent]() { return strContent; });\n\n\t\tcontentFramework.inject(output);\n\t\tvariables.inject(output);\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not open 'public/%s'!\", contentPage);\n\t\tlog_exception(MinerLogger::server, exc);\n\n\t\tif (fileContent)\n\t\t\tfileContent.close();\n\n\t\treturn notFound(request, response);\n\t}\n\n\t// not necessary, but good style \n\tfileIndex.close();\n\tfileContent.close();\n\n\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\tresponse.setChunkedTransferEncoding(true);\n\t\n\tauto& responseStream = response.send();\n\tresponseStream << output << std::flush;\n}\n\nvoid Burst::RequestHandler::loadSecuredTemplate(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\tconst std::string& templatePage, const std::string& contentPage, TemplateVariables& variables)\n{\n\tif (!checkCredentials(request, response))\n\t\treturn;\n\n\tloadTemplate(request, response, templatePage, contentPage, variables);\n}\n\nbool Burst::RequestHandler::loadAssetByPath(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response, const std::string& path)\n{\n\ttry\n\t{\n\t\tPoco::Path pathObject{ \"public/\" + path };\n\t\tPoco::FileInputStream file{ pathObject.toString(), std::ios::in };\n\t\tconst std::string str(std::istreambuf_iterator<char>{file}, {});\n\n\t\tstd::string mimeType = \"text/plain\";\n\n\t\tconst auto ext = pathObject.getExtension();\n\n\t\tif (ext == \"css\")\n\t\t\tmimeType = \"text/css\";\n\t\telse if (ext == \"js\")\n\t\t\tmimeType = \"text/javascript\";\n\t\telse if (ext == \"png\")\n\t\t\tmimeType = \"image/png\";\n\t\t//else if (ext == \"html\")\n\t\t//\tmimeType = \"text/html; charset=utf-8\";\n\n\t\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\t\tresponse.setChunkedTransferEncoding(true);\n\t\tresponse.setContentType(mimeType);\n\t\tauto& out = response.send();\n\n\t\tout << str;\n\t\treturn true;\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_error(MinerLogger::server, \"Webserver could not open 'public/%s'!\", request.getURI());\n\t\tlog_exception(MinerLogger::server, exc);\n\t\treturn false;\n\t}\n}\n\nbool Burst::RequestHandler::loadAsset(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)\n{\n\treturn loadAssetByPath(request, response, request.getURI());\n}\n\nnamespace Burst\n{\n\tvoid clearAuthCookies(Poco::Net::HTTPServerResponse& response)\n\t{\n\t\tPoco::Net::HTTPCookie cookieUser(cookieUserName);\n\t\tPoco::Net::HTTPCookie cookiePass(cookiePassName);\n\n\t\tcookieUser.setMaxAge(0);\n\t\tcookiePass.setMaxAge(0);\n\n\t\tresponse.addCookie(cookieUser);\n\t\tresponse.addCookie(cookiePass);\n\t}\n}\n\nbool Burst::RequestHandler::login(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)\n{\n\tPoco::Net::HTMLForm postBody(request, request.stream());\n\n\tpoco_ndc(RequestHandler::login);\n\n\ttry\n\t{\n\t\tconst std::string defaultCredential;\n\t\tconst auto& plainUserPost = postBody.get(cookieUserName, defaultCredential);\n\t\tconst auto& plainPassPost = postBody.get(cookiePassName, defaultCredential);\n\t\t\n\t\tconst auto credentialsOk =\n\t\t\tMinerConfig::getConfig().getServerUser().check(plainUserPost) &&\n\t\t\tMinerConfig::getConfig().getServerPass().check(plainPassPost);\n\n\t\t// save the hashed username and password in a clientside cookie\n\t\tif (credentialsOk)\n\t\t{\n\t\t\tresponse.addCookie({ cookieUserName, MinerConfig::getConfig().getServerUser().encrypted });\n\t\t\tresponse.addCookie({ cookiePassName, MinerConfig::getConfig().getServerPass().encrypted });\n\t\t}\n\n\t\treturn credentialsOk;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not login: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t\treturn false;\n\t}\n}\n\nvoid Burst::RequestHandler::logout(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)\n{\n\tclearAuthCookies(response);\n\tredirect(request, response, \"/\");\n}\n\nbool Burst::RequestHandler::isLoggedIn(Poco::Net::HTTPServerRequest& request)\n{\n\tauto credentialsOk = false;\n\n\t// if there are no credentials in the config, user dont need to\n\t// enter them\n\tif (MinerConfig::getConfig().getServerUser().empty() &&\n\t\tMinerConfig::getConfig().getServerPass().empty())\n\t\treturn true;\n\n\t// the user is already logged in\n\t// the credentials are in the cookie\n\tPoco::Net::NameValueCollection cookies;\n\trequest.getCookies(cookies);\n\t//\n\tconst std::string emptyValue;\n\n\tauto hashedUserCookie = cookies.get(cookieUserName, emptyValue);\n\tauto hashedPassCookie = cookies.get(cookiePassName, emptyValue);\n\n\tif (!hashedUserCookie.empty() || !hashedPassCookie.empty())\n\t\tcredentialsOk =\n\t\t\thashedUserCookie == MinerConfig::getConfig().getServerUser().encrypted &&\n\t\t\thashedPassCookie == MinerConfig::getConfig().getServerPass().encrypted;\n\t\n\treturn credentialsOk;\n}\n\nvoid Burst::RequestHandler::redirect(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\tconst std::string& redirectUri)\n{\n\tresponse.redirect(redirectUri);\n}\n\nvoid Burst::RequestHandler::forward(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response, HostType hostType)\n{\n\tauto forward = MinerConfig::getConfig().isForwardingEverything();\n\n\tif (!forward)\n\t{\n\t\tconst Poco::URI uri(request.getURI());\n\t\tconst auto pathAndQuery = uri.getPathAndQuery();\n\n\t\tconst auto& whitelist = MinerConfig::getConfig().getForwardingWhitelist();\n\n\t\tfor (auto i = whitelist.begin(); i != whitelist.end() && !forward; ++i)\n\t\t\tforward = regex_match(pathAndQuery, std::regex(*i));\n\n\t\tif (!forward)\n\t\t{\n\t\t\tlog_information(MinerLogger::server, \"Filtered bad request: %s\", pathAndQuery);\n\t\t\treturn RequestHandler::badRequest(request, response);\n\t\t}\n\t}\n\n\tauto session = MinerConfig::getConfig().createSession(hostType);\n\n\tif (session == nullptr)\n\t\treturn;\n\n\tlog_information(MinerLogger::server, \"Forwarding request:\\n\\t%s\", request.getURI());\n\n\ttry\n\t{\n\t\t// HTTPRequest has a private copy constructor, so we need to copy\n\t\t// all fields one by one\n\t\tPoco::Net::HTTPRequest forwardingRequest;\n\t\tforwardingRequest.setURI(request.getURI());\n\t\tforwardingRequest.setMethod(request.getMethod());\n\t\tforwardingRequest.setContentLength(request.getContentLength());\n\t\tforwardingRequest.setTransferEncoding(request.getTransferEncoding());\n\t\tforwardingRequest.setChunkedTransferEncoding(request.getChunkedTransferEncoding());\n\t\tforwardingRequest.setKeepAlive(request.getKeepAlive());\n\t\tforwardingRequest.setVersion(request.getVersion());\n\n\t\tRequest forwardRequest{ std::move(session) };\n\t\tauto forwardResponse = forwardRequest.send(forwardingRequest);\n\n\t\tlog_debug(MinerLogger::server, \"Request forwarded, waiting for response...\");\n\n\t\tstd::string data;\n\n\t\tif (forwardResponse.receive(data))\n\t\t{\n\t\t\tlog_debug(MinerLogger::server, \"Got response, sending back...\\n\\t%s\", data);\n\n\t\t\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\t\t\tresponse.setContentLength(data.size());\n\n\t\t\tauto& responseStream = response.send();\n\t\t\tresponseStream << data;\n\t\t}\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not forward request to wallet!\\n%s\\n%s\", exc.displayText(), request.getURI());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::RequestHandler::badRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)\n{\n\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);\n\tresponse.send();\n}\n\nvoid Burst::RequestHandler::rescanPlotfiles(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\tMiner& miner)\n{\n\t// first check the credentials\n\tif (!checkCredentials(request, response))\n\t\treturn;\n\n\tlog_information(MinerLogger::server, \"Got request for rescanning the plotdirs...\");\n\n\tminer.rescanPlotfiles();\n\n\t// respond to the sender\n\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\tresponse.setContentLength(0);\n\tresponse.send();\n}\n\nvoid Burst::RequestHandler::checkPlotfile(Poco::Net::HTTPServerRequest& request,\n                                          Poco::Net::HTTPServerResponse& response, Miner& miner, MinerServer& server,\n                                          const std::string& plotPath)\n{\n\tpoco_ndc(RequestHandler::checkPlotfile);\n\n\t// first check the credentials\n\tif (!checkCredentials(request, response))\n\t\treturn;\n\n\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\tresponse.setContentLength(0);\n\tresponse.send();\n\n\tlog_information(MinerLogger::server, \"Got request to check a file for corruption...\");\n\n\ttry\n\t{\n\t\tPlotGenerator::checkPlotfileIntegrity(plotPath, miner, server);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not check plotfile integrity: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::RequestHandler::checkAllPlotfiles(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response, Miner& miner, MinerServer& server)\n{\n\t// first check the credentials\n\tif (!checkCredentials(request, response))\n\t\treturn;\n\n\tpoco_ndc(RequestHandler::checkAllPlotfiles);\n\n\ttry\n\t{\n\t\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\t\tresponse.setContentLength(0);\n\t\tresponse.send();\n\n\t\tlog_information(MinerLogger::server, \"Got request to check all files for corruption...\");\n\n\t\tconst auto plotFiles = MinerConfig::getConfig().getPlotFiles();\n\t\tauto totalSize = 0ull;\n\t\tauto totalWeightedIntegrity = 0.0;\n\n\t\tfor (const auto& plotFile : plotFiles)\n\t\t{\n\t\t\tconst auto& plotPath = plotFile->getPath();\n\t\t\tconst auto integrity = PlotGenerator::checkPlotfileIntegrity(plotPath, miner, server);\n\t\t\ttotalWeightedIntegrity += integrity * plotFile->getSize();\n\t\t\ttotalSize += plotFile->getSize();\n\t\t}\n\n\t\tdouble plotIntegrity;\n\n\t\tif (totalSize == 0 || totalWeightedIntegrity == 0)\n\t\t\tplotIntegrity = 100;\n\t\telse\n\t\t\tplotIntegrity = totalWeightedIntegrity / totalSize;\n\n\t\tlog_information(MinerLogger::general, \"Overall miner plot integrity: %.2f%%\", plotIntegrity);\n\n\t\t//response\n\t\tPoco::JSON::Object json;\n\t\tjson.set(\"type\", \"totalPlotcheck-result\");\n\t\tjson.set(\"totalPlotIntegrity\", std::to_string(plotIntegrity));\n\n\t\tserver.sendToWebsockets(json);\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not check all plotfiles integrity: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nbool Burst::RequestHandler::checkCredentials(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)\n{\n\tauto credentialsOk = isLoggedIn(request);\n\n\t// the user is not logged in yet, but wants to\n\tif (!credentialsOk && request.getMethod() == \"POST\")\n\t{\n\t\tcredentialsOk = login(request, response);\n\n\t\tif (!credentialsOk)\n\t\t\tlog_information(MinerLogger::server, \"%s webserver request.\\n\"\n\t\t\t\t\"\\trequest: %s\\n\"\n\t\t\t\t\"\\tfrom: %s\",\n\t\t\t\tcredentialsOk ? std::string(\"Authorized\") : std::string(\"Unauthorized\"),\n\t\t\t\trequest.getURI(),\n\t\t\t\trequest.clientAddress().toString());\n\t}\n\n\t// not authenticated, request again\n\tif (!credentialsOk)\n\t{\n\t\tredirect(request, response, \"/login\");\n\t\treturn false;\n\t}\n\n\t// authenticated\n\treturn true;\n}\n\nvoid Burst::RequestHandler::shutdown(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response, Miner& miner, MinerServer& server)\n{\n\tpoco_ndc(\"RequestHandler::shutdown\");\n\n\tif (!checkCredentials(request, response))\n\t\treturn;\n\n\tlog_system(MinerLogger::server, \"Shutting down miner...\");\n\n\t// first we shut down the miner\n\tminer.stop();\n\n\t// then we send a response to the client\n\tstd::stringstream ss;\n\tcreateJsonShutdown().stringify(ss);\n\tauto str = ss.str();\n\n\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\tresponse.setContentLength(str.size());\n\tauto& output = response.send();\n\n\toutput << ss.str();\n\toutput.flush();\n\n\t// finally we shut down the server\n\tserver.stop();\n\n\tlog_system(MinerLogger::server, \"Goodbye\");\n}\n\nvoid Burst::RequestHandler::restart(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\tMiner& miner, MinerServer& server)\n{\n\tpoco_ndc(\"RequestHandler::restart\");\n\n\tif (!checkCredentials(request, response))\n\t\treturn;\n\n\tminer.restart();\n\n\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\tresponse.setContentLength(0);\n\tresponse.send();\n}\n\nvoid Burst::RequestHandler::submitNonce(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response, MinerServer& server, Miner& miner)\n{\n\tpoco_ndc(SubmitNonceHandler::handleRequest);\n\n\ttry\n\t{\n\t\tauto miningInfoOk = false;\n\n\t\twhile (!miningInfoOk)\n\t\t{\n\t\t\tif (miner.hasBlockData())\n\t\t\t\tminingInfoOk = true;\n\t\t\telse\n\t\t\t\tstd::this_thread::sleep_for(std::chrono::milliseconds(10));\n\t\t}\n\n\t\tPoco::URI uri{request.getURI()};\n\t\tPoco::UInt64 capacity = 0;\n\t\tPoco::UInt64 accountId = 0;\n\t\tPoco::UInt64 nonce = 0;\n\t\tPoco::UInt64 deadlineValue = 0;\n\t\tstd::string plotfile;\n\t\tPoco::UInt64 blockheight = 0;\n\t\tstd::string minerName;\n\n\t\tfor (const auto& param : uri.getQueryParameters())\n\t\t{\n\t\t\tif (param.first == \"accountId\")\n\t\t\t\taccountId = Poco::NumberParser::parseUnsigned64(param.second);\n\t\t\telse if (param.first == \"nonce\")\n\t\t\t\tnonce = Poco::NumberParser::parseUnsigned64(param.second);\n\t\t\telse if (param.first == \"blockheight\")\n\t\t\t\tblockheight = Poco::NumberParser::parseUnsigned64(param.second);\n\t\t\telse if (param.first == \"deadline\")\n\t\t\t\tdeadlineValue = Poco::NumberParser::parseUnsigned64(param.second) / miner.getBaseTarget();\n\t\t}\n\n\t\tif (request.has(xCapacity))\n\t\t\tcapacity = Poco::NumberParser::parseUnsigned64(request.get(xCapacity));\n\n\t\tif (request.has(xPlotfile))\n\t\t{\n\t\t\tconst auto& plotfileEncoded = request.get(xPlotfile);\n\t\t\tPoco::URI::decode(plotfileEncoded, plotfile);\n\t\t}\n\t\t\n\t\tif (request.has(xDeadline))\n\t\t\tdeadlineValue = Poco::NumberParser::parseUnsigned64(request.get(xDeadline));\n\n\t\tconst auto workerName = request.get(xWorker, \"\");\n\n\t\tauto account = miner.getAccount(accountId);\n\n\t\tif (account == nullptr)\n\t\t\taccount = std::make_shared<Account>(accountId);\n\t\telse\n\t\t\taccount->getOrLoadName();\n\n\t\tif (plotfile.empty())\n\t\t\tplotfile = \"unknown\";\n\t\t\n\t\tif (blockheight == 0)\n\t\t\tblockheight = miner.getBlockheight();\n\n\t\tif ((deadlineValue == 0 || MinerConfig::getConfig().isCalculatingEveryDeadline()) &&\n\t\t\tblockheight == miner.getBlockheight())\n\t\t\tdeadlineValue = PlotGenerator::generateAndCheck(accountId, nonce, miner);\n\n\t\tif (request.has(xMiner) && MinerConfig::getConfig().isForwardingMinerName())\n\t\t\tminerName = request.get(xMiner);\n\n\t\tDeadline deadline(nonce, deadlineValue, account, blockheight, plotfile);\n\t\tdeadline.setMiner(minerName);\n\t\tdeadline.setWorker(workerName);\n\t\tdeadline.setTotalPlotsize(capacity);\n\t\tdeadline.setIp(request.clientAddress().host());\n\n\t\tif (MinerConfig::getConfig().isCumulatingPlotsizes())\n\t\t\tPlotSizes::set(request.clientAddress().host(), capacity * 1024 * 1024 * 1024, false);\n\n\t\tif (blockheight != miner.getBlockheight())\n\t\t{\n\t\t\tpoco_ndc(SubmitNonceHandler::handleRequest::wrongBlock);\n\n\t\t\tlog_information(MinerLogger::server, deadline.toActionString(\"forwarded nonce discarded - wrong block\"));\n\n\t\t\tconst auto confirmation = NonceConfirmation::createWrongBlock(miner.getBlockheight(), blockheight, nonce, deadline.getDeadline());\n\t\t\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\t\t\tresponse.setContentLength(confirmation.json.size());\n\t\t\tauto& responseData = response.send();\n\t\t\tresponseData << confirmation.json << std::flush;\n\t\t}\n\t\telse if (accountId != 0 && nonce != 0 && deadlineValue != 0)\n\t\t{\n\t\t\tpoco_ndc(SubmitNonceHandler::handleRequest::forwarding);\n\t\t\tlog_information(MinerLogger::server, deadline.toActionString(\"forwarding nonce\"));\n\t\t\tNonceConfirmation confirmation;\n\t\t\tconst auto addedDeadline = miner.addDeadline(std::move(deadline), confirmation);\n\t\t\tif (addedDeadline != nullptr)\n\t\t\t\tconfirmation = miner.submitDeadline(addedDeadline);\n\t\t\telse\n\t\t\t\tconfirmation = NonceConfirmation::createSuccess(deadline.getNonce(), deadline.getDeadline(),\n\t\t\t\t                                                deadline.deadlineToReadableString());\n\t\t\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\t\t\tresponse.setContentLength(confirmation.json.size());\n\t\t\tauto& responseData = response.send();\n\t\t\tresponseData << confirmation.json << std::flush;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpoco_ndc(SubmitNonceHandler::handleRequest::forwardingBlind);\n\t\t\tlog_information(MinerLogger::server, deadline.toActionString(\"forwarding nonce - incompatible client\"));\n\n\t\t\t// sum up the capacity\n\t\t\trequest.set(xCapacity, std::to_string(PlotSizes::getTotal(PlotSizes::Type::Combined)));\n\n\t\t\t// forward the request to the pool\n\t\t\tforward(request, response, HostType::Pool);\n\t\t}\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not forward nonce! %s\", exc.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::RequestHandler::miningInfo(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response, Miner& miner)\n{\n\tpoco_ndc(MiningInfoHandler::handleRequest);\n\n\ttry\n\t{\n\t\tPoco::JSON::Object json;\n\t\tjson.set(\"baseTarget\", std::to_string(miner.getBaseTarget()));\n\t\tjson.set(\"generationSignature\", miner.getGensigStr());\n\t\tjson.set(\"targetDeadline\", MinerConfig::getConfig().getTargetDeadline());\n\t\tjson.set(\"height\", miner.getBlockheight());\n\n\t\tstd::stringstream ss;\n\t\tjson.stringify(ss);\n\t\tauto jsonStr = ss.str();\n\n\t\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_OK);\n\t\tresponse.setContentLength(jsonStr.size());\n\n\t\tauto& output = response.send();\n\t\toutput << jsonStr;\n\t}\n\tcatch (Poco::Exception& exc)\n\t{\n\t\tlog_error(MinerLogger::server, \"Webserver could not send mining info! %s\", exc.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::RequestHandler::changeSettings(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\tMiner& miner)\n{\n\tpoco_ndc(RequestHandler::changeSettings);\n\n\ttry\n\t{\n\t\tif (request.getMethod() == \"POST\")\n\t\t{\n\t\t\tif (!checkCredentials(request, response))\n\t\t\t\treturn;\n\n\t\t\tPoco::Net::HTMLForm post_body(request, request.stream());\n\n\t\t\tfor (auto& key_val : post_body)\n\t\t\t{\n\t\t\t\tconst auto& key = key_val.first;\n\t\t\t\tconst auto& value = key_val.second;\n\n\t\t\t\tusing np = Poco::NumberParser;\n\t\t\t\twhile (miner.isProcessing()) Poco::Thread::sleep(1000);\n\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tif (key == \"mining-info-url\")\n\t\t\t\t\t\tMinerConfig::getConfig().setUrl(value, HostType::MiningInfo);\n\t\t\t\t\telse if (key == \"submission-url\")\n\t\t\t\t\t\tMinerConfig::getConfig().setUrl(value, HostType::Pool);\n\t\t\t\t\telse if (key == \"wallet-url\")\n\t\t\t\t\t\tMinerConfig::getConfig().setUrl(value, HostType::Wallet);\n\t\t\t\t\telse if (key == \"intensity\")\n\t\t\t\t\t\tminer.setMiningIntensity(np::parseUnsigned(value));\n\t\t\t\t\telse if (key == \"buffer-size\")\n\t\t\t\t\t\tMiner::setMaxBufferSize(np::parseUnsigned64(value));\n\t\t\t\t\telse if (key == \"buffer-chunks\")\n\t\t\t\t\t\tMinerConfig::getConfig().setBufferChunkCount(np::parseUnsigned(value));\n\t\t\t\t\telse if (key == \"plot-readers\")\n\t\t\t\t\t\tminer.setMaxPlotReader(np::parseUnsigned(value));\n\t\t\t\t\telse if (key == \"submission-max-retry\")\n\t\t\t\t\t\tMinerConfig::getConfig().setMaxSubmissionRetry(np::parseUnsigned(value));\n\t\t\t\t\telse if (key == \"submit-probability\")\n\t\t\t\t\t\tMinerConfig::getConfig().setSubmitProbability(np::parseFloat(value));\n\t\t\t\t\telse if (key == \"max-historical-blocks\")\n\t\t\t\t\t\tMinerConfig::getConfig().setMaxHistoricalBlocks(np::parseUnsigned(value));\n\t\t\t\t\telse if (key == \"target-deadline\")\n\t\t\t\t\t\tMinerConfig::getConfig().setTargetDeadline(value, TargetDeadlineType::Local);\n\t\t\t\t\telse if (key == \"timeout\")\n\t\t\t\t\t\tMinerConfig::getConfig().setTimeout(static_cast<float>(np::parseFloat(value)));\n\t\t\t\t\telse if (key == \"log-dir\")\n\t\t\t\t\t\tMinerConfig::getConfig().setLogDir(value);\n\t\t\t\t\telse if (Poco::icompare(key, std::string(\"cmb_\").size(), std::string(\"cmb_\")) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst auto logger_name = Poco::replace(key, \"cmb_\", \"\");\n\t\t\t\t\t\tconst auto logger_priority = static_cast<Poco::Message::Priority>(np::parse(value));\n\t\t\t\t\t\tMinerLogger::setChannelPriority(logger_name, logger_priority);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tlog_warning(MinerLogger::server, \"unknown settings-key: %s\", key);\n\t\t\t\t}\n\t\t\t\tcatch (Poco::Exception& exc)\n\t\t\t\t{\n\t\t\t\t\tlog_exception(MinerLogger::server, exc);\n\t\t\t\t\tlog_current_stackframe(MinerLogger::server);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlog_system(MinerLogger::config, \"Settings changed...\");\n\t\t\tMinerConfig::getConfig().printConsole();\n\n\t\t\tif (MinerConfig::getConfig().save())\n\t\t\t\tlog_success(MinerLogger::config, \"Saved new settings!\");\n\t\t\telse\n\t\t\t\tlog_error(MinerLogger::config, \"Could not save new settings!\");\n\t\t}\n\n\t\tredirect(request, response, \"/settings\");\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not change settings: %s\", e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t}\n}\n\nvoid Burst::RequestHandler::changePlotDirs(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\tMinerServer& server, bool remove)\n{\n\tpoco_ndc(\"PlotDirHandler::handleRequest\");\n\n\tif (!checkCredentials(request, response))\n\t\treturn;\n\n\ttry\n\t{\n\t\tstd::string path;\n\t\tPoco::StreamCopier::copyToString(request.stream(), path);\n\n\t\tusing hs = Poco::Net::HTTPResponse::HTTPStatus;\n\t\tstd::string errorMessage;\n\n\t\tif (path.empty())\n\t\t{\n\t\t\terrorMessage = \"The plot dir path is empty\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_information(MinerLogger::server, \"Got request for changing the plotdirs...\");\n\n\t\t\tbool success;\n\n\t\t\tif (remove)\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tsuccess = MinerConfig::getConfig().removePlotDir(path);\n\n\t\t\t\t\tif (success)\n\t\t\t\t\t\tlog_system(MinerLogger::config, \"Removed the plotdir/file: %s\", path);\n\t\t\t\t}\n\t\t\t\tcatch (const Poco::Exception& e)\n\t\t\t\t{\n\t\t\t\t\terrorMessage = e.message();\n\t\t\t\t\tsuccess = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tsuccess = MinerConfig::getConfig().addPlotDir(path);\n\n\t\t\t\t\tif (success)\n\t\t\t\t\t\tlog_system(MinerLogger::config, \"Added the new plotdir/file: %s\", path);\n\t\t\t\t}\n\t\t\t\tcatch (const Poco::Exception& e)\n\t\t\t\t{\n\t\t\t\t\terrorMessage = e.message();\n\t\t\t\t\tsuccess = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (success)\n\t\t\t{\n\t\t\t\tif (!MinerConfig::getConfig().save())\n\t\t\t\t\terrorMessage = \"Could not save the changes to config file\";\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tserver.sendToWebsockets(createJsonPlotDirsRescan());\n\t\t\t\t\tMinerConfig::getConfig().printConsolePlots();\n\t\t\t\t\tMinerConfig::getConfig().printBufferSize();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_warning(MinerLogger::server, \"Could not %s the plotdir/file '%s': %s\",\n\t\t\t\t\tstd::string(remove ? \"remove\" : \"add\"), path, errorMessage);\n\t\t\t}\n\t\t}\n\n\t\tPoco::JSON::Object json;\n\t\tjson.set(\"error\", errorMessage);\n\t\tstd::stringstream sstream;\n\n\t\tPoco::JSON::Stringifier::condense(json, sstream);\n\t\tconst auto responseString = sstream.str();\n\n\t\tresponse.setStatus(hs::HTTP_OK);\n\t\tresponse.setContentLength(responseString.size());\n\t\tresponse.setContentType(\"application/json\");\n\t\tauto& out = response.send();\n\t\tout << responseString;\n\t}\n\tcatch (const Poco::Exception& e)\n\t{\n\t\tlog_error(MinerLogger::server, \"Could not %s the plot dir: %s\", std::string(remove ? \"remove\" : \"add\"), e.displayText());\n\t\tlog_current_stackframe(MinerLogger::server);\n\t\tbadRequest(request, response);\n\t}\n}\n\nvoid Burst::RequestHandler::notFound(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)\n{\n\tresponse.setStatus(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);\n\tresponse.send();\n}\n\nBurst::Version Burst::RequestHandler::fetchOnlineVersion() \n{\n\ttry\n\t{\n\t\t// fetch the online version file\n\t\tconst std::string versionPrefix = \"version:\";\n\t\t//\n\t\tBurst::Url url{ \"https://raw.githubusercontent.com\" };\n\t\t//\n\t\tPoco::Net::HTTPRequest getRequest{ \"GET\", \"/Creepsky/creepMiner/master/version.id\" };\n\t\t//\n\t\tBurst::Request request{ url.createSession() };\n\t\tauto response = request.send(getRequest);\n\t\t//\n\t\tstd::string responseString;\n\t\t//\n\t\tif (response.receive(responseString))\n\t\t{\n\t\t\t// first we check if the online version begins with the prefix\n\t\t\tif (Poco::icompare(responseString, 0, versionPrefix.size(), versionPrefix) == 0)\n\t\t\t{\n\t\t\t\tconst auto onlineVersionStr = responseString.substr(versionPrefix.size());\n\n\t\t\t\tBurst::Version onlineVersion{ onlineVersionStr };\n\t\t\t\treturn onlineVersion;\n\t\t\t}\n\t\t\telse\n\t\t\t\treturn Settings::project.getOnlineVersion();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn Settings::project.getOnlineVersion(); // if no response, just keep the latest Version we have fetched.\n\t\t}\n\t}\n\t// just skip if version could not be determined\n\tcatch (...)\n\t{\n\t\treturn Settings::project.getOnlineVersion(); // if it fails somehow, also just keep the latest Version we have fetched.\n\t}\n}\n"
  },
  {
    "path": "src/webserver/RequestHandler.hpp",
    "content": "﻿// ==========================================================================\n// \n// creepMiner - Burstcoin cryptocurrency CPU and GPU miner\n// Copyright (C)  2016-2018 Creepsky (creepsky@gmail.com)\n// \n// This program is free software; you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation; either version 3 of the License, or\n// (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software Foundation,\n// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301  USA\n// \n// ==========================================================================\n\n#pragma once\n\n#include <Poco/Net/HTTPRequestHandler.h>\n#include <Poco/Net/WebSocket.h>\n#include <memory>\n#include <functional>\n#include <unordered_map>\n#include \"mining/MinerConfig.hpp\"\n#include <stack>\n#include <mutex>\n\nnamespace Poco\n{\n\tnamespace JSON\n\t{\n\t\tclass Object;\n\t}\n\n\tnamespace Net\n\t{\n\t\tclass HTTPServerRequest;\n\t}\n}\n\nnamespace Burst\n{\n\tclass Miner;\n\tclass MinerServer;\n\n\t/**\n\t * \\brief This class holds key value pairs (string -> string)\n\t * that are all replaced inside a source string.\n\t * \n\t * Keys always have the structure %KEY%, while values can be every possible string value.\n\t */\n\tstruct TemplateVariables\n\t{\n\t\tusing Variable = std::function<std::string()>;\n\t\tstd::unordered_map<std::string, Variable> variables;\n\t\t\n\t\tTemplateVariables() = default;\n\t\tTemplateVariables(std::unordered_map<std::string, Variable> variables);\n\n\t\t/**\n\t\t * \\brief Replaces all keys (%KEY%) inside a string with the set values.\n\t\t * \\param source The string, in which the keys get replaced.\n\t\t */\n\t\tvoid inject(std::string& source) const;\n\n\t\tTemplateVariables operator+ (const TemplateVariables& rhs);\n\t};\n\n\tnamespace RequestHandler\n\t{\n\t\t/**\n\t\t * \\brief A request handler, that carries and executes a lambda.\n\t\t */\n\t\tclass LambdaRequestHandler : public Poco::Net::HTTPRequestHandler\n\t\t{\n\t\tpublic:\n\t\t\t/**\n\t\t\t * \\brief Simple alias for a the lambda type.\n\t\t\t */\n\t\t\tusing Lambda = std::function<void(Poco::Net::HTTPServerRequest&, Poco::Net::HTTPServerResponse&)>;\n\n\t\t\t/**\n\t\t\t * \\brief Constructor.\n\t\t\t * \\param lambda The lambda function, that is called when processing a request.\n\t\t\t */\n\t\t\tLambdaRequestHandler(Lambda lambda);\n\n\t\t\t/**\n\t\t\t * \\brief Handles an incoming HTTP request by expanding and executing the lambda.\n\t\t\t * \\param request The HTTP request.\n\t\t\t * \\param response The HTTP response.\n\t\t\t */\n\t\t\tvoid handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) override;\n\n\t\tprivate:\n\t\t\t/**\n\t\t\t * \\brief The lambda. \n\t\t\t */\n\t\t\tLambda lambda_;\n\t\t};\n\n\t\tclass WebsocketRequestHandler : public Poco::Net::HTTPRequestHandler\n\t\t{\n\t\tpublic:\n\t\t\tWebsocketRequestHandler(MinerServer& server, MinerData& data);\n\t\t\t~WebsocketRequestHandler() override;\n\t\t\tvoid handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) override;\n\n\t\tprivate:\n\t\t\tvoid onNewData(std::string& data);\n\n\t\tprivate:\n\t\t\tstd::mutex mutex_;\n\t\t\tMinerServer& server_;\n\t\t\tMinerData& data_;\n\t\t\tstd::deque<std::string> queue_;\n\t\t};\n\n\t\t/**\n\t\t * \\brief Loads a template and fills it with content.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param templatePage The template page.\n\t\t * \\param contentPage The content page, that is inserted into the template.\n\t\t * \\param variables The variables, that are inserted into template and contentpage.\n\t\t */\n\t\tvoid loadTemplate(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t                  const std::string& templatePage, const std::string& contentPage,\n\t\t                  TemplateVariables& variables);\n\n\t\t/**\n\t\t * \\brief Loads a template and fills it with content.\n\t\t * The template is only send as response, when the user is logged in.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param templatePage The template page.\n\t\t * \\param contentPage The content page, that is inserted into the template.\n\t\t * \\param variables The variables, that are inserted into template and contentpage.\n\t\t */\n\t\tvoid loadSecuredTemplate(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t\t\t\t\t\t\t const std::string& templatePage, const std::string& contentPage,\n\t\t\t\t\t\t\t\t TemplateVariables& variables);\n\n\t\t/**\n\t\t * \\brief Loads an asset from a designated path.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param path The path of the asset.\n\t\t * \\return true, when the asset could be loaded, false otherwise.\n\t\t */\n\t\tbool loadAssetByPath(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t                     const std::string& path);\n\n\t\t/**\n\t\t * \\brief Loads an asset from a designated path by extracting the path from the request.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\return true, when the asset could be loaded, false otherwise.\n\t\t */\n\t\tbool loadAsset(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);\n\n\t\t/**\n\t\t * \\brief Logins the user, if the credentials are right.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\return true, when the user was logged in, false otherwise.\n\t\t */\n\t\tbool login(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);\n\n\t\t/**\n\t\t * \\brief Logs the user out. Redirects him to the root dir.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t */\n\t\tvoid logout(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);\n\n\t\t/**\n\t\t * \\brief Checks, if the user is logged in.\n\t\t * Refreshes the login session of the user, if he was already logged in.\n\t\t * \\param request The HTTP request.\n\t\t * \\return true, if the user is logged in, false otherwise.\n\t\t */\n\t\tbool isLoggedIn(Poco::Net::HTTPServerRequest& request);\n\n\t\t/**\n\t\t * \\brief Redirects the request to another destination.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param redirectUri The URI, to which the request will be redirected.\n\t\t */\n\t\tvoid redirect(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t              const std::string& redirectUri);\n\t\t\n\t\t/**\n\t\t * \\brief Forwards a request to a destination and returns the response of it to the caller.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param hostType The HTTP session host type, that is the destination of the forwarding.\n\t\t */\n\t\tvoid forward(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t\tHostType hostType);\n\t\t\n\t\t/**\n\t\t * \\brief Sends a 400 Bad Request as a response to the caller.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t */\n\t\tvoid badRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);\n\n\t\t/**\n\t\t * \\brief Gives order to rescan all plot directories.\n\t\t * During this process, the plot size can be changed.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param miner The miner, which will propagate the changed config to his connected users.\n\t\t */\n\t\tvoid rescanPlotfiles(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t                     Miner& miner);\n\n\t\t/**\n\t\t* \\brief Checks a plot file for corruption\n\t\t* \\param request The HTTP request.\n\t\t* \\param response The HTTP response.\n\t\t* \\param miner The miner, which will propagate the changed config to his connected users.\n\t\t* \\param plotPath The path of the plot file to check for corruption.\n\t\t* \\param server The server instance, that is shut down.\n\t\t*/\n\t\tvoid checkPlotfile(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response, Miner& miner,\n\t\t\tMinerServer& server, const std::string& plotPath);\n\n\t\t/**\n\t\t* \\brief Checks all plot files for corruption\n\t\t* \\param request The HTTP request.\n\t\t* \\param response The HTTP response.\n\t\t* \\param miner The miner, which will propagate the changed config to his connected users.\n\t\t* \\param server The server instance, that is shut down.\n\t\t*/\n\t\tvoid checkAllPlotfiles(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response, Miner& miner,\n\t\t\tMinerServer& server);\n\n\t\t/**\n\t\t * \\brief Checks the credentials for a request and compares them with the credentials set in the config file.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\return true, if the request could be authenticated, false otherwise.\n\t\t */\n\t\tbool checkCredentials(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);\n\n\t\t/**\n\t\t * \\brief Shuts down the application. Before that, the credentials are checked.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param miner The miner instance, that is shut down.\n\t\t * \\param server The server instance, that is shut down.\n\t\t */\n\t\tvoid shutdown(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t              Miner& miner, MinerServer& server);\n\n\t\t/**\n\t\t* \\brief Restarts the application. Before that, the credentials are checked.\n\t\t* \\param request The HTTP request.\n\t\t* \\param response The HTTP response.\n\t\t* \\param miner The miner instance, that is restarted.\n\t\t* \\param server The server instance, that is restarted.\n\t\t*/\n\t\tvoid restart(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t             Miner& miner, MinerServer& server);\n\n\t\t/**\n\t\t * \\brief Submits a nonce by forwarding it to the pool of the local miner instance.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param server The server instance, that will propagate \n\t\t * \\param miner \n\t\t */\n\t\tvoid submitNonce(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t                 MinerServer& server, Miner& miner);\n\n\t\t/**\n\t\t * \\brief Sends back the current mining info of the local miner instance.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param miner The miner instance, from which the mining info is gathered and send.\n\t\t */\n\t\tvoid miningInfo(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t\tMiner& miner);\n\t\n\t\t/**\n\t\t * \\brief Processes setting changes from a POST request.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param miner The miner instance, which is affected by the setting changes.\n\t\t */\n\t\tvoid changeSettings(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t                    Miner& miner);\n\n\t\t/**\n\t\t * \\brief Adds or deletes a plot directory to the current configuration.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t * \\param server The Minerserver, which will propagate the changed config to his connected users.\n\t\t * \\param remove If it is set to true, the plot directory will be removed. Otherwise it will be added.\n\t\t */\n\t\tvoid changePlotDirs(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response,\n\t\t                    MinerServer& server, bool remove);\n\n\t\t/**\n\t\t * \\brief Sends a 404 Not Found as a response to the caller.\n\t\t * \\param request The HTTP request.\n\t\t * \\param response The HTTP response.\n\t\t */\n\t\tvoid notFound(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);\n\n\t\t/*\n\t\t * fetches the Online Version from github\n\t\t */\n\t\tBurst::Version fetchOnlineVersion();\n\t}\n}\n"
  },
  {
    "path": "version.id",
    "content": "version:1.9.0.0"
  }
]