diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Avatar/VrmAvatar.asset b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Avatar/VrmAvatar.asset index 86bf7ae1..6627dcb5 100644 --- a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Avatar/VrmAvatar.asset +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Avatar/VrmAvatar.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cde489008c37f77daa3d3af0b46beb0fae0131235c2d1f49bc965e50ebb881e3 -size 87762 +oid sha256:64ec321e2f8f631855b9accfa0441a13d706ee272acd9d6cbb70ce0a25a7cc00 +size 89381 diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Meshes/newton.baked.asset b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Meshes/newton.baked.asset index 2780bf80..e1dbc5a2 100644 --- a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Meshes/newton.baked.asset +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Meshes/newton.baked.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a98e96729f044f6a66bbbfeb7c1a0a95c5a605bdbe3a654a01c5a9045e8ae32 -size 3201111 +oid sha256:aca3bded3a29e6eb78e01d3f329fcfd790d96ccd33d7a6a5000727cb22861786 +size 3201078 diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.fbx.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.fbx.meta index d66ab75a..0bff8903 100644 --- a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.fbx.meta +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.fbx.meta @@ -269,7 +269,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger2Metacarpal + - boneName: LeftFinger2Proximal humanName: Left Index Proximal limit: min: {x: 0, y: 0, z: 0} @@ -277,7 +277,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger2Proximal + - boneName: LeftFinger2Medial humanName: Left Index Intermediate limit: min: {x: 0, y: 0, z: 0} @@ -285,7 +285,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger2Medial + - boneName: LeftFinger2Distal humanName: Left Index Distal limit: min: {x: 0, y: 0, z: 0} @@ -293,7 +293,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger3Metacarpal + - boneName: LeftFinger3Proximal humanName: Left Middle Proximal limit: min: {x: 0, y: 0, z: 0} @@ -301,7 +301,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger3Proximal + - boneName: LeftFinger3Medial humanName: Left Middle Intermediate limit: min: {x: 0, y: 0, z: 0} @@ -309,7 +309,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger3Medial + - boneName: LeftFinger3Distal humanName: Left Middle Distal limit: min: {x: 0, y: 0, z: 0} @@ -317,7 +317,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger4Metacarpal + - boneName: LeftFinger4Proximal humanName: Left Ring Proximal limit: min: {x: 0, y: 0, z: 0} @@ -325,7 +325,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger4Proximal + - boneName: LeftFinger4Medial humanName: Left Ring Intermediate limit: min: {x: 0, y: 0, z: 0} @@ -333,7 +333,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger4Medial + - boneName: LeftFinger4Distal humanName: Left Ring Distal limit: min: {x: 0, y: 0, z: 0} @@ -341,7 +341,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger5Metacarpal + - boneName: LeftFinger5Proximal humanName: Left Little Proximal limit: min: {x: 0, y: 0, z: 0} @@ -349,7 +349,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger5Proximal + - boneName: LeftFinger5Medial humanName: Left Little Intermediate limit: min: {x: 0, y: 0, z: 0} @@ -357,7 +357,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: LeftFinger5Medial + - boneName: LeftFinger5Distal humanName: Left Little Distal limit: min: {x: 0, y: 0, z: 0} @@ -389,7 +389,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger2Metacarpal + - boneName: RightFinger2Proximal humanName: Right Index Proximal limit: min: {x: 0, y: 0, z: 0} @@ -397,7 +397,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger2Proximal + - boneName: RightFinger2Medial humanName: Right Index Intermediate limit: min: {x: 0, y: 0, z: 0} @@ -405,7 +405,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger2Medial + - boneName: RightFinger2Distal humanName: Right Index Distal limit: min: {x: 0, y: 0, z: 0} @@ -413,7 +413,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger3Metacarpal + - boneName: RightFinger3Proximal humanName: Right Middle Proximal limit: min: {x: 0, y: 0, z: 0} @@ -421,7 +421,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger3Proximal + - boneName: RightFinger3Medial humanName: Right Middle Intermediate limit: min: {x: 0, y: 0, z: 0} @@ -429,7 +429,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger3Medial + - boneName: RightFinger3Distal humanName: Right Middle Distal limit: min: {x: 0, y: 0, z: 0} @@ -437,7 +437,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger4Metacarpal + - boneName: RightFinger4Proximal humanName: Right Ring Proximal limit: min: {x: 0, y: 0, z: 0} @@ -445,7 +445,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger4Proximal + - boneName: RightFinger4Medial humanName: Right Ring Intermediate limit: min: {x: 0, y: 0, z: 0} @@ -453,7 +453,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger4Medial + - boneName: RightFinger4Distal humanName: Right Ring Distal limit: min: {x: 0, y: 0, z: 0} @@ -461,7 +461,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger5Metacarpal + - boneName: RightFinger5Proximal humanName: Right Little Proximal limit: min: {x: 0, y: 0, z: 0} @@ -469,7 +469,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger5Proximal + - boneName: RightFinger5Medial humanName: Right Little Intermediate limit: min: {x: 0, y: 0, z: 0} @@ -477,7 +477,7 @@ ModelImporter: value: {x: 0, y: 0, z: 0} length: 0 modified: 0 - - boneName: RightFinger5Medial + - boneName: RightFinger5Distal humanName: Right Little Distal limit: min: {x: 0, y: 0, z: 0} @@ -582,7 +582,7 @@ ModelImporter: - name: LeftFinger1Metacarpal parentName: LeftHand position: {x: -0.027847009, y: 0.020784134, z: -0.001056083} - rotation: {x: 0.09904506, y: -0.36964288, z: 0.23911677, w: 0.89239985} + rotation: {x: 0.04233702, y: -0.5728508, z: 0.3376046, w: 0.74570274} scale: {x: 1.0000001, y: 0.99999994, z: 1.0000001} - name: LeftFinger1Proximal parentName: LeftFinger1Metacarpal @@ -707,7 +707,7 @@ ModelImporter: - name: RightFinger1Metacarpal parentName: RightHand position: {x: 0.027845163, y: 0.020768387, z: -0.0010154283} - rotation: {x: 0.09904415, y: 0.36964288, z: -0.23911713, w: 0.89239985} + rotation: {x: 0.04219337, y: 0.5729466, z: -0.33736277, w: 0.7457468} scale: {x: 1, y: 0.99999994, z: 0.9999998} - name: RightFinger1Proximal parentName: RightFinger1Metacarpal diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab index 96789942..b46dd531 100644 --- a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:022bbb6b2a68737c1d189fe6822631c00a2d4f0bbb109b4583d33b64297ab260 -size 89556 +oid sha256:d426caa5686dcc01231edb83fcd338cb97ef3c81185b8a25d57f285ff9167fa8 +size 93393 diff --git a/Optitrack Rokoko Glove/GloveDeviceExample/GloveDeviceExample.vcxproj b/Optitrack Rokoko Glove/GloveDeviceExample/GloveDeviceExample.vcxproj index 1547b996..ddd51374 100644 --- a/Optitrack Rokoko Glove/GloveDeviceExample/GloveDeviceExample.vcxproj +++ b/Optitrack Rokoko Glove/GloveDeviceExample/GloveDeviceExample.vcxproj @@ -68,14 +68,14 @@ copy "$(OutDir)ExampleGloveData.csv" "C:/Program Files/OptiTrack/Motive/device Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;ANALOGSYSTEM_IMPORTS;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;%(PreprocessorDefinitions) false - ..\..\include;%(AdditionalIncludeDirectories) + ..\include;%(AdditionalIncludeDirectories) Windows true NotSet PeripheralImport.lib;%(AdditionalDependencies) - ..\..\lib;%(AdditionalLibraryDirectories) + ..\lib;%(AdditionalLibraryDirectories) false @@ -88,7 +88,7 @@ copy "$(OutDir)ExampleGloveData.csv" "C:/Program Files/OptiTrack/Motive/device true true WIN32;NDEBUG;_WINDOWS;_USRDLL;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;ANALOGSYSTEM_IMPORTS;%(PreprocessorDefinitions) - ..\..\include;%(AdditionalIncludeDirectories) + ..\include;%(AdditionalIncludeDirectories) Windows @@ -96,7 +96,7 @@ copy "$(OutDir)ExampleGloveData.csv" "C:/Program Files/OptiTrack/Motive/device true true PeripheralImport.lib;%(AdditionalDependencies) - ..\..\lib;%(AdditionalLibraryDirectories) + ..\lib;%(AdditionalLibraryDirectories) diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/ExampleGloveAdapterSingleton.cpp b/Optitrack Rokoko Glove/RokokoGloveDevice/ExampleGloveAdapterSingleton.cpp index 4e2c28b2..dfad524e 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/ExampleGloveAdapterSingleton.cpp +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/ExampleGloveAdapterSingleton.cpp @@ -5,7 +5,12 @@ #include #include +#include // stringstream 사용을 위해 추가 +#include // sqrt 함수 사용을 위해 추가 +#include // setprecision 사용을 위해 추가 +#include // std::max, std::min 사용을 위해 추가 #define WIN32_LEAN_AND_MEAN +#define NOMINMAX // Windows min/max 매크로 비활성화 #include // Peripheral Import @@ -94,7 +99,7 @@ void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::DoDete bIsDetecting = false; NotifyConnectionFail(); } - std::this_thread::sleep_for(std::chrono::milliseconds(20000)); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // 🚀 실시간성 최우선 - 1ms로 최소화 } } @@ -170,8 +175,8 @@ bool OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::Connec bIsRokokoConnected = true; - // 로코코 장치 동적 감지 및 생성 - DetectAndCreateRokokoDevices(); + // 초기 장치 생성은 데이터 수신 후로 지연 + // DetectAndCreateRokokoDevices(); // 주석 처리 // 성공 메시지 출력 if (mDeviceManager) { @@ -248,7 +253,16 @@ bool OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::GetLat void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::CreateNewGloveDevice(sGloveDeviceBaseInfo& deviceInfo) { uint64_t gloveId = deviceInfo.gloveId; - std::string deviceName = "RokokoGlove_" + std::to_string(deviceInfo.gloveId); // 이름을 RokokoGlove로 변경 + + // Actor 이름을 포함한 장치 이름 생성 + std::string deviceName; + if (!deviceInfo.actorName.empty()) { + deviceName = deviceInfo.actorName + "_" + + (deviceInfo.handSide == eGloveHandSide::Left ? "Left" : "Right") + + "Hand"; + } else { + deviceName = "RokokoGlove_" + std::to_string(deviceInfo.gloveId); + } // Create device factory using the name/id/serial/client. std::unique_ptr pDF = @@ -427,73 +441,95 @@ void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::OnRoko { if (s_Instance == nullptr) return; - try { - // 로코코 데이터 처리 - s_Instance->ProcessRokokoData(data); - - // 디버그 정보 출력 (OptiTrack에서 확인 가능) - if (s_Instance->mDeviceManager) { - std::string debugMsg = "[RokokoGlove] Received " + std::to_string(data.size()) + " bytes from " + senderIP; - s_Instance->mDeviceManager->MessageToHost(debugMsg.c_str(), MessageType_StatusInfo); - } - - } catch (...) { - if (s_Instance->mDeviceManager) { - s_Instance->mDeviceManager->MessageToHost("[RokokoGlove] Error processing received data", MessageType_StatusInfo); - } - } + // 🚀 실시간성 최우선: 예외 처리 및 로그 최소화 + s_Instance->ProcessRokokoData(data); } void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ProcessRokokoData(const std::vector& data) { try { - // 1단계: LZ4 압축 해제 (필요한 경우) - std::vector decompressedData; - if (RokokoIntegration::LZ4Wrapper::IsValidLZ4Data(data.data(), static_cast(data.size()))) { - decompressedData = RokokoIntegration::LZ4Wrapper::Decompress(data.data(), static_cast(data.size())); - if (decompressedData.empty()) { - if (mDeviceManager) { - mDeviceManager->MessageToHost("[RokokoGlove] LZ4 decompression failed", MessageType_StatusInfo); + // 🚀 실시간성을 위해 정적 버퍼 사용 (메모리 할당 최소화) + static std::vector decompressedData; + decompressedData.clear(); + decompressedData.reserve(data.size() * 4); // 미리 메모리 예약 + + // 🚀 Unity 방식: LZ4 압축 해제 (모든 로그 제거) + decompressedData = RokokoIntegration::LZ4Wrapper::Decompress(data.data(), static_cast(data.size())); + + if (decompressedData.empty()) { + // 대안: LZ4 프레임 헤더 건너뛰고 압축 해제 시도 + if (data.size() > 8) { + // LZ4 프레임 헤더 건너뛰기 (일반적으로 7바이트) + std::vector dataWithoutHeader(data.begin() + 7, data.end()); + decompressedData = RokokoIntegration::LZ4Wrapper::Decompress(dataWithoutHeader.data(), static_cast(dataWithoutHeader.size())); + + if (decompressedData.empty()) { + // Unity에서는 실패 시 에러 로그만 출력하고 null 반환 + // 우리는 원본 데이터로 시도해봄 + decompressedData = data; } - return; + } else { + decompressedData = data; } - } else { - // LZ4 압축이 아닌 경우 원본 데이터 사용 - decompressedData = data; } - // 2단계: JSON 문자열로 변환 + // 2단계: JSON 문자열로 변환 (유니티 방식 정확히 구현) + // Unity 방식: string text = System.Text.Encoding.UTF8.GetString(uncompressed); std::string jsonString(decompressedData.begin(), decompressedData.end()); - // 3단계: JSON 파싱하여 Rokoko 데이터 구조로 변환 - RokokoData::LiveFrame_v4 rokokoFrame; - if (!RokokoIntegration::RokokoDataParser::ParseLiveFrame(jsonString, rokokoFrame)) { + // 🚀 성능 최적화: 데이터 미리보기 로그 제거 + + // JSON 데이터 유효성 검사 + if (jsonString.empty() || jsonString.length() < 10) { if (mDeviceManager) { - mDeviceManager->MessageToHost("[RokokoGlove] JSON parsing failed", MessageType_StatusInfo); + mDeviceManager->MessageToHost("[RokokoGlove] Invalid JSON data (too short)", MessageType_StatusInfo); } return; } + + // JSON 시작 문자 확인 + if (jsonString[0] != '{') { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Invalid JSON data (does not start with '{')", MessageType_StatusInfo); + } + + // 바이너리 데이터 분석 (첫 20바이트) + std::stringstream hexStream; + hexStream << "[RokokoGlove] Binary data detected: "; + for (size_t i = 0; i < 20 && i < decompressedData.size(); i++) { + char buf[8]; + snprintf(buf, sizeof(buf), "%02X ", static_cast(decompressedData[i])); + hexStream << buf; + } + mDeviceManager->MessageToHost(hexStream.str().c_str(), MessageType_StatusInfo); + return; + } + + // 3단계: JSON 파싱하여 Rokoko 데이터 구조로 변환 + RokokoData::LiveFrame_v4 rokokoFrame; + + // 🚀 실시간성 최우선 - 모든 로그 제거, 즉시 처리 + if (!RokokoIntegration::RokokoDataParser::ParseLiveFrame(jsonString, rokokoFrame)) { + return; // 실패 시 즉시 종료 + } - // 4단계: 다중 장치 데이터 처리 (왼손, 오른손) + // 🚀 Actor 기반 동적 장치 감지 (로그 제거) + DetectActorsFromRokokoData(rokokoFrame); + + // 🚀 첫 번째 데이터 수신 시 기본 장치도 생성 (백업) + if (mDetectedDevices.empty()) { + DetectAndCreateRokokoDevices(); + } + + // 🚀 다중 장치 데이터 처리 (왼손, 오른손) - 즉시 처리 ProcessMultipleDeviceData(rokokoFrame); - // 5단계: 최신 프레임 업데이트 + // 🚀 최신 프레임 업데이트 - 큐 없이 즉시 업데이트 mLastRokokoFrame = rokokoFrame; - // 성공 메시지 출력 - if (mDeviceManager) { - mDeviceManager->MessageToHost("[RokokoGlove] Successfully processed Rokoko data", MessageType_StatusInfo); - } - - } catch (const std::exception& e) { - if (mDeviceManager) { - std::string errorMsg = "[RokokoGlove] Exception: " + std::string(e.what()); - mDeviceManager->MessageToHost(errorMsg.c_str(), MessageType_StatusInfo); - } } catch (...) { - if (mDeviceManager) { - mDeviceManager->MessageToHost("[RokokoGlove] Unknown exception occurred", MessageType_StatusInfo); - } + // 🚀 실시간성 최우선 - 예외 발생 시 즉시 종료 (로그 제거) + return; } } @@ -551,12 +587,16 @@ void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::Detect mLatestGloveData.clear(); mLatestDeviceInfo.clear(); + // 현재는 기본 2개 장치만 생성 (나중에 동적 감지로 변경) + // TODO: 실제 Rokoko 데이터에서 Actor 정보를 기반으로 동적 감지 + // 왼손 장치 생성 sGloveDeviceBaseInfo leftHandInfo; leftHandInfo.gloveId = 1; leftHandInfo.handSide = eGloveHandSide::Left; leftHandInfo.battery = 100; leftHandInfo.signalStrength = 100; + leftHandInfo.actorName = "DefaultActor"; // Actor 이름 추가 CreateNewGloveDevice(leftHandInfo); SetLatestDeviceInfo(leftHandInfo); mDetectedDevices.push_back(1); @@ -567,6 +607,7 @@ void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::Detect rightHandInfo.handSide = eGloveHandSide::Right; rightHandInfo.battery = 100; rightHandInfo.signalStrength = 100; + rightHandInfo.actorName = "DefaultActor"; // Actor 이름 추가 CreateNewGloveDevice(rightHandInfo); SetLatestDeviceInfo(rightHandInfo); mDetectedDevices.push_back(2); @@ -584,6 +625,79 @@ void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::Detect } } +// 새로운 함수: 동적 Actor 기반 장치 감지 +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::DetectActorsFromRokokoData(const RokokoData::LiveFrame_v4& rokokoFrame) +{ + try { + // 기존 장치 정보 백업 + std::vector oldDevices = mDetectedDevices; + mDetectedDevices.clear(); + + // Actor별로 장치 생성 + for (size_t actorIndex = 0; actorIndex < rokokoFrame.scene.actors.size(); actorIndex++) { + const auto& actor = rokokoFrame.scene.actors[actorIndex]; + std::string actorName = actor.name; + + // Actor 이름이 비어있으면 기본값 사용 + if (actorName.empty()) { + actorName = "Actor" + std::to_string(actorIndex + 1); + } + + // 왼손 장치 생성 (Actor별로 고유 ID 생성) + uint64_t leftHandId = (actorIndex * 2) + 1; + sGloveDeviceBaseInfo leftHandInfo; + leftHandInfo.gloveId = static_cast(leftHandId); + leftHandInfo.handSide = eGloveHandSide::Left; + leftHandInfo.battery = 100; + leftHandInfo.signalStrength = 100; + leftHandInfo.actorName = actorName; + + // 새 장치인지 확인하고 생성 + if (std::find(oldDevices.begin(), oldDevices.end(), leftHandId) == oldDevices.end()) { + CreateNewGloveDevice(leftHandInfo); + if (mDeviceManager) { + std::string msg = "[RokokoGlove] Created new left hand device for " + actorName + " (ID: " + std::to_string(leftHandId) + ")"; + mDeviceManager->MessageToHost(msg.c_str(), MessageType_StatusInfo); + } + } + SetLatestDeviceInfo(leftHandInfo); + mDetectedDevices.push_back(leftHandId); + + // 오른손 장치 생성 + uint64_t rightHandId = (actorIndex * 2) + 2; + sGloveDeviceBaseInfo rightHandInfo; + rightHandInfo.gloveId = static_cast(rightHandId); + rightHandInfo.handSide = eGloveHandSide::Right; + rightHandInfo.battery = 100; + rightHandInfo.signalStrength = 100; + rightHandInfo.actorName = actorName; + + // 새 장치인지 확인하고 생성 + if (std::find(oldDevices.begin(), oldDevices.end(), rightHandId) == oldDevices.end()) { + CreateNewGloveDevice(rightHandInfo); + if (mDeviceManager) { + std::string msg = "[RokokoGlove] Created new right hand device for " + actorName + " (ID: " + std::to_string(rightHandId) + ")"; + mDeviceManager->MessageToHost(msg.c_str(), MessageType_StatusInfo); + } + } + SetLatestDeviceInfo(rightHandInfo); + mDetectedDevices.push_back(rightHandId); + } + + // 🚀 성능 최적화: 장치 감지 완료 로그 제거 + + } catch (const std::exception& e) { + if (mDeviceManager) { + std::string errorMsg = "[RokokoGlove] Exception in actor detection: " + std::string(e.what()); + mDeviceManager->MessageToHost(errorMsg.c_str(), MessageType_StatusInfo); + } + } catch (...) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Unknown exception in actor detection", MessageType_StatusInfo); + } + } +} + void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ProcessMultipleDeviceData(const RokokoData::LiveFrame_v4& rokokoFrame) { try { @@ -595,16 +709,23 @@ void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::Proces return; } - const auto& actor = rokokoFrame.scene.actors[0]; - - // 왼손 데이터 처리 - if (ProcessHandData(actor.body, 1, eGloveHandSide::Left)) { - UpdateDeviceInfo(1); - } - - // 오른손 데이터 처리 - if (ProcessHandData(actor.body, 2, eGloveHandSide::Right)) { - UpdateDeviceInfo(2); + // 🚀 모든 Actor의 데이터를 처리 (다중 장갑 지원) + for (size_t actorIndex = 0; actorIndex < rokokoFrame.scene.actors.size(); actorIndex++) { + const auto& actor = rokokoFrame.scene.actors[actorIndex]; + + // Actor별 고유 ID 계산 + uint64_t leftHandId = (actorIndex * 2) + 1; + uint64_t rightHandId = (actorIndex * 2) + 2; + + // 왼손 데이터 처리 + if (ProcessHandData(actor.body, leftHandId, eGloveHandSide::Left)) { + UpdateDeviceInfo(leftHandId); + } + + // 오른손 데이터 처리 + if (ProcessHandData(actor.body, rightHandId, eGloveHandSide::Right)) { + UpdateDeviceInfo(rightHandId); + } } } catch (const std::exception& e) { @@ -642,12 +763,13 @@ bool OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::Proces optiTrackData.nodes[i].node_id = i; } - // 데이터 유효성 검사 + // 🚀 실시간성 최우선 - 모든 디버깅 제거 + + // 🎯 계층적 로컬 로테이션 계산 (Rokoko 월드 데이터 → 로컬 변환) + ConvertToTrueLocalRotations(optiTrackData.nodes, body, handSide); + + // 🚀 실시간성 최우선 - 데이터 유효성 검사 (로그 제거) if (!RokokoIntegration::RokokoDataConverter::ValidateOptiTrackData(optiTrackData)) { - if (mDeviceManager) { - std::string errorMsg = "[RokokoGlove] Data validation failed for device " + std::to_string(deviceId); - mDeviceManager->MessageToHost(errorMsg.c_str(), MessageType_StatusInfo); - } return false; } @@ -659,10 +781,7 @@ bool OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::Proces return true; } catch (...) { - if (mDeviceManager) { - std::string errorMsg = "[RokokoGlove] Error processing hand data for device " + std::to_string(deviceId); - mDeviceManager->MessageToHost(errorMsg.c_str(), MessageType_StatusInfo); - } + // 🚀 실시간성 최우선 - 예외 발생 시 즉시 종료 (로그 제거) return false; } } @@ -725,9 +844,1438 @@ void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::MapRig void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::MapJoint(const RokokoData::ActorJointFrame& rokokoJoint, sFingerNode& optiTrackNode) { - // 쿼터니언 변환 + // Rokoko 로우 데이터를 직접 OptiTrack에 적용 optiTrackNode.quat_w = rokokoJoint.rotation.w; optiTrackNode.quat_x = rokokoJoint.rotation.x; optiTrackNode.quat_y = rokokoJoint.rotation.y; optiTrackNode.quat_z = rokokoJoint.rotation.z; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// 로컬 로테이션 변환 함수들 +// +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ConvertToLocalRotations(std::vector& nodes, eGloveHandSide handSide) +{ + // OptiTrack 손가락 배치: [Thumb(0-2), Index(3-5), Middle(6-8), Ring(9-11), Little(12-14)] + // 각 손가락의 계층 구조: Proximal/MP → Medial/PIP → Distal/DIP + + // 손가락별로 로컬 로테이션 계산 + for (int fingerIndex = 0; fingerIndex < 5; fingerIndex++) { + int baseIndex = fingerIndex * 3; + + // MP 관절 (루트) - 월드 로테이션 유지 + // 이미 설정된 값 사용 + + // PIP 관절 - MP 관절 기준 로컬 로테이션 + if (baseIndex + 1 < nodes.size()) { + ApplyLocalRotation(nodes[baseIndex + 1], nodes[baseIndex]); + } + + // DIP 관절 - PIP 관절 기준 로컬 로테이션 + if (baseIndex + 2 < nodes.size()) { + ApplyLocalRotation(nodes[baseIndex + 2], nodes[baseIndex + 1]); + } + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ApplyLocalRotation(sFingerNode& childNode, const sFingerNode& parentNode) +{ + // 로컬 로테이션 = parent^-1 * child + sFingerNode parentInverse; + InverseQuaternion(parentNode, parentInverse); + + sFingerNode localRotation; + MultiplyQuaternions(parentInverse, childNode, localRotation); + + // 결과를 자식 노드에 적용 + childNode.quat_w = localRotation.quat_w; + childNode.quat_x = localRotation.quat_x; + childNode.quat_y = localRotation.quat_y; + childNode.quat_z = localRotation.quat_z; + + // 정규화 + NormalizeQuaternion(childNode); +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::MultiplyQuaternions(const sFingerNode& q1, const sFingerNode& q2, sFingerNode& result) +{ + // 쿼터니언 곱셈: q1 * q2 + result.quat_w = q1.quat_w * q2.quat_w - q1.quat_x * q2.quat_x - q1.quat_y * q2.quat_y - q1.quat_z * q2.quat_z; + result.quat_x = q1.quat_w * q2.quat_x + q1.quat_x * q2.quat_w + q1.quat_y * q2.quat_z - q1.quat_z * q2.quat_y; + result.quat_y = q1.quat_w * q2.quat_y - q1.quat_x * q2.quat_z + q1.quat_y * q2.quat_w + q1.quat_z * q2.quat_x; + result.quat_z = q1.quat_w * q2.quat_z + q1.quat_x * q2.quat_y - q1.quat_y * q2.quat_x + q1.quat_z * q2.quat_w; +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::InverseQuaternion(const sFingerNode& q, sFingerNode& result) +{ + // 쿼터니언 역원: (w, -x, -y, -z) / |q|^2 + float norm = q.quat_w * q.quat_w + q.quat_x * q.quat_x + q.quat_y * q.quat_y + q.quat_z * q.quat_z; + + if (norm > 0.0001f) { // 0으로 나누기 방지 + result.quat_w = q.quat_w / norm; + result.quat_x = -q.quat_x / norm; + result.quat_y = -q.quat_y / norm; + result.quat_z = -q.quat_z / norm; + } else { + // 단위 쿼터니언으로 설정 + result.quat_w = 1.0f; + result.quat_x = 0.0f; + result.quat_y = 0.0f; + result.quat_z = 0.0f; + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::NormalizeQuaternion(sFingerNode& q) +{ + float norm = sqrt(q.quat_w * q.quat_w + q.quat_x * q.quat_x + q.quat_y * q.quat_y + q.quat_z * q.quat_z); + + if (norm > 0.0001f) { // 0으로 나누기 방지 + q.quat_w /= norm; + q.quat_x /= norm; + q.quat_y /= norm; + q.quat_z /= norm; + } else { + // 단위 쿼터니언으로 설정 + q.quat_w = 1.0f; + q.quat_x = 0.0f; + q.quat_y = 0.0f; + q.quat_z = 0.0f; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// T-포즈 캘리브레이션 시스템 +// +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::CalibrateTPose(uint64_t deviceId, const std::vector& tPoseData) +{ + try { + // T-포즈 기준값 저장 + mTPoseReferences[deviceId] = tPoseData; + mTPoseCalibrated[deviceId] = true; + + if (mDeviceManager) { + std::string msg = "[RokokoGlove] T-pose calibration completed for device " + std::to_string(deviceId); + mDeviceManager->MessageToHost(msg.c_str(), MessageType_StatusInfo); + } + + } catch (...) { + if (mDeviceManager) { + std::string errorMsg = "[RokokoGlove] Error during T-pose calibration for device " + std::to_string(deviceId); + mDeviceManager->MessageToHost(errorMsg.c_str(), MessageType_StatusInfo); + } + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ApplyTPoseOffset(std::vector& nodes, uint64_t deviceId) +{ + if (!IsTPoseCalibrated(deviceId)) { + // T-포즈 캘리브레이션이 없으면 현재 데이터를 T-포즈로 사용 + CalibrateTPose(deviceId, nodes); + + // 첫 프레임은 중립 상태로 설정 + for (auto& node : nodes) { + node.quat_w = 1.0f; + node.quat_x = 0.0f; + node.quat_y = 0.0f; + node.quat_z = 0.0f; + } + return; + } + + try { + const auto& tPoseRef = mTPoseReferences[deviceId]; + + if (tPoseRef.size() != nodes.size()) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] T-pose reference size mismatch", MessageType_StatusInfo); + } + return; + } + + // 각 관절에 대해 T-포즈 기준 오프셋 계산 + for (size_t i = 0; i < nodes.size(); i++) { + // 오프셋 = T-pose^-1 * current + sFingerNode tPoseInverse; + InverseQuaternion(tPoseRef[i], tPoseInverse); + + sFingerNode offsetRotation; + MultiplyQuaternions(tPoseInverse, nodes[i], offsetRotation); + + // 결과를 노드에 적용 + nodes[i].quat_w = offsetRotation.quat_w; + nodes[i].quat_x = offsetRotation.quat_x; + nodes[i].quat_y = offsetRotation.quat_y; + nodes[i].quat_z = offsetRotation.quat_z; + + // 정규화 + NormalizeQuaternion(nodes[i]); + } + + } catch (...) { + if (mDeviceManager) { + std::string errorMsg = "[RokokoGlove] Error applying T-pose offset for device " + std::to_string(deviceId); + mDeviceManager->MessageToHost(errorMsg.c_str(), MessageType_StatusInfo); + } + } +} + +bool OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::IsTPoseCalibrated(uint64_t deviceId) const +{ + auto it = mTPoseCalibrated.find(deviceId); + return (it != mTPoseCalibrated.end() && it->second); +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ResetTPoseCalibration(uint64_t deviceId) +{ + mTPoseReferences.erase(deviceId); + mTPoseCalibrated[deviceId] = false; + + if (mDeviceManager) { + std::string msg = "[RokokoGlove] T-pose calibration reset for device " + std::to_string(deviceId); + mDeviceManager->MessageToHost(msg.c_str(), MessageType_StatusInfo); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// 손목 기준 로컬 변환 시스템 +// +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ConvertToWristLocalRotations(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide) +{ + try { + // 손목 로테이션 가져오기 + sFingerNode wristRotation; + if (!GetWristRotation(body, handSide, wristRotation)) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Failed to get wrist rotation", MessageType_StatusInfo); + } + return; + } + + // 손목 로테이션의 역원 계산 + sFingerNode wristInverse; + InverseQuaternion(wristRotation, wristInverse); + + // 모든 손가락에 대해 손목 기준 로컬 로테이션 계산 + for (auto& node : nodes) { + // 로컬 로테이션 = 손목^-1 * 손가락 + sFingerNode localRotation; + MultiplyQuaternions(wristInverse, node, localRotation); + + // 결과 적용 + node.quat_w = localRotation.quat_w; + node.quat_x = localRotation.quat_x; + node.quat_y = localRotation.quat_y; + node.quat_z = localRotation.quat_z; + + // 정규화 + NormalizeQuaternion(node); + } + + if (mDeviceManager) { + std::string handStr = (handSide == eGloveHandSide::Left) ? "Left" : "Right"; + std::string msg = "[RokokoGlove] Applied wrist-relative rotations for " + handStr + " hand"; + mDeviceManager->MessageToHost(msg.c_str(), MessageType_StatusInfo); + } + + } catch (...) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Error in wrist-relative rotation conversion", MessageType_StatusInfo); + } + } +} + +bool OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::GetWristRotation(const RokokoData::Body& body, eGloveHandSide handSide, sFingerNode& wristRotation) +{ + try { + // 🎯 실제 손목 데이터 사용! (이제 body.leftHand, body.rightHand가 있음) + std::shared_ptr wristJoint; + + if (handSide == eGloveHandSide::Left) { + // 왼손 실제 손목 데이터 사용 + wristJoint = body.leftHand; + } else { + // 오른손 실제 손목 데이터 사용 + wristJoint = body.rightHand; + } + + if (wristJoint) { + wristRotation.quat_w = wristJoint->rotation.w; + wristRotation.quat_x = wristJoint->rotation.x; + wristRotation.quat_y = wristJoint->rotation.y; + wristRotation.quat_z = wristJoint->rotation.z; + return true; + } + + // 데이터가 없으면 단위 쿼터니언 사용 + wristRotation.quat_w = 1.0f; + wristRotation.quat_x = 0.0f; + wristRotation.quat_y = 0.0f; + wristRotation.quat_z = 0.0f; + + if (mDeviceManager) { + std::string handStr = (handSide == eGloveHandSide::Left) ? "Left" : "Right"; + std::string msg = "[RokokoGlove] " + handStr + " reference joint not available, using identity rotation"; + mDeviceManager->MessageToHost(msg.c_str(), MessageType_StatusInfo); + } + + return true; + + } catch (...) { + // 에러 시 단위 쿼터니언 + wristRotation.quat_w = 1.0f; + wristRotation.quat_x = 0.0f; + wristRotation.quat_y = 0.0f; + wristRotation.quat_z = 0.0f; + return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// 진짜 로컬 로테이션 변환 시스템 (계층적) +// +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ConvertToTrueLocalRotations(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide) +{ + try { + // 모든 손가락의 관절 데이터 가져오기 + std::vector> allFingers; + if (!GetFingerJointRotations(body, handSide, allFingers)) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Failed to get finger joint rotations", MessageType_StatusInfo); + } + return; + } + + // 각 손가락별로 계층적 로컬 로테이션 계산 + int nodeIndex = 0; + for (const auto& fingerJoints : allFingers) { + if (fingerJoints.size() >= 3) { // MP, PIP, DIP 최소 3개 + CalculateFingerLocalRotations(fingerJoints, nodes, nodeIndex, body, handSide); + nodeIndex += 3; // OptiTrack은 손가락당 3개 노드 (MP, PIP, DIP) + } + } + + // 🚀 실시간성을 위해 로그 메시지 제거 + + } catch (...) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Error in true local rotation conversion", MessageType_StatusInfo); + } + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::CalculateFingerLocalRotations(const std::vector& fingerJoints, std::vector& outputNodes, int startIndex, const RokokoData::Body& body, eGloveHandSide handSide) +{ + try { + if (fingerJoints.size() < 3 || startIndex + 2 >= outputNodes.size()) { + return; + } + + // 🎯 핵심: 실제 손목 로테이션을 부모로 사용! + sFingerNode wristRotation; + GetWristRotation(body, handSide, wristRotation); // body 파라미터 사용 + sFingerNode parentRotation = wristRotation; // 첫 번째 손가락 관절의 부모는 손목 + + // 각 관절별로 부모 기준 로컬 로테이션 계산 + for (int i = 0; i < 3 && (startIndex + i) < outputNodes.size(); i++) { + if (i < fingerJoints.size() && fingerJoints[i]) { + // 현재 관절의 월드 로테이션 + sFingerNode currentWorld; + currentWorld.quat_w = fingerJoints[i]->rotation.w; + currentWorld.quat_x = fingerJoints[i]->rotation.x; + currentWorld.quat_y = fingerJoints[i]->rotation.y; + currentWorld.quat_z = fingerJoints[i]->rotation.z; + + // 부모 로테이션의 역원 + sFingerNode parentInverse; + InverseQuaternion(parentRotation, parentInverse); + + // 로컬 로테이션 = 부모^-1 × 현재 + sFingerNode localRotation; + MultiplyQuaternions(parentInverse, currentWorld, localRotation); + + // 🔧 좌표계 변환 적용 (Rokoko → OptiTrack) - 손별 대칭성 보정 + ConvertRokokoToOptiTrackCoordinates(localRotation, handSide); + + // 🎯 손가락별 축 순서 변경 적용 (엄지와 일반 손가락 분리) + sFingerNode finalRotation = localRotation; + + // 엄지손가락인지 확인 (startIndex == 0이면 엄지) + bool isThumb = (startIndex == 0); + + if (isThumb) { + // 🖐️ 엄지손가락 전용 축 변환 + if (handSide == eGloveHandSide::Left) { + // 🤚 왼손 엄지: 특별한 축 변환 + outputNodes[startIndex + i].quat_w = finalRotation.quat_w; // W는 그대로 + outputNodes[startIndex + i].quat_x = finalRotation.quat_y; // X ← Z + outputNodes[startIndex + i].quat_y = -finalRotation.quat_z; // Y ← Y (그대로) + outputNodes[startIndex + i].quat_z = -finalRotation.quat_x; // Z ← X (엄지 전용) + } else { + // 🖐️ 오른손 엄지: 특별한 축 변환 + outputNodes[startIndex + i].quat_w = finalRotation.quat_w; // W는 그대로 + outputNodes[startIndex + i].quat_x = -finalRotation.quat_y; // X ← Z (엄지 전용) + outputNodes[startIndex + i].quat_y = -finalRotation.quat_z; // Y ← Y (그대로) + outputNodes[startIndex + i].quat_z = finalRotation.quat_x; // Z ← -X (엄지 전용) + } + } else { + // 🤚 일반 손가락 축 변환 + if (handSide == eGloveHandSide::Left) { + // 🤚 왼손 일반 손가락: x y z → z y x (기존 방식) + outputNodes[startIndex + i].quat_w = finalRotation.quat_w; // W는 그대로 + outputNodes[startIndex + i].quat_x = finalRotation.quat_z; // X ← Z + outputNodes[startIndex + i].quat_y = -finalRotation.quat_y; // Y ← -Y + outputNodes[startIndex + i].quat_z = -finalRotation.quat_x; // Z ← -X + } else { + // 🖐️ 오른손 일반 손가락: 대칭적 축 매핑 (미러링 보정) + outputNodes[startIndex + i].quat_w = finalRotation.quat_w; // W는 그대로 + outputNodes[startIndex + i].quat_x = -finalRotation.quat_z; // X ← -Z (미러링) + outputNodes[startIndex + i].quat_y = finalRotation.quat_y; // Y ← Y (그대로) + outputNodes[startIndex + i].quat_z = finalRotation.quat_x; // Z ← X (미러링) + } + } + + // 정규화 + NormalizeQuaternion(outputNodes[startIndex + i]); + + // 다음 계산을 위해 현재 관절을 부모로 설정 + parentRotation = currentWorld; + } + } + + } catch (...) { + // 에러 시 기본값 설정 + for (int i = 0; i < 3 && (startIndex + i) < outputNodes.size(); i++) { + outputNodes[startIndex + i].quat_w = 1.0f; + outputNodes[startIndex + i].quat_x = 0.0f; + outputNodes[startIndex + i].quat_y = 0.0f; + outputNodes[startIndex + i].quat_z = 0.0f; + } + } +} + +bool OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::GetFingerJointRotations(const RokokoData::Body& body, eGloveHandSide handSide, std::vector>& allFingers) +{ + try { + allFingers.clear(); + + if (handSide == eGloveHandSide::Left) { + // 왼손 손가락들 (5개 손가락) + allFingers.resize(5); + + // 엄지 + allFingers[0].push_back(body.leftThumbProximal.get()); + allFingers[0].push_back(body.leftThumbMedial.get()); + allFingers[0].push_back(body.leftThumbDistal.get()); + + // 검지 + allFingers[1].push_back(body.leftIndexProximal.get()); + allFingers[1].push_back(body.leftIndexMedial.get()); + allFingers[1].push_back(body.leftIndexDistal.get()); + + // 중지 + allFingers[2].push_back(body.leftMiddleProximal.get()); + allFingers[2].push_back(body.leftMiddleMedial.get()); + allFingers[2].push_back(body.leftMiddleDistal.get()); + + // 약지 + allFingers[3].push_back(body.leftRingProximal.get()); + allFingers[3].push_back(body.leftRingMedial.get()); + allFingers[3].push_back(body.leftRingDistal.get()); + + // 새끼 + allFingers[4].push_back(body.leftLittleProximal.get()); + allFingers[4].push_back(body.leftLittleMedial.get()); + allFingers[4].push_back(body.leftLittleDistal.get()); + + } else { + // 오른손 손가락들 (5개 손가락) + allFingers.resize(5); + + // 엄지 + allFingers[0].push_back(body.rightThumbProximal.get()); + allFingers[0].push_back(body.rightThumbMedial.get()); + allFingers[0].push_back(body.rightThumbDistal.get()); + + // 검지 + allFingers[1].push_back(body.rightIndexProximal.get()); + allFingers[1].push_back(body.rightIndexMedial.get()); + allFingers[1].push_back(body.rightIndexDistal.get()); + + // 중지 + allFingers[2].push_back(body.rightMiddleProximal.get()); + allFingers[2].push_back(body.rightMiddleMedial.get()); + allFingers[2].push_back(body.rightMiddleDistal.get()); + + // 약지 + allFingers[3].push_back(body.rightRingProximal.get()); + allFingers[3].push_back(body.rightRingMedial.get()); + allFingers[3].push_back(body.rightRingDistal.get()); + + // 새끼 + allFingers[4].push_back(body.rightLittleProximal.get()); + allFingers[4].push_back(body.rightLittleMedial.get()); + allFingers[4].push_back(body.rightLittleDistal.get()); + } + + return true; + + } catch (...) { + allFingers.clear(); + return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// 좌표계 변환 및 디버깅 시스템 +// +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ConvertRokokoToOptiTrackCoordinates(sFingerNode& node, eGloveHandSide handSide) +{ + // 🎯 손별 좌표계 변환 (왼손/오른손 대칭성 보정) + // + // 로코코: Unity 좌표계 (왼손 좌표계, Y-up, Z-forward) + // OptiTrack: 오른손 좌표계 (Y-up, Z-backward) + + float original_x = node.quat_x; + float original_z = node.quat_z; + + if (handSide == eGloveHandSide::Left) { + // 🤚 왼손: 미러링 변환 필요 (좌표계 차이로 인한 대칭성 보정) + node.quat_x = -original_x; // X축 반전 (좌우 미러링) + node.quat_z = -original_z; // Z축 반전 (앞뒤 미러링) + // Y, W는 그대로 유지 + + } else { + // 🖐️ 오른손: 직접 매핑 (OptiTrack과 좌표계 일치) + // X, Z 축 반전하지 않음 + node.quat_x = original_x; // X축 그대로 + node.quat_z = original_z; // Z축 그대로 + // Y, W는 그대로 유지 + } +} + +// 🚀 ApplyThumbOffset 함수 제거됨 - 인라인으로 처리 + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::LogRotationData(const std::string& label, const sFingerNode& rotation) +{ + if (mDeviceManager) { + std::stringstream ss; + ss << "[RokokoGlove] " << label << " - W:" << std::fixed << std::setprecision(3) << rotation.quat_w + << " X:" << rotation.quat_x << " Y:" << rotation.quat_y << " Z:" << rotation.quat_z; + mDeviceManager->MessageToHost(ss.str().c_str(), MessageType_StatusInfo); + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::DebugCoordinateSystem(const RokokoData::Body& body, eGloveHandSide handSide) +{ + // 🚀 실시간성 최우선 - 모든 디버깅 제거 (함수 비활성화) + return; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// 절대 로컬 로테이션 시스템 (손목에 완전히 독립적) +// +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ConvertToAbsoluteLocalRotations(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide) +{ + try { + // 모든 손가락의 관절 데이터 가져오기 + std::vector> allFingers; + if (!GetFingerJointRotations(body, handSide, allFingers)) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Failed to get finger joint rotations for absolute local", MessageType_StatusInfo); + } + return; + } + + // 각 손가락별로 절대 로컬 로테이션 계산 + int nodeIndex = 0; + for (const auto& fingerJoints : allFingers) { + if (fingerJoints.size() >= 3) { // MP, PIP, DIP 최소 3개 + CalculateAbsoluteLocalForFinger(fingerJoints, nodes, nodeIndex, handSide); + nodeIndex += 3; // OptiTrack은 손가락당 3개 노드 (MP, PIP, DIP) + } + } + + if (mDeviceManager) { + std::string handStr = (handSide == eGloveHandSide::Left) ? "Left" : "Right"; + std::string msg = "[RokokoGlove] Applied absolute local rotations for " + handStr + " hand"; + mDeviceManager->MessageToHost(msg.c_str(), MessageType_StatusInfo); + } + + } catch (...) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Error in absolute local rotation conversion", MessageType_StatusInfo); + } + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::CalculateAbsoluteLocalForFinger(const std::vector& fingerJoints, std::vector& outputNodes, int startIndex, eGloveHandSide handSide) +{ + try { + if (fingerJoints.size() < 3 || startIndex + 2 >= outputNodes.size()) { + return; + } + + // 각 관절별로 절대 로컬 로테이션 계산 + for (int i = 0; i < 3 && (startIndex + i) < outputNodes.size(); i++) { + if (i < fingerJoints.size() && fingerJoints[i]) { + // 현재 관절의 월드 로테이션을 가져옴 + sFingerNode worldRotation; + worldRotation.quat_w = fingerJoints[i]->rotation.w; + worldRotation.quat_x = fingerJoints[i]->rotation.x; + worldRotation.quat_y = fingerJoints[i]->rotation.y; + worldRotation.quat_z = fingerJoints[i]->rotation.z; + + // 좌표계 변환 적용 + ConvertRokokoToOptiTrackCoordinates(worldRotation, handSide); + + // 절대적인 로컬 로테이션 계산 + sFingerNode localRotation; + if (i == 0) { + // 첫 번째 관절 (MP): 기본 T-포즈 기준으로 로컬 변환 + // T-포즈 = (0, 0, 0, 1) 즉, 단위 쿼터니언 + localRotation = worldRotation; // 첫 번째는 월드 그대로 사용 + } else { + // 나머지 관절들: 이전 관절 기준으로 상대 로테이션 계산 + sFingerNode parentWorld; + parentWorld.quat_w = fingerJoints[i-1]->rotation.w; + parentWorld.quat_x = fingerJoints[i-1]->rotation.x; + parentWorld.quat_y = fingerJoints[i-1]->rotation.y; + parentWorld.quat_z = fingerJoints[i-1]->rotation.z; + + // 부모도 좌표계 변환 + ConvertRokokoToOptiTrackCoordinates(parentWorld, handSide); + + // 상대 로테이션 = parent^-1 * child + localRotation = CalculateRelativeRotation(parentWorld, worldRotation); + } + + // 결과를 출력 노드에 저장 + outputNodes[startIndex + i].quat_w = localRotation.quat_w; + outputNodes[startIndex + i].quat_x = localRotation.quat_x; + outputNodes[startIndex + i].quat_y = localRotation.quat_y; + outputNodes[startIndex + i].quat_z = localRotation.quat_z; + + // 정규화 + NormalizeQuaternion(outputNodes[startIndex + i]); + } + } + + } catch (...) { + // 에러 시 기본값 설정 + for (int i = 0; i < 3 && (startIndex + i) < outputNodes.size(); i++) { + outputNodes[startIndex + i].quat_w = 1.0f; + outputNodes[startIndex + i].quat_x = 0.0f; + outputNodes[startIndex + i].quat_y = 0.0f; + outputNodes[startIndex + i].quat_z = 0.0f; + } + } +} + +sFingerNode OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::CalculateRelativeRotation(const sFingerNode& parent, const sFingerNode& child) +{ + try { + // 상대 로테이션 = parent^-1 * child + sFingerNode parentInverse; + InverseQuaternion(parent, parentInverse); + + sFingerNode result; + MultiplyQuaternions(parentInverse, child, result); + + // 정규화 + NormalizeQuaternion(result); + + return result; + + } catch (...) { + // 에러 시 단위 쿼터니언 반환 + sFingerNode identity; + identity.quat_w = 1.0f; + identity.quat_x = 0.0f; + identity.quat_y = 0.0f; + identity.quat_z = 0.0f; + return identity; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// 가상 손 구조 시스템 (정확한 계층적 로컬 로테이션) +// +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ConvertToUnityRokokoMethod(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide) +{ + try { + // Unity 방식: 원시 Rokoko 데이터에 T-포즈 오프셋 적용 + std::vector> allFingers; + if (!GetFingerJointRotations(body, handSide, allFingers)) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Failed to get finger joint rotations for Unity method", MessageType_StatusInfo); + } + return; + } + + // 각 손가락별로 Unity 방식 적용 + int nodeIndex = 0; + for (int fingerIndex = 0; fingerIndex < allFingers.size(); fingerIndex++) { + const auto& fingerJoints = allFingers[fingerIndex]; + if (fingerJoints.size() >= 3) { // MP, PIP, DIP 최소 3개 + for (int jointIndex = 0; jointIndex < 3 && (nodeIndex + jointIndex) < nodes.size(); jointIndex++) { + if (jointIndex < fingerJoints.size() && fingerJoints[jointIndex]) { + // Unity 방식 로테이션 적용 + ApplyUnityRokokoRotation(nodes[nodeIndex + jointIndex], fingerJoints[jointIndex], fingerIndex, jointIndex, handSide); + } else { + // 데이터가 없으면 단위 쿼터니언 + nodes[nodeIndex + jointIndex].quat_w = 1.0f; + nodes[nodeIndex + jointIndex].quat_x = 0.0f; + nodes[nodeIndex + jointIndex].quat_y = 0.0f; + nodes[nodeIndex + jointIndex].quat_z = 0.0f; + } + // 노드 ID 설정 + nodes[nodeIndex + jointIndex].node_id = nodeIndex + jointIndex; + } + nodeIndex += 3; // OptiTrack은 손가락당 3개 노드 + } + } + + if (mDeviceManager) { + std::string handStr = (handSide == eGloveHandSide::Left) ? "Left" : "Right"; + std::string msg = "[RokokoGlove] Applied Unity Rokoko method for " + handStr + " hand"; + mDeviceManager->MessageToHost(msg.c_str(), MessageType_StatusInfo); + } + + } catch (...) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Error in Unity Rokoko method conversion", MessageType_StatusInfo); + } + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::BuildVirtualHandFromRokoko(VirtualHand& virtualHand, const RokokoData::Body& body, eGloveHandSide handSide) +{ + try { + // 손목 로테이션 설정 (기준점) + virtualHand.wristRotation.quat_w = 1.0f; + virtualHand.wristRotation.quat_x = 0.0f; + virtualHand.wristRotation.quat_y = 0.0f; + virtualHand.wristRotation.quat_z = 0.0f; + + // 각 손가락의 월드 로테이션 설정 + if (handSide == eGloveHandSide::Left) { + // 왼손 엄지 + if (body.leftThumbProximal) { + virtualHand.thumb.mp.worldRotation.quat_w = body.leftThumbProximal->rotation.w; + virtualHand.thumb.mp.worldRotation.quat_x = body.leftThumbProximal->rotation.x; + virtualHand.thumb.mp.worldRotation.quat_y = body.leftThumbProximal->rotation.y; + virtualHand.thumb.mp.worldRotation.quat_z = body.leftThumbProximal->rotation.z; + virtualHand.thumb.mp.parent = nullptr; // 손목이 부모 + } + if (body.leftThumbMedial) { + virtualHand.thumb.pip.worldRotation.quat_w = body.leftThumbMedial->rotation.w; + virtualHand.thumb.pip.worldRotation.quat_x = body.leftThumbMedial->rotation.x; + virtualHand.thumb.pip.worldRotation.quat_y = body.leftThumbMedial->rotation.y; + virtualHand.thumb.pip.worldRotation.quat_z = body.leftThumbMedial->rotation.z; + virtualHand.thumb.pip.parent = &virtualHand.thumb.mp; + } + if (body.leftThumbDistal) { + virtualHand.thumb.dip.worldRotation.quat_w = body.leftThumbDistal->rotation.w; + virtualHand.thumb.dip.worldRotation.quat_x = body.leftThumbDistal->rotation.x; + virtualHand.thumb.dip.worldRotation.quat_y = body.leftThumbDistal->rotation.y; + virtualHand.thumb.dip.worldRotation.quat_z = body.leftThumbDistal->rotation.z; + virtualHand.thumb.dip.parent = &virtualHand.thumb.pip; + } + + // 왼손 검지 + if (body.leftIndexProximal) { + virtualHand.index.mp.worldRotation.quat_w = body.leftIndexProximal->rotation.w; + virtualHand.index.mp.worldRotation.quat_x = body.leftIndexProximal->rotation.x; + virtualHand.index.mp.worldRotation.quat_y = body.leftIndexProximal->rotation.y; + virtualHand.index.mp.worldRotation.quat_z = body.leftIndexProximal->rotation.z; + virtualHand.index.mp.parent = nullptr; + } + if (body.leftIndexMedial) { + virtualHand.index.pip.worldRotation.quat_w = body.leftIndexMedial->rotation.w; + virtualHand.index.pip.worldRotation.quat_x = body.leftIndexMedial->rotation.x; + virtualHand.index.pip.worldRotation.quat_y = body.leftIndexMedial->rotation.y; + virtualHand.index.pip.worldRotation.quat_z = body.leftIndexMedial->rotation.z; + virtualHand.index.pip.parent = &virtualHand.index.mp; + } + if (body.leftIndexDistal) { + virtualHand.index.dip.worldRotation.quat_w = body.leftIndexDistal->rotation.w; + virtualHand.index.dip.worldRotation.quat_x = body.leftIndexDistal->rotation.x; + virtualHand.index.dip.worldRotation.quat_y = body.leftIndexDistal->rotation.y; + virtualHand.index.dip.worldRotation.quat_z = body.leftIndexDistal->rotation.z; + virtualHand.index.dip.parent = &virtualHand.index.pip; + } + + // 같은 방식으로 중지, 약지, 새끼 (여기서는 간략화) + // TODO: 나머지 손가락들도 동일하게 구현 + + } else { + // 오른손 - 같은 구조, 다른 데이터 + // TODO: 오른손 구현 + } + + } catch (...) { + // 에러 시 기본값 설정 + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::CalculateHierarchicalLocalRotations(VirtualHand& virtualHand) +{ + try { + // 각 손가락의 계층적 로컬 로테이션 계산 + + // 엄지 손가락 + virtualHand.thumb.mp.localRotation = CalculateLocalRotationFromParent(virtualHand.thumb.mp, virtualHand.thumb.mp); // 첫 번째는 손목 기준 + virtualHand.thumb.pip.localRotation = CalculateLocalRotationFromParent(virtualHand.thumb.mp, virtualHand.thumb.pip); + virtualHand.thumb.dip.localRotation = CalculateLocalRotationFromParent(virtualHand.thumb.pip, virtualHand.thumb.dip); + + // 검지 손가락 + virtualHand.index.mp.localRotation = CalculateLocalRotationFromParent(virtualHand.index.mp, virtualHand.index.mp); + virtualHand.index.pip.localRotation = CalculateLocalRotationFromParent(virtualHand.index.mp, virtualHand.index.pip); + virtualHand.index.dip.localRotation = CalculateLocalRotationFromParent(virtualHand.index.pip, virtualHand.index.dip); + + // TODO: 나머지 손가락들 + + } catch (...) { + // 에러 시 기본값 + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ExtractLocalRotationsToNodes(const VirtualHand& virtualHand, std::vector& nodes) +{ + try { + if (nodes.size() < 15) return; + + // OptiTrack 노드 순서에 맞게 추출 + // 엄지: 0, 1, 2 + nodes[0] = virtualHand.thumb.mp.localRotation; + nodes[1] = virtualHand.thumb.pip.localRotation; + nodes[2] = virtualHand.thumb.dip.localRotation; + + // 검지: 3, 4, 5 + nodes[3] = virtualHand.index.mp.localRotation; + nodes[4] = virtualHand.index.pip.localRotation; + nodes[5] = virtualHand.index.dip.localRotation; + + // TODO: 나머지 손가락들 (6~14) + + // 노드 ID 설정 + for (int i = 0; i < 15; i++) { + nodes[i].node_id = i; + NormalizeQuaternion(nodes[i]); + } + + } catch (...) { + // 에러 시 기본값 + } +} + +sFingerNode OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::CalculateLocalRotationFromParent(const VirtualJoint& parent, const VirtualJoint& child) +{ + try { + if (parent.parent == nullptr) { + // 첫 번째 관절은 월드 로테이션 그대로 (손목 기준) + return child.worldRotation; + } else { + // 부모 기준 로컬 로테이션 = parent^-1 * child + sFingerNode parentInverse; + InverseQuaternion(parent.worldRotation, parentInverse); + + sFingerNode localRotation; + MultiplyQuaternions(parentInverse, child.worldRotation, localRotation); + + return localRotation; + } + + } catch (...) { + // 에러 시 단위 쿼터니언 + sFingerNode identity; + identity.quat_w = 1.0f; + identity.quat_x = 0.0f; + identity.quat_y = 0.0f; + identity.quat_z = 0.0f; + return identity; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Unity 방식 Rokoko 데이터 처리 (원시 데이터 + T-포즈 오프셋) +// +sFingerNode OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::GetUnityTPoseOffset(int fingerIndex, int jointIndex, eGloveHandSide handSide) +{ + // Unity의 SmartsuitTPose 데이터 (정확히 동일) + sFingerNode offset; + + if (handSide == eGloveHandSide::Left) { + // 왼손 T-포즈 오프셋 (Unity Actor.cs에서 복사) + if (fingerIndex == 0) { // 엄지 + if (jointIndex == 0) { // Proximal + offset.quat_w = -0.092f; offset.quat_x = -0.561f; offset.quat_y = -0.701f; offset.quat_z = 0.430f; + } else { // Intermediate, Distal + offset.quat_w = -0.271f; offset.quat_x = -0.653f; offset.quat_y = -0.653f; offset.quat_z = 0.271f; + } + } else { // 검지, 중지, 약지, 새끼 + offset.quat_w = -0.500f; offset.quat_x = -0.500f; offset.quat_y = -0.500f; offset.quat_z = 0.500f; + } + } else { + // 오른손 T-포즈 오프셋 (Unity Actor.cs에서 복사) + if (fingerIndex == 0) { // 엄지 + if (jointIndex == 0) { // Proximal + offset.quat_w = 0.092f; offset.quat_x = 0.561f; offset.quat_y = -0.701f; offset.quat_z = 0.430f; + } else { // Intermediate, Distal + offset.quat_w = 0.271f; offset.quat_x = 0.653f; offset.quat_y = -0.653f; offset.quat_z = 0.271f; + } + } else { // 검지, 중지, 약지, 새끼 + offset.quat_w = 0.500f; offset.quat_x = 0.500f; offset.quat_y = -0.500f; offset.quat_z = 0.500f; + } + } + + return offset; +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ApplyUnityRokokoRotation(sFingerNode& node, const RokokoData::ActorJointFrame* jointFrame, int fingerIndex, int jointIndex, eGloveHandSide handSide) +{ + try { + // 1. Rokoko 원시 월드 로테이션 + sFingerNode worldRotation; + worldRotation.quat_w = jointFrame->rotation.w; + worldRotation.quat_x = jointFrame->rotation.x; + worldRotation.quat_y = jointFrame->rotation.y; + worldRotation.quat_z = jointFrame->rotation.z; + + // 2. Unity T-포즈 오프셋 + sFingerNode tposeOffset = GetUnityTPoseOffset(fingerIndex, jointIndex, handSide); + + // 3. Unity Actor.cs 공식 정확히 따라하기 + // Unity: boneTransform.rotation = parentRotation * worldRotation * offset + // OptiTrack: 각 손가락은 독립 센서이므로 worldRotation * offset만 적용 + + // 🎯 핵심: Unity는 worldRotation을 그대로 사용 (로컬 변환 안함!) + // 손가락이 손목에 따라 움직이는 것은 Unity Transform 계층에서 자동 처리됨 + sFingerNode finalRotation; + MultiplyQuaternions(worldRotation, tposeOffset, finalRotation); + + // 4. 결과 적용 + node.quat_w = finalRotation.quat_w; + node.quat_x = finalRotation.quat_x; + node.quat_y = finalRotation.quat_y; + node.quat_z = finalRotation.quat_z; + + // 5. 정규화 + NormalizeQuaternion(node); + + } catch (...) { + // 에러 시 단위 쿼터니언 + node.quat_w = 1.0f; + node.quat_x = 0.0f; + node.quat_y = 0.0f; + node.quat_z = 0.0f; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// 가상 Unity 아바타 시뮬레이션 시스템 +// +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ConvertToVirtualUnityAvatar(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide) +{ + try { + // 1. 가상 Unity 아바타 초기화 + VirtualUnityAvatar avatar; + InitializeVirtualUnityAvatar(avatar); + + // 2. Rokoko 데이터를 가상 아바타에 적용 (월드 로테이션) + ApplyRokokoDataToVirtualAvatar(avatar, body); + + // 3. Unity 방식으로 로컬 로테이션 계산 + CalculateLocalRotationsFromWorldRotations(avatar); + + // 4. 로컬 로테이션을 OptiTrack 노드로 추출 + ExtractLocalRotationsFromVirtualAvatar(avatar, nodes, handSide); + + if (mDeviceManager) { + std::string handStr = (handSide == eGloveHandSide::Left) ? "Left" : "Right"; + std::string msg = "[RokokoGlove] Applied Virtual Unity Avatar for " + handStr + " hand"; + mDeviceManager->MessageToHost(msg.c_str(), MessageType_StatusInfo); + } + + } catch (...) { + if (mDeviceManager) { + mDeviceManager->MessageToHost("[RokokoGlove] Error in Virtual Unity Avatar conversion", MessageType_StatusInfo); + } + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::InitializeVirtualUnityAvatar(VirtualUnityAvatar& avatar) +{ + try { + // Root Transform 초기화 + avatar.root.name = "Root"; + avatar.root.parent = nullptr; + avatar.root.localRotation.quat_w = 1.0f; // Identity + avatar.root.localRotation.quat_x = 0.0f; + avatar.root.localRotation.quat_y = 0.0f; + avatar.root.localRotation.quat_z = 0.0f; + avatar.root.worldRotation.quat_w = 1.0f; + avatar.root.worldRotation.quat_x = 0.0f; + avatar.root.worldRotation.quat_y = 0.0f; + avatar.root.worldRotation.quat_z = 0.0f; + + // === 전체 스켈레톤 계층 구조 생성 (Unity Humanoid와 동일) === + + // 1. 허리 (최상위 부모) + avatar.hips = new VirtualTransform(); + avatar.hips->name = "Hips"; + avatar.hips->parent = &avatar.root; + avatar.hips->localRotation.quat_w = 1.0f; + avatar.hips->localRotation.quat_x = 0.0f; + avatar.hips->localRotation.quat_y = 0.0f; + avatar.hips->localRotation.quat_z = 0.0f; + + // 2. 스파인 (허리의 자식) + avatar.spine = new VirtualTransform(); + avatar.spine->name = "Spine"; + avatar.spine->parent = avatar.hips; + avatar.spine->localRotation.quat_w = 1.0f; + avatar.spine->localRotation.quat_x = 0.0f; + avatar.spine->localRotation.quat_y = 0.0f; + avatar.spine->localRotation.quat_z = 0.0f; + + // 3. 가슴 (스파인의 자식) + avatar.chest = new VirtualTransform(); + avatar.chest->name = "Chest"; + avatar.chest->parent = avatar.spine; + avatar.chest->localRotation.quat_w = 1.0f; + avatar.chest->localRotation.quat_x = 0.0f; + avatar.chest->localRotation.quat_y = 0.0f; + avatar.chest->localRotation.quat_z = 0.0f; + + // 4. 어깨들 (가슴의 자식) + avatar.leftShoulder = new VirtualTransform(); + avatar.leftShoulder->name = "LeftShoulder"; + avatar.leftShoulder->parent = avatar.chest; + avatar.leftShoulder->localRotation.quat_w = 1.0f; + avatar.leftShoulder->localRotation.quat_x = 0.0f; + avatar.leftShoulder->localRotation.quat_y = 0.0f; + avatar.leftShoulder->localRotation.quat_z = 0.0f; + + avatar.rightShoulder = new VirtualTransform(); + avatar.rightShoulder->name = "RightShoulder"; + avatar.rightShoulder->parent = avatar.chest; + avatar.rightShoulder->localRotation.quat_w = 1.0f; + avatar.rightShoulder->localRotation.quat_x = 0.0f; + avatar.rightShoulder->localRotation.quat_y = 0.0f; + avatar.rightShoulder->localRotation.quat_z = 0.0f; + + // 5. 팔 계층 (어깨 → 상완 → 하완 → 손) + avatar.leftUpperArm = new VirtualTransform(); + avatar.leftUpperArm->name = "LeftUpperArm"; + avatar.leftUpperArm->parent = avatar.leftShoulder; + avatar.leftUpperArm->localRotation.quat_w = 1.0f; + avatar.leftUpperArm->localRotation.quat_x = 0.0f; + avatar.leftUpperArm->localRotation.quat_y = 0.0f; + avatar.leftUpperArm->localRotation.quat_z = 0.0f; + + avatar.leftLowerArm = new VirtualTransform(); + avatar.leftLowerArm->name = "LeftLowerArm"; + avatar.leftLowerArm->parent = avatar.leftUpperArm; + avatar.leftLowerArm->localRotation.quat_w = 1.0f; + avatar.leftLowerArm->localRotation.quat_x = 0.0f; + avatar.leftLowerArm->localRotation.quat_y = 0.0f; + avatar.leftLowerArm->localRotation.quat_z = 0.0f; + + avatar.leftHand = new VirtualTransform(); + avatar.leftHand->name = "LeftHand"; + avatar.leftHand->parent = avatar.leftLowerArm; + avatar.leftHand->localRotation.quat_w = 1.0f; + avatar.leftHand->localRotation.quat_x = 0.0f; + avatar.leftHand->localRotation.quat_y = 0.0f; + avatar.leftHand->localRotation.quat_z = 0.0f; + + // 오른쪽 팔도 동일 + avatar.rightUpperArm = new VirtualTransform(); + avatar.rightUpperArm->name = "RightUpperArm"; + avatar.rightUpperArm->parent = avatar.rightShoulder; + avatar.rightUpperArm->localRotation.quat_w = 1.0f; + avatar.rightUpperArm->localRotation.quat_x = 0.0f; + avatar.rightUpperArm->localRotation.quat_y = 0.0f; + avatar.rightUpperArm->localRotation.quat_z = 0.0f; + + avatar.rightLowerArm = new VirtualTransform(); + avatar.rightLowerArm->name = "RightLowerArm"; + avatar.rightLowerArm->parent = avatar.rightUpperArm; + avatar.rightLowerArm->localRotation.quat_w = 1.0f; + avatar.rightLowerArm->localRotation.quat_x = 0.0f; + avatar.rightLowerArm->localRotation.quat_y = 0.0f; + avatar.rightLowerArm->localRotation.quat_z = 0.0f; + + avatar.rightHand = new VirtualTransform(); + avatar.rightHand->name = "RightHand"; + avatar.rightHand->parent = avatar.rightLowerArm; + avatar.rightHand->localRotation.quat_w = 1.0f; + avatar.rightHand->localRotation.quat_x = 0.0f; + avatar.rightHand->localRotation.quat_y = 0.0f; + avatar.rightHand->localRotation.quat_z = 0.0f; + + // 왼손 손가락 계층 구조 생성 + for (int i = 0; i < 3; i++) { + // 엄지 + avatar.leftThumb[i] = new VirtualTransform(); + avatar.leftThumb[i]->name = "LeftThumb" + std::to_string(i); + avatar.leftThumb[i]->parent = (i == 0) ? avatar.leftHand : avatar.leftThumb[i-1]; + avatar.leftThumb[i]->localRotation.quat_w = 1.0f; + avatar.leftThumb[i]->localRotation.quat_x = 0.0f; + avatar.leftThumb[i]->localRotation.quat_y = 0.0f; + avatar.leftThumb[i]->localRotation.quat_z = 0.0f; + + // 검지 + avatar.leftIndex[i] = new VirtualTransform(); + avatar.leftIndex[i]->name = "LeftIndex" + std::to_string(i); + avatar.leftIndex[i]->parent = (i == 0) ? avatar.leftHand : avatar.leftIndex[i-1]; + avatar.leftIndex[i]->localRotation.quat_w = 1.0f; + avatar.leftIndex[i]->localRotation.quat_x = 0.0f; + avatar.leftIndex[i]->localRotation.quat_y = 0.0f; + avatar.leftIndex[i]->localRotation.quat_z = 0.0f; + + // 중지 + avatar.leftMiddle[i] = new VirtualTransform(); + avatar.leftMiddle[i]->name = "LeftMiddle" + std::to_string(i); + avatar.leftMiddle[i]->parent = (i == 0) ? avatar.leftHand : avatar.leftMiddle[i-1]; + avatar.leftMiddle[i]->localRotation.quat_w = 1.0f; + avatar.leftMiddle[i]->localRotation.quat_x = 0.0f; + avatar.leftMiddle[i]->localRotation.quat_y = 0.0f; + avatar.leftMiddle[i]->localRotation.quat_z = 0.0f; + + // 약지 + avatar.leftRing[i] = new VirtualTransform(); + avatar.leftRing[i]->name = "LeftRing" + std::to_string(i); + avatar.leftRing[i]->parent = (i == 0) ? avatar.leftHand : avatar.leftRing[i-1]; + avatar.leftRing[i]->localRotation.quat_w = 1.0f; + avatar.leftRing[i]->localRotation.quat_x = 0.0f; + avatar.leftRing[i]->localRotation.quat_y = 0.0f; + avatar.leftRing[i]->localRotation.quat_z = 0.0f; + + // 새끼 + avatar.leftLittle[i] = new VirtualTransform(); + avatar.leftLittle[i]->name = "LeftLittle" + std::to_string(i); + avatar.leftLittle[i]->parent = (i == 0) ? avatar.leftHand : avatar.leftLittle[i-1]; + avatar.leftLittle[i]->localRotation.quat_w = 1.0f; + avatar.leftLittle[i]->localRotation.quat_x = 0.0f; + avatar.leftLittle[i]->localRotation.quat_y = 0.0f; + avatar.leftLittle[i]->localRotation.quat_z = 0.0f; + } + + // 오른손도 동일하게 (간략화) + for (int i = 0; i < 3; i++) { + avatar.rightThumb[i] = new VirtualTransform(); + avatar.rightThumb[i]->name = "RightThumb" + std::to_string(i); + avatar.rightThumb[i]->parent = (i == 0) ? avatar.rightHand : avatar.rightThumb[i-1]; + avatar.rightThumb[i]->localRotation.quat_w = 1.0f; + avatar.rightThumb[i]->localRotation.quat_x = 0.0f; + avatar.rightThumb[i]->localRotation.quat_y = 0.0f; + avatar.rightThumb[i]->localRotation.quat_z = 0.0f; + + avatar.rightIndex[i] = new VirtualTransform(); + avatar.rightIndex[i]->name = "RightIndex" + std::to_string(i); + avatar.rightIndex[i]->parent = (i == 0) ? avatar.rightHand : avatar.rightIndex[i-1]; + avatar.rightIndex[i]->localRotation.quat_w = 1.0f; + avatar.rightIndex[i]->localRotation.quat_x = 0.0f; + avatar.rightIndex[i]->localRotation.quat_y = 0.0f; + avatar.rightIndex[i]->localRotation.quat_z = 0.0f; + + // 나머지 손가락들도 필요시 추가... + } + + } catch (...) { + // 에러 시 기본값 설정 + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ApplyRokokoDataToVirtualAvatar(VirtualUnityAvatar& avatar, const RokokoData::Body& body) +{ + try { + // === Rokoko 전신 + 손가락 데이터를 가상 아바타에 적용 === + // Unity BodyFrame과 동일한 구조로 전신 스켈레톤 데이터 적용 + + // 1. 전신 스켈레톤 데이터 적용 + if (body.hip) { + avatar.hips->worldRotation.quat_w = body.hip->rotation.w; + avatar.hips->worldRotation.quat_x = body.hip->rotation.x; + avatar.hips->worldRotation.quat_y = body.hip->rotation.y; + avatar.hips->worldRotation.quat_z = body.hip->rotation.z; + } + + if (body.spine) { + avatar.spine->worldRotation.quat_w = body.spine->rotation.w; + avatar.spine->worldRotation.quat_x = body.spine->rotation.x; + avatar.spine->worldRotation.quat_y = body.spine->rotation.y; + avatar.spine->worldRotation.quat_z = body.spine->rotation.z; + } + + if (body.chest) { + avatar.chest->worldRotation.quat_w = body.chest->rotation.w; + avatar.chest->worldRotation.quat_x = body.chest->rotation.x; + avatar.chest->worldRotation.quat_y = body.chest->rotation.y; + avatar.chest->worldRotation.quat_z = body.chest->rotation.z; + } + + // 2. 어깨 데이터 적용 + if (body.leftShoulder) { + avatar.leftShoulder->worldRotation.quat_w = body.leftShoulder->rotation.w; + avatar.leftShoulder->worldRotation.quat_x = body.leftShoulder->rotation.x; + avatar.leftShoulder->worldRotation.quat_y = body.leftShoulder->rotation.y; + avatar.leftShoulder->worldRotation.quat_z = body.leftShoulder->rotation.z; + } + + if (body.rightShoulder) { + avatar.rightShoulder->worldRotation.quat_w = body.rightShoulder->rotation.w; + avatar.rightShoulder->worldRotation.quat_x = body.rightShoulder->rotation.x; + avatar.rightShoulder->worldRotation.quat_y = body.rightShoulder->rotation.y; + avatar.rightShoulder->worldRotation.quat_z = body.rightShoulder->rotation.z; + } + + // 3. 팔 데이터 적용 + if (body.leftUpperArm) { + avatar.leftUpperArm->worldRotation.quat_w = body.leftUpperArm->rotation.w; + avatar.leftUpperArm->worldRotation.quat_x = body.leftUpperArm->rotation.x; + avatar.leftUpperArm->worldRotation.quat_y = body.leftUpperArm->rotation.y; + avatar.leftUpperArm->worldRotation.quat_z = body.leftUpperArm->rotation.z; + } + + if (body.leftLowerArm) { + avatar.leftLowerArm->worldRotation.quat_w = body.leftLowerArm->rotation.w; + avatar.leftLowerArm->worldRotation.quat_x = body.leftLowerArm->rotation.x; + avatar.leftLowerArm->worldRotation.quat_y = body.leftLowerArm->rotation.y; + avatar.leftLowerArm->worldRotation.quat_z = body.leftLowerArm->rotation.z; + } + + if (body.leftHand) { + avatar.leftHand->worldRotation.quat_w = body.leftHand->rotation.w; + avatar.leftHand->worldRotation.quat_x = body.leftHand->rotation.x; + avatar.leftHand->worldRotation.quat_y = body.leftHand->rotation.y; + avatar.leftHand->worldRotation.quat_z = body.leftHand->rotation.z; + } + + // 오른쪽 팔도 동일 + if (body.rightUpperArm) { + avatar.rightUpperArm->worldRotation.quat_w = body.rightUpperArm->rotation.w; + avatar.rightUpperArm->worldRotation.quat_x = body.rightUpperArm->rotation.x; + avatar.rightUpperArm->worldRotation.quat_y = body.rightUpperArm->rotation.y; + avatar.rightUpperArm->worldRotation.quat_z = body.rightUpperArm->rotation.z; + } + + if (body.rightLowerArm) { + avatar.rightLowerArm->worldRotation.quat_w = body.rightLowerArm->rotation.w; + avatar.rightLowerArm->worldRotation.quat_x = body.rightLowerArm->rotation.x; + avatar.rightLowerArm->worldRotation.quat_y = body.rightLowerArm->rotation.y; + avatar.rightLowerArm->worldRotation.quat_z = body.rightLowerArm->rotation.z; + } + + if (body.rightHand) { + avatar.rightHand->worldRotation.quat_w = body.rightHand->rotation.w; + avatar.rightHand->worldRotation.quat_x = body.rightHand->rotation.x; + avatar.rightHand->worldRotation.quat_y = body.rightHand->rotation.y; + avatar.rightHand->worldRotation.quat_z = body.rightHand->rotation.z; + } + + // 4. 손가락 데이터 적용 + + // 왼손 엄지 + if (body.leftThumbProximal) { + avatar.leftThumb[0]->worldRotation.quat_w = body.leftThumbProximal->rotation.w; + avatar.leftThumb[0]->worldRotation.quat_x = body.leftThumbProximal->rotation.x; + avatar.leftThumb[0]->worldRotation.quat_y = body.leftThumbProximal->rotation.y; + avatar.leftThumb[0]->worldRotation.quat_z = body.leftThumbProximal->rotation.z; + } + if (body.leftThumbMedial) { + avatar.leftThumb[1]->worldRotation.quat_w = body.leftThumbMedial->rotation.w; + avatar.leftThumb[1]->worldRotation.quat_x = body.leftThumbMedial->rotation.x; + avatar.leftThumb[1]->worldRotation.quat_y = body.leftThumbMedial->rotation.y; + avatar.leftThumb[1]->worldRotation.quat_z = body.leftThumbMedial->rotation.z; + } + if (body.leftThumbDistal) { + avatar.leftThumb[2]->worldRotation.quat_w = body.leftThumbDistal->rotation.w; + avatar.leftThumb[2]->worldRotation.quat_x = body.leftThumbDistal->rotation.x; + avatar.leftThumb[2]->worldRotation.quat_y = body.leftThumbDistal->rotation.y; + avatar.leftThumb[2]->worldRotation.quat_z = body.leftThumbDistal->rotation.z; + } + + // 왼손 검지 + if (body.leftIndexProximal) { + avatar.leftIndex[0]->worldRotation.quat_w = body.leftIndexProximal->rotation.w; + avatar.leftIndex[0]->worldRotation.quat_x = body.leftIndexProximal->rotation.x; + avatar.leftIndex[0]->worldRotation.quat_y = body.leftIndexProximal->rotation.y; + avatar.leftIndex[0]->worldRotation.quat_z = body.leftIndexProximal->rotation.z; + } + if (body.leftIndexMedial) { + avatar.leftIndex[1]->worldRotation.quat_w = body.leftIndexMedial->rotation.w; + avatar.leftIndex[1]->worldRotation.quat_x = body.leftIndexMedial->rotation.x; + avatar.leftIndex[1]->worldRotation.quat_y = body.leftIndexMedial->rotation.y; + avatar.leftIndex[1]->worldRotation.quat_z = body.leftIndexMedial->rotation.z; + } + if (body.leftIndexDistal) { + avatar.leftIndex[2]->worldRotation.quat_w = body.leftIndexDistal->rotation.w; + avatar.leftIndex[2]->worldRotation.quat_x = body.leftIndexDistal->rotation.x; + avatar.leftIndex[2]->worldRotation.quat_y = body.leftIndexDistal->rotation.y; + avatar.leftIndex[2]->worldRotation.quat_z = body.leftIndexDistal->rotation.z; + } + + // TODO: 나머지 손가락들과 오른손도 추가 + + } catch (...) { + // 에러 시 기본값 유지 + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::CalculateLocalRotationsFromWorldRotations(VirtualUnityAvatar& avatar) +{ + try { + // Unity 공식: localRotation = Quaternion.Inverse(parent.rotation) * child.rotation + + // === 전체 스켈레톤 계층적 로컬 로테이션 계산 === + + // 1. 몸통 계층 계산 + if (avatar.hips && avatar.hips->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.hips->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.hips->worldRotation, avatar.hips->localRotation); + } + + if (avatar.spine && avatar.spine->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.spine->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.spine->worldRotation, avatar.spine->localRotation); + } + + if (avatar.chest && avatar.chest->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.chest->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.chest->worldRotation, avatar.chest->localRotation); + } + + // 2. 어깨 계층 계산 + if (avatar.leftShoulder && avatar.leftShoulder->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.leftShoulder->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.leftShoulder->worldRotation, avatar.leftShoulder->localRotation); + } + + if (avatar.rightShoulder && avatar.rightShoulder->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.rightShoulder->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.rightShoulder->worldRotation, avatar.rightShoulder->localRotation); + } + + // 3. 팔 계층 계산 (상완 → 하완 → 손) + if (avatar.leftUpperArm && avatar.leftUpperArm->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.leftUpperArm->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.leftUpperArm->worldRotation, avatar.leftUpperArm->localRotation); + } + + if (avatar.leftLowerArm && avatar.leftLowerArm->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.leftLowerArm->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.leftLowerArm->worldRotation, avatar.leftLowerArm->localRotation); + } + + if (avatar.leftHand && avatar.leftHand->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.leftHand->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.leftHand->worldRotation, avatar.leftHand->localRotation); + } + + // 오른쪽 팔도 동일 + if (avatar.rightUpperArm && avatar.rightUpperArm->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.rightUpperArm->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.rightUpperArm->worldRotation, avatar.rightUpperArm->localRotation); + } + + if (avatar.rightLowerArm && avatar.rightLowerArm->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.rightLowerArm->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.rightLowerArm->worldRotation, avatar.rightLowerArm->localRotation); + } + + if (avatar.rightHand && avatar.rightHand->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.rightHand->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.rightHand->worldRotation, avatar.rightHand->localRotation); + } + + // 4. 손가락 계층 계산 (이제 손을 올바른 부모로 사용) + for (int i = 0; i < 3; i++) { + if (avatar.leftThumb[i] && avatar.leftThumb[i]->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.leftThumb[i]->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.leftThumb[i]->worldRotation, avatar.leftThumb[i]->localRotation); + } + + if (avatar.leftIndex[i] && avatar.leftIndex[i]->parent) { + sFingerNode parentInverse; + InverseQuaternion(avatar.leftIndex[i]->parent->worldRotation, parentInverse); + MultiplyQuaternions(parentInverse, avatar.leftIndex[i]->worldRotation, avatar.leftIndex[i]->localRotation); + } + + // TODO: 나머지 손가락들과 오른손도 추가 + } + + } catch (...) { + // 에러 시 기본값 유지 + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::ExtractLocalRotationsFromVirtualAvatar(const VirtualUnityAvatar& avatar, std::vector& nodes, eGloveHandSide handSide) +{ + try { + if (nodes.size() < 15) return; + + if (handSide == eGloveHandSide::Left) { + // 왼손 엄지: 0, 1, 2 + for (int i = 0; i < 3; i++) { + if (avatar.leftThumb[i]) { + nodes[i] = avatar.leftThumb[i]->localRotation; + nodes[i].node_id = i; + NormalizeQuaternion(nodes[i]); + } + } + + // 왼손 검지: 3, 4, 5 + for (int i = 0; i < 3; i++) { + if (avatar.leftIndex[i]) { + nodes[3 + i] = avatar.leftIndex[i]->localRotation; + nodes[3 + i].node_id = 3 + i; + NormalizeQuaternion(nodes[3 + i]); + } + } + + // TODO: 나머지 손가락들 (6~14) + } else { + // 오른손 처리 + // TODO: 오른손 구현 + } + + } catch (...) { + // 에러 시 기본값 + } +} + +void OptiTrackPluginDevices::ExampleDevice::ExampleGloveAdapterSingleton::UpdateWorldRotationFromParent(VirtualTransform* transform) +{ + // Unity 공식: rotation = parent.rotation * localRotation + try { + if (transform && transform->parent) { + MultiplyQuaternions(transform->parent->worldRotation, transform->localRotation, transform->worldRotation); + } + } catch (...) { + // 에러 시 기본값 유지 + } } \ No newline at end of file diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/ExampleGloveAdapterSingleton.h b/Optitrack Rokoko Glove/RokokoGloveDevice/ExampleGloveAdapterSingleton.h index 6f35ad9c..67029d97 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/ExampleGloveAdapterSingleton.h +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/ExampleGloveAdapterSingleton.h @@ -134,9 +134,13 @@ namespace OptiTrackPluginDevices * Example data map for storing aggregated device data. */ uint16_t mDeviceCount = 0; - std::vector mDetectedDevices; - std::unordered_map mLatestGloveData; - std::unordered_map mLatestDeviceInfo; + std::vector mDetectedDevices; + std::unordered_map mLatestGloveData; + std::unordered_map mLatestDeviceInfo; + + // T-포즈 캘리브레이션 데이터 (로컬 로테이션 계산을 위해 필요) + std::unordered_map> mTPoseReferences; // 장치별 T-포즈 기준값 + std::unordered_map mTPoseCalibrated; // 장치별 캘리브레이션 상태 /** * Rokoko integration members @@ -173,14 +177,9 @@ namespace OptiTrackPluginDevices */ void UpdateDeviceInfo(uint64_t deviceId); - /** - * Detect and create Rokoko devices dynamically - */ + // Dynamic Device Detection and Management void DetectAndCreateRokokoDevices(); - - /** - * Process data for multiple devices (left/right hand) - */ + void DetectActorsFromRokokoData(const RokokoData::LiveFrame_v4& rokokoFrame); void ProcessMultipleDeviceData(const RokokoData::LiveFrame_v4& rokokoFrame); /** @@ -202,6 +201,128 @@ namespace OptiTrackPluginDevices * Map individual joint data */ void MapJoint(const RokokoData::ActorJointFrame& rokokoJoint, sFingerNode& optiTrackNode); + + // 로컬 로테이션 변환 함수들 + void ConvertToLocalRotations(std::vector& nodes, eGloveHandSide handSide); + void ApplyLocalRotation(sFingerNode& childNode, const sFingerNode& parentNode); + + // 쿼터니언 연산 헬퍼 함수들 + void MultiplyQuaternions(const sFingerNode& q1, const sFingerNode& q2, sFingerNode& result); + void InverseQuaternion(const sFingerNode& q, sFingerNode& result); + void NormalizeQuaternion(sFingerNode& q); + + // T-포즈 캘리브레이션 시스템 + void CalibrateTPose(uint64_t deviceId, const std::vector& tPoseData); + void ApplyTPoseOffset(std::vector& nodes, uint64_t deviceId); + bool IsTPoseCalibrated(uint64_t deviceId) const; + void ResetTPoseCalibration(uint64_t deviceId); + + // 손목 기준 로컬 변환 시스템 (기존) + void ConvertToWristLocalRotations(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide); + bool GetWristRotation(const RokokoData::Body& body, eGloveHandSide handSide, sFingerNode& wristRotation); + + // 진짜 로컬 로테이션 변환 시스템 (계층적) + void ConvertToTrueLocalRotations(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide); + void CalculateFingerLocalRotations(const std::vector& fingerJoints, std::vector& outputNodes, int startIndex, const RokokoData::Body& body, eGloveHandSide handSide); + bool GetFingerJointRotations(const RokokoData::Body& body, eGloveHandSide handSide, std::vector>& allFingers); + + // 좌표계 변환 및 디버깅 + void ConvertRokokoToOptiTrackCoordinates(sFingerNode& node, eGloveHandSide handSide); + void LogRotationData(const std::string& label, const sFingerNode& rotation); + void DebugCoordinateSystem(const RokokoData::Body& body, eGloveHandSide handSide); + + // 절대 로컬 로테이션 시스템 (손목에 완전히 독립적) + void ConvertToAbsoluteLocalRotations(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide); + void CalculateAbsoluteLocalForFinger(const std::vector& fingerJoints, std::vector& outputNodes, int startIndex, eGloveHandSide handSide); + sFingerNode CalculateRelativeRotation(const sFingerNode& parent, const sFingerNode& child); + + // Unity 방식 Rokoko 데이터 처리 (원시 데이터 + T-포즈 오프셋) + void ConvertToUnityRokokoMethod(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide); + sFingerNode GetUnityTPoseOffset(int fingerIndex, int jointIndex, eGloveHandSide handSide); + void ApplyUnityRokokoRotation(sFingerNode& node, const RokokoData::ActorJointFrame* jointFrame, int fingerIndex, int jointIndex, eGloveHandSide handSide); + + // 가상 Unity 아바타 시뮬레이션 시스템 + void ConvertToVirtualUnityAvatar(std::vector& nodes, const RokokoData::Body& body, eGloveHandSide handSide); + + // Unity Transform 시뮬레이션 구조 + struct VirtualTransform { + sFingerNode localRotation; // Unity localRotation + sFingerNode worldRotation; // Unity rotation (world) + VirtualTransform* parent; // Unity parent transform + std::vector children; // Unity children + std::string name; // 디버깅용 + }; + + struct VirtualUnityAvatar { + // 전체 스켈레톤 구조 (Unity Humanoid와 동일한 계층) + VirtualTransform root; + + // 몸통 구조 + VirtualTransform* hips; // 허리 (Root) + VirtualTransform* spine; // 스파인 + VirtualTransform* chest; // 가슴 + + // 어깨 구조 + VirtualTransform* leftShoulder; // 왼쪽 어깨 + VirtualTransform* rightShoulder; // 오른쪽 어깨 + + // 팔 구조 + VirtualTransform* leftUpperArm; // 왼쪽 상완 + VirtualTransform* leftLowerArm; // 왼쪽 하완 + VirtualTransform* leftHand; // 왼쪽 손 + + VirtualTransform* rightUpperArm; // 오른쪽 상완 + VirtualTransform* rightLowerArm; // 오른쪽 하완 + VirtualTransform* rightHand; // 오른쪽 손 + + // 손가락 구조 (Unity 계층과 동일) + VirtualTransform* leftThumb[3]; // Proximal, Intermediate, Distal + VirtualTransform* leftIndex[3]; + VirtualTransform* leftMiddle[3]; + VirtualTransform* leftRing[3]; + VirtualTransform* leftLittle[3]; + + VirtualTransform* rightThumb[3]; + VirtualTransform* rightIndex[3]; + VirtualTransform* rightMiddle[3]; + VirtualTransform* rightRing[3]; + VirtualTransform* rightLittle[3]; + }; + + // 가상 Unity 아바타 헬퍼 함수들 + void InitializeVirtualUnityAvatar(VirtualUnityAvatar& avatar); + void ApplyRokokoDataToVirtualAvatar(VirtualUnityAvatar& avatar, const RokokoData::Body& body); + void CalculateLocalRotationsFromWorldRotations(VirtualUnityAvatar& avatar); + void ExtractLocalRotationsFromVirtualAvatar(const VirtualUnityAvatar& avatar, std::vector& nodes, eGloveHandSide handSide); + void UpdateWorldRotationFromParent(VirtualTransform* transform); + + // 가상 손 노드 구조 + struct VirtualJoint { + sFingerNode worldRotation; + sFingerNode localRotation; + VirtualJoint* parent; + }; + + struct VirtualFinger { + VirtualJoint mp; // Metacarpophalangeal + VirtualJoint pip; // Proximal Interphalangeal + VirtualJoint dip; // Distal Interphalangeal + }; + + struct VirtualHand { + sFingerNode wristRotation; + VirtualFinger thumb; + VirtualFinger index; + VirtualFinger middle; + VirtualFinger ring; + VirtualFinger little; + }; + + // 가상 손 구조 헬퍼 함수들 + void BuildVirtualHandFromRokoko(VirtualHand& virtualHand, const RokokoData::Body& body, eGloveHandSide handSide); + void CalculateHierarchicalLocalRotations(VirtualHand& virtualHand); + void ExtractLocalRotationsToNodes(const VirtualHand& virtualHand, std::vector& nodes); + sFingerNode CalculateLocalRotationFromParent(const VirtualJoint& parent, const VirtualJoint& child); protected: diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/GloveDataFormat.h b/Optitrack Rokoko Glove/RokokoGloveDevice/GloveDataFormat.h index d434bca8..193eb2a6 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/GloveDataFormat.h +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/GloveDataFormat.h @@ -74,6 +74,7 @@ struct sGloveDeviceBaseInfo int battery = 0 ; int signalStrength= 0; eGloveHandSide handSide = eGloveHandSide::Unknown; + std::string actorName = ""; // Actor 이름 (다중 장비 구분용) }; diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/LZ4Wrapper.cpp b/Optitrack Rokoko Glove/RokokoGloveDevice/LZ4Wrapper.cpp index 8623e5e7..302fe07c 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/LZ4Wrapper.cpp +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/LZ4Wrapper.cpp @@ -3,9 +3,48 @@ //====================================================================================================== #include "LZ4Wrapper.h" -#include "lz4.h" #include #include +#include + +// Unity LZ4 DLL 동적 로딩 +static HMODULE lz4Module = nullptr; +static decltype(&Unity_LZ4_uncompressSize) pUnity_LZ4_uncompressSize = nullptr; +static decltype(&Unity_LZ4_decompress) pUnity_LZ4_decompress = nullptr; + +static bool LoadUnityLZ4() +{ + if (lz4Module == nullptr) { + // 다양한 경로에서 Unity LZ4 DLL 로드 시도 + const wchar_t* dllPaths[] = { + L"lz4.dll", // 현재 디렉토리 + L".\\lz4.dll", // 명시적 현재 디렉토리 + L"x64\\Debug\\lz4.dll", // 디버그 폴더 + L"C:\\Users\\user\\Documents\\Streamingle_URP\\Assets\\External\\Rokoko\\Scripts\\Plugins\\LZ4\\x86_64\\lz4.dll" // Unity 절대 경로 + }; + + for (const auto& path : dllPaths) { + lz4Module = LoadLibrary(path); + if (lz4Module != nullptr) { + // DLL 로드 성공 - 함수 포인터 획득 + pUnity_LZ4_uncompressSize = (decltype(pUnity_LZ4_uncompressSize))GetProcAddress(lz4Module, "Unity_LZ4_uncompressSize"); + pUnity_LZ4_decompress = (decltype(pUnity_LZ4_decompress))GetProcAddress(lz4Module, "Unity_LZ4_decompress"); + + if (pUnity_LZ4_uncompressSize != nullptr && pUnity_LZ4_decompress != nullptr) { + // 성공 + break; + } else { + // 함수를 찾지 못함 - DLL 언로드하고 다음 시도 + FreeLibrary(lz4Module); + lz4Module = nullptr; + pUnity_LZ4_uncompressSize = nullptr; + pUnity_LZ4_decompress = nullptr; + } + } + } + } + return (lz4Module != nullptr && pUnity_LZ4_uncompressSize != nullptr && pUnity_LZ4_decompress != nullptr); +} namespace RokokoIntegration { @@ -17,33 +56,38 @@ namespace RokokoIntegration return {}; } - // LZ4 데이터 유효성 검사 - if (!IsValidLZ4Data(compressedData, compressedSize)) { + // Unity LZ4 DLL 로드 + if (!LoadUnityLZ4()) { return {}; } - // 압축 해제된 크기 추정 - int decompressedSize = GetDecompressedSize(compressedData, compressedSize); - if (decompressedSize <= 0) { + // Unity 방식 정확히 구현 + // 1. Unity_LZ4_uncompressSize로 압축 해제된 크기 구하기 + int uncompressedSize = pUnity_LZ4_uncompressSize( + reinterpret_cast(compressedData), + compressedSize + ); + + if (uncompressedSize <= 0) { return {}; } // 크기 유효성 검사 - if (!ValidateDecompressedSize(compressedSize, decompressedSize)) { + if (uncompressedSize > MAX_DECOMPRESSED_SIZE) { return {}; } - // 압축 해제 실행 - std::vector decompressed(decompressedSize); - int actualSize = LZ4_decompress_safe( + // 2. Unity_LZ4_decompress로 압축 해제 + std::vector decompressed(uncompressedSize); + int result = pUnity_LZ4_decompress( reinterpret_cast(compressedData), - reinterpret_cast(decompressed.data()), compressedSize, - decompressedSize + reinterpret_cast(decompressed.data()), + uncompressedSize ); - // 압축 해제 결과 검증 - if (actualSize != decompressedSize) { + // Unity에서는 result != 0이면 실패 + if (result != 0) { return {}; } @@ -61,20 +105,37 @@ namespace RokokoIntegration return false; } - // LZ4 매직 넘버 확인 (간단한 검증) - // 실제로는 더 정교한 검증이 필요할 수 있음 + // Rokoko Studio의 LZ4 데이터는 일반적으로 JSON이 아니므로 + // 첫 번째 바이트가 '{'가 아닌 경우 LZ4로 간주 + if (size > 0 && data[0] == '{') { + return false; // JSON 데이터는 LZ4가 아님 + } + + // 기본적인 LZ4 매직 넘버 확인 + // LZ4 프레임 헤더의 일부 패턴 확인 + if (size >= 4) { + // LZ4 프레임 헤더의 매직 넘버 (0x184D2204) + if (data[0] == 0x04 && data[1] == 0x22 && data[2] == 0x4D && data[3] == 0x18) { + return true; + } + } + + // 매직 넘버가 없어도 압축된 데이터로 간주 (Rokoko Studio 특성상) return true; } int LZ4Wrapper::GetDecompressedSize(const uint8_t* compressedData, int compressedSize) { try { - // LZ4에서 압축 해제된 크기 추정 - int decompressedSize = LZ4_decompress_safe( + // Unity LZ4 DLL 로드 + if (!LoadUnityLZ4()) { + return -1; + } + + // Unity 방식으로 압축 해제된 크기 구하기 + int decompressedSize = pUnity_LZ4_uncompressSize( reinterpret_cast(compressedData), - nullptr, - compressedSize, - 0 + compressedSize ); return decompressedSize; diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/LZ4Wrapper.h b/Optitrack Rokoko Glove/RokokoGloveDevice/LZ4Wrapper.h index 50e6ac23..120230f3 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/LZ4Wrapper.h +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/LZ4Wrapper.h @@ -10,6 +10,12 @@ #include #include +// Unity LZ4 함수들 선언 +extern "C" { + int Unity_LZ4_uncompressSize(const char* srcBuffer, int srcSize); + int Unity_LZ4_decompress(const char* src, int srcSize, char* dst, int dstCapacity); +} + namespace RokokoIntegration { class LZ4Wrapper diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoData.h b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoData.h index b4abbf0e..8f166964 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoData.h +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoData.h @@ -37,9 +37,39 @@ namespace RokokoData Vector4Frame rotation; }; - // Body structure containing finger joints + // Body structure containing full skeleton (Unity BodyFrame와 동일) struct Body { + // 전신 스켈레톤 데이터 (Unity BodyFrame과 동일) + std::shared_ptr hip; + std::shared_ptr spine; + std::shared_ptr chest; + std::shared_ptr neck; + std::shared_ptr head; + + std::shared_ptr leftShoulder; + std::shared_ptr leftUpperArm; + std::shared_ptr leftLowerArm; + std::shared_ptr leftHand; + + std::shared_ptr rightShoulder; + std::shared_ptr rightUpperArm; + std::shared_ptr rightLowerArm; + std::shared_ptr rightHand; + + // 다리 데이터 (필요시) + std::shared_ptr leftUpLeg; + std::shared_ptr leftLeg; + std::shared_ptr leftFoot; + std::shared_ptr leftToe; + std::shared_ptr leftToeEnd; + + std::shared_ptr rightUpLeg; + std::shared_ptr rightLeg; + std::shared_ptr rightFoot; + std::shared_ptr rightToe; + std::shared_ptr rightToeEnd; + // Left hand finger joints std::shared_ptr leftThumbProximal; std::shared_ptr leftThumbMedial; diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoDataParser.cpp b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoDataParser.cpp index 54338487..6cb73c01 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoDataParser.cpp +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoDataParser.cpp @@ -14,101 +14,173 @@ namespace RokokoIntegration bool RokokoDataParser::ParseLiveFrame(const std::string& jsonString, RokokoData::LiveFrame_v4& frame) { try { - // 간단한 JSON 파싱 구현 (실제로는 nlohmann/json 라이브러리 사용 권장) - // 현재는 기본 구조만 생성 + // nlohmann/json을 사용하여 JSON 파싱 + nlohmann::json j = nlohmann::json::parse(jsonString); - // 기본 프레임 데이터 초기화 - frame.scene.actors.clear(); - frame.scene.actors.push_back(RokokoData::ActorData()); + // Unity JsonLiveSerializerV3.cs와 동일한 구조로 파싱 - // 기본 손가락 데이터 구조 생성 - auto& actor = frame.scene.actors[0]; - - // 왼손 데이터 초기화 (모든 손가락) - // 엄지 - actor.body.leftThumbMedial = std::make_shared(); - actor.body.leftThumbDistal = std::make_shared(); - actor.body.leftThumbTip = std::make_shared(); - // 검지 - actor.body.leftIndexMedial = std::make_shared(); - actor.body.leftIndexDistal = std::make_shared(); - actor.body.leftIndexTip = std::make_shared(); - // 중지 - actor.body.leftMiddleMedial = std::make_shared(); - actor.body.leftMiddleDistal = std::make_shared(); - actor.body.leftMiddleTip = std::make_shared(); - // 약지 - actor.body.leftRingMedial = std::make_shared(); - actor.body.leftRingDistal = std::make_shared(); - actor.body.leftRingTip = std::make_shared(); - // 새끼 - actor.body.leftLittleMedial = std::make_shared(); - actor.body.leftLittleDistal = std::make_shared(); - actor.body.leftLittleTip = std::make_shared(); - - // 오른손 데이터 초기화 (모든 손가락) - // 엄지 - actor.body.rightThumbMedial = std::make_shared(); - actor.body.rightThumbDistal = std::make_shared(); - actor.body.rightThumbTip = std::make_shared(); - // 검지 - actor.body.rightIndexMedial = std::make_shared(); - actor.body.rightIndexDistal = std::make_shared(); - actor.body.rightIndexTip = std::make_shared(); - // 중지 - actor.body.rightMiddleMedial = std::make_shared(); - actor.body.rightMiddleDistal = std::make_shared(); - actor.body.rightMiddleTip = std::make_shared(); - // 약지 - actor.body.rightRingMedial = std::make_shared(); - actor.body.rightRingDistal = std::make_shared(); - actor.body.rightRingTip = std::make_shared(); - // 새끼 - actor.body.rightLittleMedial = std::make_shared(); - actor.body.rightLittleDistal = std::make_shared(); - actor.body.rightLittleTip = std::make_shared(); - - // 기본 쿼터니언 값 설정 (정규화된 단위 쿼터니언) - RokokoData::Vector4Frame defaultRotation = {1.0f, 0.0f, 0.0f, 0.0f}; - - // 왼손 기본값 설정 - actor.body.leftThumbMedial->rotation = defaultRotation; - actor.body.leftThumbDistal->rotation = defaultRotation; - actor.body.leftThumbTip->rotation = defaultRotation; - actor.body.leftIndexMedial->rotation = defaultRotation; - actor.body.leftIndexDistal->rotation = defaultRotation; - actor.body.leftIndexTip->rotation = defaultRotation; - actor.body.leftMiddleMedial->rotation = defaultRotation; - actor.body.leftMiddleDistal->rotation = defaultRotation; - actor.body.leftMiddleTip->rotation = defaultRotation; - actor.body.leftRingMedial->rotation = defaultRotation; - actor.body.leftRingDistal->rotation = defaultRotation; - actor.body.leftRingTip->rotation = defaultRotation; - actor.body.leftLittleMedial->rotation = defaultRotation; - actor.body.leftLittleDistal->rotation = defaultRotation; - actor.body.leftLittleTip->rotation = defaultRotation; - - // 오른손 기본값 설정 - actor.body.rightThumbMedial->rotation = defaultRotation; - actor.body.rightThumbDistal->rotation = defaultRotation; - actor.body.rightThumbTip->rotation = defaultRotation; - actor.body.rightIndexMedial->rotation = defaultRotation; - actor.body.rightIndexDistal->rotation = defaultRotation; - actor.body.rightIndexTip->rotation = defaultRotation; - actor.body.rightMiddleMedial->rotation = defaultRotation; - actor.body.rightMiddleDistal->rotation = defaultRotation; - actor.body.rightMiddleTip->rotation = defaultRotation; - actor.body.rightRingMedial->rotation = defaultRotation; - actor.body.rightRingDistal->rotation = defaultRotation; - actor.body.rightRingTip->rotation = defaultRotation; - actor.body.rightLittleMedial->rotation = defaultRotation; - actor.body.rightLittleDistal->rotation = defaultRotation; - actor.body.rightLittleTip->rotation = defaultRotation; + // Scene 데이터 파싱 + if (j.contains("scene")) { + auto& scene = j["scene"]; + + // 타임스탬프 + if (scene.contains("timestamp")) { + frame.timestamp = scene["timestamp"]; + } + + // Actors 파싱 + if (scene.contains("actors") && scene["actors"].is_array()) { + auto& actors = scene["actors"]; + for (const auto& actorJson : actors) { + RokokoData::ActorData actor; + + // Actor 기본 정보 + if (actorJson.contains("name")) { + actor.name = actorJson["name"]; + } + + // Body 데이터 파싱 + if (actorJson.contains("body")) { + ParseBodyFrame(actorJson["body"], actor.body); + } + + frame.scene.actors.push_back(actor); + } + } + } return true; - } catch (...) { + } catch (const nlohmann::json::exception& e) { + // JSON 파싱 에러 처리 + std::cerr << "JSON parsing error: " << e.what() << std::endl; return false; + } catch (...) { + // 기타 예외 처리 + std::cerr << "Unknown error during JSON parsing" << std::endl; + return false; + } + } + + void RokokoDataParser::ParseBodyFrame(const nlohmann::json& bodyJson, RokokoData::Body& body) + { + // Unity JsonLiveSerializerV3.cs의 BodyFrame 구조와 동일하게 파싱 + + // === 전신 스켈레톤 데이터 파싱 (Unity BodyFrame과 동일) === + + // 몸통 파싱 + ParseFingerJoint(bodyJson, "hip", body.hip); + ParseFingerJoint(bodyJson, "spine", body.spine); + ParseFingerJoint(bodyJson, "chest", body.chest); + ParseFingerJoint(bodyJson, "neck", body.neck); + ParseFingerJoint(bodyJson, "head", body.head); + + // 왼쪽 팔 파싱 + ParseFingerJoint(bodyJson, "leftShoulder", body.leftShoulder); + ParseFingerJoint(bodyJson, "leftUpperArm", body.leftUpperArm); + ParseFingerJoint(bodyJson, "leftLowerArm", body.leftLowerArm); + ParseFingerJoint(bodyJson, "leftHand", body.leftHand); + + // 오른쪽 팔 파싱 + ParseFingerJoint(bodyJson, "rightShoulder", body.rightShoulder); + ParseFingerJoint(bodyJson, "rightUpperArm", body.rightUpperArm); + ParseFingerJoint(bodyJson, "rightLowerArm", body.rightLowerArm); + ParseFingerJoint(bodyJson, "rightHand", body.rightHand); + + // 다리 파싱 (필요시) + ParseFingerJoint(bodyJson, "leftUpLeg", body.leftUpLeg); + ParseFingerJoint(bodyJson, "leftLeg", body.leftLeg); + ParseFingerJoint(bodyJson, "leftFoot", body.leftFoot); + ParseFingerJoint(bodyJson, "leftToe", body.leftToe); + ParseFingerJoint(bodyJson, "leftToeEnd", body.leftToeEnd); + + ParseFingerJoint(bodyJson, "rightUpLeg", body.rightUpLeg); + ParseFingerJoint(bodyJson, "rightLeg", body.rightLeg); + ParseFingerJoint(bodyJson, "rightFoot", body.rightFoot); + ParseFingerJoint(bodyJson, "rightToe", body.rightToe); + ParseFingerJoint(bodyJson, "rightToeEnd", body.rightToeEnd); + + // === 손가락 데이터 파싱 === + + // 왼손 손가락 데이터 파싱 + ParseFingerJoint(bodyJson, "leftThumbProximal", body.leftThumbProximal); + ParseFingerJoint(bodyJson, "leftThumbMedial", body.leftThumbMedial); + ParseFingerJoint(bodyJson, "leftThumbDistal", body.leftThumbDistal); + ParseFingerJoint(bodyJson, "leftThumbTip", body.leftThumbTip); + + ParseFingerJoint(bodyJson, "leftIndexProximal", body.leftIndexProximal); + ParseFingerJoint(bodyJson, "leftIndexMedial", body.leftIndexMedial); + ParseFingerJoint(bodyJson, "leftIndexDistal", body.leftIndexDistal); + ParseFingerJoint(bodyJson, "leftIndexTip", body.leftIndexTip); + + ParseFingerJoint(bodyJson, "leftMiddleProximal", body.leftMiddleProximal); + ParseFingerJoint(bodyJson, "leftMiddleMedial", body.leftMiddleMedial); + ParseFingerJoint(bodyJson, "leftMiddleDistal", body.leftMiddleDistal); + ParseFingerJoint(bodyJson, "leftMiddleTip", body.leftMiddleTip); + + ParseFingerJoint(bodyJson, "leftRingProximal", body.leftRingProximal); + ParseFingerJoint(bodyJson, "leftRingMedial", body.leftRingMedial); + ParseFingerJoint(bodyJson, "leftRingDistal", body.leftRingDistal); + ParseFingerJoint(bodyJson, "leftRingTip", body.leftRingTip); + + ParseFingerJoint(bodyJson, "leftLittleProximal", body.leftLittleProximal); + ParseFingerJoint(bodyJson, "leftLittleMedial", body.leftLittleMedial); + ParseFingerJoint(bodyJson, "leftLittleDistal", body.leftLittleDistal); + ParseFingerJoint(bodyJson, "leftLittleTip", body.leftLittleTip); + + // 오른손 손가락 데이터 파싱 + ParseFingerJoint(bodyJson, "rightThumbProximal", body.rightThumbProximal); + ParseFingerJoint(bodyJson, "rightThumbMedial", body.rightThumbMedial); + ParseFingerJoint(bodyJson, "rightThumbDistal", body.rightThumbDistal); + ParseFingerJoint(bodyJson, "rightThumbTip", body.rightThumbTip); + + ParseFingerJoint(bodyJson, "rightIndexProximal", body.rightIndexProximal); + ParseFingerJoint(bodyJson, "rightIndexMedial", body.rightIndexMedial); + ParseFingerJoint(bodyJson, "rightIndexDistal", body.rightIndexDistal); + ParseFingerJoint(bodyJson, "rightIndexTip", body.rightIndexTip); + + ParseFingerJoint(bodyJson, "rightMiddleProximal", body.rightMiddleProximal); + ParseFingerJoint(bodyJson, "rightMiddleMedial", body.rightMiddleMedial); + ParseFingerJoint(bodyJson, "rightMiddleDistal", body.rightMiddleDistal); + ParseFingerJoint(bodyJson, "rightMiddleTip", body.rightMiddleTip); + + ParseFingerJoint(bodyJson, "rightRingProximal", body.rightRingProximal); + ParseFingerJoint(bodyJson, "rightRingMedial", body.rightRingMedial); + ParseFingerJoint(bodyJson, "rightRingDistal", body.rightRingDistal); + ParseFingerJoint(bodyJson, "rightRingTip", body.rightRingTip); + + ParseFingerJoint(bodyJson, "rightLittleProximal", body.rightLittleProximal); + ParseFingerJoint(bodyJson, "rightLittleMedial", body.rightLittleMedial); + ParseFingerJoint(bodyJson, "rightLittleDistal", body.rightLittleDistal); + ParseFingerJoint(bodyJson, "rightLittleTip", body.rightLittleTip); + } + + void RokokoDataParser::ParseFingerJoint(const nlohmann::json& bodyJson, const std::string& jointName, std::shared_ptr& joint) + { + if (bodyJson.contains(jointName)) { + auto& jointJson = bodyJson[jointName]; + + joint = std::make_shared(); + + // Position 파싱 + if (jointJson.contains("position")) { + auto& pos = jointJson["position"]; + joint->position.x = pos.value("x", 0.0f); + joint->position.y = pos.value("y", 0.0f); + joint->position.z = pos.value("z", 0.0f); + } + + // Rotation 파싱 + if (jointJson.contains("rotation")) { + auto& rot = jointJson["rotation"]; + joint->rotation.x = rot.value("x", 0.0f); + joint->rotation.y = rot.value("y", 0.0f); + joint->rotation.z = rot.value("z", 0.0f); + joint->rotation.w = rot.value("w", 1.0f); + + // 쿼터니언 정규화 + NormalizeQuaternion(joint->rotation.x, joint->rotation.y, joint->rotation.z, joint->rotation.w); + } } } @@ -122,7 +194,7 @@ namespace RokokoIntegration const auto& actor = frame.scene.actors[0]; - // 손가락 데이터 검증 + // 손가락 데이터 검증 (왼손 엄지손가락만 체크) if (!actor.body.leftThumbMedial || !actor.body.leftThumbDistal || !actor.body.leftThumbTip) { return false; } @@ -148,19 +220,57 @@ namespace RokokoIntegration const auto& actor = frame.scene.actors[0]; - // 왼손 데이터 추출 - if (actor.body.leftThumbMedial) { - leftHandFingers.push_back(*actor.body.leftThumbMedial); - } - if (actor.body.leftThumbDistal) { - leftHandFingers.push_back(*actor.body.leftThumbDistal); - } - if (actor.body.leftThumbTip) { - leftHandFingers.push_back(*actor.body.leftThumbTip); - } + // 왼손 데이터 추출 (20개 관절) + if (actor.body.leftThumbProximal) leftHandFingers.push_back(*actor.body.leftThumbProximal); + if (actor.body.leftThumbMedial) leftHandFingers.push_back(*actor.body.leftThumbMedial); + if (actor.body.leftThumbDistal) leftHandFingers.push_back(*actor.body.leftThumbDistal); + if (actor.body.leftThumbTip) leftHandFingers.push_back(*actor.body.leftThumbTip); - // 오른손 데이터는 현재 구현되지 않음 (기본값 사용) - // 실제 구현에서는 actor.body.rightThumb* 데이터 사용 + if (actor.body.leftIndexProximal) leftHandFingers.push_back(*actor.body.leftIndexProximal); + if (actor.body.leftIndexMedial) leftHandFingers.push_back(*actor.body.leftIndexMedial); + if (actor.body.leftIndexDistal) leftHandFingers.push_back(*actor.body.leftIndexDistal); + if (actor.body.leftIndexTip) leftHandFingers.push_back(*actor.body.leftIndexTip); + + if (actor.body.leftMiddleProximal) leftHandFingers.push_back(*actor.body.leftMiddleProximal); + if (actor.body.leftMiddleMedial) leftHandFingers.push_back(*actor.body.leftMiddleMedial); + if (actor.body.leftMiddleDistal) leftHandFingers.push_back(*actor.body.leftMiddleDistal); + if (actor.body.leftMiddleTip) leftHandFingers.push_back(*actor.body.leftMiddleTip); + + if (actor.body.leftRingProximal) leftHandFingers.push_back(*actor.body.leftRingProximal); + if (actor.body.leftRingMedial) leftHandFingers.push_back(*actor.body.leftRingMedial); + if (actor.body.leftRingDistal) leftHandFingers.push_back(*actor.body.leftRingDistal); + if (actor.body.leftRingTip) leftHandFingers.push_back(*actor.body.leftRingTip); + + if (actor.body.leftLittleProximal) leftHandFingers.push_back(*actor.body.leftLittleProximal); + if (actor.body.leftLittleMedial) leftHandFingers.push_back(*actor.body.leftLittleMedial); + if (actor.body.leftLittleDistal) leftHandFingers.push_back(*actor.body.leftLittleDistal); + if (actor.body.leftLittleTip) leftHandFingers.push_back(*actor.body.leftLittleTip); + + // 오른손 데이터 추출 (20개 관절) + if (actor.body.rightThumbProximal) rightHandFingers.push_back(*actor.body.rightThumbProximal); + if (actor.body.rightThumbMedial) rightHandFingers.push_back(*actor.body.rightThumbMedial); + if (actor.body.rightThumbDistal) rightHandFingers.push_back(*actor.body.rightThumbDistal); + if (actor.body.rightThumbTip) rightHandFingers.push_back(*actor.body.rightThumbTip); + + if (actor.body.rightIndexProximal) rightHandFingers.push_back(*actor.body.rightIndexProximal); + if (actor.body.rightIndexMedial) rightHandFingers.push_back(*actor.body.rightIndexMedial); + if (actor.body.rightIndexDistal) rightHandFingers.push_back(*actor.body.rightIndexDistal); + if (actor.body.rightIndexTip) rightHandFingers.push_back(*actor.body.rightIndexTip); + + if (actor.body.rightMiddleProximal) rightHandFingers.push_back(*actor.body.rightMiddleProximal); + if (actor.body.rightMiddleMedial) rightHandFingers.push_back(*actor.body.rightMiddleMedial); + if (actor.body.rightMiddleDistal) rightHandFingers.push_back(*actor.body.rightMiddleDistal); + if (actor.body.rightMiddleTip) rightHandFingers.push_back(*actor.body.rightMiddleTip); + + if (actor.body.rightRingProximal) rightHandFingers.push_back(*actor.body.rightRingProximal); + if (actor.body.rightRingMedial) rightHandFingers.push_back(*actor.body.rightRingMedial); + if (actor.body.rightRingDistal) rightHandFingers.push_back(*actor.body.rightRingDistal); + if (actor.body.rightRingTip) rightHandFingers.push_back(*actor.body.rightRingTip); + + if (actor.body.rightLittleProximal) rightHandFingers.push_back(*actor.body.rightLittleProximal); + if (actor.body.rightLittleMedial) rightHandFingers.push_back(*actor.body.rightLittleMedial); + if (actor.body.rightLittleDistal) rightHandFingers.push_back(*actor.body.rightLittleDistal); + if (actor.body.rightLittleTip) rightHandFingers.push_back(*actor.body.rightLittleTip); return true; @@ -197,7 +307,7 @@ namespace RokokoIntegration // 쿼터니언 길이 체크 (정규화된 경우 1.0에 가까워야 함) float length = std::sqrt(x * x + y * y + z * z + w * w); - if (std::abs(length - 1.0f) > 0.1f) { + if (length < 0.1f || length > 10.0f) { return false; } @@ -207,15 +317,13 @@ namespace RokokoIntegration void RokokoDataParser::NormalizeQuaternion(float& x, float& y, float& z, float& w) { float length = std::sqrt(x * x + y * y + z * z + w * w); - - if (length > 0.0f) { - float invLength = 1.0f / length; - x *= invLength; - y *= invLength; - z *= invLength; - w *= invLength; + if (length > 0.0001f) { + x /= length; + y /= length; + z /= length; + w /= length; } else { - // 유효하지 않은 쿼터니언인 경우 기본값 설정 + // 기본값 설정 x = 0.0f; y = 0.0f; z = 0.0f; diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoDataParser.h b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoDataParser.h index 7d5ef00c..5f0ab931 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoDataParser.h +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoDataParser.h @@ -10,6 +10,7 @@ #include #include #include +#include // Forward declarations for JSON data structures namespace RokokoData @@ -19,6 +20,7 @@ namespace RokokoData struct ActorJointFrame; struct ActorData; struct LiveFrame_v4; + struct Body; } namespace RokokoIntegration @@ -53,6 +55,22 @@ namespace RokokoIntegration std::vector& rightHandFingers); private: + /** + * Parses body frame data from JSON + * @param bodyJson JSON object containing body data + * @param body Output body data structure + */ + static void ParseBodyFrame(const nlohmann::json& bodyJson, RokokoData::Body& body); + + /** + * Parses individual finger joint data from JSON + * @param bodyJson JSON object containing body data + * @param jointName Name of the joint to parse + * @param joint Output joint data structure + */ + static void ParseFingerJoint(const nlohmann::json& bodyJson, const std::string& jointName, + std::shared_ptr& joint); + /** * Parses actor data from JSON * @param actorJson JSON object containing actor data diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoGloveDevice.vcxproj b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoGloveDevice.vcxproj index e2c634af..6d0a016d 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoGloveDevice.vcxproj +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoGloveDevice.vcxproj @@ -72,14 +72,15 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C stdcpp17 WIN32;_DEBUG;_WINDOWS;_USRDLL;ANALOGSYSTEM_IMPORTS;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;%(PreprocessorDefinitions) false - ..\..\include;%(AdditionalIncludeDirectories) + ..\include;..\external;..\external\nlohmann;%(AdditionalIncludeDirectories) + /utf-8 %(AdditionalOptions) Windows true NotSet PeripheralImport.lib;ws2_32.lib;%(AdditionalDependencies) - ..\..\lib;%(AdditionalLibraryDirectories) + ..\lib;%(AdditionalLibraryDirectories) false @@ -93,7 +94,8 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C true stdcpp17 WIN32;NDEBUG;_WINDOWS;_USRDLL;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;ANALOGSYSTEM_IMPORTS;%(PreprocessorDefinitions) - ..\..\include;%(AdditionalIncludeDirectories) + ..\include;..\external;..\external\nlohmann;%(AdditionalIncludeDirectories) + /utf-8 %(AdditionalOptions) Windows @@ -101,7 +103,7 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C true true PeripheralImport.lib;ws2_32.lib;%(AdditionalDependencies) - ..\..\lib;%(AdditionalLibraryDirectories) + ..\lib;%(AdditionalLibraryDirectories) @@ -111,7 +113,7 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C - + @@ -130,7 +132,7 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C - + diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoUDPReceiver.cpp b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoUDPReceiver.cpp index f447e404..6397d889 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoUDPReceiver.cpp +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/RokokoUDPReceiver.cpp @@ -195,8 +195,7 @@ namespace RokokoIntegration } } - // CPU 사용률 조절 - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + // 🚀 실시간성 최우선 - sleep 제거 (CPU 사용률보다 반응성 우선) } catch (...) { SetError("Exception in receive thread"); diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveAdapterSingleton.obj b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveAdapterSingleton.obj index eb625e2b..a87fe54f 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveAdapterSingleton.obj +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveAdapterSingleton.obj @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2bcc5341ff6326f2e644dac6941ceae06ffe113f020d4979d420d1d13567565d -size 1900385 +oid sha256:f6fe6dc43c5014ad1c43821b887eb31362e61a429f919c8da111600d0eb6a1be +size 3541367 diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveDevice.obj b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveDevice.obj index a64bd2a6..4f954f7f 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveDevice.obj +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveDevice.obj @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e828db2ae2584af3aa2382a807e639350239607b54e3e1317f14f121dbe23ac -size 411123 +oid sha256:aefc3a79f1f9eebfecc2c884bf5d189fb4c4a379571d52ac12e0ae22df1f20c2 +size 627589 diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/GloveDeviceBase.obj b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/GloveDeviceBase.obj index e758fcb3..67eeda28 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/GloveDeviceBase.obj +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/GloveDeviceBase.obj @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba3436308df0b6cd5bd9da32aad30a949aee5ff01b804ead4f611c8afb07f7c0 -size 368143 +oid sha256:361885b9262a598997ded5a79fd40e4ef77bf3f22c1b95da10511bdc7217b151 +size 371467 diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/LZ4Wrapper.obj b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/LZ4Wrapper.obj index 764b2526..70f36089 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/LZ4Wrapper.obj +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/LZ4Wrapper.obj @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f57f67431c5e5c23f44a3a5c9785f204269c47e10b20c8853287abf491eeb27 -size 169548 +oid sha256:6e12ddee47cc5ddd5ed91cb71704538e18e217faa69e806305a8db4e37937019 +size 188054 diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataConverter.obj b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataConverter.obj index 22293387..69394e01 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataConverter.obj +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataConverter.obj @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ec59716322b316b1bca098666afe786abce44a88683bd8e49571e5385d72d16 -size 408468 +oid sha256:49545fe193fda88a99aff30873978e48c31eea5963920edc865c2c9d98173131 +size 408444 diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataParser.obj b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataParser.obj index 17d34595..0df6470d 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataParser.obj +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataParser.obj @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:156f16eafecd6b0b8bb5a9b47e3a58364ee96e47030faa04b96612c5b80c4c50 -size 379349 +oid sha256:c0326dd5cd75fd6a3ebd76c855dcf0edf6248b6f4d3087ea05790d537aa92ebd +size 5909881 diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.command.1.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.command.1.tlog index 1b64c85a..8f384092 100644 Binary files a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.command.1.tlog and b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.command.1.tlog differ diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.read.1.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.read.1.tlog index 030b673a..3c957845 100644 Binary files a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.read.1.tlog and b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.read.1.tlog differ diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.write.1.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.write.1.tlog index c3665854..ebcef3ae 100644 Binary files a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.write.1.tlog and b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CL.write.1.tlog differ diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.command.1.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.command.1.tlog index 9be77f59..8500ffda 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.command.1.tlog +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.command.1.tlog @@ -1,2 +1,2 @@ -^C:\USERS\QSCFT\ONEDRIVE\문서\OPTITRACK\MOTIVE\PERIPHERALAPI\EXAMPLE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV -C:\Users\qscft\OneDrive\문서\OptiTrack\Motive\PeripheralAPI\example\x64\Debug\ExampleGloveData.csv +^C:\USERS\USER\DOCUMENTS\STREAMINGLE_URP\OPTITRACK ROKOKO GLOVE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV +C:\Users\user\Documents\Streamingle_URP\Optitrack Rokoko Glove\x64\Debug\ExampleGloveData.csv diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.read.1.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.read.1.tlog index 120ee5e5..91d479f4 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.read.1.tlog +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.read.1.tlog @@ -1 +1 @@ -^C:\USERS\QSCFT\ONEDRIVE\문서\OPTITRACK\MOTIVE\PERIPHERALAPI\EXAMPLE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV +^C:\USERS\USER\DOCUMENTS\STREAMINGLE_URP\OPTITRACK ROKOKO GLOVE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.write.1.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.write.1.tlog index 849c02ff..78e57e7f 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.write.1.tlog +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/CopyFile.write.1.tlog @@ -1,2 +1,2 @@ -^C:\USERS\QSCFT\ONEDRIVE\문서\OPTITRACK\MOTIVE\PERIPHERALAPI\EXAMPLE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV -C:\USERS\QSCFT\ONEDRIVE\문서\OPTITRACK\MOTIVE\PERIPHERALAPI\EXAMPLE\X64\DEBUG\EXAMPLEGLOVEDATA.CSV +^C:\USERS\USER\DOCUMENTS\STREAMINGLE_URP\OPTITRACK ROKOKO GLOVE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV +C:\USERS\USER\DOCUMENTS\STREAMINGLE_URP\OPTITRACK ROKOKO GLOVE\X64\DEBUG\EXAMPLEGLOVEDATA.CSV diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/RokokoGloveDevice.lastbuildstate b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/RokokoGloveDevice.lastbuildstate index ca77c90a..27ddd87a 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/RokokoGloveDevice.lastbuildstate +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/RokokoGloveDevice.lastbuildstate @@ -1,2 +1,2 @@ -PlatformToolSet=v142:VCToolArchitecture=Native64Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=8.1:VcpkgTriplet=x64-windows: -Debug|x64|C:\Users\qscft\OneDrive\문서\OptiTrack\Motive\PeripheralAPI\example\| +PlatformToolSet=v142:VCToolArchitecture=Native64Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=8.1: +Debug|x64|C:\Users\user\Documents\Streamingle_URP\Optitrack Rokoko Glove\| diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/RokokoGloveDevice.write.1u.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/RokokoGloveDevice.write.1u.tlog index 4698b933..f0a27aab 100644 Binary files a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/RokokoGloveDevice.write.1u.tlog and b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/RokokoGloveDevice.write.1u.tlog differ diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.command.1.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.command.1.tlog index cc64a2f4..f6dbb298 100644 Binary files a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.command.1.tlog and b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.command.1.tlog differ diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.read.1.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.read.1.tlog index 693ff8ac..46e9fee1 100644 Binary files a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.read.1.tlog and b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.read.1.tlog differ diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.write.1.tlog b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.write.1.tlog index 47acec86..6af6286f 100644 Binary files a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.write.1.tlog and b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGl.513E58BC.tlog/link.write.1.tlog differ diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGloveDevice.dll.recipe b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGloveDevice.dll.recipe index 339ec984..68ea365b 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGloveDevice.dll.recipe +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGloveDevice.dll.recipe @@ -2,7 +2,7 @@ - C:\Users\qscft\OneDrive\문서\OptiTrack\Motive\PeripheralAPI\example\x64\Debug\RokokoGloveDevice.dll + C:\Users\user\Documents\Streamingle_URP\Optitrack Rokoko Glove\x64\Debug\RokokoGloveDevice.dll diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGloveDevice.ilk b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGloveDevice.ilk index 87b69ffa..d231c607 100644 Binary files a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGloveDevice.ilk and b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoGloveDevice.ilk differ diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoUDPReceiver.obj b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoUDPReceiver.obj index 39c1db9e..5e4a9096 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoUDPReceiver.obj +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoUDPReceiver.obj @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80b256c2ede8a3d4285192069d2a25e2ae56d17900bef555e26c3aef751f8edf -size 674337 +oid sha256:3c96bfc1e905899005cf8aa8b3ce0489912f5e198c8d11f2d3ca4e880bfcf512 +size 602380 diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/dllmain.obj b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/dllmain.obj index d78fb7c8..36df90ed 100644 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/dllmain.obj +++ b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/dllmain.obj @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09ee07f42e48385a35cb9f33f6bcdcc760bada2d85e79f0311a055f61b161817 -size 278719 +oid sha256:53756e5e0ff8e744dfa7226344ed02efd644183a50a47a73624d86ea9321c36e +size 435135 diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/lz4.obj b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/lz4.obj deleted file mode 100644 index 4e918ddb..00000000 --- a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/lz4.obj +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:90c2abd5142ada866a1336c9189e7ec65e0d68dccf3e4f4d05c4b0d97ecc75ba -size 134890 diff --git a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/vc142.idb b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/vc142.idb index 366c488b..ac87499a 100644 Binary files a/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/vc142.idb and b/Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/vc142.idb differ diff --git a/Optitrack Rokoko Glove/SimpleDeviceExample/SimpleDeviceExample.vcxproj b/Optitrack Rokoko Glove/SimpleDeviceExample/SimpleDeviceExample.vcxproj index fa15da70..87636826 100644 --- a/Optitrack Rokoko Glove/SimpleDeviceExample/SimpleDeviceExample.vcxproj +++ b/Optitrack Rokoko Glove/SimpleDeviceExample/SimpleDeviceExample.vcxproj @@ -67,14 +67,14 @@ copy "$(OutDir)SimpleDeviceExample.dll" "C:/Program Files/OptiTrack/Motive/dev Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;ANALOGSYSTEM_IMPORTS;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;%(PreprocessorDefinitions) false - ..\..\include;%(AdditionalIncludeDirectories) + ..\include;%(AdditionalIncludeDirectories) Windows true NotSet PeripheralImport.lib;%(AdditionalDependencies) - ..\..\lib;%(AdditionalLibraryDirectories) + ..\lib;%(AdditionalLibraryDirectories) @@ -84,7 +84,7 @@ copy "$(OutDir)SimpleDeviceExample.dll" "C:/Program Files/OptiTrack/Motive/dev true true WIN32;NDEBUG;_WINDOWS;_USRDLL;ANALOGSYSTEM_IMPORTS;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;%(PreprocessorDefinitions) - ..\..\include;%(AdditionalIncludeDirectories) + ..\include;%(AdditionalIncludeDirectories) Windows @@ -92,7 +92,7 @@ copy "$(OutDir)SimpleDeviceExample.dll" "C:/Program Files/OptiTrack/Motive/dev true true PeripheralImport.lib;%(AdditionalDependencies) - ..\..\lib;%(AdditionalLibraryDirectories) + ..\lib;%(AdditionalLibraryDirectories) diff --git a/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/SimpleDe.CBF66948.tlog/SimpleDeviceExample.lastbuildstate b/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/SimpleDe.CBF66948.tlog/SimpleDeviceExample.lastbuildstate index ca77c90a..27ddd87a 100644 --- a/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/SimpleDe.CBF66948.tlog/SimpleDeviceExample.lastbuildstate +++ b/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/SimpleDe.CBF66948.tlog/SimpleDeviceExample.lastbuildstate @@ -1,2 +1,2 @@ -PlatformToolSet=v142:VCToolArchitecture=Native64Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=8.1:VcpkgTriplet=x64-windows: -Debug|x64|C:\Users\qscft\OneDrive\문서\OptiTrack\Motive\PeripheralAPI\example\| +PlatformToolSet=v142:VCToolArchitecture=Native64Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=8.1: +Debug|x64|C:\Users\user\Documents\Streamingle_URP\Optitrack Rokoko Glove\| diff --git a/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/dllmain.obj b/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/dllmain.obj deleted file mode 100644 index 3fc151b9..00000000 --- a/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/dllmain.obj +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d866e6a7e9d9cc51f0cf06aafbea365578bc1fe030bc1b4b3e2a7eb2eb4bd050 -size 88247 diff --git a/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/vc142.idb b/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/vc142.idb index 6d9dea15..17aca725 100644 Binary files a/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/vc142.idb and b/Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/vc142.idb differ diff --git a/Optitrack Rokoko Glove/external/nlohmann/json.hpp b/Optitrack Rokoko Glove/external/nlohmann/json.hpp new file mode 100644 index 00000000..8b72ea65 --- /dev/null +++ b/Optitrack Rokoko Glove/external/nlohmann/json.hpp @@ -0,0 +1,24765 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple +#include // char_traits + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +///////////////// +// char_traits // +///////////////// + +// Primary template of char_traits calls std char_traits +template +struct char_traits : std::char_traits +{}; + +// Explicitly define char traits for unsigned char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = unsigned char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +// Explicitly define char traits for signed char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = signed char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template