diff --git a/applications/sandbox/assets/scenes/Scene Test.cornflake b/applications/sandbox/assets/scenes/Scene Test.cornflake deleted file mode 100644 index 48bb34ee4..000000000 --- a/applications/sandbox/assets/scenes/Scene Test.cornflake +++ /dev/null @@ -1,1932 +0,0 @@ -{ - "class legion::core::ecs::entity_handle": { - "Name": "Scene Test", - "Id": 33, - "Name": "Entity", - "Components": [ - { - "Owner": 33, - "Component Type": 5290901135681259365, - "Component Name": "legion::core::scenemanagement::scene", - "NAME": "Scene" - }, - { - "Owner": 33, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [ - { - "Name": "Skybox", - "Id": 2, - "Name": "Entity", - "Components": [ - { - "Owner": 2, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - }, - { - "Owner": 2, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 8436013952758271681, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 2, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\skybox.material" - } - }, - { - "Owner": 2, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 2, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 2, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.0, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "Ground Plane", - "Id": 3, - "Name": "Entity", - "Components": [ - { - "Owner": 3, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - }, - { - "Owner": 3, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 3566131216048347293, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 3, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\floor.material" - } - }, - { - "Owner": 3, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 3, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 3, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.0, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 4, - "Name": "Entity", - "Components": [ - { - "Owner": 4, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 4, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.16837938129901887, - "y": 0.6738424897193909, - "z": -0.16186246275901795, - "w": 0.70098876953125 - }, - { - "Owner": 4, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -22.988643646240236, - "y": 17.683238983154298, - "z": -2.940082311630249 - }, - { - "Owner": 4, - "Component Type": 11518894322830570044, - "Component Name": "legion::audio::audio_listener" - }, - { - "Owner": 4, - "Component Type": 15654855102072282618, - "Component Name": "legion::rendering::camera", - "Fov": 22.5, - "NearZ": 0.0010000000474974514, - "FarZ": 1000.0 - }, - { - "Owner": 4, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Decal", - "Id": 5, - "Name": "Entity", - "Components": [ - { - "Owner": 5, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - }, - { - "Owner": 5, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 2.999999761581421, - "y": 2.0, - "z": 2.999999761581421 - }, - { - "Owner": 5, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.3826834559440613, - "z": 0.0, - "w": 0.9238795638084412 - }, - { - "Owner": 5, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 5.0, - "y": 0.0, - "z": 5.0 - }, - { - "Owner": 5, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 7109538280558967578, - "Filepath": "assets:\\\\models\\cube.obj" - }, - { - "Owner": 5, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\decal.material" - } - } - ], - "Children": [] - }, - { - "Name": "Defaut Plane", - "Id": 6, - "Name": "Entity", - "Components": [ - { - "Owner": 6, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 3566131216048347293, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 6, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\default.material" - } - }, - { - "Owner": 6, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 6, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 6, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.009999999776482582, - "z": 0.0 - }, - { - "Owner": 6, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Copper Plane", - "Id": 7, - "Name": "Entity", - "Components": [ - { - "Owner": 7, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 3566131216048347293, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 7, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\copper.material" - } - }, - { - "Owner": 7, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 7, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 7, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 0.009999999776482582, - "z": 0.0 - }, - { - "Owner": 7, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Rock Plane", - "Id": 8, - "Name": "Entity", - "Components": [ - { - "Owner": 8, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 3566131216048347293, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 8, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\rock.material" - } - }, - { - "Owner": 8, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 8, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 8, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.956764221191407, - "y": 0.009999992325901986, - "z": 11.581987380981446 - }, - { - "Owner": 8, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Granite Plane", - "Id": 9, - "Name": "Entity", - "Components": [ - { - "Owner": 9, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 3566131216048347293, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 9, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\granite.material" - } - }, - { - "Owner": 9, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 9, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 9, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 0.009999999776482582, - "z": -10.0 - }, - { - "Owner": 9, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "UV Plane", - "Id": 10, - "Name": "Entity", - "Components": [ - { - "Owner": 10, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 3566131216048347293, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 10, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\uv.material" - } - }, - { - "Owner": 10, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 10, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 10, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -14.415493965148926, - "y": 0.010000031441450119, - "z": -2.4945240020751955 - }, - { - "Owner": 10, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Normal Plane", - "Id": 11, - "Name": "Entity", - "Components": [ - { - "Owner": 11, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 3566131216048347293, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 11, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\normal.material" - } - }, - { - "Owner": 11, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 9.994988441467286, - "y": 9.999067306518555, - "z": 9.999065399169922 - }, - { - "Owner": 11, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": -7.004159670032095e-7, - "y": 0.7372754216194153, - "z": -0.6755922436714172, - "w": 5.825457378705323e-7 - }, - { - "Owner": 11, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -12.0, - "y": 5.0, - "z": 13.0 - }, - { - "Owner": 11, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Wireframe Plane", - "Id": 12, - "Name": "Entity", - "Components": [ - { - "Owner": 12, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 3566131216048347293, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 12, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\wireframe.material" - } - }, - { - "Owner": 12, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 12, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 12, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.009999999776482582, - "z": 10.0 - }, - { - "Owner": 12, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Vertex Color Plane", - "Id": 13, - "Name": "Entity", - "Components": [ - { - "Owner": 13, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 3566131216048347293, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 13, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\vertex color.material" - } - }, - { - "Owner": 13, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 13, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 13, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -0.9283102750778198, - "y": 0.010000022128224373, - "z": -13.383755683898926 - }, - { - "Owner": 13, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Entity 14", - "Id": 14, - "Name": "Entity", - "Components": [ - { - "Owner": 14, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Green Spotlight 0", - "Id": 15, - "Name": "Entity", - "Components": [ - { - "Owner": 15, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 12356534967552134382, - "Filepath": "assets:\\\\models\\spot-light.obj" - }, - { - "Owner": 15, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\spot light.material" - } - }, - { - "Owner": 15, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 2, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 4, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 0.0, - "y": 1.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 15, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 15, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 15, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -10.0, - "y": 0.5, - "z": -10.0 - }, - { - "Owner": 15, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Green Spotlight 1", - "Id": 16, - "Name": "Entity", - "Components": [ - { - "Owner": 16, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 12356534967552134382, - "Filepath": "assets:\\\\models\\spot-light.obj" - }, - { - "Owner": 16, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\spot light.material" - } - }, - { - "Owner": 16, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 2, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 7, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 0.0, - "y": 1.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 16, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 16, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 16, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.5, - "z": -10.0 - }, - { - "Owner": 16, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Green Spotlight 2", - "Id": 17, - "Name": "Entity", - "Components": [ - { - "Owner": 17, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 12356534967552134382, - "Filepath": "assets:\\\\models\\spot-light.obj" - }, - { - "Owner": 17, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\spot light.material" - } - }, - { - "Owner": 17, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 2, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 10, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 0.0, - "y": 1.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 17, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 17, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 17, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 0.5, - "z": -10.0 - }, - { - "Owner": 17, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Red Pointlight 1", - "Id": 18, - "Name": "Entity", - "Components": [ - { - "Owner": 18, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18342160618331844328, - "Filepath": "assets:\\\\models\\point-light.obj" - }, - { - "Owner": 18, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\point light.material" - } - }, - { - "Owner": 18, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 0, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 13, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 1.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 18, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 18, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 18, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 1.0, - "z": 0.0 - }, - { - "Owner": 18, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Red pointlight 0", - "Id": 19, - "Name": "Entity", - "Components": [ - { - "Owner": 19, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18342160618331844328, - "Filepath": "assets:\\\\models\\point-light.obj" - }, - { - "Owner": 19, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\point light.material" - } - }, - { - "Owner": 19, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 0, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 16, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 1.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 19, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 19, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 19, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -10.0, - "y": 1.0, - "z": 0.0 - }, - { - "Owner": 19, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Red Pointlight 2", - "Id": 20, - "Name": "Entity", - "Components": [ - { - "Owner": 20, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18342160618331844328, - "Filepath": "assets:\\\\models\\point-light.obj" - }, - { - "Owner": 20, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\point light.material" - } - }, - { - "Owner": 20, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 0, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 19, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 1.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 20, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 20, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 20, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 1.0, - "z": 0.0 - }, - { - "Owner": 20, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Embedded Material Suzzane", - "Id": 21, - "Name": "Entity", - "Components": [ - { - "Owner": 21, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 6546381963644500447, - "Filepath": "assets:\\\\models\\suzanne-test.obj" - }, - { - "Owner": 21, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\suzanne\\Material.001.material" - } - }, - { - "Owner": 21, - "Component Type": 9566391368147235142, - "Component Name": "legion::core::use_embedded_material", - "EmbeddedMaterialPath": "assets://models/suzanne-test.obj", - "MaterialName": "suzanne/Material.001" - }, - { - "Owner": 21, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 21, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.001564860343933, - "y": 0.9999997615814209, - "z": 1.001565933227539 - }, - { - "Owner": 21, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.00003474406912573613, - "y": 0.2931915819644928, - "z": -0.00001827613596105948, - "w": 0.9600598812103272 - }, - { - "Owner": 21, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": 5.099999904632568 - }, - { - "Owner": 21, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Wireframe Suzanne", - "Id": 22, - "Name": "Entity", - "Components": [ - { - "Owner": 22, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 2198368113600752348, - "Filepath": "assets:\\\\models\\suzanne-test.obj" - }, - { - "Owner": 22, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\wireframe.material" - } - }, - { - "Owner": 22, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 22, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0213717222213746, - "y": 0.9999997615814209, - "z": 1.0213708877563477 - }, - { - "Owner": 22, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.000027855361622641796, - "y": -0.3172142803668976, - "z": -0.000023673990654060618, - "w": -0.9517044425010681 - }, - { - "Owner": 22, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": 8.100000381469727 - }, - { - "Owner": 22, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Copper Suzanne", - "Id": 23, - "Name": "Entity", - "Components": [ - { - "Owner": 23, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 2198368113600752348, - "Filepath": "assets:\\\\models\\suzanne-test.obj" - }, - { - "Owner": 23, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\copper.material" - } - }, - { - "Owner": 23, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 23, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.00273597240448, - "y": 0.9999998807907105, - "z": 1.0027371644973755 - }, - { - "Owner": 23, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": -0.000012020113899779972, - "y": -0.32635098695755007, - "z": 0.000011627163075900171, - "w": -0.9480004906654358 - }, - { - "Owner": 23, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": 11.100000381469727 - }, - { - "Owner": 23, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Test Cube", - "Id": 24, - "Name": "Entity", - "Components": [ - { - "Owner": 24, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 7109538280558967578, - "Filepath": "assets:\\\\models\\cube.obj" - }, - { - "Owner": 24, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\default.material" - } - }, - { - "Owner": 24, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 24, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0350501537322999, - "y": 0.9999995827674866, - "z": 1.035048246383667 - }, - { - "Owner": 24, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.000029796141461702065, - "y": 0.31285515427589419, - "z": -0.00005751029311795719, - "w": 0.9502673745155335 - }, - { - "Owner": 24, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 5.099999904632568, - "y": 9.0, - "z": 0.0 - }, - { - "Owner": 24, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Copper Ball", - "Id": 25, - "Name": "Entity", - "Components": [ - { - "Owner": 25, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 7189033483858936074, - "Filepath": "assets:\\\\models\\sphere.obj" - }, - { - "Owner": 25, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\copper.material" - } - }, - { - "Owner": 25, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 25, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0435477495193482, - "y": 0.9999998807907105, - "z": 1.0435477495193482 - }, - { - "Owner": 25, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": -0.000008761940080148634, - "y": 0.35315263271331789, - "z": 0.000013634088645630982, - "w": 0.9355693459510803 - }, - { - "Owner": 25, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -5.099999904632568 - }, - { - "Owner": 25, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 26, - "Name": "Entity", - "Components": [ - { - "Owner": 26, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 7189033483858936074, - "Filepath": "assets:\\\\models\\sphere.obj" - }, - { - "Owner": 26, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\granite2.material" - } - }, - { - "Owner": 26, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 26, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 26, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.4072188436985016, - "z": 0.0, - "w": 0.9325306415557861 - }, - { - "Owner": 26, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -8.0 - }, - { - "Owner": 26, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 27, - "Name": "Entity", - "Components": [ - { - "Owner": 27, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 7189033483858936074, - "Filepath": "assets:\\\\models\\sphere.obj" - }, - { - "Owner": 27, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\rock2.material" - } - }, - { - "Owner": 27, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 27, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 27, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.4048698842525482, - "z": 0.0, - "w": 0.9335601329803467 - }, - { - "Owner": 27, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -2.200000047683716 - }, - { - "Owner": 27, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 28, - "Name": "Entity", - "Components": [ - { - "Owner": 28, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 7189033483858936074, - "Filepath": "assets:\\\\models\\sphere.obj" - }, - { - "Owner": 28, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\default.material" - } - }, - { - "Owner": 28, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 28, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 28, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.4023154675960541, - "z": 0.0, - "w": 0.9346229434013367 - }, - { - "Owner": 28, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 4.0, - "y": 3.0, - "z": -8.0 - }, - { - "Owner": 28, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 29, - "Name": "Entity", - "Components": [ - { - "Owner": 29, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 8436013952758271681, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 29, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\copper.material" - } - }, - { - "Owner": 29, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 29, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 29, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.4000115692615509, - "z": 0.0, - "w": 0.9356839060783386 - }, - { - "Owner": 29, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -3.5999999046325685 - }, - { - "Owner": 29, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 30, - "Name": "Entity", - "Components": [ - { - "Owner": 30, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 8436013952758271681, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 30, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\granite2.material" - } - }, - { - "Owner": 30, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 30, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 30, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.39871278405189516, - "z": 0.0, - "w": 0.9362139105796814 - }, - { - "Owner": 30, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -6.5 - }, - { - "Owner": 30, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 31, - "Name": "Entity", - "Components": [ - { - "Owner": 31, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 8436013952758271681, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 31, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\rock2.material" - } - }, - { - "Owner": 31, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 31, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 31, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.39700275659561159, - "z": 0.0, - "w": 0.9369962811470032 - }, - { - "Owner": 31, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -0.699999988079071 - }, - { - "Owner": 31, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 32, - "Name": "Entity", - "Components": [ - { - "Owner": 32, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 8436013952758271681, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 32, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\default.material" - } - }, - { - "Owner": 32, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 32, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 32, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.39544665813446047, - "z": 0.0, - "w": 0.9376160502433777 - }, - { - "Owner": 32, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 4.0, - "y": 3.0, - "z": -6.5 - }, - { - "Owner": 32, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - }, - { - "Name": "Sun", - "Id": 34, - "Name": "Entity", - "Components": [ - { - "Owner": 34, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 7757082633988396914, - "Filepath": "assets:\\\\models\\directional-light.obj" - }, - { - "Owner": 34, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\directional light.material" - } - }, - { - "Owner": 34, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 1, - "Attenuation": 10.0, - "Intensity": 10.0, - "Index": 22, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.1415927410125734, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 1.0, - "y": 1.0, - "z": 0.800000011920929, - "w": 1.0 - } - }, - { - "Owner": 34, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 34, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.115916907787323, - "y": -0.8804763555526733, - "z": 0.2798481583595276, - "w": 0.3647052049636841 - }, - { - "Owner": 34, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 34, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [] - } - ] - } -} \ No newline at end of file diff --git a/applications/sandbox/assets/scenes/Scene.cornflake b/applications/sandbox/assets/scenes/Scene.cornflake deleted file mode 100644 index 1fbed6537..000000000 --- a/applications/sandbox/assets/scenes/Scene.cornflake +++ /dev/null @@ -1,1779 +0,0 @@ -{ - "class legion::core::ecs::entity_handle": { - "Name": "Scene", - "Id": 33, - "Name": "Entity", - "Components": [ - { - "Owner": 33, - "Component Type": 5290901135681259365, - "Component Name": "legion::core::scenemanagement::scene", - "NAME": "Scene" - }, - { - "Owner": 33, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - } - ], - "Children": [ - { - "Name": "Skybox", - "Id": 2, - "Name": "Entity", - "Components": [ - { - "Owner": 2, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - }, - { - "Owner": 2, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 16147701225056486911, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 2, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\skybox.material" - } - }, - { - "Owner": 2, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 2, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 2, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.0, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "Ground Plane", - "Id": 3, - "Name": "Entity", - "Components": [ - { - "Owner": 3, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - }, - { - "Owner": 3, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 11545668865037648829, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 3, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\floor.material" - } - }, - { - "Owner": 3, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 3, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 3, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.0, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 4, - "Name": "Entity", - "Components": [ - { - "Owner": 4, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 4, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": -0.0, - "y": -0.0, - "z": -0.0, - "w": 1.0 - }, - { - "Owner": 4, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": 0.0 - }, - { - "Owner": 4, - "Component Type": 11518894322830570044, - "Component Name": "legion::audio::audio_listener" - }, - { - "Owner": 4, - "Component Type": 15654855102072282618, - "Component Name": "legion::rendering::camera", - "Fov": 22.5, - "NearZ": 0.0010000000474974514, - "FarZ": 1000.0 - } - ], - "Children": [] - }, - { - "Name": "Decal", - "Id": 5, - "Name": "Entity", - "Components": [ - { - "Owner": 5, - "Component Type": 14234945005408008119, - "Component Name": "legion::core::hierarchy" - }, - { - "Owner": 5, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 3.0, - "y": 2.0, - "z": 3.0 - }, - { - "Owner": 5, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.3826834559440613, - "z": 0.0, - "w": 0.9238795042037964 - }, - { - "Owner": 5, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 5.0, - "y": 0.0, - "z": 5.0 - }, - { - "Owner": 5, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 5503224543670688896, - "Filepath": "assets:\\\\models\\cube.obj" - }, - { - "Owner": 5, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\decal.material" - } - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 6, - "Name": "Entity", - "Components": [ - { - "Owner": 6, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18257050065998780757, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 6, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\default.material" - } - }, - { - "Owner": 6, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 6, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 6, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.009999999776482582, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 7, - "Name": "Entity", - "Components": [ - { - "Owner": 7, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18257050065998780757, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 7, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\copper.material" - } - }, - { - "Owner": 7, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 7, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 7, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 0.009999999776482582, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 8, - "Name": "Entity", - "Components": [ - { - "Owner": 8, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18257050065998780757, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 8, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\rock.material" - } - }, - { - "Owner": 8, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 8, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 8, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 0.009999999776482582, - "z": 10.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 9, - "Name": "Entity", - "Components": [ - { - "Owner": 9, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18257050065998780757, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 9, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\granite.material" - } - }, - { - "Owner": 9, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 9, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 9, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 0.009999999776482582, - "z": -10.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 10, - "Name": "Entity", - "Components": [ - { - "Owner": 10, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18257050065998780757, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 10, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\uv.material" - } - }, - { - "Owner": 10, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 10, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 10, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -10.0, - "y": 0.009999999776482582, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 11, - "Name": "Entity", - "Components": [ - { - "Owner": 11, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18257050065998780757, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 11, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\normal.material" - } - }, - { - "Owner": 11, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 11, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 11, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -10.0, - "y": 0.009999999776482582, - "z": 10.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 12, - "Name": "Entity", - "Components": [ - { - "Owner": 12, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18257050065998780757, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 12, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\wireframe.material" - } - }, - { - "Owner": 12, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 12, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 12, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.009999999776482582, - "z": 10.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 13, - "Name": "Entity", - "Components": [ - { - "Owner": 13, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 18257050065998780757, - "Filepath": "assets:\\\\models\\plane.obj" - }, - { - "Owner": 13, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\vertex color.material" - } - }, - { - "Owner": 13, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 10.0, - "y": 10.0, - "z": 10.0 - }, - { - "Owner": 13, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 13, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.009999999776482582, - "z": -10.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 14, - "Name": "Entity", - "Components": [ - { - "Owner": 14, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 5112364170975192303, - "Filepath": "assets:\\\\models\\directional-light.obj" - }, - { - "Owner": 14, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\directional light.material" - } - }, - { - "Owner": 14, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 1, - "Attenuation": 10.0, - "Intensity": 10.0, - "Index": 1, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.1415927410125734, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 1.0, - "y": 1.0, - "z": 0.800000011920929, - "w": 1.0 - } - }, - { - "Owner": 14, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 14, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.115916907787323, - "y": -0.8804763555526733, - "z": 0.2798481583595276, - "w": 0.3647052049636841 - }, - { - "Owner": 14, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 10.0, - "z": 10.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 15, - "Name": "Entity", - "Components": [ - { - "Owner": 15, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 4127307817236017217, - "Filepath": "assets:\\\\models\\spot-light.obj" - }, - { - "Owner": 15, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\spot light.material" - } - }, - { - "Owner": 15, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 2, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 4, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 0.0, - "y": 1.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 15, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 15, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": -0.0, - "y": -0.0, - "z": -0.0, - "w": 1.0 - }, - { - "Owner": 15, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -10.0, - "y": 0.5, - "z": -10.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 16, - "Name": "Entity", - "Components": [ - { - "Owner": 16, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 4127307817236017217, - "Filepath": "assets:\\\\models\\spot-light.obj" - }, - { - "Owner": 16, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\spot light.material" - } - }, - { - "Owner": 16, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 2, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 7, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 0.0, - "y": 1.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 16, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 16, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": -0.0, - "y": -0.0, - "z": -0.0, - "w": 1.0 - }, - { - "Owner": 16, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 0.5, - "z": -10.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 17, - "Name": "Entity", - "Components": [ - { - "Owner": 17, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 4127307817236017217, - "Filepath": "assets:\\\\models\\spot-light.obj" - }, - { - "Owner": 17, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\spot light.material" - } - }, - { - "Owner": 17, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 2, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 10, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 0.0, - "y": 1.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 17, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 17, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": -0.0, - "y": -0.0, - "z": -0.0, - "w": 1.0 - }, - { - "Owner": 17, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 0.5, - "z": -10.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 18, - "Name": "Entity", - "Components": [ - { - "Owner": 18, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 5592977308715235853, - "Filepath": "assets:\\\\models\\point-light.obj" - }, - { - "Owner": 18, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\point light.material" - } - }, - { - "Owner": 18, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 0, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 13, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 1.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 18, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 18, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 18, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 1.0, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 19, - "Name": "Entity", - "Components": [ - { - "Owner": 19, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 5592977308715235853, - "Filepath": "assets:\\\\models\\point-light.obj" - }, - { - "Owner": 19, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\point light.material" - } - }, - { - "Owner": 19, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 0, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 16, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 1.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 19, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 19, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 19, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": -10.0, - "y": 1.0, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 20, - "Name": "Entity", - "Components": [ - { - "Owner": 20, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 5592977308715235853, - "Filepath": "assets:\\\\models\\point-light.obj" - }, - { - "Owner": 20, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\point light.material" - } - }, - { - "Owner": 20, - "Component Type": 17923777057385106779, - "Component Name": "legion::rendering::light", - "LightType": 0, - "Attenuation": 50.0, - "Intensity": 0.5, - "Index": 19, - "Direction": { - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "Falloff": 3.141592025756836, - "Position": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "Angle": 0.7853981852531433, - "Color": { - "x": 1.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - } - }, - { - "Owner": 20, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 20, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - { - "Owner": 20, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 10.0, - "y": 1.0, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 21, - "Name": "Entity", - "Components": [ - { - "Owner": 21, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 6546381963644500447, - "Filepath": "assets:\\\\models\\suzanne-test.obj" - }, - { - "Owner": 21, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\suzanne\\Material.001.material" - } - }, - { - "Owner": 21, - "Component Type": 9566391368147235142, - "Component Name": "legion::core::use_embedded_material", - "EmbeddedMaterialPath": "assets://models/suzanne-test.obj", - "MaterialName": "suzanne/Material.001" - }, - { - "Owner": 21, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 21, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 21, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.4662056863307953, - "z": 0.0, - "w": 0.8847147822380066 - }, - { - "Owner": 21, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": 5.099999904632568 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 22, - "Name": "Entity", - "Components": [ - { - "Owner": 22, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 6546381963644500447, - "Filepath": "assets:\\\\models\\suzanne-test.obj" - }, - { - "Owner": 22, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\wireframe.material" - } - }, - { - "Owner": 22, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 22, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 22, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.467636376619339, - "z": 0.0, - "w": 0.8839595317840576 - }, - { - "Owner": 22, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": 8.100000381469727 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 23, - "Name": "Entity", - "Components": [ - { - "Owner": 23, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 6546381963644500447, - "Filepath": "assets:\\\\models\\suzanne-test.obj" - }, - { - "Owner": 23, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\copper.material" - } - }, - { - "Owner": 23, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 23, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 23, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.46892985701560976, - "z": 0.0, - "w": 0.883274257183075 - }, - { - "Owner": 23, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": 11.100000381469727 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 24, - "Name": "Entity", - "Components": [ - { - "Owner": 24, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 5503224543670688896, - "Filepath": "assets:\\\\models\\cube.obj" - }, - { - "Owner": 24, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\default.material" - } - }, - { - "Owner": 24, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 24, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 24, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.47037407755851748, - "z": 0.0, - "w": 0.8825060129165649 - }, - { - "Owner": 24, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 5.099999904632568, - "y": 9.0, - "z": 0.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 25, - "Name": "Entity", - "Components": [ - { - "Owner": 25, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 9915782786907616376, - "Filepath": "assets:\\\\models\\sphere.obj" - }, - { - "Owner": 25, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\copper.material" - } - }, - { - "Owner": 25, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 25, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 25, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.47164008021354678, - "z": 0.0, - "w": 0.8818301558494568 - }, - { - "Owner": 25, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -5.099999904632568 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 26, - "Name": "Entity", - "Components": [ - { - "Owner": 26, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 9915782786907616376, - "Filepath": "assets:\\\\models\\sphere.obj" - }, - { - "Owner": 26, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\granite2.material" - } - }, - { - "Owner": 26, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 26, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 26, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.47287577390670779, - "z": 0.0, - "w": 0.881103515625 - }, - { - "Owner": 26, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -8.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 27, - "Name": "Entity", - "Components": [ - { - "Owner": 27, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 9915782786907616376, - "Filepath": "assets:\\\\models\\sphere.obj" - }, - { - "Owner": 27, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\rock2.material" - } - }, - { - "Owner": 27, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 27, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 27, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.47440704703330996, - "z": 0.0, - "w": 0.8803448677062988 - }, - { - "Owner": 27, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -2.200000047683716 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 28, - "Name": "Entity", - "Components": [ - { - "Owner": 28, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 9915782786907616376, - "Filepath": "assets:\\\\models\\sphere.obj" - }, - { - "Owner": 28, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\default.material" - } - }, - { - "Owner": 28, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 28, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 28, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.4759359657764435, - "z": 0.0, - "w": 0.8795194029808044 - }, - { - "Owner": 28, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 4.0, - "y": 3.0, - "z": -8.0 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 29, - "Name": "Entity", - "Components": [ - { - "Owner": 29, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 16147701225056486911, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 29, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\copper.material" - } - }, - { - "Owner": 29, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 29, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 29, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.4773801565170288, - "z": 0.0, - "w": 0.8787364959716797 - }, - { - "Owner": 29, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -3.5999999046325685 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 30, - "Name": "Entity", - "Components": [ - { - "Owner": 30, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 16147701225056486911, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 30, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\granite2.material" - } - }, - { - "Owner": 30, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 30, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 30, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.4789886772632599, - "z": 0.0, - "w": 0.8778609037399292 - }, - { - "Owner": 30, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -6.5 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 31, - "Name": "Entity", - "Components": [ - { - "Owner": 31, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 16147701225056486911, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 31, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\rock2.material" - } - }, - { - "Owner": 31, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 31, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 31, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.4804815948009491, - "z": 0.0, - "w": 0.8770447969436646 - }, - { - "Owner": 31, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 0.0, - "y": 3.0, - "z": -0.699999988079071 - } - ], - "Children": [] - }, - { - "Name": "", - "Id": 32, - "Name": "Entity", - "Components": [ - { - "Owner": 32, - "Component Type": 17829838403855360956, - "Component Name": "legion::core::mesh_filter", - "value0": 16147701225056486911, - "Filepath": "assets:\\\\models\\uvsphere.obj" - }, - { - "Owner": 32, - "Component Type": 14566645459790289390, - "Component Name": "legion::rendering::mesh_renderer", - "material": { - "MaterialFile": "assets:\\\\materials\\default.material" - } - }, - { - "Owner": 32, - "Component Type": 13028145369583378910, - "Component Name": "custom_component" - }, - { - "Owner": 32, - "Component Type": 7976621606494152606, - "Component Name": "legion::core::scale", - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - { - "Owner": 32, - "Component Type": 6841436683689612098, - "Component Name": "legion::core::rotation", - "x": 0.0, - "y": 0.48212143778800967, - "z": 0.0, - "w": 0.8761447668075562 - }, - { - "Owner": 32, - "Component Type": 5024733841066084311, - "Component Name": "legion::core::position", - "x": 4.0, - "y": 3.0, - "z": -6.5 - } - ], - "Children": [] - } - ] - } -} \ No newline at end of file diff --git a/applications/sandbox/assets/scenes/scene1.bson b/applications/sandbox/assets/scenes/scene1.bson new file mode 100644 index 000000000..a1e4fa637 Binary files /dev/null and b/applications/sandbox/assets/scenes/scene1.bson differ diff --git a/applications/sandbox/assets/scenes/scene1.json b/applications/sandbox/assets/scenes/scene1.json new file mode 100644 index 000000000..f072975ec --- /dev/null +++ b/applications/sandbox/assets/scenes/scene1.json @@ -0,0 +1,96 @@ +{ + "scene": { + "type_name": "legion::core::ecs::entity_data", + "name": "Root", + "active": true, + "children": [ + { + "type_name": "legion::core::ecs::entity_data", + "name": "7", + "active": true, + "children": [ + { + "type_name": "legion::core::ecs::entity_data", + "name": "8", + "active": true, + "children": [], + "components": [ + { + "type_name": "example_comp", + "value": 0 + } + ] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "9", + "active": true, + "children": [], + "components": [] + } + ], + "components": [] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "10", + "active": true, + "children": [ + { + "type_name": "legion::core::ecs::entity_data", + "name": "11", + "active": true, + "children": [], + "components": [ + { + "type_name": "example_comp", + "value": 1 + } + ] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "12", + "active": true, + "children": [], + "components": [] + } + ], + "components": [] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "13", + "active": true, + "children": [ + { + "type_name": "legion::core::ecs::entity_data", + "name": "14", + "active": true, + "children": [], + "components": [ + { + "type_name": "example_comp", + "value": 2 + } + ] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "15", + "active": true, + "children": [], + "components": [] + } + ], + "components": [] + } + ], + "components": [ + { + "type_name": "example_comp", + "value": 1 + } + ] + } +} \ No newline at end of file diff --git a/applications/sandbox/assets/scenes/scene1.yaml b/applications/sandbox/assets/scenes/scene1.yaml new file mode 100644 index 000000000..82eca5d8f --- /dev/null +++ b/applications/sandbox/assets/scenes/scene1.yaml @@ -0,0 +1,71 @@ +scene: + type_name: legion::core::ecs::entity_data + name: Root + active: true + children: + - type_name: legion::core::ecs::entity_data + name: 7 + active: true + children: + - type_name: legion::core::ecs::entity_data + name: 8 + active: true + children: + [] + components: + - type_name: example_comp + value: 0 + - type_name: legion::core::ecs::entity_data + name: 9 + active: true + children: + [] + components: + [] + components: + [] + - type_name: legion::core::ecs::entity_data + name: 10 + active: true + children: + - type_name: legion::core::ecs::entity_data + name: 11 + active: true + children: + [] + components: + - type_name: example_comp + value: 1 + - type_name: legion::core::ecs::entity_data + name: 12 + active: true + children: + [] + components: + [] + components: + [] + - type_name: legion::core::ecs::entity_data + name: 13 + active: true + children: + - type_name: legion::core::ecs::entity_data + name: 14 + active: true + children: + [] + components: + - type_name: example_comp + value: 2 + - type_name: legion::core::ecs::entity_data + name: 15 + active: true + children: + [] + components: + [] + components: + [] + components: + - type_name: example_comp + value: 1 \ No newline at end of file diff --git a/applications/sandbox/assets/scenes/scene2.bson b/applications/sandbox/assets/scenes/scene2.bson new file mode 100644 index 000000000..a1e4fa637 Binary files /dev/null and b/applications/sandbox/assets/scenes/scene2.bson differ diff --git a/applications/sandbox/assets/scenes/scene2.json b/applications/sandbox/assets/scenes/scene2.json new file mode 100644 index 000000000..f072975ec --- /dev/null +++ b/applications/sandbox/assets/scenes/scene2.json @@ -0,0 +1,96 @@ +{ + "scene": { + "type_name": "legion::core::ecs::entity_data", + "name": "Root", + "active": true, + "children": [ + { + "type_name": "legion::core::ecs::entity_data", + "name": "7", + "active": true, + "children": [ + { + "type_name": "legion::core::ecs::entity_data", + "name": "8", + "active": true, + "children": [], + "components": [ + { + "type_name": "example_comp", + "value": 0 + } + ] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "9", + "active": true, + "children": [], + "components": [] + } + ], + "components": [] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "10", + "active": true, + "children": [ + { + "type_name": "legion::core::ecs::entity_data", + "name": "11", + "active": true, + "children": [], + "components": [ + { + "type_name": "example_comp", + "value": 1 + } + ] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "12", + "active": true, + "children": [], + "components": [] + } + ], + "components": [] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "13", + "active": true, + "children": [ + { + "type_name": "legion::core::ecs::entity_data", + "name": "14", + "active": true, + "children": [], + "components": [ + { + "type_name": "example_comp", + "value": 2 + } + ] + }, + { + "type_name": "legion::core::ecs::entity_data", + "name": "15", + "active": true, + "children": [], + "components": [] + } + ], + "components": [] + } + ], + "components": [ + { + "type_name": "example_comp", + "value": 1 + } + ] + } +} \ No newline at end of file diff --git a/applications/sandbox/assets/scenes/scene2.yaml b/applications/sandbox/assets/scenes/scene2.yaml new file mode 100644 index 000000000..82eca5d8f --- /dev/null +++ b/applications/sandbox/assets/scenes/scene2.yaml @@ -0,0 +1,71 @@ +scene: + type_name: legion::core::ecs::entity_data + name: Root + active: true + children: + - type_name: legion::core::ecs::entity_data + name: 7 + active: true + children: + - type_name: legion::core::ecs::entity_data + name: 8 + active: true + children: + [] + components: + - type_name: example_comp + value: 0 + - type_name: legion::core::ecs::entity_data + name: 9 + active: true + children: + [] + components: + [] + components: + [] + - type_name: legion::core::ecs::entity_data + name: 10 + active: true + children: + - type_name: legion::core::ecs::entity_data + name: 11 + active: true + children: + [] + components: + - type_name: example_comp + value: 1 + - type_name: legion::core::ecs::entity_data + name: 12 + active: true + children: + [] + components: + [] + components: + [] + - type_name: legion::core::ecs::entity_data + name: 13 + active: true + children: + - type_name: legion::core::ecs::entity_data + name: 14 + active: true + children: + [] + components: + - type_name: example_comp + value: 2 + - type_name: legion::core::ecs::entity_data + name: 15 + active: true + children: + [] + components: + [] + components: + [] + components: + - type_name: example_comp + value: 1 \ No newline at end of file diff --git a/applications/sandbox/assets/serialization_output/output.json b/applications/sandbox/assets/serialization_output/output.json new file mode 100644 index 000000000..584572b18 --- /dev/null +++ b/applications/sandbox/assets/serialization_output/output.json @@ -0,0 +1 @@ +{"":{"name":"World","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"Skybox","alive":true,"active":true,"children":[],"components":[{"legion::core::scale":{"x":1.0,"y":1.0,"z":1.0}},{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"Ground Plane","alive":true,"active":true,"children":[],"components":[{"legion::core::scale":{"x":1.0,"y":1.0,"z":1.0}},{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"Camera","alive":true,"active":true,"children":[],"components":[{"legion::core::scale":{"x":1.0,"y":1.0,"z":1.0}},{"legion::core::rotation":{"x":-0.0,"y":-0.0,"z":-0.0,"w":1.0}},{"legion::core::position":{"x":0.0,"y":3.0,"z":-30.0}}]}},{"legion::core::ecs::entity":{"name":"Sun","alive":true,"active":true,"children":[],"components":[{"legion::core::scale":{"x":1.0,"y":1.0,"z":1.0}},{"legion::core::rotation":{"x":0.115916907787323,"y":-0.8804763555526733,"z":0.2798481583595276,"w":0.3647052049636841}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"6","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"7","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"8","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"9","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"10","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"11","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"12","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"13","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"14","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"15","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"16","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"17","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"18","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"19","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"20","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"21","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"22","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"23","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}},{"legion::core::ecs::entity":{"name":"24","alive":true,"active":true,"children":[{"legion::core::ecs::entity":{"name":"25","alive":true,"active":true,"children":[],"components":[{"legion::core::rotation":{"x":0.0,"y":0.0,"z":0.0,"w":1.0}},{"legion::core::example_comp":{"value":1}}]}}],"components":[{"legion::core::example_comp":{"value":1}},{"legion::core::position":{"x":0.0,"y":0.0,"z":0.0}},{"legion::core::velocity":{"x":0.0,"y":0.0,"z":0.0}}]}}],"components":[]}} \ No newline at end of file diff --git a/applications/sandbox/imgui.ini b/applications/sandbox/imgui.ini index fa7fa31e2..28c30a17b 100644 --- a/applications/sandbox/imgui.ini +++ b/applications/sandbox/imgui.ini @@ -39,8 +39,8 @@ Size=450,444 Collapsed=0 [Window][###] -Pos=46,71 -Size=268,967 +Pos=5,20 +Size=383,1033 Collapsed=0 [Window][Edit Transform] @@ -49,7 +49,7 @@ Size=424,457 Collapsed=0 [Window][Edit Entity] -Pos=1355,192 -Size=472,453 +Pos=902,64 +Size=538,832 Collapsed=0 diff --git a/applications/sandbox/sandbox.vcxproj b/applications/sandbox/sandbox.vcxproj index 071ace8cb..1d8a53b0e 100644 --- a/applications/sandbox/sandbox.vcxproj +++ b/applications/sandbox/sandbox.vcxproj @@ -68,7 +68,7 @@ true stdcpp17 true - -Werror=return-type %(AdditionalOptions) + -Werror=return-type %(AdditionalOptions) AdvancedVectorExtensions MultiThreadedDebugDLL @@ -76,7 +76,7 @@ Console true $(SolutionDir)lib\;$(SolutionDir)deps\lib\;%(AdditionalLibraryDirectories) - legion-core-d.lib;legion-application-d.lib;legion-rendering-d.lib;legion-audio-d.lib;OpenCL.lib;OpenAL32.lib;glfw3.lib;Voro++D.lib;OptickCore.lib;%(AdditionalDependencies) + legion-core-d.lib;legion-application-d.lib;legion-rendering-d.lib;legion-audio-d.lib;OpenCL.lib;OpenAL32.lib;glfw3.lib;Voro++D.lib;OptickCore.lib;yaml-cpp-d.lib;%(AdditionalDependencies) @@ -101,7 +101,7 @@ true false $(SolutionDir)lib\;$(SolutionDir)deps\lib\;%(AdditionalLibraryDirectories) - legion-core.lib;legion-application.lib;legion-rendering.lib;legion-audio.lib;OpenCL.lib;OpenAL32.lib;glfw3.lib;Voro++.lib;OptickCore.lib;%(AdditionalDependencies) + legion-core.lib;legion-application.lib;legion-rendering.lib;legion-audio.lib;OpenCL.lib;OpenAL32.lib;glfw3.lib;Voro++.lib;OptickCore.lib;yaml-cpp.lib;%(AdditionalDependencies) ' - return 0; // Do not produce comment node - } - - // Remember value start - Ch *value_ = text; - - // Skip until end of comment - while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) - { - if (!text[0]) - CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Create comment node - xml_node *comment = this->allocate_node(node_comment); - comment->value(value_, static_cast(text - value_)); - - // Place zero terminator after comment value - if (!(Flags & parse_no_string_terminators)) - *text = Ch('\0'); - - text += 3; // Skip '-->' - return comment; - } - - // Parse DOCTYPE - template - xml_node *parse_doctype(Ch *&text) - { - // Remember value start - Ch *value_ = text; - - // Skip to > - while (*text != Ch('>')) - { - // Determine character type - switch (*text) - { - - // If '[' encountered, scan for matching ending ']' using naive algorithm with depth - // This works for all W3C test files except for 2 most wicked - case Ch('['): - { - ++text; // Skip '[' - int depth = 1; - while (depth > 0) - { - switch (*text) - { - case Ch('['): ++depth; break; - case Ch(']'): --depth; break; - case 0: CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text); - } - ++text; - } - break; - } - - // Error on end of text - case Ch('\0'): - CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Other character, skip it - default: - ++text; - - } - } - - // If DOCTYPE nodes enabled - if (Flags & parse_doctype_node) - { - // Create a new doctype node - xml_node *doctype = this->allocate_node(node_doctype); - doctype->value(value_, static_cast(text - value_)); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) - *text = Ch('\0'); - - text += 1; // skip '>' - return doctype; - } - else - { - text += 1; // skip '>' - return 0; - } - - } - - // Parse PI - template - xml_node *parse_pi(Ch *&text) - { - // If creation of PI nodes is enabled - if (Flags & parse_pi_nodes) - { - // Create pi node - xml_node *pi = this->allocate_node(node_pi); - - // Extract PI target name - Ch *name_ = text; - skip(text); - if (text == name_) - CEREAL_RAPIDXML_PARSE_ERROR("expected PI target", text); - pi->name(name_, static_cast(text - name_)); - - // Skip whitespace between pi target and pi - skip(text); - - // Remember start of pi - Ch *value_ = text; - - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) - { - if (*text == Ch('\0')) - CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Set pi value (verbatim, no entity expansion or whitespace normalization) - pi->value(value_, static_cast(text - value_)); - - // Place zero terminator after name and value - if (!(Flags & parse_no_string_terminators)) - { - pi->name()[pi->name_size()] = Ch('\0'); - pi->value()[pi->value_size()] = Ch('\0'); - } - - text += 2; // Skip '?>' - return pi; - } - else - { - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) - { - if (*text == Ch('\0')) - CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 2; // Skip '?>' - return 0; - } - } - - // Parse and append data - // Return character that ends data. - // This is necessary because this character might have been overwritten by a terminating 0 - template - Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) - { - // Backup to contents start if whitespace trimming is disabled - if (!(Flags & parse_trim_whitespace)) - text = contents_start; - - const bool preserve_space = internal::preserve_space(node); - - // Skip until end of data - Ch *value_ = text, *end; - if ((Flags & parse_normalize_whitespace) && !preserve_space) - end = skip_and_expand_character_refs(text, false); - else - end = skip_and_expand_character_refs(text, preserve_space); - - // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > - if ((Flags & parse_trim_whitespace) && !preserve_space) - { - if (Flags & parse_normalize_whitespace) - { - // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end - if (*(end - 1) == Ch(' ')) - --end; - } - else - { - // Backup until non-whitespace character is found - while (whitespace_pred::test(*(end - 1))) - --end; - } - } - - // If characters are still left between end and value (this test is only necessary if normalization is enabled) - // Create new data node - if (!(Flags & parse_no_data_nodes)) - { - xml_node *data = this->allocate_node(node_data); - data->value(value_, static_cast(end - value_)); - node->append_node(data); - } - - // Add data to parent node if no data exists yet - if (!(Flags & parse_no_element_values)) - if (*node->value() == Ch('\0')) - node->value(value_, static_cast(end - value_)); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) - { - Ch ch = *text; - *end = Ch('\0'); - return ch; // Return character that ends data; this is required because zero terminator overwritten it - } - - // Return character that ends data - return *text; - } - - // Parse CDATA - template - xml_node *parse_cdata(Ch *&text) - { - // If CDATA is disabled - if (Flags & parse_no_data_nodes) - { - // Skip until end of cdata - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) - { - if (!text[0]) - CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 3; // Skip ]]> - return 0; // Do not produce CDATA node - } - - // Skip until end of cdata - Ch *value_ = text; - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) - { - if (!text[0]) - CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Create new cdata node - xml_node *cdata = this->allocate_node(node_cdata); - cdata->value(value_, static_cast(text - value_)); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) - *text = Ch('\0'); - - text += 3; // Skip ]]> - return cdata; - } - - // Parse element node - template - xml_node *parse_element(Ch *&text) - { - // Create element node - xml_node *element = this->allocate_node(node_element); - - // Extract element name - Ch *name_ = text; - skip(text); - if (text == name_) - CEREAL_RAPIDXML_PARSE_ERROR("expected element name", text); - element->name(name_, static_cast(text - name_)); - - // Skip whitespace between element name and attributes or > - skip(text); - - // Parse attributes, if any - parse_node_attributes(text, element); - - // Determine ending type - if (*text == Ch('>')) - { - ++text; - parse_node_contents(text, element); - } - else if (*text == Ch('/')) - { - ++text; - if (*text != Ch('>')) - CEREAL_RAPIDXML_PARSE_ERROR("expected >", text); - ++text; - } - else - CEREAL_RAPIDXML_PARSE_ERROR("expected >", text); - - // Place zero terminator after name - if (!(Flags & parse_no_string_terminators)) - element->name()[element->name_size()] = Ch('\0'); - - // Return parsed element - return element; - } - - // Determine node type, and parse it - template - xml_node *parse_node(Ch *&text) - { - // Parse proper node type - switch (text[0]) - { - - // <... - default: - // Parse and append element node - return parse_element(text); - - // (text); - } - else - { - // Parse PI - return parse_pi(text); - } - - // (text); - } - break; - - // (text); - } - break; - - // (text); - } - - } // switch - - // Attempt to skip other, unrecognized node types starting with ')) - { - if (*text == 0) - CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - ++text; // Skip '>' - return 0; // No node recognized - - } - } - - // Parse contents of the node - children, data etc. - template - void parse_node_contents(Ch *&text, xml_node *node) - { - // For all children and text - while (1) - { - // Skip whitespace between > and node contents - Ch *contents_start = text; // Store start of node contents before whitespace is skipped - skip(text); - Ch next_char = *text; - - // After data nodes, instead of continuing the loop, control jumps here. - // This is because zero termination inside parse_and_append_data() function - // would wreak havoc with the above code. - // Also, skipping whitespace after data nodes is unnecessary. - after_data_node: - - // Determine what comes next: node closing, child node, data node, or 0? - switch (next_char) - { - - // Node closing or child node - case Ch('<'): - if (text[1] == Ch('/')) - { - Ch *contents_end = 0; - if (internal::preserve_space(node)) - { - contents_end = text; - } - - // Node closing - text += 2; // Skip '(text); - if (!internal::compare(node->name(), node->name_size(), closing_name, static_cast(text - closing_name), true)) - CEREAL_RAPIDXML_PARSE_ERROR("invalid closing tag name", text); - } - else - { - // No validation, just skip name - skip(text); - } - // Skip remaining whitespace after node name - skip(text); - if (*text != Ch('>')) - CEREAL_RAPIDXML_PARSE_ERROR("expected >", text); - ++text; // Skip '>' - - if (contents_end && contents_end != contents_start) - { - node->value(contents_start, static_cast(contents_end - contents_start)); - node->value()[node->value_size()] = Ch('\0'); - } - return; // Node closed, finished parsing contents - } - else - { - // Child node - ++text; // Skip '<' - if (xml_node *child = parse_node(text)) - node->append_node(child); - } - break; - - // End of data - error - case Ch('\0'): - CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Data node - default: - next_char = parse_and_append_data(node, text, contents_start); - goto after_data_node; // Bypass regular processing after data nodes - - } - } - } - - // Parse XML attributes of the node - template - void parse_node_attributes(Ch *&text, xml_node *node) - { - // For all attributes - while (attribute_name_pred::test(*text)) - { - // Extract attribute name - Ch *name_ = text; - ++text; // Skip first character of attribute name - skip(text); - if (text == name_) - CEREAL_RAPIDXML_PARSE_ERROR("expected attribute name", name_); - - // Create new attribute - xml_attribute *attribute = this->allocate_attribute(); - attribute->name(name_, static_cast(text - name_)); - node->append_attribute(attribute); - - // Skip whitespace after attribute name - skip(text); - - // Skip = - if (*text != Ch('=')) - CEREAL_RAPIDXML_PARSE_ERROR("expected =", text); - ++text; - - // Add terminating zero after name - if (!(Flags & parse_no_string_terminators)) - attribute->name()[attribute->name_size()] = 0; - - // Skip whitespace after = - skip(text); - - // Skip quote and remember if it was ' or " - Ch quote = *text; - if (quote != Ch('\'') && quote != Ch('"')) - CEREAL_RAPIDXML_PARSE_ERROR("expected ' or \"", text); - ++text; - - // Extract attribute value and expand char refs in it - Ch *value_ = text, *end; - const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes - if (quote == Ch('\'')) - end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text, false); - else - end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text, false); - - // Set attribute value - attribute->value(value_, static_cast(end - value_)); - - // Make sure that end quote is present - if (*text != quote) - CEREAL_RAPIDXML_PARSE_ERROR("expected ' or \"", text); - ++text; // Skip quote - - // Add terminating zero after value - if (!(Flags & parse_no_string_terminators)) - attribute->value()[attribute->value_size()] = 0; - - // Skip whitespace after attribute value - skip(text); - } - } - - }; - - //! \cond internal - namespace internal - { - - // Whitespace (space \n \r \t) - template - const unsigned char lookup_tables::lookup_whitespace[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F - }; - - // Node name (anything but space \n \r \t / > ? \0) - template - const unsigned char lookup_tables::lookup_node_name[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Text (i.e. PCDATA) (anything but < \0) - template - const unsigned char lookup_tables::lookup_text[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled - // (anything but < \0 &) - template - const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled - // (anything but < \0 & space \n \r \t) - template - const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute name (anything but space \n \r \t / < > = ? ! \0) - template - const unsigned char lookup_tables::lookup_attribute_name[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute data with single quote (anything but ' \0) - template - const unsigned char lookup_tables::lookup_attribute_data_1[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute data with single quote that does not require processing (anything but ' \0 &) - template - const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute data with double quote (anything but " \0) - template - const unsigned char lookup_tables::lookup_attribute_data_2[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute data with double quote that does not require processing (anything but " \0 &) - template - const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Digits (dec and hex, 255 denotes end of numeric character reference) - template - const unsigned char lookup_tables::lookup_digits[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3 - 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5 - 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F - }; - - // Upper case conversion - template - const unsigned char lookup_tables::lookup_upcase[256] = - { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 - 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6 - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7 - 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8 - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9 - 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A - 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B - 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C - 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D - 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E - 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F - }; - } - //! \endcond - -} -} // end namespace cereal - -// Undefine internal macros -#undef CEREAL_RAPIDXML_PARSE_ERROR - -// On MSVC, restore warnings state -#ifdef _MSC_VER - #pragma warning(pop) -#endif - -#endif diff --git a/deps/include/cereal/external/rapidxml/rapidxml_iterators.hpp b/deps/include/cereal/external/rapidxml/rapidxml_iterators.hpp deleted file mode 100644 index 736d46c39..000000000 --- a/deps/include/cereal/external/rapidxml/rapidxml_iterators.hpp +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef CEREAL_RAPIDXML_ITERATORS_HPP_INCLUDED -#define CEREAL_RAPIDXML_ITERATORS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ - -#include "rapidxml.hpp" - -namespace cereal { -namespace rapidxml -{ - - //! Iterator of child nodes of xml_node - template - class node_iterator - { - - public: - - typedef typename xml_node value_type; - typedef typename xml_node &reference; - typedef typename xml_node *pointer; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - node_iterator() - : m_node(0) - { - } - - node_iterator(xml_node *node) - : m_node(node->first_node()) - { - } - - reference operator *() const - { - assert(m_node); - return *m_node; - } - - pointer operator->() const - { - assert(m_node); - return m_node; - } - - node_iterator& operator++() - { - assert(m_node); - m_node = m_node->next_sibling(); - return *this; - } - - node_iterator operator++(int) - { - node_iterator tmp = *this; - ++this; - return tmp; - } - - node_iterator& operator--() - { - assert(m_node && m_node->previous_sibling()); - m_node = m_node->previous_sibling(); - return *this; - } - - node_iterator operator--(int) - { - node_iterator tmp = *this; - ++this; - return tmp; - } - - bool operator ==(const node_iterator &rhs) - { - return m_node == rhs.m_node; - } - - bool operator !=(const node_iterator &rhs) - { - return m_node != rhs.m_node; - } - - private: - - xml_node *m_node; - - }; - - //! Iterator of child attributes of xml_node - template - class attribute_iterator - { - - public: - - typedef typename xml_attribute value_type; - typedef typename xml_attribute &reference; - typedef typename xml_attribute *pointer; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - attribute_iterator() - : m_attribute(0) - { - } - - attribute_iterator(xml_node *node) - : m_attribute(node->first_attribute()) - { - } - - reference operator *() const - { - assert(m_attribute); - return *m_attribute; - } - - pointer operator->() const - { - assert(m_attribute); - return m_attribute; - } - - attribute_iterator& operator++() - { - assert(m_attribute); - m_attribute = m_attribute->next_attribute(); - return *this; - } - - attribute_iterator operator++(int) - { - attribute_iterator tmp = *this; - ++this; - return tmp; - } - - attribute_iterator& operator--() - { - assert(m_attribute && m_attribute->previous_attribute()); - m_attribute = m_attribute->previous_attribute(); - return *this; - } - - attribute_iterator operator--(int) - { - attribute_iterator tmp = *this; - ++this; - return tmp; - } - - bool operator ==(const attribute_iterator &rhs) - { - return m_attribute == rhs.m_attribute; - } - - bool operator !=(const attribute_iterator &rhs) - { - return m_attribute != rhs.m_attribute; - } - - private: - - xml_attribute *m_attribute; - - }; - -} -} // namespace cereal - -#endif diff --git a/deps/include/cereal/external/rapidxml/rapidxml_print.hpp b/deps/include/cereal/external/rapidxml/rapidxml_print.hpp deleted file mode 100644 index 7fbb962e1..000000000 --- a/deps/include/cereal/external/rapidxml/rapidxml_print.hpp +++ /dev/null @@ -1,428 +0,0 @@ -#ifndef CEREAL_RAPIDXML_PRINT_HPP_INCLUDED -#define CEREAL_RAPIDXML_PRINT_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ - -#include "rapidxml.hpp" - -// Only include streams if not disabled -#ifndef CEREAL_RAPIDXML_NO_STREAMS - #include - #include -#endif - -namespace cereal { -namespace rapidxml -{ - - /////////////////////////////////////////////////////////////////////// - // Printing flags - - const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. - - /////////////////////////////////////////////////////////////////////// - // Internal - - //! \cond internal - namespace internal - { - - /////////////////////////////////////////////////////////////////////////// - // Internal character operations - - // Copy characters from given range to given output iterator - template - inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) - { - while (begin != end) - *out++ = *begin++; - return out; - } - - // Copy characters from given range to given output iterator and expand - // characters into references (< > ' " &) - template - inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out) - { - while (begin != end) - { - if (*begin == noexpand) - { - *out++ = *begin; // No expansion, copy character - } - else - { - switch (*begin) - { - case Ch('<'): - *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); - break; - case Ch('>'): - *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); - break; - case Ch('\''): - *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); - break; - case Ch('"'): - *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); - break; - case Ch('&'): - *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); - break; - default: - *out++ = *begin; // No expansion, copy character - } - } - ++begin; // Step to next character - } - return out; - } - - // Fill given output iterator with repetitions of the same character - template - inline OutIt fill_chars(OutIt out, int n, Ch ch) - { - for (int i = 0; i < n; ++i) - *out++ = ch; - return out; - } - - // Find character - template - inline bool find_char(const Ch *begin, const Ch *end) - { - while (begin != end) - if (*begin++ == ch) - return true; - return false; - } - - /////////////////////////////////////////////////////////////////////////// - // Internal printing operations - - // Print node - template - inline OutIt print_node(OutIt out, const xml_node *node, int flags, int indent); - - // Print children of the node - template - inline OutIt print_children(OutIt out, const xml_node *node, int flags, int indent) - { - for (xml_node *child = node->first_node(); child; child = child->next_sibling()) - out = print_node(out, child, flags, indent); - return out; - } - - // Print attributes of the node - template - inline OutIt print_attributes(OutIt out, const xml_node *node, int /*flags*/) - { - for (xml_attribute *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) - { - if (attribute->name() && attribute->value()) - { - // Print attribute name - *out = Ch(' '), ++out; - out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out); - *out = Ch('='), ++out; - // Print attribute value using appropriate quote type - if (find_char(attribute->value(), attribute->value() + attribute->value_size())) - { - *out = Ch('\''), ++out; - out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out); - *out = Ch('\''), ++out; - } - else - { - *out = Ch('"'), ++out; - out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out); - *out = Ch('"'), ++out; - } - } - } - return out; - } - - // Print data node - template - inline OutIt print_data_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_data); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); - return out; - } - - // Print data node - template - inline OutIt print_cdata_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_cdata); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'); ++out; - *out = Ch('!'); ++out; - *out = Ch('['); ++out; - *out = Ch('C'); ++out; - *out = Ch('D'); ++out; - *out = Ch('A'); ++out; - *out = Ch('T'); ++out; - *out = Ch('A'); ++out; - *out = Ch('['); ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch(']'); ++out; - *out = Ch(']'); ++out; - *out = Ch('>'); ++out; - return out; - } - - // Print element node - template - inline OutIt print_element_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_element); - - // Print element name and attributes, if any - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - out = print_attributes(out, node, flags); - - // If node is childless - if (node->value_size() == 0 && !node->first_node()) - { - // Print childless node tag ending - *out = Ch('/'), ++out; - *out = Ch('>'), ++out; - } - else - { - // Print normal node tag ending - *out = Ch('>'), ++out; - - // Test if node contains a single data node only (and no other nodes) - xml_node *child = node->first_node(); - if (!child) - { - // If node has no children, only print its value without indenting - out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); - } - else if (child->next_sibling() == 0 && child->type() == node_data) - { - // If node has a sole data child, only print its value without indenting - out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out); - } - else - { - // Print all children with full indenting - if (!(flags & print_no_indenting)) - *out = Ch('\n'), ++out; - out = print_children(out, node, flags, indent + 1); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - } - - // Print node end - *out = Ch('<'), ++out; - *out = Ch('/'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - *out = Ch('>'), ++out; - } - return out; - } - - // Print declaration node - template - inline OutIt print_declaration_node(OutIt out, const xml_node *node, int flags, int indent) - { - // Print declaration start - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - *out = Ch('x'), ++out; - *out = Ch('m'), ++out; - *out = Ch('l'), ++out; - - // Print attributes - out = print_attributes(out, node, flags); - - // Print declaration end - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - - return out; - } - - // Print comment node - template - inline OutIt print_comment_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_comment); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - *out = Ch('>'), ++out; - return out; - } - - // Print doctype node - template - inline OutIt print_doctype_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_doctype); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('D'), ++out; - *out = Ch('O'), ++out; - *out = Ch('C'), ++out; - *out = Ch('T'), ++out; - *out = Ch('Y'), ++out; - *out = Ch('P'), ++out; - *out = Ch('E'), ++out; - *out = Ch(' '), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('>'), ++out; - return out; - } - - // Print pi node - template - inline OutIt print_pi_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_pi); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - *out = Ch(' '), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - return out; - } - - // Print node - template - inline OutIt print_node(OutIt out, const xml_node *node, int flags, int indent) - { - // Print proper node type - switch (node->type()) - { - - // Document - case node_document: - out = print_children(out, node, flags, indent); - break; - - // Element - case node_element: - out = print_element_node(out, node, flags, indent); - break; - - // Data - case node_data: - out = print_data_node(out, node, flags, indent); - break; - - // CDATA - case node_cdata: - out = print_cdata_node(out, node, flags, indent); - break; - - // Declaration - case node_declaration: - out = print_declaration_node(out, node, flags, indent); - break; - - // Comment - case node_comment: - out = print_comment_node(out, node, flags, indent); - break; - - // Doctype - case node_doctype: - out = print_doctype_node(out, node, flags, indent); - break; - - // Pi - case node_pi: - out = print_pi_node(out, node, flags, indent); - break; - -#ifndef __GNUC__ - // Unknown - default: - assert(0); - break; -#endif - } - - // If indenting not disabled, add line break after node - if (!(flags & print_no_indenting)) - *out = Ch('\n'), ++out; - - // Return modified iterator - return out; - } - - } - //! \endcond - - /////////////////////////////////////////////////////////////////////////// - // Printing - - //! Prints XML to given output iterator. - //! \param out Output iterator to print to. - //! \param node Node to be printed. Pass xml_document to print entire document. - //! \param flags Flags controlling how XML is printed. - //! \return Output iterator pointing to position immediately after last character of printed text. - template - inline OutIt print(OutIt out, const xml_node &node, int flags = 0) - { - return internal::print_node(out, &node, flags, 0); - } - -#ifndef CEREAL_RAPIDXML_NO_STREAMS - - //! Prints XML to given output stream. - //! \param out Output stream to print to. - //! \param node Node to be printed. Pass xml_document to print entire document. - //! \param flags Flags controlling how XML is printed. - //! \return Output stream. - template - inline std::basic_ostream &print(std::basic_ostream &out, const xml_node &node, int flags = 0) - { - print(std::ostream_iterator(out), node, flags); - return out; - } - - //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. - //! \param out Output stream to print to. - //! \param node Node to be printed. - //! \return Output stream. - template - inline std::basic_ostream &operator <<(std::basic_ostream &out, const xml_node &node) - { - return print(out, node); - } - -#endif - -} -} // namespace cereal - -#endif diff --git a/deps/include/cereal/external/rapidxml/rapidxml_utils.hpp b/deps/include/cereal/external/rapidxml/rapidxml_utils.hpp deleted file mode 100644 index e11ecf319..000000000 --- a/deps/include/cereal/external/rapidxml/rapidxml_utils.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef CEREAL_RAPIDXML_UTILS_HPP_INCLUDED -#define CEREAL_RAPIDXML_UTILS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. - -#include "rapidxml.hpp" -#include -#include -#include -#include - -namespace cereal { -namespace rapidxml -{ - - //! Represents data loaded from a file - template - class file - { - - public: - - //! Loads file into the memory. Data will be automatically destroyed by the destructor. - //! \param filename Filename to load. - file(const char *filename) - { - using namespace std; - - // Open stream - basic_ifstream stream(filename, ios::binary); - if (!stream) - throw runtime_error(string("cannot open file ") + filename); - stream.unsetf(ios::skipws); - - // Determine stream size - stream.seekg(0, ios::end); - size_t size = stream.tellg(); - stream.seekg(0); - - // Load data and add terminating 0 - m_data.resize(size + 1); - stream.read(&m_data.front(), static_cast(size)); - m_data[size] = 0; - } - - //! Loads file into the memory. Data will be automatically destroyed by the destructor - //! \param stream Stream to load from - file(std::basic_istream &stream) - { - using namespace std; - - // Load data and add terminating 0 - stream.unsetf(ios::skipws); - m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); - if (stream.fail() || stream.bad()) - throw runtime_error("error reading stream"); - m_data.push_back(0); - } - - //! Gets file data. - //! \return Pointer to data of file. - Ch *data() - { - return &m_data.front(); - } - - //! Gets file data. - //! \return Pointer to data of file. - const Ch *data() const - { - return &m_data.front(); - } - - //! Gets file data size. - //! \return Size of file data, in characters. - std::size_t size() const - { - return m_data.size(); - } - - private: - - std::vector m_data; // File data - - }; - - //! Counts children of node. Time complexity is O(n). - //! \return Number of children of node - template - inline std::size_t count_children(xml_node *node) - { - xml_node *child = node->first_node(); - std::size_t count = 0; - while (child) - { - ++count; - child = child->next_sibling(); - } - return count; - } - - //! Counts attributes of node. Time complexity is O(n). - //! \return Number of attributes of node - template - inline std::size_t count_attributes(xml_node *node) - { - xml_attribute *attr = node->first_attribute(); - std::size_t count = 0; - while (attr) - { - ++count; - attr = attr->next_attribute(); - } - return count; - } - -} -} // namespace cereal - -#endif diff --git a/deps/include/cereal/macros.hpp b/deps/include/cereal/macros.hpp deleted file mode 100644 index 96ca7516b..000000000 --- a/deps/include/cereal/macros.hpp +++ /dev/null @@ -1,154 +0,0 @@ -/*! \file macros.hpp - \brief Preprocessor macros that can customise the cereal library - - By default, cereal looks for serialization functions with very - specific names, that is: serialize, load, save, load_minimal, - or save_minimal. - - This file allows an advanced user to change these names to conform - to some other style or preference. This is implemented using - preprocessor macros. - - As a result of this, in internal cereal code you will see macros - used for these function names. In user code, you should name - the functions like you normally would and not use the macros - to improve readability. - \ingroup utility */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef CEREAL_MACROS_HPP_ -#define CEREAL_MACROS_HPP_ - -#ifndef CEREAL_THREAD_SAFE -//! Whether cereal should be compiled for a threaded environment -/*! This macro causes cereal to use mutexes to control access to - global internal state in a thread safe manner. - - Note that even with this enabled you must still ensure that - archives are accessed by only one thread at a time; it is safe - to use multiple archives in paralel, but not to access one archive - from many places simultaneously. */ -#define CEREAL_THREAD_SAFE 0 -#endif // CEREAL_THREAD_SAFE - -#ifndef CEREAL_SIZE_TYPE -//! Determines the data type used for size_type -/*! cereal uses size_type to ensure that the serialized size of - dynamic containers is compatible across different architectures - (e.g. 32 vs 64 bit), which may use different underlying types for - std::size_t. - - More information can be found in cereal/details/helpers.hpp. - - If you choose to modify this type, ensure that you use a fixed - size type (e.g. uint32_t). */ -#define CEREAL_SIZE_TYPE uint64_t -#endif // CEREAL_SIZE_TYPE - -// ###################################################################### -#ifndef CEREAL_SERIALIZE_FUNCTION_NAME -//! The serialization/deserialization function name to search for. -/*! You can define @c CEREAL_SERIALIZE_FUNCTION_NAME to be different assuming - you do so before this file is included. */ -#define CEREAL_SERIALIZE_FUNCTION_NAME serialize -#endif // CEREAL_SERIALIZE_FUNCTION_NAME - -#ifndef CEREAL_LOAD_FUNCTION_NAME -//! The deserialization (load) function name to search for. -/*! You can define @c CEREAL_LOAD_FUNCTION_NAME to be different assuming you do so - before this file is included. */ -#define CEREAL_LOAD_FUNCTION_NAME load -#endif // CEREAL_LOAD_FUNCTION_NAME - -#ifndef CEREAL_SAVE_FUNCTION_NAME -//! The serialization (save) function name to search for. -/*! You can define @c CEREAL_SAVE_FUNCTION_NAME to be different assuming you do so - before this file is included. */ -#define CEREAL_SAVE_FUNCTION_NAME save -#endif // CEREAL_SAVE_FUNCTION_NAME - -#ifndef CEREAL_LOAD_MINIMAL_FUNCTION_NAME -//! The deserialization (load_minimal) function name to search for. -/*! You can define @c CEREAL_LOAD_MINIMAL_FUNCTION_NAME to be different assuming you do so - before this file is included. */ -#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME load_minimal -#endif // CEREAL_LOAD_MINIMAL_FUNCTION_NAME - -#ifndef CEREAL_SAVE_MINIMAL_FUNCTION_NAME -//! The serialization (save_minimal) function name to search for. -/*! You can define @c CEREAL_SAVE_MINIMAL_FUNCTION_NAME to be different assuming you do so - before this file is included. */ -#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME save_minimal -#endif // CEREAL_SAVE_MINIMAL_FUNCTION_NAME - -// ###################################################################### -//! Defines the CEREAL_NOEXCEPT macro to use instead of noexcept -/*! If a compiler we support does not support noexcept, this macro - will detect this and define CEREAL_NOEXCEPT as a no-op - @internal */ -#if !defined(CEREAL_HAS_NOEXCEPT) - #if defined(__clang__) - #if __has_feature(cxx_noexcept) - #define CEREAL_HAS_NOEXCEPT - #endif - #else // NOT clang - #if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \ - defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026 - #define CEREAL_HAS_NOEXCEPT - #endif // end GCC/MSVC check - #endif // end NOT clang block - - #ifndef CEREAL_NOEXCEPT - #ifdef CEREAL_HAS_NOEXCEPT - #define CEREAL_NOEXCEPT noexcept - #else - #define CEREAL_NOEXCEPT - #endif // end CEREAL_HAS_NOEXCEPT - #endif // end !defined(CEREAL_HAS_NOEXCEPT) -#endif // ifndef CEREAL_NOEXCEPT - -// ###################################################################### -//! Checks if C++17 is available -#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -#define CEREAL_HAS_CPP17 -#endif - -//! Checks if C++14 is available -#if __cplusplus >= 201402L -#define CEREAL_HAS_CPP14 -#endif - -// ###################################################################### -//! Defines the CEREAL_ALIGNOF macro to use instead of alignof -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define CEREAL_ALIGNOF __alignof -#else // not MSVC 2013 or older -#define CEREAL_ALIGNOF alignof -#endif // end MSVC check - -#endif // CEREAL_MACROS_HPP_ diff --git a/deps/include/cereal/specialize.hpp b/deps/include/cereal/specialize.hpp deleted file mode 100644 index b9276db25..000000000 --- a/deps/include/cereal/specialize.hpp +++ /dev/null @@ -1,139 +0,0 @@ -/*! \file specialize.hpp - \brief Serialization disambiguation */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef CEREAL_SPECIALIZE_HPP_ -#define CEREAL_SPECIALIZE_HPP_ - -namespace cereal -{ - // Forward declaration of access class that users can become friends with - class access; - - // ###################################################################### - //! A specifier used in conjunction with cereal::specialize to disambiguate - //! serialization in special cases - /*! @relates specialize - @ingroup Access */ - enum class specialization - { - member_serialize, //!< Force the use of a member serialize function - member_load_save, //!< Force the use of a member load/save pair - member_load_save_minimal, //!< Force the use of a member minimal load/save pair - non_member_serialize, //!< Force the use of a non-member serialize function - non_member_load_save, //!< Force the use of a non-member load/save pair - non_member_load_save_minimal //!< Force the use of a non-member minimal load/save pair - }; - - //! A class used to disambiguate cases where cereal cannot detect a unique way of serializing a class - /*! cereal attempts to figure out which method of serialization (member vs. non-member serialize - or load/save pair) at compile time. If for some reason cereal cannot find a non-ambiguous way - of serializing a type, it will produce a static assertion complaining about this. - - This can happen because you have both a serialize and load/save pair, or even because a base - class has a serialize (public or private with friend access) and a derived class does not - overwrite this due to choosing some other serialization type. - - Specializing this class will tell cereal to explicitly use the serialization type you specify - and it will not complain about ambiguity in its compile time selection. However, if cereal detects - an ambiguity in specializations, it will continue to issue a static assertion. - - @code{.cpp} - class MyParent - { - friend class cereal::access; - template - void serialize( Archive & ar ) {} - }; - - // Although serialize is private in MyParent, to cereal::access it will look public, - // even through MyDerived - class MyDerived : public MyParent - { - public: - template - void load( Archive & ar ) {} - - template - void save( Archive & ar ) {} - }; - - // The load/save pair in MyDerived is ambiguous because serialize in MyParent can - // be accessed from cereal::access. This looks the same as making serialize public - // in MyParent, making it seem as though MyDerived has both a serialize and a load/save pair. - // cereal will complain about this at compile time unless we disambiguate: - - namespace cereal - { - // This struct specialization will tell cereal which is the right way to serialize the ambiguity - template struct specialize {}; - - // If we only had a disambiguation for a specific archive type, it would look something like this - template <> struct specialize {}; - } - @endcode - - You can also choose to use the macros CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES or - CEREAL_SPECIALIZE_FOR_ARCHIVE if you want to type a little bit less. - - @tparam T The type to specialize the serialization for - @tparam S The specialization type to use for T - @ingroup Access */ - template - struct specialize : public std::false_type {}; - - //! Convenient macro for performing specialization for all archive types - /*! This performs specialization for the specific type for all types of archives. - This macro should be placed at the global namespace. - - @code{cpp} - struct MyType {}; - CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( MyType, cereal::specialization::member_load_save ); - @endcode - - @relates specialize - @ingroup Access */ - #define CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( Type, Specialization ) \ - namespace cereal { template struct specialize {}; } - - //! Convenient macro for performing specialization for a single archive type - /*! This performs specialization for the specific type for a single type of archive. - This macro should be placed at the global namespace. - - @code{cpp} - struct MyType {}; - CEREAL_SPECIALIZE_FOR_ARCHIVE( cereal::XMLInputArchive, MyType, cereal::specialization::member_load_save ); - @endcode - - @relates specialize - @ingroup Access */ - #define CEREAL_SPECIALIZE_FOR_ARCHIVE( Archive, Type, Specialization ) \ - namespace cereal { template <> struct specialize {}; } -} - -#endif diff --git a/deps/include/cereal/types/array.hpp b/deps/include/cereal/types/array.hpp deleted file mode 100644 index f5d510abf..000000000 --- a/deps/include/cereal/types/array.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/*! \file array.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_ARRAY_HPP_ -#define CEREAL_TYPES_ARRAY_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - //! Saving for std::array primitive types - //! using binary serialization, if supported - template inline - typename std::enable_if, Archive>::value - && std::is_arithmetic::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array const & array ) - { - ar( binary_data( array.data(), sizeof(array) ) ); - } - - //! Loading for std::array primitive types - //! using binary serialization, if supported - template inline - typename std::enable_if, Archive>::value - && std::is_arithmetic::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array & array ) - { - ar( binary_data( array.data(), sizeof(array) ) ); - } - - //! Saving for std::array all other types - template inline - typename std::enable_if, Archive>::value - || !std::is_arithmetic::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array const & array ) - { - for( auto const & i : array ) - ar( i ); - } - - //! Loading for std::array all other types - template inline - typename std::enable_if, Archive>::value - || !std::is_arithmetic::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array & array ) - { - for( auto & i : array ) - ar( i ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_ARRAY_HPP_ diff --git a/deps/include/cereal/types/atomic.hpp b/deps/include/cereal/types/atomic.hpp deleted file mode 100644 index 03d8b8722..000000000 --- a/deps/include/cereal/types/atomic.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/*! \file atomic.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_ATOMIC_HPP_ -#define CEREAL_TYPES_ATOMIC_HPP_ - -#include -#include - -namespace cereal -{ - //! Serializing (save) for std::atomic - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::atomic const & a ) - { - ar( CEREAL_NVP_("atomic_data", a.load()) ); - } - - //! Serializing (load) for std::atomic - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::atomic & a ) - { - T tmp; - ar( CEREAL_NVP_("atomic_data", tmp) ); - a.store( tmp ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_ATOMIC_HPP_ diff --git a/deps/include/cereal/types/base_class.hpp b/deps/include/cereal/types/base_class.hpp deleted file mode 100644 index fd7423e6f..000000000 --- a/deps/include/cereal/types/base_class.hpp +++ /dev/null @@ -1,203 +0,0 @@ -/*! \file base_class.hpp - \brief Support for base classes (virtual and non-virtual) - \ingroup OtherTypes */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_BASE_CLASS_HPP_ -#define CEREAL_TYPES_BASE_CLASS_HPP_ - -#include "cereal/details/traits.hpp" -#include "cereal/details/polymorphic_impl_fwd.hpp" - -namespace cereal -{ - namespace base_class_detail - { - //! Used to register polymorphic relations and avoid the need to include - //! polymorphic.hpp when no polymorphism is used - /*! @internal */ - template ::value> - struct RegisterPolymorphicBaseClass - { - static void bind() - { } - }; - - //! Polymorphic version - /*! @internal */ - template - struct RegisterPolymorphicBaseClass - { - static void bind() - { detail::RegisterPolymorphicCaster::bind(); } - }; - } - - //! Casts a derived class to its non-virtual base class in a way that safely supports abstract classes - /*! This should be used in cases when a derived type needs to serialize its base type. This is better than directly - using static_cast, as it allows for serialization of pure virtual (abstract) base classes. - - This also automatically registers polymorphic relation between the base and derived class, assuming they - are indeed polymorphic. Note this is not the same as polymorphic type registration. For more information - see the documentation on polymorphism. If using a polymorphic class, be sure to include support for - polymorphism (cereal/types/polymorphic.hpp). - - \sa virtual_base_class - - @code{.cpp} - struct MyBase - { - int x; - - virtual void foo() = 0; - - template - void serialize( Archive & ar ) - { - ar( x ); - } - }; - - struct MyDerived : public MyBase //<-- Note non-virtual inheritance - { - int y; - - virtual void foo() {}; - - template - void serialize( Archive & ar ) - { - ar( cereal::base_class(this) ); - ar( y ); - } - }; - @endcode */ - template - struct base_class : private traits::detail::BaseCastBase - { - template - base_class(Derived const * derived) : - base_ptr(const_cast(static_cast(derived))) - { - static_assert( std::is_base_of::value, "Can only use base_class on a valid base class" ); - base_class_detail::RegisterPolymorphicBaseClass::bind(); - } - - Base * base_ptr; - }; - - //! Casts a derived class to its virtual base class in a way that allows cereal to track inheritance - /*! This should be used in cases when a derived type features virtual inheritance from some - base type. This allows cereal to track the inheritance and to avoid making duplicate copies - during serialization. - - It is safe to use virtual_base_class in all circumstances for serializing base classes, even in cases - where virtual inheritance does not take place, though it may be slightly faster to utilize - cereal::base_class<> if you do not need to worry about virtual inheritance. - - This also automatically registers polymorphic relation between the base and derived class, assuming they - are indeed polymorphic. Note this is not the same as polymorphic type registration. For more information - see the documentation on polymorphism. If using a polymorphic class, be sure to include support for - polymorphism (cereal/types/polymorphic.hpp). - - \sa base_class - - @code{.cpp} - struct MyBase - { - int x; - - template - void serialize( Archive & ar ) - { - ar( x ); - } - }; - - struct MyLeft : virtual MyBase //<-- Note the virtual inheritance - { - int y; - - template - void serialize( Archive & ar ) - { - ar( cereal::virtual_base_class( this ) ); - ar( y ); - } - }; - - struct MyRight : virtual MyBase - { - int z; - - template - void serialize( Archive & ar ) - { - ar( cereal::virtual_base_clas( this ) ); - ar( z ); - } - }; - - // diamond virtual inheritance; contains one copy of each base class - struct MyDerived : virtual MyLeft, virtual MyRight - { - int a; - - template - void serialize( Archive & ar ) - { - ar( cereal::virtual_base_class( this ) ); // safely serialize data members in MyLeft - ar( cereal::virtual_base_class( this ) ); // safely serialize data members in MyRight - ar( a ); - - // Because we used virtual_base_class, cereal will ensure that only one instance of MyBase is - // serialized as we traverse the inheritance heirarchy. This means that there will be one copy - // each of the variables x, y, z, and a - - // If we had chosen to use static_cast<> instead, cereal would perform no tracking and - // assume that every base class should be serialized (in this case leading to a duplicate - // serialization of MyBase due to diamond inheritance - }; - } - @endcode */ - template - struct virtual_base_class : private traits::detail::BaseCastBase - { - template - virtual_base_class(Derived const * derived) : - base_ptr(const_cast(static_cast(derived))) - { - static_assert( std::is_base_of::value, "Can only use virtual_base_class on a valid base class" ); - base_class_detail::RegisterPolymorphicBaseClass::bind(); - } - - Base * base_ptr; - }; - -} // namespace cereal - -#endif // CEREAL_TYPES_BASE_CLASS_HPP_ diff --git a/deps/include/cereal/types/bitset.hpp b/deps/include/cereal/types/bitset.hpp deleted file mode 100644 index 22ff534f6..000000000 --- a/deps/include/cereal/types/bitset.hpp +++ /dev/null @@ -1,176 +0,0 @@ -/*! \file bitset.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_BITSET_HPP_ -#define CEREAL_TYPES_BITSET_HPP_ - -#include "cereal/cereal.hpp" -#include "cereal/types/string.hpp" -#include - -namespace cereal -{ - namespace bitset_detail - { - //! The type the bitset is encoded with - /*! @internal */ - enum class type : uint8_t - { - ulong, - ullong, - string, - bits - }; - } - - //! Serializing (save) for std::bitset when BinaryData optimization supported - template , Archive>::value> - = traits::sfinae> inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset const & bits ) - { - ar( CEREAL_NVP_("type", bitset_detail::type::bits) ); - - // Serialize 8 bit chunks - std::uint8_t chunk = 0; - std::uint8_t mask = 0x80; - - // Set each chunk using a rotating mask for the current bit - for( std::size_t i = 0; i < N; ++i ) - { - if( bits[i] ) - chunk |= mask; - - mask = static_cast(mask >> 1); - - // output current chunk when mask is empty (8 bits) - if( mask == 0 ) - { - ar( chunk ); - chunk = 0; - mask = 0x80; - } - } - - // serialize remainder, if it exists - if( mask != 0x80 ) - ar( chunk ); - } - - //! Serializing (save) for std::bitset when BinaryData is not supported - template , Archive>::value> - = traits::sfinae> inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset const & bits ) - { - try - { - auto const b = bits.to_ulong(); - ar( CEREAL_NVP_("type", bitset_detail::type::ulong) ); - ar( CEREAL_NVP_("data", b) ); - } - catch( std::overflow_error const & ) - { - try - { - auto const b = bits.to_ullong(); - ar( CEREAL_NVP_("type", bitset_detail::type::ullong) ); - ar( CEREAL_NVP_("data", b) ); - } - catch( std::overflow_error const & ) - { - ar( CEREAL_NVP_("type", bitset_detail::type::string) ); - ar( CEREAL_NVP_("data", bits.to_string()) ); - } - } - } - - //! Serializing (load) for std::bitset - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::bitset & bits ) - { - bitset_detail::type t; - ar( CEREAL_NVP_("type", t) ); - - switch( t ) - { - case bitset_detail::type::ulong: - { - unsigned long b; - ar( CEREAL_NVP_("data", b) ); - bits = std::bitset( b ); - break; - } - case bitset_detail::type::ullong: - { - unsigned long long b; - ar( CEREAL_NVP_("data", b) ); - bits = std::bitset( b ); - break; - } - case bitset_detail::type::string: - { - std::string b; - ar( CEREAL_NVP_("data", b) ); - bits = std::bitset( b ); - break; - } - case bitset_detail::type::bits: - { - // Normally we would use BinaryData to route this at compile time, - // but doing this at runtime doesn't break any old serialization - std::uint8_t chunk = 0; - std::uint8_t mask = 0; - - bits.reset(); - - // Load one chunk at a time, rotating through the chunk - // to set bits in the bitset - for( std::size_t i = 0; i < N; ++i ) - { - if( mask == 0 ) - { - ar( chunk ); - mask = 0x80; - } - - if( chunk & mask ) - bits[i] = 1; - - mask = static_cast(mask >> 1); - } - break; - } - default: - throw Exception("Invalid bitset data representation"); - } - } -} // namespace cereal - -#endif // CEREAL_TYPES_BITSET_HPP_ diff --git a/deps/include/cereal/types/boost_variant.hpp b/deps/include/cereal/types/boost_variant.hpp deleted file mode 100644 index 5f64de508..000000000 --- a/deps/include/cereal/types/boost_variant.hpp +++ /dev/null @@ -1,164 +0,0 @@ -/*! \file boost_variant.hpp - \brief Support for boost::variant - \ingroup OtherTypes */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_BOOST_VARIANT_HPP_ -#define CEREAL_TYPES_BOOST_VARIANT_HPP_ - -//! @internal -#if defined(_MSC_VER) && _MSC_VER < 1911 -#define CEREAL_CONSTEXPR_LAMBDA -#else // MSVC 2017 or newer, all other compilers -#define CEREAL_CONSTEXPR_LAMBDA constexpr -#endif - -#include "cereal/cereal.hpp" -#include -#include - -namespace cereal -{ - namespace boost_variant_detail - { - //! @internal - template - struct variant_save_visitor : boost::static_visitor<> - { - variant_save_visitor(Archive & ar_) : ar(ar_) {} - - template - void operator()(T const & value) const - { - ar( CEREAL_NVP_("data", value) ); - } - - Archive & ar; - }; - - //! @internal - template - struct LoadAndConstructLoadWrapper - { - using ST = typename std::aligned_storage::type; - - LoadAndConstructLoadWrapper() : - construct( reinterpret_cast( &st ) ) - { } - - ~LoadAndConstructLoadWrapper() - { - if (construct.itsValid) - { - construct->~T(); - } - } - - void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar ) - { - ::cereal::detail::Construct::load_andor_construct( ar, construct ); - } - - ST st; - ::cereal::construct construct; - }; - - //! @internal - template struct load_variant_wrapper; - - //! Avoid serializing variant void_ type - /*! @internal */ - template <> - struct load_variant_wrapper - { - template - static void load_variant( Archive &, Variant & ) - { } - }; - - //! @internal - template - struct load_variant_wrapper - { - // default constructible - template - static void load_variant_impl( Archive & ar, Variant & variant, std::true_type ) - { - T value; - ar( CEREAL_NVP_("data", value) ); - variant = std::move(value); - } - - // not default constructible - template - static void load_variant_impl(Archive & ar, Variant & variant, std::false_type ) - { - LoadAndConstructLoadWrapper loadWrapper; - - ar( CEREAL_NVP_("data", loadWrapper) ); - variant = std::move(*loadWrapper.construct.ptr()); - } - - //! @internal - template - static void load_variant(Archive & ar, Variant & variant) - { - load_variant_impl( ar, variant, typename std::is_default_constructible::type() ); - } - }; - } // namespace boost_variant_detail - - //! Saving for boost::variant - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant const & variant ) - { - int32_t which = variant.which(); - ar( CEREAL_NVP_("which", which) ); - boost_variant_detail::variant_save_visitor visitor(ar); - variant.apply_visitor(visitor); - } - - //! Loading for boost::variant - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant & variant ) - { - int32_t which; - ar( CEREAL_NVP_("which", which) ); - - using LoadFuncType = void(*)(Archive &, boost::variant &); - CEREAL_CONSTEXPR_LAMBDA LoadFuncType loadFuncArray[] = {&boost_variant_detail::load_variant_wrapper::load_variant...}; - - if(which >= int32_t(sizeof(loadFuncArray)/sizeof(loadFuncArray[0]))) - throw Exception("Invalid 'which' selector when deserializing boost::variant"); - - loadFuncArray[which](ar, variant); - } -} // namespace cereal - -#undef CEREAL_CONSTEXPR_LAMBDA - -#endif // CEREAL_TYPES_BOOST_VARIANT_HPP_ diff --git a/deps/include/cereal/types/chrono.hpp b/deps/include/cereal/types/chrono.hpp deleted file mode 100644 index 12ee4cb7c..000000000 --- a/deps/include/cereal/types/chrono.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/*! \file chrono.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_CHRONO_HPP_ -#define CEREAL_TYPES_CHRONO_HPP_ - -#include - -namespace cereal -{ - //! Saving std::chrono::duration - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::chrono::duration const & dur ) - { - ar( CEREAL_NVP_("count", dur.count()) ); - } - - //! Loading std::chrono::duration - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::chrono::duration & dur ) - { - R count; - ar( CEREAL_NVP_("count", count) ); - - dur = std::chrono::duration{count}; - } - - //! Saving std::chrono::time_point - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::chrono::time_point const & dur ) - { - ar( CEREAL_NVP_("time_since_epoch", dur.time_since_epoch()) ); - } - - //! Loading std::chrono::time_point - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::chrono::time_point & dur ) - { - D elapsed; - ar( CEREAL_NVP_("time_since_epoch", elapsed) ); - - dur = std::chrono::time_point{elapsed}; - } -} // namespace cereal - -#endif // CEREAL_TYPES_CHRONO_HPP_ diff --git a/deps/include/cereal/types/common.hpp b/deps/include/cereal/types/common.hpp deleted file mode 100644 index b239daa76..000000000 --- a/deps/include/cereal/types/common.hpp +++ /dev/null @@ -1,129 +0,0 @@ -/*! \file common.hpp - \brief Support common types - always included automatically - \ingroup OtherTypes */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_COMMON_HPP_ -#define CEREAL_TYPES_COMMON_HPP_ - -#include "cereal/cereal.hpp" - -namespace cereal -{ - namespace common_detail - { - //! Serialization for arrays if BinaryData is supported and we are arithmetic - /*! @internal */ - template inline - void serializeArray( Archive & ar, T & array, std::true_type /* binary_supported */ ) - { - ar( binary_data( array, sizeof(array) ) ); - } - - //! Serialization for arrays if BinaryData is not supported or we are not arithmetic - /*! @internal */ - template inline - void serializeArray( Archive & ar, T & array, std::false_type /* binary_supported */ ) - { - for( auto & i : array ) - ar( i ); - } - - namespace - { - //! Gets the underlying type of an enum - /*! @internal */ - template - struct enum_underlying_type : std::false_type {}; - - //! Gets the underlying type of an enum - /*! Specialization for when we actually have an enum - @internal */ - template - struct enum_underlying_type { using type = typename std::underlying_type::type; }; - } // anon namespace - - //! Checks if a type is an enum - /*! This is needed over simply calling std::is_enum because the type - traits checking at compile time will attempt to call something like - load_minimal with a special NoConvertRef struct that wraps up the true type. - - This will strip away any of that and also expose the true underlying type. - @internal */ - template - class is_enum - { - private: - using DecayedT = typename std::decay::type; - using StrippedT = typename ::cereal::traits::strip_minimal::type; - - public: - static const bool value = std::is_enum::value; - using type = StrippedT; - using base_type = typename enum_underlying_type::type; - }; - } - - //! Saving for enum types - template inline - typename std::enable_if::value, - typename common_detail::is_enum::base_type>::type - CEREAL_SAVE_MINIMAL_FUNCTION_NAME( Archive const &, T const & t ) - { - return static_cast::base_type>(t); - } - - //! Loading for enum types - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_MINIMAL_FUNCTION_NAME( Archive const &, T && t, - typename common_detail::is_enum::base_type const & value ) - { - t = reinterpret_cast::type const &>( value ); - } - - //! Serialization for raw pointers - /*! This exists only to throw a static_assert to let users know we don't support raw pointers. */ - template inline - void CEREAL_SERIALIZE_FUNCTION_NAME( Archive &, T * & ) - { - static_assert(cereal::traits::detail::delay_static_assert::value, - "Cereal does not support serializing raw pointers - please use a smart pointer"); - } - - //! Serialization for C style arrays - template inline - typename std::enable_if::value, void>::type - CEREAL_SERIALIZE_FUNCTION_NAME(Archive & ar, T & array) - { - common_detail::serializeArray( ar, array, - std::integral_constant, Archive>::value && - std::is_arithmetic::type>::value>() ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_COMMON_HPP_ diff --git a/deps/include/cereal/types/complex.hpp b/deps/include/cereal/types/complex.hpp deleted file mode 100644 index 7e6ff54f4..000000000 --- a/deps/include/cereal/types/complex.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/*! \file complex.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_COMPLEX_HPP_ -#define CEREAL_TYPES_COMPLEX_HPP_ - -#include - -namespace cereal -{ - //! Serializing (save) for std::complex - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::complex const & comp ) - { - ar( CEREAL_NVP_("real", comp.real()), - CEREAL_NVP_("imag", comp.imag()) ); - } - - //! Serializing (load) for std::complex - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::complex & bits ) - { - T real, imag; - ar( CEREAL_NVP_("real", real), - CEREAL_NVP_("imag", imag) ); - bits = {real, imag}; - } -} // namespace cereal - -#endif // CEREAL_TYPES_COMPLEX_HPP_ diff --git a/deps/include/cereal/types/concepts/pair_associative_container.hpp b/deps/include/cereal/types/concepts/pair_associative_container.hpp deleted file mode 100644 index 5f0fd746c..000000000 --- a/deps/include/cereal/types/concepts/pair_associative_container.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/*! \file pair_associative_container.hpp - \brief Support for the PairAssociativeContainer refinement of the - AssociativeContainer concept. - \ingroup TypeConcepts */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_ -#define CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_ - -#include "cereal/cereal.hpp" - -namespace cereal -{ - //! Saving for std-like pair associative containers - template class Map, typename... Args, typename = typename Map::mapped_type> inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, Map const & map ) - { - ar( make_size_tag( static_cast(map.size()) ) ); - - for( const auto & i : map ) - ar( make_map_item(i.first, i.second) ); - } - - //! Loading for std-like pair associative containers - template class Map, typename... Args, typename = typename Map::mapped_type> inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, Map & map ) - { - size_type size; - ar( make_size_tag( size ) ); - - map.clear(); - - auto hint = map.begin(); - for( size_t i = 0; i < size; ++i ) - { - typename Map::key_type key; - typename Map::mapped_type value; - - ar( make_map_item(key, value) ); - #ifdef CEREAL_OLDER_GCC - hint = map.insert( hint, std::make_pair(std::move(key), std::move(value)) ); - #else // NOT CEREAL_OLDER_GCC - hint = map.emplace_hint( hint, std::move( key ), std::move( value ) ); - #endif // NOT CEREAL_OLDER_GCC - } - } -} // namespace cereal - -#endif // CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_ diff --git a/deps/include/cereal/types/deque.hpp b/deps/include/cereal/types/deque.hpp deleted file mode 100644 index 0491d28d0..000000000 --- a/deps/include/cereal/types/deque.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/*! \file deque.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_DEQUE_HPP_ -#define CEREAL_TYPES_DEQUE_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - //! Saving for std::deque - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::deque const & deque ) - { - ar( make_size_tag( static_cast(deque.size()) ) ); - - for( auto const & i : deque ) - ar( i ); - } - - //! Loading for std::deque - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::deque & deque ) - { - size_type size; - ar( make_size_tag( size ) ); - - deque.resize( static_cast( size ) ); - - for( auto & i : deque ) - ar( i ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_DEQUE_HPP_ diff --git a/deps/include/cereal/types/forward_list.hpp b/deps/include/cereal/types/forward_list.hpp deleted file mode 100644 index db87e1f5c..000000000 --- a/deps/include/cereal/types/forward_list.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/*! \file forward_list.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_FORWARD_LIST_HPP_ -#define CEREAL_TYPES_FORWARD_LIST_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - //! Saving for std::forward_list all other types - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::forward_list const & forward_list ) - { - // write the size - note that this is slow because we need to traverse - // the entire list. there are ways we could avoid this but this was chosen - // since it works in the most general fashion with any archive type - size_type const size = std::distance( forward_list.begin(), forward_list.end() ); - - ar( make_size_tag( size ) ); - - // write the list - for( const auto & i : forward_list ) - ar( i ); - } - - //! Loading for std::forward_list all other types from - template - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::forward_list & forward_list ) - { - size_type size; - ar( make_size_tag( size ) ); - - forward_list.resize( static_cast( size ) ); - - for( auto & i : forward_list ) - ar( i ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_FORWARD_LIST_HPP_ diff --git a/deps/include/cereal/types/functional.hpp b/deps/include/cereal/types/functional.hpp deleted file mode 100644 index 0023ec400..000000000 --- a/deps/include/cereal/types/functional.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/*! \file functional.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2016, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_FUNCTIONAL_HPP_ -#define CEREAL_TYPES_FUNCTIONAL_HPP_ - -#include - -namespace cereal -{ - //! Saving for std::less - template inline - void serialize( Archive &, std::less & ) - { } -} // namespace cereal - -#endif // CEREAL_TYPES_FUNCTIONAL_HPP_ diff --git a/deps/include/cereal/types/list.hpp b/deps/include/cereal/types/list.hpp deleted file mode 100644 index 6008204ff..000000000 --- a/deps/include/cereal/types/list.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/*! \file list.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_LIST_HPP_ -#define CEREAL_TYPES_LIST_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - //! Saving for std::list - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::list const & list ) - { - ar( make_size_tag( static_cast(list.size()) ) ); - - for( auto const & i : list ) - ar( i ); - } - - //! Loading for std::list - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::list & list ) - { - size_type size; - ar( make_size_tag( size ) ); - - list.resize( static_cast( size ) ); - - for( auto & i : list ) - ar( i ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_LIST_HPP_ diff --git a/deps/include/cereal/types/map.hpp b/deps/include/cereal/types/map.hpp deleted file mode 100644 index 41845e980..000000000 --- a/deps/include/cereal/types/map.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/*! \file map.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_MAP_HPP_ -#define CEREAL_TYPES_MAP_HPP_ - -#include "cereal/types/concepts/pair_associative_container.hpp" -#include - -#endif // CEREAL_TYPES_MAP_HPP_ diff --git a/deps/include/cereal/types/memory.hpp b/deps/include/cereal/types/memory.hpp deleted file mode 100644 index 59e9da9be..000000000 --- a/deps/include/cereal/types/memory.hpp +++ /dev/null @@ -1,425 +0,0 @@ -/*! \file memory.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_SHARED_PTR_HPP_ -#define CEREAL_TYPES_SHARED_PTR_HPP_ - -#include "cereal/cereal.hpp" -#include -#include - -namespace cereal -{ - namespace memory_detail - { - //! A wrapper class to notify cereal that it is ok to serialize the contained pointer - /*! This mechanism allows us to intercept and properly handle polymorphic pointers - @internal */ - template - struct PtrWrapper - { - PtrWrapper(T && p) : ptr(std::forward(p)) {} - T & ptr; - - PtrWrapper( PtrWrapper const & ) = default; - PtrWrapper & operator=( PtrWrapper const & ) = delete; - }; - - //! Make a PtrWrapper - /*! @internal */ - template inline - PtrWrapper make_ptr_wrapper(T && t) - { - return {std::forward(t)}; - } - - //! A struct that acts as a wrapper around calling load_andor_construct - /*! The purpose of this is to allow a load_and_construct call to properly enter into the - 'data' NVP of the ptr_wrapper - @internal */ - template - struct LoadAndConstructLoadWrapper - { - LoadAndConstructLoadWrapper( T * ptr ) : - construct( ptr ) - { } - - //! Constructor for embedding an early call for restoring shared_from_this - template - LoadAndConstructLoadWrapper( T * ptr, F && sharedFromThisFunc ) : - construct( ptr, sharedFromThisFunc ) - { } - - inline void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar ) - { - ::cereal::detail::Construct::load_andor_construct( ar, construct ); - } - - ::cereal::construct construct; - }; - - //! A helper struct for saving and restoring the state of types that derive from - //! std::enable_shared_from_this - /*! This special struct is necessary because when a user uses load_and_construct, - the weak_ptr (or whatever implementation defined variant) that allows - enable_shared_from_this to function correctly will not be initialized properly. - - This internal weak_ptr can also be modified by the shared_ptr that is created - during the serialization of a polymorphic pointer, where cereal creates a - wrapper shared_ptr out of a void pointer to the real data. - - In the case of load_and_construct, this happens because it is the allocation - of shared_ptr that perform this initialization, which we let happen on a buffer - of memory (aligned_storage). This buffer is then used for placement new - later on, effectively overwriting any initialized weak_ptr with a default - initialized one, eventually leading to issues when the user calls shared_from_this. - - To get around these issues, we will store the memory for the enable_shared_from_this - portion of the class and replace it after whatever happens to modify it (e.g. the - user performing construction or the wrapper shared_ptr in saving). - - Note that this goes into undefined behavior territory, but as of the initial writing - of this, all standard library implementations of std::enable_shared_from_this are - compatible with this memory manipulation. It is entirely possible that this may someday - break or may not work with convoluted use cases. - - Example usage: - - @code{.cpp} - T * myActualPointer; - { - EnableSharedStateHelper helper( myActualPointer ); // save the state - std::shared_ptr myPtr( myActualPointer ); // modifies the internal weak_ptr - // helper restores state when it goes out of scope - } - @endcode - - When possible, this is designed to be used in an RAII fashion - it will save state on - construction and restore it on destruction. The restore can be done at an earlier time - (e.g. after construct() is called in load_and_construct) in which case the destructor will - do nothing. Performing the restore immediately following construct() allows a user to call - shared_from_this within their load_and_construct function. - - @tparam T Type pointed to by shared_ptr - @internal */ - template - class EnableSharedStateHelper - { - // typedefs for parent type and storage type - using BaseType = typename ::cereal::traits::get_shared_from_this_base::type; - using ParentType = std::enable_shared_from_this; - using StorageType = typename std::aligned_storage::type; - - public: - //! Saves the state of some type inheriting from enable_shared_from_this - /*! @param ptr The raw pointer held by the shared_ptr */ - inline EnableSharedStateHelper( T * ptr ) : - itsPtr( static_cast( ptr ) ), - itsState(), - itsRestored( false ) - { - std::memcpy( &itsState, itsPtr, sizeof(ParentType) ); - } - - //! Restores the state of the held pointer (can only be done once) - inline void restore() - { - if( !itsRestored ) - { - // void * cast needed when type has no trivial copy-assignment - std::memcpy( static_cast(itsPtr), &itsState, sizeof(ParentType) ); - itsRestored = true; - } - } - - //! Restores the state of the held pointer if not done previously - inline ~EnableSharedStateHelper() - { - restore(); - } - - private: - ParentType * itsPtr; - StorageType itsState; - bool itsRestored; - }; // end EnableSharedStateHelper - - //! Performs loading and construction for a shared pointer that is derived from - //! std::enable_shared_from_this - /*! @param ar The archive - @param ptr Raw pointer held by the shared_ptr - @internal */ - template inline - void loadAndConstructSharedPtr( Archive & ar, T * ptr, std::true_type /* has_shared_from_this */ ) - { - memory_detail::EnableSharedStateHelper state( ptr ); - memory_detail::LoadAndConstructLoadWrapper loadWrapper( ptr, [&](){ state.restore(); } ); - - // let the user perform their initialization, shared state will be restored as soon as construct() - // is called - ar( CEREAL_NVP_("data", loadWrapper) ); - } - - //! Performs loading and construction for a shared pointer that is NOT derived from - //! std::enable_shared_from_this - /*! This is the typical case, where we simply pass the load wrapper to the - archive. - - @param ar The archive - @param ptr Raw pointer held by the shared_ptr - @internal */ - template inline - void loadAndConstructSharedPtr( Archive & ar, T * ptr, std::false_type /* has_shared_from_this */ ) - { - memory_detail::LoadAndConstructLoadWrapper loadWrapper( ptr ); - ar( CEREAL_NVP_("data", loadWrapper) ); - } - } // end namespace memory_detail - - //! Saving std::shared_ptr for non polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr const & ptr ) - { - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); - } - - //! Loading std::shared_ptr, case when no user load and construct for non polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::shared_ptr & ptr ) - { - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); - } - - //! Saving std::weak_ptr for non polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::weak_ptr const & ptr ) - { - auto const sptr = ptr.lock(); - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) ); - } - - //! Loading std::weak_ptr for non polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::weak_ptr & ptr ) - { - std::shared_ptr sptr; - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) ); - ptr = sptr; - } - - //! Saving std::unique_ptr for non polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr const & ptr ) - { - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); - } - - //! Loading std::unique_ptr, case when user provides load_and_construct for non polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unique_ptr & ptr ) - { - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) ); - } - - // ###################################################################### - // Pointer wrapper implementations follow below - - //! Saving std::shared_ptr (wrapper implementation) - /*! @internal */ - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper const &> const & wrapper ) - { - auto & ptr = wrapper.ptr; - - uint32_t id = ar.registerSharedPointer( ptr.get() ); - ar( CEREAL_NVP_("id", id) ); - - if( id & detail::msb_32bit ) - { - ar( CEREAL_NVP_("data", *ptr) ); - } - } - - //! Loading std::shared_ptr, case when user load and construct (wrapper implementation) - /*! @internal */ - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) - { - uint32_t id; - - ar( CEREAL_NVP_("id", id) ); - - if( id & detail::msb_32bit ) - { - // Storage type for the pointer - since we can't default construct this type, - // we'll allocate it using std::aligned_storage and use a custom deleter - using ST = typename std::aligned_storage::type; - - // Valid flag - set to true once construction finishes - // This prevents us from calling the destructor on - // uninitialized data. - auto valid = std::make_shared( false ); - - // Allocate our storage, which we will treat as - // uninitialized until initialized with placement new - using NonConstT = typename std::remove_const::type; - std::shared_ptr ptr(reinterpret_cast(new ST()), - [=]( NonConstT * t ) - { - if( *valid ) - t->~T(); - - delete reinterpret_cast( t ); - } ); - - // Register the pointer - ar.registerSharedPointer( id, ptr ); - - // Perform the actual loading and allocation - memory_detail::loadAndConstructSharedPtr( ar, ptr.get(), typename ::cereal::traits::has_shared_from_this::type() ); - - // Mark pointer as valid (initialized) - *valid = true; - wrapper.ptr = std::move(ptr); - } - else - wrapper.ptr = std::static_pointer_cast(ar.getSharedPointer(id)); - } - - //! Loading std::shared_ptr, case when no user load and construct (wrapper implementation) - /*! @internal */ - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) - { - uint32_t id; - - ar( CEREAL_NVP_("id", id) ); - - if( id & detail::msb_32bit ) - { - using NonConstT = typename std::remove_const::type; - std::shared_ptr ptr( detail::Construct::load_andor_construct() ); - ar.registerSharedPointer( id, ptr ); - ar( CEREAL_NVP_("data", *ptr) ); - wrapper.ptr = std::move(ptr); - } - else - wrapper.ptr = std::static_pointer_cast(ar.getSharedPointer(id)); - } - - //! Saving std::unique_ptr (wrapper implementation) - /*! @internal */ - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper const &> const & wrapper ) - { - auto & ptr = wrapper.ptr; - - // unique_ptr get one byte of metadata which signifies whether they were a nullptr - // 0 == nullptr - // 1 == not null - - if( !ptr ) - ar( CEREAL_NVP_("valid", uint8_t(0)) ); - else - { - ar( CEREAL_NVP_("valid", uint8_t(1)) ); - ar( CEREAL_NVP_("data", *ptr) ); - } - } - - //! Loading std::unique_ptr, case when user provides load_and_construct (wrapper implementation) - /*! @internal */ - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) - { - uint8_t isValid; - ar( CEREAL_NVP_("valid", isValid) ); - - auto & ptr = wrapper.ptr; - - if( isValid ) - { - using NonConstT = typename std::remove_const::type; - // Storage type for the pointer - since we can't default construct this type, - // we'll allocate it using std::aligned_storage - using ST = typename std::aligned_storage::type; - - // Allocate storage - note the ST type so that deleter is correct if - // an exception is thrown before we are initialized - std::unique_ptr stPtr( new ST() ); - - // Use wrapper to enter into "data" nvp of ptr_wrapper - memory_detail::LoadAndConstructLoadWrapper loadWrapper( reinterpret_cast( stPtr.get() ) ); - - // Initialize storage - ar( CEREAL_NVP_("data", loadWrapper) ); - - // Transfer ownership to correct unique_ptr type - ptr.reset( reinterpret_cast( stPtr.release() ) ); - } - else - ptr.reset( nullptr ); - } - - //! Loading std::unique_ptr, case when no load_and_construct (wrapper implementation) - /*! @internal */ - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper &> & wrapper ) - { - uint8_t isValid; - ar( CEREAL_NVP_("valid", isValid) ); - - if( isValid ) - { - using NonConstT = typename std::remove_const::type; - std::unique_ptr ptr( detail::Construct::load_andor_construct() ); - ar( CEREAL_NVP_( "data", *ptr ) ); - wrapper.ptr = std::move(ptr); - } - else - { - wrapper.ptr.reset( nullptr ); - } - } -} // namespace cereal - -// automatically include polymorphic support -#include "cereal/types/polymorphic.hpp" - -#endif // CEREAL_TYPES_SHARED_PTR_HPP_ diff --git a/deps/include/cereal/types/optional.hpp b/deps/include/cereal/types/optional.hpp deleted file mode 100644 index 3b2444654..000000000 --- a/deps/include/cereal/types/optional.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/*! \file optional.hpp - \brief Support for std::optional - \ingroup STLSupport */ -/* - Copyright (c) 2017, Juan Pedro Bolivar Puente - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_STD_OPTIONAL_ -#define CEREAL_TYPES_STD_OPTIONAL_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal { - //! Saving for std::optional - template inline - void CEREAL_SAVE_FUNCTION_NAME(Archive& ar, const std::optional& optional) - { - if(!optional) { - ar(CEREAL_NVP_("nullopt", true)); - } else { - ar(CEREAL_NVP_("nullopt", false), - CEREAL_NVP_("data", *optional)); - } - } - - //! Loading for std::optional - template inline - void CEREAL_LOAD_FUNCTION_NAME(Archive& ar, std::optional& optional) - { - bool nullopt; - ar(CEREAL_NVP_("nullopt", nullopt)); - - if (nullopt) { - optional = std::nullopt; - } else { - T value; - ar(CEREAL_NVP_("data", value)); - optional = std::move(value); - } - } -} // namespace cereal - -#endif // CEREAL_TYPES_STD_OPTIONAL_ diff --git a/deps/include/cereal/types/polymorphic.hpp b/deps/include/cereal/types/polymorphic.hpp deleted file mode 100644 index f3db78f6c..000000000 --- a/deps/include/cereal/types/polymorphic.hpp +++ /dev/null @@ -1,483 +0,0 @@ -/*! \file polymorphic.hpp - \brief Support for pointers to polymorphic base classes - \ingroup OtherTypes */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_POLYMORPHIC_HPP_ -#define CEREAL_TYPES_POLYMORPHIC_HPP_ - -#include "cereal/cereal.hpp" -#include "cereal/types/memory.hpp" - -#include "cereal/details/util.hpp" -#include "cereal/details/helpers.hpp" -#include "cereal/details/traits.hpp" -#include "cereal/details/polymorphic_impl.hpp" - -#ifdef _MSC_VER -#define CEREAL_STATIC_CONSTEXPR static -#else -#define CEREAL_STATIC_CONSTEXPR static constexpr -#endif - -//! Registers a derived polymorphic type with cereal -/*! Polymorphic types must be registered before smart - pointers to them can be serialized. Note that base - classes do not need to be registered. - - Registering a type lets cereal know how to properly - serialize it when a smart pointer to a base object is - used in conjunction with a derived class. - - This assumes that all relevant archives have also - previously been registered. Registration for archives - is usually done in the header file in which they are - defined. This means that type registration needs to - happen after specific archives to be used are included. - - It is recommended that type registration be done in - the header file in which the type is declared. - - Registration can also be placed in a source file, - but this may require the use of the - CEREAL_REGISTER_DYNAMIC_INIT macro (see below). - - Registration may be called repeatedly for the same - type in different translation units to add support - for additional archives if they are not initially - available (included and registered). - - When building serialization support as a DLL on - Windows, registration must happen in the header file. - On Linux and Mac things should still work properly - if placed in a source file, but see the above comments - on registering in source files. - - Polymorphic support in cereal requires RTTI to be - enabled */ -#define CEREAL_REGISTER_TYPE(...) \ - namespace cereal { \ - namespace detail { \ - template <> \ - struct binding_name<__VA_ARGS__> \ - { \ - CEREAL_STATIC_CONSTEXPR char const * name() { return #__VA_ARGS__; } \ - }; \ - } } /* end namespaces */ \ - CEREAL_BIND_TO_ARCHIVES(__VA_ARGS__) - -//! Registers a polymorphic type with cereal, giving it a -//! user defined name -/*! In some cases the default name used with - CEREAL_REGISTER_TYPE (the name of the type) may not be - suitable. This macro allows any name to be associated - with the type. The name should be unique */ -#define CEREAL_REGISTER_TYPE_WITH_NAME(T, Name) \ - namespace cereal { \ - namespace detail { \ - template <> \ - struct binding_name \ - { CEREAL_STATIC_CONSTEXPR char const * name() { return Name; } }; \ - } } /* end namespaces */ \ - CEREAL_BIND_TO_ARCHIVES(T) - -//! Registers the base-derived relationship for a polymorphic type -/*! When polymorphic serialization occurs, cereal needs to know how to - properly cast between derived and base types for the polymorphic - type. Normally this happens automatically whenever cereal::base_class - or cereal::virtual_base_class are used to serialize a base class. In - cases where neither of these is ever called but a base class still - exists, this explicit registration is required. - - The Derived class should be the most derived type that will be serialized, - and the Base type any possible base that has not been covered under a base - class serialization that will be used to store a Derived pointer. - - Placement of this is the same as for CEREAL_REGISTER_TYPE. */ -#define CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, Derived) \ - namespace cereal { \ - namespace detail { \ - template <> \ - struct PolymorphicRelation \ - { static void bind() { RegisterPolymorphicCaster::bind(); } }; \ - } } /* end namespaces */ - -//! Adds a way to force initialization of a translation unit containing -//! calls to CEREAL_REGISTER_TYPE -/*! In C++, dynamic initialization of non-local variables of a translation - unit may be deferred until "the first odr-use of any function or variable - defined in the same translation unit as the variable to be initialized." - - Informally, odr-use means that your program takes the address of or binds - a reference directly to an object, which must have a definition. - - Since polymorphic type support in cereal relies on the dynamic - initialization of certain global objects happening before - serialization is performed, it is important to ensure that something - from files that call CEREAL_REGISTER_TYPE is odr-used before serialization - occurs, otherwise the registration will never take place. This may often - be the case when serialization is built as a shared library external from - your main program. - - This macro, with any name of your choosing, should be placed into the - source file that contains calls to CEREAL_REGISTER_TYPE. - - Its counterpart, CEREAL_FORCE_DYNAMIC_INIT, should be placed in its - associated header file such that it is included in the translation units - (source files) in which you want the registration to appear. - - @relates CEREAL_FORCE_DYNAMIC_INIT - */ -#define CEREAL_REGISTER_DYNAMIC_INIT(LibName) \ - namespace cereal { \ - namespace detail { \ - void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName() {} \ - } } /* end namespaces */ - -//! Forces dynamic initialization of polymorphic support in a -//! previously registered source file -/*! @sa CEREAL_REGISTER_DYNAMIC_INIT - - See CEREAL_REGISTER_DYNAMIC_INIT for detailed explanation - of how this macro should be used. The name used should - match that for CEREAL_REGISTER_DYNAMIC_INIT. */ -#define CEREAL_FORCE_DYNAMIC_INIT(LibName) \ - namespace cereal { \ - namespace detail { \ - void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName(); \ - } /* end detail */ \ - } /* end cereal */ \ - namespace { \ - struct dynamic_init_##LibName { \ - dynamic_init_##LibName() { \ - ::cereal::detail::dynamic_init_dummy_##LibName(); \ - } \ - } dynamic_init_instance_##LibName; \ - } /* end anonymous namespace */ - -namespace cereal -{ - namespace polymorphic_detail - { - //! Error message used for unregistered polymorphic types - /*! @internal */ - #define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name) \ - throw cereal::Exception("Trying to " #LoadSave " an unregistered polymorphic type (" + Name + ").\n" \ - "Make sure your type is registered with CEREAL_REGISTER_TYPE and that the archive " \ - "you are using was included (and registered with CEREAL_REGISTER_ARCHIVE) prior to calling CEREAL_REGISTER_TYPE.\n" \ - "If your type is already registered and you still see this error, you may need to use CEREAL_REGISTER_DYNAMIC_INIT."); - - //! Get an input binding from the given archive by deserializing the type meta data - /*! @internal */ - template inline - typename ::cereal::detail::InputBindingMap::Serializers getInputBinding(Archive & ar, std::uint32_t const nameid) - { - // If the nameid is zero, we serialized a null pointer - if(nameid == 0) - { - typename ::cereal::detail::InputBindingMap::Serializers emptySerializers; - emptySerializers.shared_ptr = [](void*, std::shared_ptr & ptr, std::type_info const &) { ptr.reset(); }; - emptySerializers.unique_ptr = [](void*, std::unique_ptr> & ptr, std::type_info const &) { ptr.reset( nullptr ); }; - return emptySerializers; - } - - std::string name; - if(nameid & detail::msb_32bit) - { - ar( CEREAL_NVP_("polymorphic_name", name) ); - ar.registerPolymorphicName(nameid, name); - } - else - name = ar.getPolymorphicName(nameid); - - auto const & bindingMap = detail::StaticObject>::getInstance().map; - - auto binding = bindingMap.find(name); - if(binding == bindingMap.end()) - UNREGISTERED_POLYMORPHIC_EXCEPTION(load, name) - return binding->second; - } - - //! Serialize a shared_ptr if the 2nd msb in the nameid is set, and if we can actually construct the pointee - /*! This check lets us try and skip doing polymorphic machinery if we can get away with - using the derived class serialize function - - Note that on MSVC 2013 preview, is_default_constructible returns true for abstract classes with - default constructors, but on clang/gcc this will return false. So we also need to check for that here. - @internal */ - template inline - typename std::enable_if<(traits::is_default_constructible::value - || traits::has_load_and_construct::value) - && !std::is_abstract::value, bool>::type - serialize_wrapper(Archive & ar, std::shared_ptr & ptr, std::uint32_t const nameid) - { - if(nameid & detail::msb2_32bit) - { - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); - return true; - } - return false; - } - - //! Serialize a unique_ptr if the 2nd msb in the nameid is set, and if we can actually construct the pointee - /*! This check lets us try and skip doing polymorphic machinery if we can get away with - using the derived class serialize function - @internal */ - template inline - typename std::enable_if<(traits::is_default_constructible::value - || traits::has_load_and_construct::value) - && !std::is_abstract::value, bool>::type - serialize_wrapper(Archive & ar, std::unique_ptr & ptr, std::uint32_t const nameid) - { - if(nameid & detail::msb2_32bit) - { - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); - return true; - } - return false; - } - - //! Serialize a shared_ptr if the 2nd msb in the nameid is set, and if we can actually construct the pointee - /*! This case is for when we can't actually construct the shared pointer. Normally this would be caught - as the pointer itself is serialized, but since this is a polymorphic pointer, if we tried to serialize - the pointer we'd end up back here recursively. So we have to catch the error here as well, if - this was a polymorphic type serialized by its proper pointer type - @internal */ - template inline - typename std::enable_if<(!traits::is_default_constructible::value - && !traits::has_load_and_construct::value) - || std::is_abstract::value, bool>::type - serialize_wrapper(Archive &, std::shared_ptr &, std::uint32_t const nameid) - { - if(nameid & detail::msb2_32bit) - throw cereal::Exception("Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function"); - return false; - } - - //! Serialize a unique_ptr if the 2nd msb in the nameid is set, and if we can actually construct the pointee - /*! This case is for when we can't actually construct the unique pointer. Normally this would be caught - as the pointer itself is serialized, but since this is a polymorphic pointer, if we tried to serialize - the pointer we'd end up back here recursively. So we have to catch the error here as well, if - this was a polymorphic type serialized by its proper pointer type - @internal */ - template inline - typename std::enable_if<(!traits::is_default_constructible::value - && !traits::has_load_and_construct::value) - || std::is_abstract::value, bool>::type - serialize_wrapper(Archive &, std::unique_ptr &, std::uint32_t const nameid) - { - if(nameid & detail::msb2_32bit) - throw cereal::Exception("Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function"); - return false; - } - } // polymorphic_detail - - // ###################################################################### - // Pointer serialization for polymorphic types - - //! Saving std::shared_ptr for polymorphic types, abstract - template inline - typename std::enable_if::value && std::is_abstract::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr const & ptr ) - { - if(!ptr) - { - // same behavior as nullptr in memory implementation - ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) ); - return; - } - - std::type_info const & ptrinfo = typeid(*ptr.get()); - static std::type_info const & tinfo = typeid(T); - // ptrinfo can never be equal to T info since we can't have an instance - // of an abstract object - // this implies we need to do the lookup - - auto const & bindingMap = detail::StaticObject>::getInstance().map; - - auto binding = bindingMap.find(std::type_index(ptrinfo)); - if(binding == bindingMap.end()) - UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name())) - - binding->second.shared_ptr(&ar, ptr.get(), tinfo); - } - - //! Saving std::shared_ptr for polymorphic types, not abstract - template inline - typename std::enable_if::value && !std::is_abstract::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr const & ptr ) - { - if(!ptr) - { - // same behavior as nullptr in memory implementation - ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) ); - return; - } - - std::type_info const & ptrinfo = typeid(*ptr.get()); - static std::type_info const & tinfo = typeid(T); - - if(ptrinfo == tinfo) - { - // The 2nd msb signals that the following pointer does not need to be - // cast with our polymorphic machinery - ar( CEREAL_NVP_("polymorphic_id", detail::msb2_32bit) ); - - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); - - return; - } - - auto const & bindingMap = detail::StaticObject>::getInstance().map; - - auto binding = bindingMap.find(std::type_index(ptrinfo)); - if(binding == bindingMap.end()) - UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name())) - - binding->second.shared_ptr(&ar, ptr.get(), tinfo); - } - - //! Loading std::shared_ptr for polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::shared_ptr & ptr ) - { - std::uint32_t nameid; - ar( CEREAL_NVP_("polymorphic_id", nameid) ); - - // Check to see if we can skip all of this polymorphism business - if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid)) - return; - - auto binding = polymorphic_detail::getInputBinding(ar, nameid); - std::shared_ptr result; - binding.shared_ptr(&ar, result, typeid(T)); - ptr = std::static_pointer_cast(result); - } - - //! Saving std::weak_ptr for polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::weak_ptr const & ptr ) - { - auto const sptr = ptr.lock(); - ar( CEREAL_NVP_("locked_ptr", sptr) ); - } - - //! Loading std::weak_ptr for polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::weak_ptr & ptr ) - { - std::shared_ptr sptr; - ar( CEREAL_NVP_("locked_ptr", sptr) ); - ptr = sptr; - } - - //! Saving std::unique_ptr for polymorphic types that are abstract - template inline - typename std::enable_if::value && std::is_abstract::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr const & ptr ) - { - if(!ptr) - { - // same behavior as nullptr in memory implementation - ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) ); - return; - } - - std::type_info const & ptrinfo = typeid(*ptr.get()); - static std::type_info const & tinfo = typeid(T); - // ptrinfo can never be equal to T info since we can't have an instance - // of an abstract object - // this implies we need to do the lookup - - auto const & bindingMap = detail::StaticObject>::getInstance().map; - - auto binding = bindingMap.find(std::type_index(ptrinfo)); - if(binding == bindingMap.end()) - UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name())) - - binding->second.unique_ptr(&ar, ptr.get(), tinfo); - } - - //! Saving std::unique_ptr for polymorphic types, not abstract - template inline - typename std::enable_if::value && !std::is_abstract::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr const & ptr ) - { - if(!ptr) - { - // same behavior as nullptr in memory implementation - ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) ); - return; - } - - std::type_info const & ptrinfo = typeid(*ptr.get()); - static std::type_info const & tinfo = typeid(T); - - if(ptrinfo == tinfo) - { - // The 2nd msb signals that the following pointer does not need to be - // cast with our polymorphic machinery - ar( CEREAL_NVP_("polymorphic_id", detail::msb2_32bit) ); - - ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) ); - - return; - } - - auto const & bindingMap = detail::StaticObject>::getInstance().map; - - auto binding = bindingMap.find(std::type_index(ptrinfo)); - if(binding == bindingMap.end()) - UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name())) - - binding->second.unique_ptr(&ar, ptr.get(), tinfo); - } - - //! Loading std::unique_ptr, case when user provides load_and_construct for polymorphic types - template inline - typename std::enable_if::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unique_ptr & ptr ) - { - std::uint32_t nameid; - ar( CEREAL_NVP_("polymorphic_id", nameid) ); - - // Check to see if we can skip all of this polymorphism business - if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid)) - return; - - auto binding = polymorphic_detail::getInputBinding(ar, nameid); - std::unique_ptr> result; - binding.unique_ptr(&ar, result, typeid(T)); - ptr.reset(static_cast(result.release())); - } - - #undef UNREGISTERED_POLYMORPHIC_EXCEPTION -} // namespace cereal -#endif // CEREAL_TYPES_POLYMORPHIC_HPP_ diff --git a/deps/include/cereal/types/queue.hpp b/deps/include/cereal/types/queue.hpp deleted file mode 100644 index 52d26a2f0..000000000 --- a/deps/include/cereal/types/queue.hpp +++ /dev/null @@ -1,132 +0,0 @@ -/*! \file queue.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_QUEUE_HPP_ -#define CEREAL_TYPES_QUEUE_HPP_ - -#include "cereal/details/helpers.hpp" -#include - -// The default container for queue is deque, so let's include that too -#include "cereal/types/deque.hpp" -// The default comparator for queue is less -#include "cereal/types/functional.hpp" - -namespace cereal -{ - namespace queue_detail - { - //! Allows access to the protected container in queue - /*! @internal */ - template inline - C const & container( std::queue const & queue ) - { - struct H : public std::queue - { - static C const & get( std::queue const & q ) - { - return q.*(&H::c); - } - }; - - return H::get( queue ); - } - - //! Allows access to the protected container in priority queue - /*! @internal */ - template inline - C const & container( std::priority_queue const & priority_queue ) - { - struct H : public std::priority_queue - { - static C const & get( std::priority_queue const & pq ) - { - return pq.*(&H::c); - } - }; - - return H::get( priority_queue ); - } - - //! Allows access to the protected comparator in priority queue - /*! @internal */ - template inline - Comp const & comparator( std::priority_queue const & priority_queue ) - { - struct H : public std::priority_queue - { - static Comp const & get( std::priority_queue const & pq ) - { - return pq.*(&H::comp); - } - }; - - return H::get( priority_queue ); - } - } - - //! Saving for std::queue - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::queue const & queue ) - { - ar( CEREAL_NVP_("container", queue_detail::container( queue )) ); - } - - //! Loading for std::queue - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::queue & queue ) - { - C container; - ar( CEREAL_NVP_("container", container) ); - queue = std::queue( std::move( container ) ); - } - - //! Saving for std::priority_queue - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::priority_queue const & priority_queue ) - { - ar( CEREAL_NVP_("comparator", queue_detail::comparator( priority_queue )) ); - ar( CEREAL_NVP_("container", queue_detail::container( priority_queue )) ); - } - - //! Loading for std::priority_queue - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::priority_queue & priority_queue ) - { - Comp comparator; - ar( CEREAL_NVP_("comparator", comparator) ); - - C container; - ar( CEREAL_NVP_("container", container) ); - - priority_queue = std::priority_queue( comparator, std::move( container ) ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_QUEUE_HPP_ diff --git a/deps/include/cereal/types/set.hpp b/deps/include/cereal/types/set.hpp deleted file mode 100644 index 149a5b45a..000000000 --- a/deps/include/cereal/types/set.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/*! \file set.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_SET_HPP_ -#define CEREAL_TYPES_SET_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - namespace set_detail - { - //! @internal - template inline - void save( Archive & ar, SetT const & set ) - { - ar( make_size_tag( static_cast(set.size()) ) ); - - for( const auto & i : set ) - ar( i ); - } - - //! @internal - template inline - void load( Archive & ar, SetT & set ) - { - size_type size; - ar( make_size_tag( size ) ); - - set.clear(); - - auto hint = set.begin(); - for( size_type i = 0; i < size; ++i ) - { - typename SetT::key_type key; - - ar( key ); - #ifdef CEREAL_OLDER_GCC - hint = set.insert( hint, std::move( key ) ); - #else // NOT CEREAL_OLDER_GCC - hint = set.emplace_hint( hint, std::move( key ) ); - #endif // NOT CEREAL_OLDER_GCC - } - } - } - - //! Saving for std::set - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::set const & set ) - { - set_detail::save( ar, set ); - } - - //! Loading for std::set - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::set & set ) - { - set_detail::load( ar, set ); - } - - //! Saving for std::multiset - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::multiset const & multiset ) - { - set_detail::save( ar, multiset ); - } - - //! Loading for std::multiset - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::multiset & multiset ) - { - set_detail::load( ar, multiset ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_SET_HPP_ diff --git a/deps/include/cereal/types/stack.hpp b/deps/include/cereal/types/stack.hpp deleted file mode 100644 index b69b66000..000000000 --- a/deps/include/cereal/types/stack.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/*! \file stack.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_STACK_HPP_ -#define CEREAL_TYPES_STACK_HPP_ - -#include "cereal/cereal.hpp" -#include - -// The default container for stack is deque, so let's include that too -#include "cereal/types/deque.hpp" - -namespace cereal -{ - namespace stack_detail - { - //! Allows access to the protected container in stack - template inline - C const & container( std::stack const & stack ) - { - struct H : public std::stack - { - static C const & get( std::stack const & s ) - { - return s.*(&H::c); - } - }; - - return H::get( stack ); - } - } - - //! Saving for std::stack - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::stack const & stack ) - { - ar( CEREAL_NVP_("container", stack_detail::container( stack )) ); - } - - //! Loading for std::stack - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::stack & stack ) - { - C container; - ar( CEREAL_NVP_("container", container) ); - stack = std::stack( std::move( container ) ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_STACK_HPP_ diff --git a/deps/include/cereal/types/string.hpp b/deps/include/cereal/types/string.hpp deleted file mode 100644 index e7488a9c2..000000000 --- a/deps/include/cereal/types/string.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/*! \file string.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_STRING_HPP_ -#define CEREAL_TYPES_STRING_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - //! Serialization for basic_string types, if binary data is supported - template inline - typename std::enable_if, Archive>::value, void>::type - CEREAL_SAVE_FUNCTION_NAME(Archive & ar, std::basic_string const & str) - { - // Save number of chars + the data - ar( make_size_tag( static_cast(str.size()) ) ); - ar( binary_data( str.data(), str.size() * sizeof(CharT) ) ); - } - - //! Serialization for basic_string types, if binary data is supported - template inline - typename std::enable_if, Archive>::value, void>::type - CEREAL_LOAD_FUNCTION_NAME(Archive & ar, std::basic_string & str) - { - size_type size; - ar( make_size_tag( size ) ); - str.resize(static_cast(size)); - ar( binary_data( const_cast( str.data() ), static_cast(size) * sizeof(CharT) ) ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_STRING_HPP_ - diff --git a/deps/include/cereal/types/tuple.hpp b/deps/include/cereal/types/tuple.hpp deleted file mode 100644 index 23013cdbd..000000000 --- a/deps/include/cereal/types/tuple.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/*! \file tuple.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_TUPLE_HPP_ -#define CEREAL_TYPES_TUPLE_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - namespace tuple_detail - { - //! Creates a c string from a sequence of characters - /*! The c string created will always be prefixed by "tuple_element" - Based on code from: http://stackoverflow/a/20973438/710791 - @internal */ - template - struct char_seq_to_c_str - { - static const int size = 14;// Size of array for the word: tuple_element - typedef const char (&arr_type)[sizeof...(Cs) + size]; - static const char str[sizeof...(Cs) + size]; - }; - - // the word tuple_element plus a number - //! @internal - template - const char char_seq_to_c_str::str[sizeof...(Cs) + size] = - {'t','u','p','l','e','_','e','l','e','m','e','n','t', Cs..., '\0'}; - - //! Converts a number into a sequence of characters - /*! @tparam Q The quotient of dividing the original number by 10 - @tparam R The remainder of dividing the original number by 10 - @tparam C The sequence built so far - @internal */ - template - struct to_string_impl - { - using type = typename to_string_impl(R+std::size_t{'0'}), C...>::type; - }; - - //! Base case with no quotient - /*! @internal */ - template - struct to_string_impl<0, R, C...> - { - using type = char_seq_to_c_str(R+std::size_t{'0'}), C...>; - }; - - //! Generates a c string for a given index of a tuple - /*! Example use: - @code{cpp} - tuple_element_name<3>::c_str();// returns "tuple_element3" - @endcode - @internal */ - template - struct tuple_element_name - { - using type = typename to_string_impl::type; - static const typename type::arr_type c_str(){ return type::str; } - }; - - // unwinds a tuple to save it - //! @internal - template - struct serialize - { - template inline - static void apply( Archive & ar, std::tuple & tuple ) - { - serialize::template apply( ar, tuple ); - ar( CEREAL_NVP_(tuple_element_name::c_str(), - std::get( tuple )) ); - } - }; - - // Zero height specialization - nothing to do here - //! @internal - template <> - struct serialize<0> - { - template inline - static void apply( Archive &, std::tuple & ) - { } - }; - } - - //! Serializing for std::tuple - template inline - void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, std::tuple & tuple ) - { - tuple_detail::serialize>::value>::template apply( ar, tuple ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_TUPLE_HPP_ diff --git a/deps/include/cereal/types/unordered_map.hpp b/deps/include/cereal/types/unordered_map.hpp deleted file mode 100644 index 3b0f80ba4..000000000 --- a/deps/include/cereal/types/unordered_map.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/*! \file unordered_map.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_UNORDERED_MAP_HPP_ -#define CEREAL_TYPES_UNORDERED_MAP_HPP_ - -#include "cereal/types/concepts/pair_associative_container.hpp" -#include - -#endif // CEREAL_TYPES_UNORDERED_MAP_HPP_ diff --git a/deps/include/cereal/types/unordered_set.hpp b/deps/include/cereal/types/unordered_set.hpp deleted file mode 100644 index b86d8e5c1..000000000 --- a/deps/include/cereal/types/unordered_set.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/*! \file unordered_set.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_UNORDERED_SET_HPP_ -#define CEREAL_TYPES_UNORDERED_SET_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - namespace unordered_set_detail - { - //! @internal - template inline - void save( Archive & ar, SetT const & set ) - { - ar( make_size_tag( static_cast(set.size()) ) ); - - for( const auto & i : set ) - ar( i ); - } - - //! @internal - template inline - void load( Archive & ar, SetT & set ) - { - size_type size; - ar( make_size_tag( size ) ); - - set.clear(); - set.reserve( static_cast( size ) ); - - for( size_type i = 0; i < size; ++i ) - { - typename SetT::key_type key; - - ar( key ); - set.emplace( std::move( key ) ); - } - } - } - - //! Saving for std::unordered_set - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_set const & unordered_set ) - { - unordered_set_detail::save( ar, unordered_set ); - } - - //! Loading for std::unordered_set - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_set & unordered_set ) - { - unordered_set_detail::load( ar, unordered_set ); - } - - //! Saving for std::unordered_multiset - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_multiset const & unordered_multiset ) - { - unordered_set_detail::save( ar, unordered_multiset ); - } - - //! Loading for std::unordered_multiset - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_multiset & unordered_multiset ) - { - unordered_set_detail::load( ar, unordered_multiset ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_UNORDERED_SET_HPP_ diff --git a/deps/include/cereal/types/utility.hpp b/deps/include/cereal/types/utility.hpp deleted file mode 100644 index 076bea893..000000000 --- a/deps/include/cereal/types/utility.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/*! \file utility.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_UTILITY_HPP_ -#define CEREAL_TYPES_UTILITY_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - //! Serializing for std::pair - template inline - void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, std::pair & pair ) - { - ar( CEREAL_NVP_("first", pair.first), - CEREAL_NVP_("second", pair.second) ); - } -} // namespace cereal - -#endif // CEREAL_TYPES_UTILITY_HPP_ diff --git a/deps/include/cereal/types/valarray.hpp b/deps/include/cereal/types/valarray.hpp deleted file mode 100644 index dcc471d77..000000000 --- a/deps/include/cereal/types/valarray.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/*! \file valarray.hpp -\brief Support for types found in \ -\ingroup STLSupport */ - -/* -Copyright (c) 2014, Randolph Voorhies, Shane Grant -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. -* Neither the name of cereal nor the -names of its contributors may be used to endorse or promote products -derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef CEREAL_TYPES_VALARRAY_HPP_ -#define CEREAL_TYPES_VALARRAY_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - //! Saving for std::valarray arithmetic types, using binary serialization, if supported - template inline - typename std::enable_if, Archive>::value - && std::is_arithmetic::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::valarray const & valarray ) - { - ar( make_size_tag( static_cast(valarray.size()) ) ); // number of elements - ar( binary_data( &valarray[0], valarray.size() * sizeof(T) ) ); // &valarray[0] ok since guaranteed contiguous - } - - //! Loading for std::valarray arithmetic types, using binary serialization, if supported - template inline - typename std::enable_if, Archive>::value - && std::is_arithmetic::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::valarray & valarray ) - { - size_type valarraySize; - ar( make_size_tag( valarraySize ) ); - - valarray.resize( static_cast( valarraySize ) ); - ar( binary_data( &valarray[0], static_cast( valarraySize ) * sizeof(T) ) ); - } - - //! Saving for std::valarray all other types - template inline - typename std::enable_if, Archive>::value - || !std::is_arithmetic::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::valarray const & valarray ) - { - ar( make_size_tag( static_cast(valarray.size()) ) ); // number of elements - for(auto && v : valarray) - ar(v); - } - - //! Loading for std::valarray all other types - template inline - typename std::enable_if, Archive>::value - || !std::is_arithmetic::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::valarray & valarray ) - { - size_type valarraySize; - ar( make_size_tag( valarraySize ) ); - - valarray.resize( static_cast( valarraySize ) ); - for(auto && v : valarray) - ar(v); - } -} // namespace cereal - -#endif // CEREAL_TYPES_VALARRAY_HPP_ diff --git a/deps/include/cereal/types/variant.hpp b/deps/include/cereal/types/variant.hpp deleted file mode 100644 index 8bea397bf..000000000 --- a/deps/include/cereal/types/variant.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/*! \file variant.hpp - \brief Support for std::variant - \ingroup STLSupport */ -/* - Copyright (c) 2014, 2017, Randolph Voorhies, Shane Grant, Juan Pedro - Bolivar Puente. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_STD_VARIANT_HPP_ -#define CEREAL_TYPES_STD_VARIANT_HPP_ - -#include "cereal/cereal.hpp" -#include -#include - -namespace cereal -{ - namespace variant_detail - { - //! @internal - template - struct variant_save_visitor - { - variant_save_visitor(Archive & ar_) : ar(ar_) {} - - template - void operator()(T const & value) const - { - ar( CEREAL_NVP_("data", value) ); - } - - Archive & ar; - }; - - //! @internal - template - typename std::enable_if, void>::type - load_variant(Archive & /*ar*/, int /*target*/, Variant & /*variant*/) - { - throw ::cereal::Exception("Error traversing variant during load"); - } - //! @internal - template - typename std::enable_if, void>::type - load_variant(Archive & ar, int target, Variant & variant) - { - if(N == target) - { - H value; - ar( CEREAL_NVP_("data", value) ); - variant = std::move(value); - } - else - load_variant(ar, target, variant); - } - - } // namespace variant_detail - - //! Saving for std::variant - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::variant const & variant ) - { - std::int32_t index = static_cast(variant.index()); - ar( CEREAL_NVP_("index", index) ); - variant_detail::variant_save_visitor visitor(ar); - std::visit(visitor, variant); - } - - //! Loading for std::variant - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::variant & variant ) - { - using variant_t = typename std::variant; - - std::int32_t index; - ar( CEREAL_NVP_("index", index) ); - if(index >= static_cast(std::variant_size_v)) - throw Exception("Invalid 'index' selector when deserializing std::variant"); - - variant_detail::load_variant<0, variant_t, VariantTypes...>(ar, index, variant); - } - - //! Serializing a std::monostate - template - void CEREAL_SERIALIZE_FUNCTION_NAME( Archive &, std::monostate const & ) {} -} // namespace cereal - -#endif // CEREAL_TYPES_STD_VARIANT_HPP_ diff --git a/deps/include/cereal/types/vector.hpp b/deps/include/cereal/types/vector.hpp deleted file mode 100644 index 4984bd3ed..000000000 --- a/deps/include/cereal/types/vector.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/*! \file vector.hpp - \brief Support for types found in \ - \ingroup STLSupport */ -/* - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef CEREAL_TYPES_VECTOR_HPP_ -#define CEREAL_TYPES_VECTOR_HPP_ - -#include "cereal/cereal.hpp" -#include - -namespace cereal -{ - //! Serialization for std::vectors of arithmetic (but not bool) using binary serialization, if supported - template inline - typename std::enable_if, Archive>::value - && std::is_arithmetic::value && !std::is_same::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector const & vector ) - { - ar( make_size_tag( static_cast(vector.size()) ) ); // number of elements - ar( binary_data( vector.data(), vector.size() * sizeof(T) ) ); - } - - //! Serialization for std::vectors of arithmetic (but not bool) using binary serialization, if supported - template inline - typename std::enable_if, Archive>::value - && std::is_arithmetic::value && !std::is_same::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector & vector ) - { - size_type vectorSize; - ar( make_size_tag( vectorSize ) ); - - vector.resize( static_cast( vectorSize ) ); - ar( binary_data( vector.data(), static_cast( vectorSize ) * sizeof(T) ) ); - } - - //! Serialization for non-arithmetic vector types - template inline - typename std::enable_if<(!traits::is_output_serializable, Archive>::value - || !std::is_arithmetic::value) && !std::is_same::value, void>::type - CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector const & vector ) - { - ar( make_size_tag( static_cast(vector.size()) ) ); // number of elements - for(auto && v : vector) - ar( v ); - } - - //! Serialization for non-arithmetic vector types - template inline - typename std::enable_if<(!traits::is_input_serializable, Archive>::value - || !std::is_arithmetic::value) && !std::is_same::value, void>::type - CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector & vector ) - { - size_type size; - ar( make_size_tag( size ) ); - - vector.resize( static_cast( size ) ); - for(auto && v : vector) - ar( v ); - } - - //! Serialization for bool vector types - template inline - void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector const & vector ) - { - ar( make_size_tag( static_cast(vector.size()) ) ); // number of elements - for(const auto v : vector) - ar( static_cast(v) ); - } - - //! Serialization for bool vector types - template inline - void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector & vector ) - { - size_type size; - ar( make_size_tag( size ) ); - - vector.resize( static_cast( size ) ); - for(auto v : vector) - { - bool b; - ar( b ); - v = b; - } - } -} // namespace cereal - -#endif // CEREAL_TYPES_VECTOR_HPP_ diff --git a/deps/include/cereal/version.hpp b/deps/include/cereal/version.hpp deleted file mode 100644 index 2a9dada94..000000000 --- a/deps/include/cereal/version.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/*! \file version.hpp - \brief Macros to detect cereal version - - These macros can assist in determining the version of cereal. Be - warned that cereal is not guaranteed to be compatible across - different versions. For more information on releases of cereal, - see https://github.com/USCiLab/cereal/releases. - - \ingroup utility */ -/* - Copyright (c) 2018, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef CEREAL_VERSION_HPP_ -#define CEREAL_VERSION_HPP_ - -//! The major version -#define CEREAL_VERSION_MAJOR 1 -//! The minor version -#define CEREAL_VERSION_MINOR 3 -//! The patch version -#define CEREAL_VERSION_PATCH 0 - -//! The full version as a single number -#define CEREAL_VERSION (CEREAL_VERSION_MAJOR * 10000 \ - + CEREAL_VERSION_MINOR * 100 \ - + CEREAL_VERSION_PATCH) - -#endif // CEREAL_VERSION_HPP_ diff --git a/deps/include/nlohmann/json.hpp b/deps/include/nlohmann/json.hpp new file mode 100644 index 000000000..19e65bbdc --- /dev/null +++ b/deps/include/nlohmann/json.hpp @@ -0,0 +1,22101 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.10.5 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2022 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/****************************************************************************\ + * 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 doc/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 10 +#define NLOHMANN_JSON_VERSION_PATCH 5 + +#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 // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include + + +#include +#include + +// #include + + +#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 + + +#include // exception +#include // runtime_error +#include // to_string +#include // vector + +// #include + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +namespace nlohmann +{ +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 +*/ +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + 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); + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +} +} // namespace detail +} // namespace nlohmann + +// #include + + +#include +// #include + + +#include // declval, pair +// #include + + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +#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) */ + +// #include + + +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + + +// https://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +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 +} // namespace nlohmann + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// 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 + +#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 + +// 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> + +#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); + +/*! +@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__)) } + +/*! +@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__)) } + + +// 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_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + + +namespace nlohmann +{ +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 +*/ +inline void replace_substring(std::string& s, const std::string& f, + const std::string& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != std::string::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. + */ +inline std::string escape(std::string s) +{ + replace_substring(s, "~", "~0"); + replace_substring(s, "/", "~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. + */ +static void unescape(std::string& s) +{ + replace_substring(s, "~1", "/"); + replace_substring(s, "~0", "~"); +} + +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // size_t + +namespace nlohmann +{ +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 +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// + +/// @brief general exception of the @ref basic_json class +/// @sa https://json.nlohmann.me/api/basic_json/exception/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) + + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + template + static std::string diagnostics(const BasicJsonType& leaf_element) + { +#if JSON_DIAGNOSTICS + std::vector tokens; + for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent) + { + switch (current->m_parent->type()) + { + case value_t::array: + { + for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) + { + if (¤t->m_parent->m_value.array->operator[](i) == current) + { + tokens.emplace_back(std::to_string(i)); + break; + } + } + break; + } + + case value_t::object: + { + for (const auto& element : *current->m_parent->m_value.object) + { + if (&element.second == current) + { + tokens.emplace_back(element.first.c_str()); + break; + } + } + break; + } + + case value_t::null: // LCOV_EXCL_LINE + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + break; // LCOV_EXCL_LINE + } + } + + if (tokens.empty()) + { + return ""; + } + + return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + detail::escape(b); + }) + ") "; +#else + static_cast(leaf_element); + return ""; +#endif + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/// @brief exception indicating a parse error +/// @sa https://json.nlohmann.me/api/basic_json/parse_error/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + template + static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + exception::diagnostics(context) + what_arg; + return {id_, pos.chars_read_total, w.c_str()}; + } + + template + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + exception::diagnostics(context) + what_arg; + return {id_, byte_, w.c_str()}; + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } +}; + +/// @brief exception indicating errors with iterators +/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ +class invalid_iterator : public exception +{ + public: + template + static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg; + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/// @brief exception indicating executing a member function with a wrong type +/// @sa https://json.nlohmann.me/api/basic_json/type_error/ +class type_error : public exception +{ + public: + template + static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg; + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/// @brief exception indicating access out of the defined range +/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ +class out_of_range : public exception +{ + public: + template + static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg; + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/// @brief exception indicating other library errors +/// @sa https://json.nlohmann.me/api/basic_json/other_error/ +class other_error : public exception +{ + public: + template + static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg; + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#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 + + +namespace nlohmann +{ +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 constexpr T value{}; +}; + +template +constexpr T static_const::value; // NOLINT(readability-redundant-declaration) + +} // namespace detail +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ +namespace detail +{ +// dispatching helper struct +template struct identity_tag {}; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple + +// #include + + +// #include + + +#include // random_access_iterator_tag + +// #include + +// #include + + +namespace nlohmann +{ +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 +} // namespace nlohmann + +// #include + + +// #include + + +namespace nlohmann +{ +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); +} // namespace nlohmann + +// #include + + +// #include + + +namespace nlohmann +{ +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); +} // namespace nlohmann + +// #include + +// #include + +// #include +#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 + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ +/*! +@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> +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; + +} // namespace nlohmann + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +namespace nlohmann +{ +/*! +@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 {}; + +////////////////////// +// 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; +}; + + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B1 { }; +template +struct conjunction +: std::conditional, B1>::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 +{ + static constexpr auto value = + is_constructible::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...> {}; + +// a naive helper to check if a type is an ordered_map (exploits the fact that +// ordered_map inherits capacity() from std::vector) +template +struct is_ordered_map +{ + using one = char; + + struct two + { + char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + }; + + template static one test( decltype(&C::capacity) ) ; + template static two test(...); + + enum { value = sizeof(test(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) +}; + +// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) +template < typename T, typename U, enable_if_t < !std::is_same::value, int > = 0 > +T conditional_static_cast(U value) +{ + return static_cast(value); +} + +template::value, int> = 0> +T conditional_static_cast(U value) +{ + return value; +} + +} // namespace detail +} // namespace nlohmann + +// #include + + +#if JSON_HAS_EXPERIMENTAL_FILESYSTEM +#include +namespace nlohmann::detail +{ +namespace std_fs = std::experimental::filesystem; +} // namespace nlohmann::detail +#elif JSON_HAS_FILESYSTEM +#include +namespace nlohmann::detail +{ +namespace std_fs = std::filesystem; +} // namespace nlohmann::detail +#endif + +namespace nlohmann +{ +namespace detail +{ +template +void from_json(const BasicJsonType& j, typename std::nullptr_t& n) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_null())) + { + JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j)); + } + n = nullptr; +} + +// overloads for basic_json template parameters +template < typename BasicJsonType, typename ArithmeticType, + enable_if_t < std::is_arithmetic::value&& + !std::is_same::value, + int > = 0 > +void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); + } +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) + { + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j)); + } + b = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + } + s = *j.template get_ptr(); +} + +template < + typename BasicJsonType, typename ConstructibleStringType, + enable_if_t < + is_constructible_string_type::value&& + !std::is_same::value, + int > = 0 > +void from_json(const BasicJsonType& j, ConstructibleStringType& s) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + } + + s = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +{ + get_arithmetic_value(j, val); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, EnumType& e) +{ + typename std::underlying_type::type val; + get_arithmetic_value(j, val); + e = static_cast(val); +} + +// forward_list doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::forward_list& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + l.clear(); + std::transform(j.rbegin(), j.rend(), + std::front_inserter(l), [](const BasicJsonType & i) + { + return i.template get(); + }); +} + +// valarray doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::valarray& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + l.resize(j.size()); + std::transform(j.begin(), j.end(), std::begin(l), + [](const BasicJsonType & elem) + { + return elem.template get(); + }); +} + +template +auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template +void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) +{ + arr = *j.template get_ptr(); +} + +template +auto from_json_array_impl(const BasicJsonType& j, std::array& arr, + priority_tag<2> /*unused*/) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template::value, + int> = 0> +auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) +-> decltype( + arr.reserve(std::declval()), + j.template get(), + void()) +{ + using std::end; + + ConstructibleArrayType ret; + ret.reserve(j.size()); + std::transform(j.begin(), j.end(), + std::inserter(ret, end(ret)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template::value, + int> = 0> +void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, + priority_tag<0> /*unused*/) +{ + using std::end; + + ConstructibleArrayType ret; + std::transform( + j.begin(), j.end(), std::inserter(ret, end(ret)), + [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template < typename BasicJsonType, typename ConstructibleArrayType, + enable_if_t < + is_constructible_array_type::value&& + !is_constructible_object_type::value&& + !is_constructible_string_type::value&& + !std::is_same::value&& + !is_basic_json::value, + int > = 0 > +auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) +-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), +j.template get(), +void()) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + + from_json_array_impl(j, arr, priority_tag<3> {}); +} + +template < typename BasicJsonType, typename T, std::size_t... Idx > +std::array from_json_inplace_array_impl(BasicJsonType&& j, + identity_tag> /*unused*/, index_sequence /*unused*/) +{ + return { { std::forward(j).at(Idx).template get()... } }; +} + +template < typename BasicJsonType, typename T, std::size_t N > +auto from_json(BasicJsonType&& j, identity_tag> tag) +-> decltype(from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {})) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + + return from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {}); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) + { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j)); + } + + bin = *j.template get_ptr(); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_object())) + { + JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j)); + } + + ConstructibleObjectType ret; + const auto* inner_object = j.template get_ptr(); + using value_type = typename ConstructibleObjectType::value_type; + std::transform( + inner_object->begin(), inner_object->end(), + std::inserter(ret, ret.begin()), + [](typename BasicJsonType::object_t::value_type const & p) + { + return value_type(p.first, p.second.template get()); + }); + obj = std::move(ret); +} + +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? +template < typename BasicJsonType, typename ArithmeticType, + enable_if_t < + std::is_arithmetic::value&& + !std::is_same::value&& + !std::is_same::value&& + !std::is_same::value&& + !std::is_same::value, + int > = 0 > +void from_json(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::boolean: + { + val = static_cast(*j.template get_ptr()); + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); + } +} + +template +std::tuple from_json_tuple_impl_base(BasicJsonType&& j, index_sequence /*unused*/) +{ + return std::make_tuple(std::forward(j).at(Idx).template get()...); +} + +template < typename BasicJsonType, class A1, class A2 > +std::pair from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<0> /*unused*/) +{ + return {std::forward(j).at(0).template get(), + std::forward(j).at(1).template get()}; +} + +template +void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) +{ + p = from_json_tuple_impl(std::forward(j), identity_tag> {}, priority_tag<0> {}); +} + +template +std::tuple from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<2> /*unused*/) +{ + return from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); +} + +template +void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) +{ + t = from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); +} + +template +auto from_json(BasicJsonType&& j, TupleRelated&& t) +-> decltype(from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {})) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + + return from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {}); +} + +template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, + typename = enable_if_t < !std::is_constructible < + typename BasicJsonType::string_t, Key >::value >> +void from_json(const BasicJsonType& j, std::map& m) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, + typename = enable_if_t < !std::is_constructible < + typename BasicJsonType::string_t, Key >::value >> +void from_json(const BasicJsonType& j, std::unordered_map& m) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM +template +void from_json(const BasicJsonType& j, std_fs::path& p) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + } + p = *j.template get_ptr(); +} +#endif + +struct from_json_fn +{ + template + auto operator()(const BasicJsonType& j, T&& val) const + noexcept(noexcept(from_json(j, std::forward(val)))) + -> decltype(from_json(j, std::forward(val))) + { + return from_json(j, std::forward(val)); + } +}; +} // namespace detail + +/// namespace to hold default `from_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) +{ +constexpr const auto& from_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) +} // namespace +} // namespace nlohmann + +// #include + + +#include // copy +#include // begin, end +#include // string +#include // tuple, get +#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type +#include // move, forward, declval, pair +#include // valarray +#include // vector + +// #include + +// #include + + +#include // size_t +#include // input_iterator_tag +#include // string, to_string +#include // tuple_size, get, tuple_element +#include // move + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +void int_to_string( string_type& target, std::size_t value ) +{ + // For ADL + using std::to_string; + target = to_string(value); +} +template class iteration_proxy_value +{ + public: + using difference_type = std::ptrdiff_t; + using value_type = iteration_proxy_value; + using pointer = value_type * ; + using reference = value_type & ; + using iterator_category = std::input_iterator_tag; + using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; + + private: + /// the iterator + IteratorType anchor; + /// an index for arrays (used to create key names) + std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; + /// a string representation of the array index + mutable string_type array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + const string_type empty_str{}; + + public: + explicit iteration_proxy_value(IteratorType it) noexcept + : anchor(std::move(it)) + {} + + /// dereference operator (needed for range-based for) + iteration_proxy_value& operator*() + { + return *this; + } + + /// increment operator (needed for range-based for) + iteration_proxy_value& operator++() + { + ++anchor; + ++array_index; + + return *this; + } + + /// equality operator (needed for InputIterator) + bool operator==(const iteration_proxy_value& o) const + { + return anchor == o.anchor; + } + + /// inequality operator (needed for range-based for) + bool operator!=(const iteration_proxy_value& o) const + { + return anchor != o.anchor; + } + + /// return key of the iterator + const string_type& key() const + { + JSON_ASSERT(anchor.m_object != nullptr); + + switch (anchor.m_object->type()) + { + // use integer array index as key + case value_t::array: + { + if (array_index != array_index_last) + { + int_to_string( array_index_str, array_index ); + array_index_last = array_index; + } + return array_index_str; + } + + // use key from the object + case value_t::object: + return anchor.key(); + + // use an empty key for all primitive types + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return empty_str; + } + } + + /// return value of the iterator + typename IteratorType::reference value() const + { + return anchor.value(); + } +}; + +/// proxy class for the items() function +template class iteration_proxy +{ + private: + /// the container to iterate + typename IteratorType::reference container; + + public: + /// construct iteration proxy from a container + explicit iteration_proxy(typename IteratorType::reference cont) noexcept + : container(cont) {} + + /// return iterator begin (needed for range-based for) + iteration_proxy_value begin() noexcept + { + return iteration_proxy_value(container.begin()); + } + + /// return iterator end (needed for range-based for) + iteration_proxy_value end() noexcept + { + return iteration_proxy_value(container.end()); + } +}; +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) +{ + return i.key(); +} +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) +{ + return i.value(); +} +} // namespace detail +} // namespace nlohmann + +// The Addition to the STD Namespace is required to add +// Structured Bindings Support to the iteration_proxy_value class +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +namespace std +{ +#if defined(__clang__) + // Fix: https://github.com/nlohmann/json/issues/1401 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wmismatched-tags" +#endif +template +class tuple_size<::nlohmann::detail::iteration_proxy_value> + : public std::integral_constant {}; + +template +class tuple_element> +{ + public: + using type = decltype( + get(std::declval < + ::nlohmann::detail::iteration_proxy_value> ())); +}; +#if defined(__clang__) + #pragma clang diagnostic pop +#endif +} // namespace std + +// #include + +// #include + +// #include + + +#if JSON_HAS_EXPERIMENTAL_FILESYSTEM +#include +namespace nlohmann::detail +{ +namespace std_fs = std::experimental::filesystem; +} // namespace nlohmann::detail +#elif JSON_HAS_FILESYSTEM +#include +namespace nlohmann::detail +{ +namespace std_fs = std::filesystem; +} // namespace nlohmann::detail +#endif + +namespace nlohmann +{ +namespace detail +{ +////////////////// +// constructors // +////////////////// + +/* + * Note all external_constructor<>::construct functions need to call + * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an + * allocated value (e.g., a string). See bug issue + * https://github.com/nlohmann/json/issues/2865 for more information. + */ + +template struct external_constructor; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::boolean; + j.m_value = b; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = s; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = std::move(s); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleStringType, + enable_if_t < !std::is_same::value, + int > = 0 > + static void construct(BasicJsonType& j, const CompatibleStringType& str) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value.string = j.template create(str); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(b); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(std::move(b)); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_float; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_integer; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = arr; + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = std::move(arr); + j.set_parents(); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < !std::is_same::value, + int > = 0 > + static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + { + using std::begin; + using std::end; + + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, const std::vector& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (const bool x : arr) + { + j.m_value.array->push_back(x); + j.set_parent(j.m_value.array->back()); + } + j.assert_invariant(); + } + + template::value, int> = 0> + static void construct(BasicJsonType& j, const std::valarray& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->resize(arr.size()); + if (arr.size() > 0) + { + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + } + j.set_parents(); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = obj; + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = std::move(obj); + j.set_parents(); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleObjectType, + enable_if_t < !std::is_same::value, int > = 0 > + static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + { + using std::begin; + using std::end; + + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); + j.set_parents(); + j.assert_invariant(); + } +}; + +///////////// +// to_json // +///////////// + +template::value, int> = 0> +void to_json(BasicJsonType& j, T b) noexcept +{ + external_constructor::construct(j, b); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleString& s) +{ + external_constructor::construct(j, s); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +{ + external_constructor::construct(j, std::move(s)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, FloatType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, EnumType e) noexcept +{ + using underlying_type = typename std::underlying_type::type; + external_constructor::construct(j, static_cast(e)); +} + +template +void to_json(BasicJsonType& j, const std::vector& e) +{ + external_constructor::construct(j, e); +} + +template < typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < is_compatible_array_type::value&& + !is_compatible_object_type::value&& + !is_compatible_string_type::value&& + !std::is_same::value&& + !is_basic_json::value, + int > = 0 > +void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +{ + external_constructor::construct(j, arr); +} + +template +void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) +{ + external_constructor::construct(j, bin); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const std::valarray& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template < typename BasicJsonType, typename CompatibleObjectType, + enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > +void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +{ + external_constructor::construct(j, obj); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +{ + external_constructor::construct(j, std::move(obj)); +} + +template < + typename BasicJsonType, typename T, std::size_t N, + enable_if_t < !std::is_constructible::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + int > = 0 > +void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +{ + external_constructor::construct(j, arr); +} + +template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > +void to_json(BasicJsonType& j, const std::pair& p) +{ + j = { p.first, p.second }; +} + +// for https://github.com/nlohmann/json/pull/1134 +template>::value, int> = 0> +void to_json(BasicJsonType& j, const T& b) +{ + j = { {b.key(), b.value()} }; +} + +template +void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) +{ + j = { std::get(t)... }; +} + +template::value, int > = 0> +void to_json(BasicJsonType& j, const T& t) +{ + to_json_tuple_impl(j, t, make_index_sequence::value> {}); +} + +#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM +template +void to_json(BasicJsonType& j, const std_fs::path& p) +{ + j = p.string(); +} +#endif + +struct to_json_fn +{ + template + auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) + { + return to_json(j, std::forward(val)); + } +}; +} // namespace detail + +/// namespace to hold default `to_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) +{ +constexpr const auto& to_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) +} // namespace +} // namespace nlohmann + +// #include + +// #include + + +namespace nlohmann +{ + +/// @sa https://json.nlohmann.me/api/adl_serializer/ +template +struct adl_serializer +{ + /// @brief convert a JSON value to any value type + /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ + template + static auto from_json(BasicJsonType && j, TargetType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) + -> decltype(::nlohmann::from_json(std::forward(j), val), void()) + { + ::nlohmann::from_json(std::forward(j), val); + } + + /// @brief convert a JSON value to any value type + /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ + template + static auto from_json(BasicJsonType && j) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), detail::identity_tag {}))) + -> decltype(::nlohmann::from_json(std::forward(j), detail::identity_tag {})) + { + return ::nlohmann::from_json(std::forward(j), detail::identity_tag {}); + } + + /// @brief convert any value type to a JSON value + /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/ + template + static auto to_json(BasicJsonType& j, TargetType && val) noexcept( + noexcept(::nlohmann::to_json(j, std::forward(val)))) + -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) + { + ::nlohmann::to_json(j, std::forward(val)); + } +}; +} // namespace nlohmann + +// #include + + +#include // uint8_t, uint64_t +#include // tie +#include // move + +namespace nlohmann +{ + +/// @brief an internal type for a backed binary type +/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ +template +class byte_container_with_subtype : public BinaryType +{ + public: + using container_type = BinaryType; + using subtype_type = std::uint64_t; + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype() noexcept(noexcept(container_type())) + : container_type() + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) + : container_type(b) + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)) + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) + : container_type(b) + , m_subtype(subtype_) + , m_has_subtype(true) + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)) + , m_subtype(subtype_) + , m_has_subtype(true) + {} + + bool operator==(const byte_container_with_subtype& rhs) const + { + return std::tie(static_cast(*this), m_subtype, m_has_subtype) == + std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); + } + + bool operator!=(const byte_container_with_subtype& rhs) const + { + return !(rhs == *this); + } + + /// @brief sets the binary subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/ + void set_subtype(subtype_type subtype_) noexcept + { + m_subtype = subtype_; + m_has_subtype = true; + } + + /// @brief return the binary subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/ + constexpr subtype_type subtype() const noexcept + { + return m_has_subtype ? m_subtype : static_cast(-1); + } + + /// @brief return whether the value has a subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/ + constexpr bool has_subtype() const noexcept + { + return m_has_subtype; + } + + /// @brief clears the binary subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/ + void clear_subtype() noexcept + { + m_subtype = 0; + m_has_subtype = false; + } + + private: + subtype_type m_subtype = 0; + bool m_has_subtype = false; +}; + +} // namespace nlohmann + +// #include + +// #include + +// #include + +// #include + + +#include // uint8_t +#include // size_t +#include // hash + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +// boost::hash_combine +inline std::size_t combine(std::size_t seed, std::size_t h) noexcept +{ + seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); + return seed; +} + +/*! +@brief hash a JSON value + +The hash function tries to rely on std::hash where possible. Furthermore, the +type of the JSON value is taken into account to have different hash values for +null, 0, 0U, and false, etc. + +@tparam BasicJsonType basic_json specialization +@param j JSON value to hash +@return hash value of j +*/ +template +std::size_t hash(const BasicJsonType& j) +{ + using string_t = typename BasicJsonType::string_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + + const auto type = static_cast(j.type()); + switch (j.type()) + { + case BasicJsonType::value_t::null: + case BasicJsonType::value_t::discarded: + { + return combine(type, 0); + } + + case BasicJsonType::value_t::object: + { + auto seed = combine(type, j.size()); + for (const auto& element : j.items()) + { + const auto h = std::hash {}(element.key()); + seed = combine(seed, h); + seed = combine(seed, hash(element.value())); + } + return seed; + } + + case BasicJsonType::value_t::array: + { + auto seed = combine(type, j.size()); + for (const auto& element : j) + { + seed = combine(seed, hash(element)); + } + return seed; + } + + case BasicJsonType::value_t::string: + { + const auto h = std::hash {}(j.template get_ref()); + return combine(type, h); + } + + case BasicJsonType::value_t::boolean: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_integer: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_unsigned: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_float: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::binary: + { + auto seed = combine(type, j.get_binary().size()); + const auto h = std::hash {}(j.get_binary().has_subtype()); + seed = combine(seed, h); + seed = combine(seed, static_cast(j.get_binary().subtype())); + for (const auto byte : j.get_binary()) + { + seed = combine(seed, std::hash {}(byte)); + } + return seed; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return 0; // LCOV_EXCL_LINE + } +} + +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // generate_n +#include // array +#include // ldexp +#include // size_t +#include // uint8_t, uint16_t, uint32_t, uint64_t +#include // snprintf +#include // memcpy +#include // back_inserter +#include // numeric_limits +#include // char_traits, string +#include // make_pair, move +#include // vector + +// #include + +// #include + + +#include // array +#include // size_t +#include // strlen +#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next +#include // shared_ptr, make_shared, addressof +#include // accumulate +#include // string, char_traits +#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer +#include // pair, declval + +#ifndef JSON_NO_IO + #include // FILE * + #include // istream +#endif // JSON_NO_IO + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/// the supported input formats +enum class input_format_t { json, cbor, msgpack, ubjson, bson }; + +//////////////////// +// input adapters // +//////////////////// + +#ifndef JSON_NO_IO +/*! +Input adapter for stdio file access. This adapter read only 1 byte and do not use any + buffer. This adapter is a very low level adapter. +*/ +class file_input_adapter +{ + public: + using char_type = char; + + JSON_HEDLEY_NON_NULL(2) + explicit file_input_adapter(std::FILE* f) noexcept + : m_file(f) + {} + + // make class move-only + file_input_adapter(const file_input_adapter&) = delete; + file_input_adapter(file_input_adapter&&) noexcept = default; + file_input_adapter& operator=(const file_input_adapter&) = delete; + file_input_adapter& operator=(file_input_adapter&&) = delete; + ~file_input_adapter() = default; + + std::char_traits::int_type get_character() noexcept + { + return std::fgetc(m_file); + } + + private: + /// the file pointer to read from + std::FILE* m_file; +}; + + +/*! +Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at +beginning of input. Does not support changing the underlying std::streambuf +in mid-input. Maintains underlying std::istream and std::streambuf to support +subsequent use of standard std::istream operations to process any input +characters following those used in parsing the JSON input. Clears the +std::istream flags; any input errors (e.g., EOF) will be detected by the first +subsequent call for input from the std::istream. +*/ +class input_stream_adapter +{ + public: + using char_type = char; + + ~input_stream_adapter() + { + // clear stream flags; we use underlying streambuf I/O, do not + // maintain ifstream flags, except eof + if (is != nullptr) + { + is->clear(is->rdstate() & std::ios::eofbit); + } + } + + explicit input_stream_adapter(std::istream& i) + : is(&i), sb(i.rdbuf()) + {} + + // delete because of pointer members + input_stream_adapter(const input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&&) = delete; + + input_stream_adapter(input_stream_adapter&& rhs) noexcept + : is(rhs.is), sb(rhs.sb) + { + rhs.is = nullptr; + rhs.sb = nullptr; + } + + // std::istream/std::streambuf use std::char_traits::to_int_type, to + // ensure that std::char_traits::eof() and the character 0xFF do not + // end up as the same value, e.g. 0xFFFFFFFF. + std::char_traits::int_type get_character() + { + auto res = sb->sbumpc(); + // set eof manually, as we don't use the istream interface. + if (JSON_HEDLEY_UNLIKELY(res == std::char_traits::eof())) + { + is->clear(is->rdstate() | std::ios::eofbit); + } + return res; + } + + private: + /// the associated input stream + std::istream* is = nullptr; + std::streambuf* sb = nullptr; +}; +#endif // JSON_NO_IO + +// General-purpose iterator-based adapter. It might not be as fast as +// theoretically possible for some containers, but it is extremely versatile. +template +class iterator_input_adapter +{ + public: + using char_type = typename std::iterator_traits::value_type; + + iterator_input_adapter(IteratorType first, IteratorType last) + : current(std::move(first)), end(std::move(last)) + {} + + typename std::char_traits::int_type get_character() + { + if (JSON_HEDLEY_LIKELY(current != end)) + { + auto result = std::char_traits::to_int_type(*current); + std::advance(current, 1); + return result; + } + + return std::char_traits::eof(); + } + + private: + IteratorType current; + IteratorType end; + + template + friend struct wide_string_input_helper; + + bool empty() const + { + return current == end; + } +}; + + +template +struct wide_string_input_helper; + +template +struct wide_string_input_helper +{ + // UTF-32 + static void fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = input.get_character(); + + // UTF-32 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (wc <= 0xFFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } + else if (wc <= 0x10FFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + // unknown character + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } +}; + +template +struct wide_string_input_helper +{ + // UTF-16 + static void fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = input.get_character(); + + // UTF-16 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (0xD800 > wc || wc >= 0xE000) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } + else + { + if (JSON_HEDLEY_UNLIKELY(!input.empty())) + { + const auto wc2 = static_cast(input.get_character()); + const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); + utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } + } +}; + +// Wraps another input apdater to convert wide character types into individual bytes. +template +class wide_string_input_adapter +{ + public: + using char_type = char; + + wide_string_input_adapter(BaseInputAdapter base) + : base_adapter(base) {} + + typename std::char_traits::int_type get_character() noexcept + { + // check if buffer needs to be filled + if (utf8_bytes_index == utf8_bytes_filled) + { + fill_buffer(); + + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index == 0); + } + + // use buffer + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); + return utf8_bytes[utf8_bytes_index++]; + } + + private: + BaseInputAdapter base_adapter; + + template + void fill_buffer() + { + wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); + } + + /// a buffer for UTF-8 bytes + std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; + + /// index to the utf8_codes array for the next valid byte + std::size_t utf8_bytes_index = 0; + /// number of valid bytes in the utf8_codes array + std::size_t utf8_bytes_filled = 0; +}; + + +template +struct iterator_input_adapter_factory +{ + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using adapter_type = iterator_input_adapter; + + static adapter_type create(IteratorType first, IteratorType last) + { + return adapter_type(std::move(first), std::move(last)); + } +}; + +template +struct is_iterator_of_multibyte +{ + using value_type = typename std::iterator_traits::value_type; + enum + { + value = sizeof(value_type) > 1 + }; +}; + +template +struct iterator_input_adapter_factory::value>> +{ + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using base_adapter_type = iterator_input_adapter; + using adapter_type = wide_string_input_adapter; + + static adapter_type create(IteratorType first, IteratorType last) + { + return adapter_type(base_adapter_type(std::move(first), std::move(last))); + } +}; + +// General purpose iterator-based input +template +typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) +{ + using factory_type = iterator_input_adapter_factory; + return factory_type::create(first, last); +} + +// Convenience shorthand from container to iterator +// Enables ADL on begin(container) and end(container) +// Encloses the using declarations in namespace for not to leak them to outside scope + +namespace container_input_adapter_factory_impl +{ + +using std::begin; +using std::end; + +template +struct container_input_adapter_factory {}; + +template +struct container_input_adapter_factory< ContainerType, + void_t()), end(std::declval()))>> + { + using adapter_type = decltype(input_adapter(begin(std::declval()), end(std::declval()))); + + static adapter_type create(const ContainerType& container) +{ + return input_adapter(begin(container), end(container)); +} + }; + +} // namespace container_input_adapter_factory_impl + +template +typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) +{ + return container_input_adapter_factory_impl::container_input_adapter_factory::create(container); +} + +#ifndef JSON_NO_IO +// Special cases with fast paths +inline file_input_adapter input_adapter(std::FILE* file) +{ + return file_input_adapter(file); +} + +inline input_stream_adapter input_adapter(std::istream& stream) +{ + return input_stream_adapter(stream); +} + +inline input_stream_adapter input_adapter(std::istream&& stream) +{ + return input_stream_adapter(stream); +} +#endif // JSON_NO_IO + +using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); + +// Null-delimited strings, and the like. +template < typename CharT, + typename std::enable_if < + std::is_pointer::value&& + !std::is_array::value&& + std::is_integral::type>::value&& + sizeof(typename std::remove_pointer::type) == 1, + int >::type = 0 > +contiguous_bytes_input_adapter input_adapter(CharT b) +{ + auto length = std::strlen(reinterpret_cast(b)); + const auto* ptr = reinterpret_cast(b); + return input_adapter(ptr, ptr + length); +} + +template +auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +{ + return input_adapter(array, array + N); +} + +// This class only handles inputs of input_buffer_adapter type. +// It's required so that expressions like {ptr, len} can be implicitly cast +// to the correct adapter. +class span_input_adapter +{ + public: + template < typename CharT, + typename std::enable_if < + std::is_pointer::value&& + std::is_integral::type>::value&& + sizeof(typename std::remove_pointer::type) == 1, + int >::type = 0 > + span_input_adapter(CharT b, std::size_t l) + : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} + + template::iterator_category, std::random_access_iterator_tag>::value, + int>::type = 0> + span_input_adapter(IteratorType first, IteratorType last) + : ia(input_adapter(first, last)) {} + + contiguous_bytes_input_adapter&& get() + { + return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) + } + + private: + contiguous_bytes_input_adapter ia; +}; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include +#include // string +#include // move +#include // vector + +// #include + +// #include + + +namespace nlohmann +{ + +/*! +@brief SAX interface + +This class describes the SAX interface used by @ref nlohmann::json::sax_parse. +Each function is called in different situations while the input is parsed. The +boolean return value informs the parser whether to continue processing the +input. +*/ +template +struct json_sax +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + /*! + @brief a null value was read + @return whether parsing should proceed + */ + virtual bool null() = 0; + + /*! + @brief a boolean value was read + @param[in] val boolean value + @return whether parsing should proceed + */ + virtual bool boolean(bool val) = 0; + + /*! + @brief an integer number was read + @param[in] val integer value + @return whether parsing should proceed + */ + virtual bool number_integer(number_integer_t val) = 0; + + /*! + @brief an unsigned integer number was read + @param[in] val unsigned integer value + @return whether parsing should proceed + */ + virtual bool number_unsigned(number_unsigned_t val) = 0; + + /*! + @brief a floating-point number was read + @param[in] val floating-point value + @param[in] s raw token value + @return whether parsing should proceed + */ + virtual bool number_float(number_float_t val, const string_t& s) = 0; + + /*! + @brief a string value was read + @param[in] val string value + @return whether parsing should proceed + @note It is safe to move the passed string value. + */ + virtual bool string(string_t& val) = 0; + + /*! + @brief a binary value was read + @param[in] val binary value + @return whether parsing should proceed + @note It is safe to move the passed binary value. + */ + virtual bool binary(binary_t& val) = 0; + + /*! + @brief the beginning of an object was read + @param[in] elements number of object elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_object(std::size_t elements) = 0; + + /*! + @brief an object key was read + @param[in] val object key + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool key(string_t& val) = 0; + + /*! + @brief the end of an object was read + @return whether parsing should proceed + */ + virtual bool end_object() = 0; + + /*! + @brief the beginning of an array was read + @param[in] elements number of array elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_array(std::size_t elements) = 0; + + /*! + @brief the end of an array was read + @return whether parsing should proceed + */ + virtual bool end_array() = 0; + + /*! + @brief a parse error occurred + @param[in] position the position in the input where the error occurs + @param[in] last_token the last read token + @param[in] ex an exception object describing the error + @return whether parsing should proceed (must return false) + */ + virtual bool parse_error(std::size_t position, + const std::string& last_token, + const detail::exception& ex) = 0; + + json_sax() = default; + json_sax(const json_sax&) = default; + json_sax(json_sax&&) noexcept = default; + json_sax& operator=(const json_sax&) = default; + json_sax& operator=(json_sax&&) noexcept = default; + virtual ~json_sax() = default; +}; + + +namespace detail +{ +/*! +@brief SAX implementation to create a JSON value from SAX events + +This class implements the @ref json_sax interface and processes the SAX events +to create a JSON value which makes it basically a DOM parser. The structure or +hierarchy of the JSON value is managed by the stack `ref_stack` which contains +a pointer to the respective array or object for each recursion depth. + +After successful parsing, the value that is passed by reference to the +constructor contains the parsed value. + +@tparam BasicJsonType the JSON type +*/ +template +class json_sax_dom_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + /*! + @param[in,out] r reference to a JSON value that is manipulated while + parsing + @param[in] allow_exceptions_ whether parse errors yield exceptions + */ + explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) + : root(r), allow_exceptions(allow_exceptions_) + {} + + // make class move-only + json_sax_dom_parser(const json_sax_dom_parser&) = delete; + json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; + json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); + + if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool key(string_t& val) + { + // add null at given key and store the reference for later + object_element = &(ref_stack.back()->m_value.object->operator[](val)); + return true; + } + + bool end_object() + { + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + bool start_array(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); + + if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool end_array() + { + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + */ + template + JSON_HEDLEY_RETURNS_NON_NULL + BasicJsonType* handle_value(Value&& v) + { + if (ref_stack.empty()) + { + root = BasicJsonType(std::forward(v)); + return &root; + } + + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_value.array->back()); + } + + JSON_ASSERT(ref_stack.back()->is_object()); + JSON_ASSERT(object_element); + *object_element = BasicJsonType(std::forward(v)); + return object_element; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +template +class json_sax_dom_callback_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using parser_callback_t = typename BasicJsonType::parser_callback_t; + using parse_event_t = typename BasicJsonType::parse_event_t; + + json_sax_dom_callback_parser(BasicJsonType& r, + const parser_callback_t cb, + const bool allow_exceptions_ = true) + : root(r), callback(cb), allow_exceptions(allow_exceptions_) + { + keep_stack.push_back(true); + } + + // make class move-only + json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_callback_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + // check callback for object start + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::object, true); + ref_stack.push_back(val.second); + + // check object limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool key(string_t& val) + { + BasicJsonType k = BasicJsonType(val); + + // check callback for key + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); + key_keep_stack.push_back(keep); + + // add discarded value at given key and store the reference for later + if (keep && ref_stack.back()) + { + object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); + } + + return true; + } + + bool end_object() + { + if (ref_stack.back()) + { + if (!callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) + { + // discard object + *ref_stack.back() = discarded; + } + else + { + ref_stack.back()->set_parents(); + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) + { + // remove discarded value + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) + { + if (it->is_discarded()) + { + ref_stack.back()->erase(it); + break; + } + } + } + + return true; + } + + bool start_array(std::size_t len) + { + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::array, true); + ref_stack.push_back(val.second); + + // check array limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool end_array() + { + bool keep = true; + + if (ref_stack.back()) + { + keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); + if (keep) + { + ref_stack.back()->set_parents(); + } + else + { + // discard array + *ref_stack.back() = discarded; + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + // remove discarded value + if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->pop_back(); + } + + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @param[in] v value to add to the JSON value we build during parsing + @param[in] skip_callback whether we should skip calling the callback + function; this is required after start_array() and + start_object() SAX events, because otherwise we would call the + callback function with an empty array or object, respectively. + + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + + @return pair of boolean (whether value should be kept) and pointer (to the + passed value in the ref_stack hierarchy; nullptr if not kept) + */ + template + std::pair handle_value(Value&& v, const bool skip_callback = false) + { + JSON_ASSERT(!keep_stack.empty()); + + // do not handle this value if we know it would be added to a discarded + // container + if (!keep_stack.back()) + { + return {false, nullptr}; + } + + // create value + auto value = BasicJsonType(std::forward(v)); + + // check callback + const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); + + // do not handle this value if we just learnt it shall be discarded + if (!keep) + { + return {false, nullptr}; + } + + if (ref_stack.empty()) + { + root = std::move(value); + return {true, &root}; + } + + // skip this value if we already decided to skip the parent + // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) + if (!ref_stack.back()) + { + return {false, nullptr}; + } + + // we now only expect arrays and objects + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + // array + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->emplace_back(std::move(value)); + return {true, &(ref_stack.back()->m_value.array->back())}; + } + + // object + JSON_ASSERT(ref_stack.back()->is_object()); + // check if we should store an element for the current key + JSON_ASSERT(!key_keep_stack.empty()); + const bool store_element = key_keep_stack.back(); + key_keep_stack.pop_back(); + + if (!store_element) + { + return {false, nullptr}; + } + + JSON_ASSERT(object_element); + *object_element = std::move(value); + return {true, object_element}; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// stack to manage which values to keep + std::vector keep_stack {}; + /// stack to manage which object keys to keep + std::vector key_keep_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// callback function + const parser_callback_t callback = nullptr; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// a discarded value for the callback + BasicJsonType discarded = BasicJsonType::value_t::discarded; +}; + +template +class json_sax_acceptor +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + bool null() + { + return true; + } + + bool boolean(bool /*unused*/) + { + return true; + } + + bool number_integer(number_integer_t /*unused*/) + { + return true; + } + + bool number_unsigned(number_unsigned_t /*unused*/) + { + return true; + } + + bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) + { + return true; + } + + bool string(string_t& /*unused*/) + { + return true; + } + + bool binary(binary_t& /*unused*/) + { + return true; + } + + bool start_object(std::size_t /*unused*/ = static_cast(-1)) + { + return true; + } + + bool key(string_t& /*unused*/) + { + return true; + } + + bool end_object() + { + return true; + } + + bool start_array(std::size_t /*unused*/ = static_cast(-1)) + { + return true; + } + + bool end_array() + { + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) + { + return false; + } +}; +} // namespace detail + +} // namespace nlohmann + +// #include + + +#include // array +#include // localeconv +#include // size_t +#include // snprintf +#include // strtof, strtod, strtold, strtoll, strtoull +#include // initializer_list +#include // char_traits, string +#include // move +#include // vector + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/////////// +// lexer // +/////////// + +template +class lexer_base +{ + public: + /// token types for the parser + enum class token_type + { + uninitialized, ///< indicating the scanner is uninitialized + literal_true, ///< the `true` literal + literal_false, ///< the `false` literal + literal_null, ///< the `null` literal + value_string, ///< a string -- use get_string() for actual value + value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value + value_integer, ///< a signed integer -- use get_number_integer() for actual value + value_float, ///< an floating point number -- use get_number_float() for actual value + begin_array, ///< the character for array begin `[` + begin_object, ///< the character for object begin `{` + end_array, ///< the character for array end `]` + end_object, ///< the character for object end `}` + name_separator, ///< the name separator `:` + value_separator, ///< the value separator `,` + parse_error, ///< indicating a parse error + end_of_input, ///< indicating the end of the input buffer + literal_or_value ///< a literal or the begin of a value (only for diagnostics) + }; + + /// return name of values of type token_type (only used for errors) + JSON_HEDLEY_RETURNS_NON_NULL + JSON_HEDLEY_CONST + static const char* token_type_name(const token_type t) noexcept + { + switch (t) + { + case token_type::uninitialized: + return ""; + case token_type::literal_true: + return "true literal"; + case token_type::literal_false: + return "false literal"; + case token_type::literal_null: + return "null literal"; + case token_type::value_string: + return "string literal"; + case token_type::value_unsigned: + case token_type::value_integer: + case token_type::value_float: + return "number literal"; + case token_type::begin_array: + return "'['"; + case token_type::begin_object: + return "'{'"; + case token_type::end_array: + return "']'"; + case token_type::end_object: + return "'}'"; + case token_type::name_separator: + return "':'"; + case token_type::value_separator: + return "','"; + case token_type::parse_error: + return ""; + case token_type::end_of_input: + return "end of input"; + case token_type::literal_or_value: + return "'[', '{', or a literal"; + // LCOV_EXCL_START + default: // catch non-enum values + return "unknown token"; + // LCOV_EXCL_STOP + } + } +}; +/*! +@brief lexical analysis + +This class organizes the lexical analysis during JSON deserialization. +*/ +template +class lexer : public lexer_base +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename std::char_traits::int_type; + + public: + using token_type = typename lexer_base::token_type; + + explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept + : ia(std::move(adapter)) + , ignore_comments(ignore_comments_) + , decimal_point_char(static_cast(get_decimal_point())) + {} + + // delete because of pointer members + lexer(const lexer&) = delete; + lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + lexer& operator=(lexer&) = delete; + lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~lexer() = default; + + private: + ///////////////////// + // locales + ///////////////////// + + /// return the locale-dependent decimal point + JSON_HEDLEY_PURE + static char get_decimal_point() noexcept + { + const auto* loc = localeconv(); + JSON_ASSERT(loc != nullptr); + return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); + } + + ///////////////////// + // scan functions + ///////////////////// + + /*! + @brief get codepoint from 4 hex characters following `\u` + + For input "\u c1 c2 c3 c4" the codepoint is: + (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 + = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) + + Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' + must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The + conversion is done by subtracting the offset (0x30, 0x37, and 0x57) + between the ASCII value of the character and the desired integer value. + + @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or + non-hex character) + */ + int get_codepoint() + { + // this function only makes sense after reading `\u` + JSON_ASSERT(current == 'u'); + int codepoint = 0; + + const auto factors = { 12u, 8u, 4u, 0u }; + for (const auto factor : factors) + { + get(); + + if (current >= '0' && current <= '9') + { + codepoint += static_cast((static_cast(current) - 0x30u) << factor); + } + else if (current >= 'A' && current <= 'F') + { + codepoint += static_cast((static_cast(current) - 0x37u) << factor); + } + else if (current >= 'a' && current <= 'f') + { + codepoint += static_cast((static_cast(current) - 0x57u) << factor); + } + else + { + return -1; + } + } + + JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); + return codepoint; + } + + /*! + @brief check if the next byte(s) are inside a given range + + Adds the current byte and, for each passed range, reads a new byte and + checks if it is inside the range. If a violation was detected, set up an + error message and return false. Otherwise, return true. + + @param[in] ranges list of integers; interpreted as list of pairs of + inclusive lower and upper bound, respectively + + @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, + 1, 2, or 3 pairs. This precondition is enforced by an assertion. + + @return true if and only if no range violation was detected + */ + bool next_byte_in_range(std::initializer_list ranges) + { + JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); + add(current); + + for (auto range = ranges.begin(); range != ranges.end(); ++range) + { + get(); + if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) + { + add(current); + } + else + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return false; + } + } + + return true; + } + + /*! + @brief scan a string literal + + This function scans a string according to Sect. 7 of RFC 8259. While + scanning, bytes are escaped and copied into buffer token_buffer. Then the + function returns successfully, token_buffer is *not* null-terminated (as it + may contain \0 bytes), and token_buffer.size() is the number of bytes in the + string. + + @return token_type::value_string if string could be successfully scanned, + token_type::parse_error otherwise + + @note In case of errors, variable error_message contains a textual + description. + */ + token_type scan_string() + { + // reset token_buffer (ignore opening quote) + reset(); + + // we entered the function by reading an open quote + JSON_ASSERT(current == '\"'); + + while (true) + { + // get next character + switch (get()) + { + // end of file while parsing string + case std::char_traits::eof(): + { + error_message = "invalid string: missing closing quote"; + return token_type::parse_error; + } + + // closing quote + case '\"': + { + return token_type::value_string; + } + + // escapes + case '\\': + { + switch (get()) + { + // quotation mark + case '\"': + add('\"'); + break; + // reverse solidus + case '\\': + add('\\'); + break; + // solidus + case '/': + add('/'); + break; + // backspace + case 'b': + add('\b'); + break; + // form feed + case 'f': + add('\f'); + break; + // line feed + case 'n': + add('\n'); + break; + // carriage return + case 'r': + add('\r'); + break; + // tab + case 't': + add('\t'); + break; + + // unicode escapes + case 'u': + { + const int codepoint1 = get_codepoint(); + int codepoint = codepoint1; // start with codepoint1 + + if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if code point is a high surrogate + if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) + { + // expect next \uxxxx entry + if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) + { + const int codepoint2 = get_codepoint(); + + if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if codepoint2 is a low surrogate + if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) + { + // overwrite codepoint + codepoint = static_cast( + // high surrogate occupies the most significant 22 bits + (static_cast(codepoint1) << 10u) + // low surrogate occupies the least significant 15 bits + + static_cast(codepoint2) + // there is still the 0xD800, 0xDC00 and 0x10000 noise + // in the result, so we have to subtract with: + // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 + - 0x35FDC00u); + } + else + { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; + return token_type::parse_error; + } + } + + // result of the above calculation yields a proper codepoint + JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); + + // translate codepoint into bytes + if (codepoint < 0x80) + { + // 1-byte characters: 0xxxxxxx (ASCII) + add(static_cast(codepoint)); + } + else if (codepoint <= 0x7FF) + { + // 2-byte characters: 110xxxxx 10xxxxxx + add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else if (codepoint <= 0xFFFF) + { + // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx + add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else + { + // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + + break; + } + + // other characters after escape + default: + error_message = "invalid string: forbidden character after backslash"; + return token_type::parse_error; + } + + break; + } + + // invalid control characters + case 0x00: + { + error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + return token_type::parse_error; + } + + case 0x01: + { + error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } + + case 0x02: + { + error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } + + case 0x03: + { + error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } + + case 0x04: + { + error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } + + case 0x05: + { + error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } + + case 0x06: + { + error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } + + case 0x07: + { + error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } + + case 0x08: + { + error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; + return token_type::parse_error; + } + + case 0x09: + { + error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; + return token_type::parse_error; + } + + case 0x0A: + { + error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; + return token_type::parse_error; + } + + case 0x0B: + { + error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } + + case 0x0C: + { + error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; + return token_type::parse_error; + } + + case 0x0D: + { + error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; + return token_type::parse_error; + } + + case 0x0E: + { + error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } + + case 0x0F: + { + error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } + + case 0x10: + { + error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } + + case 0x11: + { + error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } + + case 0x12: + { + error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } + + case 0x13: + { + error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } + + case 0x14: + { + error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } + + case 0x15: + { + error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } + + case 0x16: + { + error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } + + case 0x17: + { + error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } + + case 0x18: + { + error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } + + case 0x19: + { + error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } + + case 0x1A: + { + error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } + + case 0x1B: + { + error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } + + case 0x1C: + { + error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } + + case 0x1D: + { + error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } + + case 0x1E: + { + error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } + + case 0x1F: + { + error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; + return token_type::parse_error; + } + + // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) + case 0x20: + case 0x21: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + { + add(current); + break; + } + + // U+0080..U+07FF: bytes C2..DF 80..BF + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + { + if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) + { + return token_type::parse_error; + } + break; + } + + // U+0800..U+0FFF: bytes E0 A0..BF 80..BF + case 0xE0: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF + // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+D000..U+D7FF: bytes ED 80..9F 80..BF + case 0xED: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + case 0xF0: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + case 0xF1: + case 0xF2: + case 0xF3: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + case 0xF4: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // remaining bytes (80..C1 and F5..FF) are ill-formed + default: + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return token_type::parse_error; + } + } + } + } + + /*! + * @brief scan a comment + * @return whether comment could be scanned successfully + */ + bool scan_comment() + { + switch (get()) + { + // single-line comments skip input until a newline or EOF is read + case '/': + { + while (true) + { + switch (get()) + { + case '\n': + case '\r': + case std::char_traits::eof(): + case '\0': + return true; + + default: + break; + } + } + } + + // multi-line comments skip input until */ is read + case '*': + { + while (true) + { + switch (get()) + { + case std::char_traits::eof(): + case '\0': + { + error_message = "invalid comment; missing closing '*/'"; + return false; + } + + case '*': + { + switch (get()) + { + case '/': + return true; + + default: + { + unget(); + continue; + } + } + } + + default: + continue; + } + } + } + + // unexpected character after reading '/' + default: + { + error_message = "invalid comment; expecting '/' or '*' after '/'"; + return false; + } + } + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(float& f, const char* str, char** endptr) noexcept + { + f = std::strtof(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(double& f, const char* str, char** endptr) noexcept + { + f = std::strtod(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(long double& f, const char* str, char** endptr) noexcept + { + f = std::strtold(str, endptr); + } + + /*! + @brief scan a number literal + + This function scans a string according to Sect. 6 of RFC 8259. + + The function is realized with a deterministic finite state machine derived + from the grammar described in RFC 8259. Starting in state "init", the + input is read and used to determined the next state. Only state "done" + accepts the number. State "error" is a trap state to model errors. In the + table below, "anything" means any character but the ones listed before. + + state | 0 | 1-9 | e E | + | - | . | anything + ---------|----------|----------|----------|---------|---------|----------|----------- + init | zero | any1 | [error] | [error] | minus | [error] | [error] + minus | zero | any1 | [error] | [error] | [error] | [error] | [error] + zero | done | done | exponent | done | done | decimal1 | done + any1 | any1 | any1 | exponent | done | done | decimal1 | done + decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] + decimal2 | decimal2 | decimal2 | exponent | done | done | done | done + exponent | any2 | any2 | [error] | sign | sign | [error] | [error] + sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] + any2 | any2 | any2 | done | done | done | done | done + + The state machine is realized with one label per state (prefixed with + "scan_number_") and `goto` statements between them. The state machine + contains cycles, but any cycle can be left when EOF is read. Therefore, + the function is guaranteed to terminate. + + During scanning, the read bytes are stored in token_buffer. This string is + then converted to a signed integer, an unsigned integer, or a + floating-point number. + + @return token_type::value_unsigned, token_type::value_integer, or + token_type::value_float if number could be successfully scanned, + token_type::parse_error otherwise + + @note The scanner is independent of the current locale. Internally, the + locale's decimal point is used instead of `.` to work with the + locale-dependent converters. + */ + token_type scan_number() // lgtm [cpp/use-of-goto] + { + // reset token_buffer to store the number's bytes + reset(); + + // the type of the parsed number; initially set to unsigned; will be + // changed if minus sign, decimal point or exponent is read + token_type number_type = token_type::value_unsigned; + + // state (init): we just found out we need to scan a number + switch (current) + { + case '-': + { + add(current); + goto scan_number_minus; + } + + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + // all other characters are rejected outside scan_number() + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + +scan_number_minus: + // state: we just parsed a leading minus sign + number_type = token_type::value_integer; + switch (get()) + { + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + default: + { + error_message = "invalid number; expected digit after '-'"; + return token_type::parse_error; + } + } + +scan_number_zero: + // state: we just parse a zero (maybe with a leading minus sign) + switch (get()) + { + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_any1: + // state: we just parsed a number 0-9 (maybe with a leading minus sign) + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_decimal1: + // state: we just parsed a decimal point + number_type = token_type::value_float; + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + default: + { + error_message = "invalid number; expected digit after '.'"; + return token_type::parse_error; + } + } + +scan_number_decimal2: + // we just parsed at least one number after a decimal point + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_exponent: + // we just parsed an exponent + number_type = token_type::value_float; + switch (get()) + { + case '+': + case '-': + { + add(current); + goto scan_number_sign; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = + "invalid number; expected '+', '-', or digit after exponent"; + return token_type::parse_error; + } + } + +scan_number_sign: + // we just parsed an exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = "invalid number; expected digit after exponent sign"; + return token_type::parse_error; + } + } + +scan_number_any2: + // we just parsed a number after the exponent or exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + goto scan_number_done; + } + +scan_number_done: + // unget the character after the number (we only read it to know that + // we are done scanning a number) + unget(); + + char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + errno = 0; + + // try to parse integers first and fall back to floats + if (number_type == token_type::value_unsigned) + { + const auto x = std::strtoull(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_unsigned = static_cast(x); + if (value_unsigned == x) + { + return token_type::value_unsigned; + } + } + } + else if (number_type == token_type::value_integer) + { + const auto x = std::strtoll(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_integer = static_cast(x); + if (value_integer == x) + { + return token_type::value_integer; + } + } + } + + // this code is reached if we parse a floating-point number or if an + // integer conversion above failed + strtof(value_float, token_buffer.data(), &endptr); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + return token_type::value_float; + } + + /*! + @param[in] literal_text the literal text to expect + @param[in] length the length of the passed literal text + @param[in] return_type the token type to return on success + */ + JSON_HEDLEY_NON_NULL(2) + token_type scan_literal(const char_type* literal_text, const std::size_t length, + token_type return_type) + { + JSON_ASSERT(std::char_traits::to_char_type(current) == literal_text[0]); + for (std::size_t i = 1; i < length; ++i) + { + if (JSON_HEDLEY_UNLIKELY(std::char_traits::to_char_type(get()) != literal_text[i])) + { + error_message = "invalid literal"; + return token_type::parse_error; + } + } + return return_type; + } + + ///////////////////// + // input management + ///////////////////// + + /// reset token_buffer; current character is beginning of token + void reset() noexcept + { + token_buffer.clear(); + token_string.clear(); + token_string.push_back(std::char_traits::to_char_type(current)); + } + + /* + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a + `std::char_traits::eof()` in that case. Stores the scanned characters + for use in error messages. + + @return character read from the input + */ + char_int_type get() + { + ++position.chars_read_total; + ++position.chars_read_current_line; + + if (next_unget) + { + // just reset the next_unget variable and work with current + next_unget = false; + } + else + { + current = ia.get_character(); + } + + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) + { + token_string.push_back(std::char_traits::to_char_type(current)); + } + + if (current == '\n') + { + ++position.lines_read; + position.chars_read_current_line = 0; + } + + return current; + } + + /*! + @brief unget current character (read it again on next get) + + We implement unget by setting variable next_unget to true. The input is not + changed - we just simulate ungetting by modifying chars_read_total, + chars_read_current_line, and token_string. The next call to get() will + behave as if the unget character is read again. + */ + void unget() + { + next_unget = true; + + --position.chars_read_total; + + // in case we "unget" a newline, we have to also decrement the lines_read + if (position.chars_read_current_line == 0) + { + if (position.lines_read > 0) + { + --position.lines_read; + } + } + else + { + --position.chars_read_current_line; + } + + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) + { + JSON_ASSERT(!token_string.empty()); + token_string.pop_back(); + } + } + + /// add a character to token_buffer + void add(char_int_type c) + { + token_buffer.push_back(static_cast(c)); + } + + public: + ///////////////////// + // value getters + ///////////////////// + + /// return integer value + constexpr number_integer_t get_number_integer() const noexcept + { + return value_integer; + } + + /// return unsigned integer value + constexpr number_unsigned_t get_number_unsigned() const noexcept + { + return value_unsigned; + } + + /// return floating-point value + constexpr number_float_t get_number_float() const noexcept + { + return value_float; + } + + /// return current string value (implicitly resets the token; useful only once) + string_t& get_string() + { + return token_buffer; + } + + ///////////////////// + // diagnostics + ///////////////////// + + /// return position of last read token + constexpr position_t get_position() const noexcept + { + return position; + } + + /// return the last read token (for errors only). Will never contain EOF + /// (an arbitrary value that is not a valid char value, often -1), because + /// 255 may legitimately occur. May contain NUL, which should be escaped. + std::string get_token_string() const + { + // escape control characters + std::string result; + for (const auto c : token_string) + { + if (static_cast(c) <= '\x1F') + { + // escape control characters + std::array cs{{}}; + static_cast((std::snprintf)(cs.data(), cs.size(), "", static_cast(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + result += cs.data(); + } + else + { + // add character as is + result.push_back(static_cast(c)); + } + } + + return result; + } + + /// return syntax error message + JSON_HEDLEY_RETURNS_NON_NULL + constexpr const char* get_error_message() const noexcept + { + return error_message; + } + + ///////////////////// + // actual scanner + ///////////////////// + + /*! + @brief skip the UTF-8 byte order mark + @return true iff there is no BOM or the correct BOM has been skipped + */ + bool skip_bom() + { + if (get() == 0xEF) + { + // check if we completely parse the BOM + return get() == 0xBB && get() == 0xBF; + } + + // the first character is not the beginning of the BOM; unget it to + // process is later + unget(); + return true; + } + + void skip_whitespace() + { + do + { + get(); + } + while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); + } + + token_type scan() + { + // initially, skip the BOM + if (position.chars_read_total == 0 && !skip_bom()) + { + error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; + return token_type::parse_error; + } + + // read next character and ignore whitespace + skip_whitespace(); + + // ignore comments + while (ignore_comments && current == '/') + { + if (!scan_comment()) + { + return token_type::parse_error; + } + + // skip following whitespace + skip_whitespace(); + } + + switch (current) + { + // structural characters + case '[': + return token_type::begin_array; + case ']': + return token_type::end_array; + case '{': + return token_type::begin_object; + case '}': + return token_type::end_object; + case ':': + return token_type::name_separator; + case ',': + return token_type::value_separator; + + // literals + case 't': + { + std::array true_literal = {{static_cast('t'), static_cast('r'), static_cast('u'), static_cast('e')}}; + return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); + } + case 'f': + { + std::array false_literal = {{static_cast('f'), static_cast('a'), static_cast('l'), static_cast('s'), static_cast('e')}}; + return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); + } + case 'n': + { + std::array null_literal = {{static_cast('n'), static_cast('u'), static_cast('l'), static_cast('l')}}; + return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); + } + + // string + case '\"': + return scan_string(); + + // number + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); + + // end of input (the null byte is needed when parsing from + // string literals) + case '\0': + case std::char_traits::eof(): + return token_type::end_of_input; + + // error + default: + error_message = "invalid literal"; + return token_type::parse_error; + } + } + + private: + /// input adapter + InputAdapterType ia; + + /// whether comments should be ignored (true) or signaled as errors (false) + const bool ignore_comments = false; + + /// the current character + char_int_type current = std::char_traits::eof(); + + /// whether the next get() call should just return current + bool next_unget = false; + + /// the start position of the current token + position_t position {}; + + /// raw input token string (for error messages) + std::vector token_string {}; + + /// buffer for variable-length tokens (numbers, strings) + string_t token_buffer {}; + + /// a description of occurred lexer errors + const char* error_message = ""; + + // number values + number_integer_t value_integer = 0; + number_unsigned_t value_unsigned = 0; + number_float_t value_float = 0; + + /// the decimal point + const char_int_type decimal_point_char = '.'; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // size_t +#include // declval +#include // string + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +using null_function_t = decltype(std::declval().null()); + +template +using boolean_function_t = + decltype(std::declval().boolean(std::declval())); + +template +using number_integer_function_t = + decltype(std::declval().number_integer(std::declval())); + +template +using number_unsigned_function_t = + decltype(std::declval().number_unsigned(std::declval())); + +template +using number_float_function_t = decltype(std::declval().number_float( + std::declval(), std::declval())); + +template +using string_function_t = + decltype(std::declval().string(std::declval())); + +template +using binary_function_t = + decltype(std::declval().binary(std::declval())); + +template +using start_object_function_t = + decltype(std::declval().start_object(std::declval())); + +template +using key_function_t = + decltype(std::declval().key(std::declval())); + +template +using end_object_function_t = decltype(std::declval().end_object()); + +template +using start_array_function_t = + decltype(std::declval().start_array(std::declval())); + +template +using end_array_function_t = decltype(std::declval().end_array()); + +template +using parse_error_function_t = decltype(std::declval().parse_error( + std::declval(), std::declval(), + std::declval())); + +template +struct is_sax +{ + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); + + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; + + public: + static constexpr bool value = + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value; +}; + +template +struct is_sax_static_asserts +{ + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); + + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; + + public: + static_assert(is_detected_exact::value, + "Missing/invalid function: bool null()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_integer(number_integer_t)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool string(string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool binary(binary_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_object(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool key(string_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_object()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_array(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_array()"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool parse_error(std::size_t, const " + "std::string&, const exception&)"); +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +/// how to treat CBOR tags +enum class cbor_tag_handler_t +{ + error, ///< throw a parse_error exception in case of a tag + ignore, ///< ignore tags + store ///< store tags as binary type +}; + +/*! +@brief determine system byte order + +@return true if and only if system's byte order is little endian + +@note from https://stackoverflow.com/a/1001328/266378 +*/ +static inline bool little_endianness(int num = 1) noexcept +{ + return *reinterpret_cast(&num) == 1; +} + + +/////////////////// +// binary reader // +/////////////////// + +/*! +@brief deserialization of CBOR, MessagePack, and UBJSON values +*/ +template> +class binary_reader +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using json_sax_t = SAX; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename std::char_traits::int_type; + + public: + /*! + @brief create a binary reader + + @param[in] adapter input adapter to read from + */ + explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter)) + { + (void)detail::is_sax_static_asserts {}; + } + + // make class move-only + binary_reader(const binary_reader&) = delete; + binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + binary_reader& operator=(const binary_reader&) = delete; + binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~binary_reader() = default; + + /*! + @param[in] format the binary format to parse + @param[in] sax_ a SAX event processor + @param[in] strict whether to expect the input to be consumed completed + @param[in] tag_handler how to treat CBOR tags + + @return whether parsing was successful + */ + JSON_HEDLEY_NON_NULL(3) + bool sax_parse(const input_format_t format, + json_sax_t* sax_, + const bool strict = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + sax = sax_; + bool result = false; + + switch (format) + { + case input_format_t::bson: + result = parse_bson_internal(); + break; + + case input_format_t::cbor: + result = parse_cbor_internal(true, tag_handler); + break; + + case input_format_t::msgpack: + result = parse_msgpack_internal(); + break; + + case input_format_t::ubjson: + result = parse_ubjson_internal(); + break; + + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + + // strict mode: next byte must be EOF + if (result && strict) + { + if (format == input_format_t::ubjson) + { + get_ignore_noop(); + } + else + { + get(); + } + + if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) + { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType())); + } + } + + return result; + } + + private: + ////////// + // BSON // + ////////// + + /*! + @brief Reads in a BSON-object and passes it to the SAX-parser. + @return whether a valid BSON-value was passed to the SAX parser + */ + bool parse_bson_internal() + { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) + { + return false; + } + + return sax->end_object(); + } + + /*! + @brief Parses a C-style string from the BSON input. + @param[in,out] result A reference to the string variable where the read + string is to be stored. + @return `true` if the \x00-byte indicating the end of the string was + encountered before the EOF; false` indicates an unexpected EOF. + */ + bool get_bson_cstr(string_t& result) + { + auto out = std::back_inserter(result); + while (true) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) + { + return false; + } + if (current == 0x00) + { + return true; + } + *out++ = static_cast(current); + } + } + + /*! + @brief Parses a zero-terminated string of length @a len from the BSON + input. + @param[in] len The length (including the zero-byte at the end) of the + string to be read. + @param[in,out] result A reference to the string variable where the read + string is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 1 + @return `true` if the string was successfully parsed + */ + template + bool get_bson_string(const NumberType len, string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(len < 1)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType())); + } + + return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); + } + + /*! + @brief Parses a byte array input of length @a len from the BSON input. + @param[in] len The length of the byte array to be read. + @param[in,out] result A reference to the binary variable where the read + array is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 0 + @return `true` if the byte array was successfully parsed + */ + template + bool get_bson_binary(const NumberType len, binary_t& result) + { + if (JSON_HEDLEY_UNLIKELY(len < 0)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType())); + } + + // All BSON binary values have a subtype + std::uint8_t subtype{}; + get_number(input_format_t::bson, subtype); + result.set_subtype(subtype); + + return get_binary(input_format_t::bson, len, result); + } + + /*! + @brief Read a BSON document element of the given @a element_type. + @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html + @param[in] element_type_parse_position The position in the input stream, + where the `element_type` was read. + @warning Not all BSON element types are supported yet. An unsupported + @a element_type will give rise to a parse_error.114: + Unsupported BSON record type 0x... + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_internal(const char_int_type element_type, + const std::size_t element_type_parse_position) + { + switch (element_type) + { + case 0x01: // double + { + double number{}; + return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); + } + + case 0x02: // string + { + std::int32_t len{}; + string_t value; + return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); + } + + case 0x03: // object + { + return parse_bson_internal(); + } + + case 0x04: // array + { + return parse_bson_array(); + } + + case 0x05: // binary + { + std::int32_t len{}; + binary_t value; + return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); + } + + case 0x08: // boolean + { + return sax->boolean(get() != 0); + } + + case 0x0A: // null + { + return sax->null(); + } + + case 0x10: // int32 + { + std::int32_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + case 0x12: // int64 + { + std::int64_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + default: // anything else not supported (yet) + { + std::array cr{{}}; + static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType())); + } + } + } + + /*! + @brief Read a BSON element list (as specified in the BSON-spec) + + The same binary layout is used for objects and arrays, hence it must be + indicated with the argument @a is_array which one is expected + (true --> array, false --> object). + + @param[in] is_array Determines if the element list being read is to be + treated as an object (@a is_array == false), or as an + array (@a is_array == true). + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_list(const bool is_array) + { + string_t key; + + while (auto element_type = get()) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) + { + return false; + } + + const std::size_t element_type_parse_position = chars_read; + if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) + { + return false; + } + + if (!is_array && !sax->key(key)) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) + { + return false; + } + + // get_bson_cstr only appends + key.clear(); + } + + return true; + } + + /*! + @brief Reads an array from the BSON input and passes it to the SAX-parser. + @return whether a valid BSON-array was passed to the SAX parser + */ + bool parse_bson_array() + { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) + { + return false; + } + + return sax->end_array(); + } + + ////////// + // CBOR // + ////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true) or whether the last read character should + be considered instead (false) + @param[in] tag_handler how CBOR tags should be treated + + @return whether a valid CBOR value was passed to the SAX parser + */ + bool parse_cbor_internal(const bool get_char, + const cbor_tag_handler_t tag_handler) + { + switch (get_char ? get() : current) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::cbor, "value"); + + // Integer 0x00..0x17 (0..23) + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return sax->number_unsigned(static_cast(current)); + + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x1A: // Unsigned integer (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + // Negative integer -1-0x00..-1-0x17 (-1..-24) + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + return sax->number_integer(static_cast(0x20 - 1 - current)); + + case 0x38: // Negative integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) + - static_cast(number)); + } + + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: // Binary data (one-byte uint8_t for n follows) + case 0x59: // Binary data (two-byte uint16_t for n follow) + case 0x5A: // Binary data (four-byte uint32_t for n follow) + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + case 0x5F: // Binary data (indefinite length) + { + binary_t b; + return get_cbor_binary(b) && sax->binary(b); + } + + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) + { + string_t s; + return get_cbor_string(s) && sax->string(s); + } + + // array (0x00..0x17 data items follow) + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); + + case 0x98: // array (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x99: // array (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x9A: // array (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x9B: // array (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast(len), tag_handler); + } + + case 0x9F: // array (indefinite length) + return get_cbor_array(static_cast(-1), tag_handler); + + // map (0x00..0x17 pairs of data items follow) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); + + case 0xB8: // map (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xB9: // map (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xBA: // map (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xBB: // map (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast(len), tag_handler); + } + + case 0xBF: // map (indefinite length) + return get_cbor_object(static_cast(-1), tag_handler); + + case 0xC6: // tagged item + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD8: // tagged item (1 bytes follow) + case 0xD9: // tagged item (2 bytes follow) + case 0xDA: // tagged item (4 bytes follow) + case 0xDB: // tagged item (8 bytes follow) + { + switch (tag_handler) + { + case cbor_tag_handler_t::error: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + + case cbor_tag_handler_t::ignore: + { + // ignore binary subtype + switch (current) + { + case 0xD8: + { + std::uint8_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xD9: + { + std::uint16_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xDA: + { + std::uint32_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xDB: + { + std::uint64_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + default: + break; + } + return parse_cbor_internal(true, tag_handler); + } + + case cbor_tag_handler_t::store: + { + binary_t b; + // use binary subtype and store in binary container + switch (current) + { + case 0xD8: + { + std::uint8_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xD9: + { + std::uint16_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDA: + { + std::uint32_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDB: + { + std::uint64_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + default: + return parse_cbor_internal(true, tag_handler); + } + get(); + return get_cbor_binary(b) && sax->binary(b); + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } + } + + case 0xF4: // false + return sax->boolean(false); + + case 0xF5: // true + return sax->boolean(true); + + case 0xF6: // null + return sax->null(); + + case 0xF9: // Half-Precision Float (two-byte IEEE 754) + { + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte1 << 8u) + byte2); + const double val = [&half] + { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp&& exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) + { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); + } + + case 0xFA: // Single-Precision Float (four-byte IEEE 754) + { + float number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) + { + double number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + default: // anything else (0xFF is handled inside the other types) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + } + } + + /*! + @brief reads a CBOR string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + Additionally, CBOR's strings with indefinite lengths are supported. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_cbor_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) + { + return false; + } + + switch (current) + { + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + { + return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7F: // UTF-8 string (indefinite length) + { + while (get() != 0xFF) + { + string_t chunk; + if (!get_cbor_string(chunk)) + { + return false; + } + result.append(chunk); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType())); + } + } + } + + /*! + @brief reads a CBOR byte array + + This function first reads starting bytes to determine the expected + byte array length and then copies this number of bytes into the byte array. + Additionally, CBOR's byte arrays with indefinite lengths are supported. + + @param[out] result created byte array + + @return whether byte array creation completed + */ + bool get_cbor_binary(binary_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) + { + return false; + } + + switch (current) + { + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + { + return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x58: // Binary data (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x59: // Binary data (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5A: // Binary data (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5F: // Binary data (indefinite length) + { + while (get() != 0xFF) + { + binary_t chunk; + if (!get_cbor_binary(chunk)) + { + return false; + } + result.insert(result.end(), chunk.begin(), chunk.end()); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType())); + } + } + } + + /*! + @param[in] len the length of the array or static_cast(-1) for an + array of indefinite size + @param[in] tag_handler how CBOR tags should be treated + @return whether array creation completed + */ + bool get_cbor_array(const std::size_t len, + const cbor_tag_handler_t tag_handler) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) + { + return false; + } + + if (len != static_cast(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) + { + return false; + } + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object or static_cast(-1) for an + object of indefinite size + @param[in] tag_handler how CBOR tags should be treated + @return whether object creation completed + */ + bool get_cbor_object(const std::size_t len, + const cbor_tag_handler_t tag_handler) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + if (len != 0) + { + string_t key; + if (len != static_cast(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + key.clear(); + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + key.clear(); + } + } + } + + return sax->end_object(); + } + + ///////////// + // MsgPack // + ///////////// + + /*! + @return whether a valid MessagePack value was passed to the SAX parser + */ + bool parse_msgpack_internal() + { + switch (get()) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::msgpack, "value"); + + // positive fixint + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + return sax->number_unsigned(static_cast(current)); + + // fixmap + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); + + // fixarray + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); + + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 + { + string_t s; + return get_msgpack_string(s) && sax->string(s); + } + + case 0xC0: // nil + return sax->null(); + + case 0xC2: // false + return sax->boolean(false); + + case 0xC3: // true + return sax->boolean(true); + + case 0xC4: // bin 8 + case 0xC5: // bin 16 + case 0xC6: // bin 32 + case 0xC7: // ext 8 + case 0xC8: // ext 16 + case 0xC9: // ext 32 + case 0xD4: // fixext 1 + case 0xD5: // fixext 2 + case 0xD6: // fixext 4 + case 0xD7: // fixext 8 + case 0xD8: // fixext 16 + { + binary_t b; + return get_msgpack_binary(b) && sax->binary(b); + } + + case 0xCA: // float 32 + { + float number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCB: // float 64 + { + double number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCC: // uint 8 + { + std::uint8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCD: // uint 16 + { + std::uint16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCE: // uint 32 + { + std::uint32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCF: // uint 64 + { + std::uint64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xD0: // int 8 + { + std::int8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD1: // int 16 + { + std::int16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD2: // int 32 + { + std::int32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD3: // int 64 + { + std::int64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xDC: // array 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + } + + case 0xDD: // array 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + } + + case 0xDE: // map 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + } + + case 0xDF: // map 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + } + + // negative fixint + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: + return sax->number_integer(static_cast(current)); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + } + } + + /*! + @brief reads a MessagePack string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_msgpack_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) + { + return false; + } + + switch (current) + { + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + { + return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); + } + + case 0xD9: // str 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDA: // str 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDB: // str 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType())); + } + } + } + + /*! + @brief reads a MessagePack byte array + + This function first reads starting bytes to determine the expected + byte array length and then copies this number of bytes into a byte array. + + @param[out] result created byte array + + @return whether byte array creation completed + */ + bool get_msgpack_binary(binary_t& result) + { + // helper function to set the subtype + auto assign_and_return_true = [&result](std::int8_t subtype) + { + result.set_subtype(static_cast(subtype)); + return true; + }; + + switch (current) + { + case 0xC4: // bin 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC5: // bin 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC6: // bin 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC7: // ext 8 + { + std::uint8_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC8: // ext 16 + { + std::uint16_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC9: // ext 32 + { + std::uint32_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xD4: // fixext 1 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 1, result) && + assign_and_return_true(subtype); + } + + case 0xD5: // fixext 2 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 2, result) && + assign_and_return_true(subtype); + } + + case 0xD6: // fixext 4 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 4, result) && + assign_and_return_true(subtype); + } + + case 0xD7: // fixext 8 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 8, result) && + assign_and_return_true(subtype); + } + + case 0xD8: // fixext 16 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 16, result) && + assign_and_return_true(subtype); + } + + default: // LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } + } + + /*! + @param[in] len the length of the array + @return whether array creation completed + */ + bool get_msgpack_array(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) + { + return false; + } + + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) + { + return false; + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object + @return whether object creation completed + */ + bool get_msgpack_object(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + string_t key; + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) + { + return false; + } + key.clear(); + } + + return sax->end_object(); + } + + //////////// + // UBJSON // + //////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid UBJSON value was passed to the SAX parser + */ + bool parse_ubjson_internal(const bool get_char = true) + { + return get_ubjson_value(get_char ? get_ignore_noop() : current); + } + + /*! + @brief reads a UBJSON string + + This function is either called after reading the 'S' byte explicitly + indicating a string, or in case of an object key where the 'S' byte can be + left out. + + @param[out] result created string + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether string creation completed + */ + bool get_ubjson_string(string_t& result, const bool get_char = true) + { + if (get_char) + { + get(); // TODO(niels): may we ignore N here? + } + + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + + switch (current) + { + case 'U': + { + std::uint8_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'i': + { + std::int8_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'I': + { + std::int16_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'l': + { + std::int32_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'L': + { + std::int64_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + default: + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType())); + } + } + + /*! + @param[out] result determined size + @return whether size determination completed + */ + bool get_ubjson_size_value(std::size_t& result) + { + switch (get_ignore_noop()) + { + case 'U': + { + std::uint8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'i': + { + std::int8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char + return true; + } + + case 'I': + { + std::int16_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'l': + { + std::int32_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'L': + { + std::int64_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType())); + } + } + } + + /*! + @brief determine the type and size for a container + + In the optimized UBJSON format, a type and a size can be provided to allow + for a more compact representation. + + @param[out] result pair of the size and the type + + @return whether pair creation completed + */ + bool get_ubjson_size_type(std::pair& result) + { + result.first = string_t::npos; // size + result.second = 0; // type + + get_ignore_noop(); + + if (current == '$') + { + result.second = get(); // must not ignore 'N', because 'N' maybe the type + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) + { + return false; + } + + get_ignore_noop(); + if (JSON_HEDLEY_UNLIKELY(current != '#')) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType())); + } + + return get_ubjson_size_value(result.first); + } + + if (current == '#') + { + return get_ubjson_size_value(result.first); + } + + return true; + } + + /*! + @param prefix the previously read or set type prefix + @return whether value creation completed + */ + bool get_ubjson_value(const char_int_type prefix) + { + switch (prefix) + { + case std::char_traits::eof(): // EOF + return unexpect_eof(input_format_t::ubjson, "value"); + + case 'T': // true + return sax->boolean(true); + case 'F': // false + return sax->boolean(false); + + case 'Z': // null + return sax->null(); + + case 'U': + { + std::uint8_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); + } + + case 'i': + { + std::int8_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'I': + { + std::int16_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'l': + { + std::int32_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'L': + { + std::int64_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'd': + { + float number{}; + return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + } + + case 'D': + { + double number{}; + return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + } + + case 'H': + { + return get_ubjson_high_precision_number(); + } + + case 'C': // char + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(current > 127)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType())); + } + string_t s(1, static_cast(current)); + return sax->string(s); + } + + case 'S': // string + { + string_t s; + return get_ubjson_string(s) && sax->string(s); + } + + case '[': // array + return get_ubjson_array(); + + case '{': // object + return get_ubjson_object(); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + } + } + + /*! + @return whether array creation completed + */ + bool get_ubjson_array() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) + { + return false; + } + + if (size_and_type.first != string_t::npos) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + { + return false; + } + + while (current != ']') + { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) + { + return false; + } + get_ignore_noop(); + } + } + + return sax->end_array(); + } + + /*! + @return whether object creation completed + */ + bool get_ubjson_object() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) + { + return false; + } + + string_t key; + if (size_and_type.first != string_t::npos) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + key.clear(); + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + key.clear(); + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + { + return false; + } + + while (current != '}') + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + get_ignore_noop(); + key.clear(); + } + } + + return sax->end_object(); + } + + // Note, no reader for UBJSON binary types is implemented because they do + // not exist + + bool get_ubjson_high_precision_number() + { + // get size of following number string + std::size_t size{}; + auto res = get_ubjson_size_value(size); + if (JSON_HEDLEY_UNLIKELY(!res)) + { + return res; + } + + // get number string + std::vector number_vector; + for (std::size_t i = 0; i < size; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) + { + return false; + } + number_vector.push_back(static_cast(current)); + } + + // parse number string + using ia_type = decltype(detail::input_adapter(number_vector)); + auto number_lexer = detail::lexer(detail::input_adapter(number_vector), false); + const auto result_number = number_lexer.scan(); + const auto number_string = number_lexer.get_token_string(); + const auto result_remainder = number_lexer.scan(); + + using token_type = typename detail::lexer_base::token_type; + + if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) + { + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); + } + + switch (result_number) + { + case token_type::value_integer: + return sax->number_integer(number_lexer.get_number_integer()); + case token_type::value_unsigned: + return sax->number_unsigned(number_lexer.get_number_unsigned()); + case token_type::value_float: + return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); + case token_type::uninitialized: + case token_type::literal_true: + case token_type::literal_false: + case token_type::literal_null: + case token_type::value_string: + case token_type::begin_array: + case token_type::begin_object: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::parse_error: + case token_type::end_of_input: + case token_type::literal_or_value: + default: + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); + } + } + + /////////////////////// + // Utility functions // + /////////////////////// + + /*! + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a -'ve valued + `std::char_traits::eof()` in that case. + + @return character read from the input + */ + char_int_type get() + { + ++chars_read; + return current = ia.get_character(); + } + + /*! + @return character read from the input after ignoring all 'N' entries + */ + char_int_type get_ignore_noop() + { + do + { + get(); + } + while (current == 'N'); + + return current; + } + + /* + @brief read a number from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[out] result number of type @a NumberType + + @return whether conversion completed + + @note This function needs to respect the system's endianness, because + bytes in CBOR, MessagePack, and UBJSON are stored in network order + (big endian) and therefore need reordering on little endian systems. + */ + template + bool get_number(const input_format_t format, NumberType& result) + { + // step 1: read input into array with system's byte order + std::array vec{}; + for (std::size_t i = 0; i < sizeof(NumberType); ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) + { + return false; + } + + // reverse byte order prior to conversion if necessary + if (is_little_endian != InputIsLittleEndian) + { + vec[sizeof(NumberType) - i - 1] = static_cast(current); + } + else + { + vec[i] = static_cast(current); // LCOV_EXCL_LINE + } + } + + // step 2: convert array into number of type T and return + std::memcpy(&result, vec.data(), sizeof(NumberType)); + return true; + } + + /*! + @brief create a string by reading characters from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of characters to read + @param[out] result string created by reading @a len bytes + + @return whether string creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of string memory. + */ + template + bool get_string(const input_format_t format, + const NumberType len, + string_t& result) + { + bool success = true; + for (NumberType i = 0; i < len; i++) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) + { + success = false; + break; + } + result.push_back(static_cast(current)); + } + return success; + } + + /*! + @brief create a byte array by reading bytes from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of bytes to read + @param[out] result byte array created by reading @a len bytes + + @return whether byte array creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of memory. + */ + template + bool get_binary(const input_format_t format, + const NumberType len, + binary_t& result) + { + bool success = true; + for (NumberType i = 0; i < len; i++) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) + { + success = false; + break; + } + result.push_back(static_cast(current)); + } + return success; + } + + /*! + @param[in] format the current format (for diagnostics) + @param[in] context further context information (for diagnostics) + @return whether the last read character is not EOF + */ + JSON_HEDLEY_NON_NULL(3) + bool unexpect_eof(const input_format_t format, const char* context) const + { + if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) + { + return sax->parse_error(chars_read, "", + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType())); + } + return true; + } + + /*! + @return a string representation of the last read byte + */ + std::string get_token_string() const + { + std::array cr{{}}; + static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return std::string{cr.data()}; + } + + /*! + @param[in] format the current format + @param[in] detail a detailed error message + @param[in] context further context information + @return a message string to use in the parse_error exceptions + */ + std::string exception_message(const input_format_t format, + const std::string& detail, + const std::string& context) const + { + std::string error_msg = "syntax error while parsing "; + + switch (format) + { + case input_format_t::cbor: + error_msg += "CBOR"; + break; + + case input_format_t::msgpack: + error_msg += "MessagePack"; + break; + + case input_format_t::ubjson: + error_msg += "UBJSON"; + break; + + case input_format_t::bson: + error_msg += "BSON"; + break; + + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + + return error_msg + " " + context + ": " + detail; + } + + private: + /// input adapter + InputAdapterType ia; + + /// the current character + char_int_type current = std::char_traits::eof(); + + /// the number of characters read + std::size_t chars_read = 0; + + /// whether we can assume little endianness + const bool is_little_endian = little_endianness(); + + /// the SAX parser + json_sax_t* sax = nullptr; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include // isfinite +#include // uint8_t +#include // function +#include // string +#include // move +#include // vector + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +//////////// +// parser // +//////////// + +enum class parse_event_t : std::uint8_t +{ + /// the parser read `{` and started to process a JSON object + object_start, + /// the parser read `}` and finished processing a JSON object + object_end, + /// the parser read `[` and started to process a JSON array + array_start, + /// the parser read `]` and finished processing a JSON array + array_end, + /// the parser read a key of a value in an object + key, + /// the parser finished reading a JSON value + value +}; + +template +using parser_callback_t = + std::function; + +/*! +@brief syntax analysis + +This class implements a recursive descent parser. +*/ +template +class parser +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using lexer_t = lexer; + using token_type = typename lexer_t::token_type; + + public: + /// a parser reading from an input adapter + explicit parser(InputAdapterType&& adapter, + const parser_callback_t cb = nullptr, + const bool allow_exceptions_ = true, + const bool skip_comments = false) + : callback(cb) + , m_lexer(std::move(adapter), skip_comments) + , allow_exceptions(allow_exceptions_) + { + // read first token + get_token(); + } + + /*! + @brief public parser interface + + @param[in] strict whether to expect the last token to be EOF + @param[in,out] result parsed JSON value + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ + void parse(const bool strict, BasicJsonType& result) + { + if (callback) + { + json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); + sax_parse_internal(&sdp); + + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"), BasicJsonType())); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + + // set top-level value to null if it was discarded by the callback + // function + if (result.is_discarded()) + { + result = nullptr; + } + } + else + { + json_sax_dom_parser sdp(result, allow_exceptions); + sax_parse_internal(&sdp); + + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + } + + result.assert_invariant(); + } + + /*! + @brief public accept interface + + @param[in] strict whether to expect the last token to be EOF + @return whether the input is a proper JSON text + */ + bool accept(const bool strict = true) + { + json_sax_acceptor sax_acceptor; + return sax_parse(&sax_acceptor, strict); + } + + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse(SAX* sax, const bool strict = true) + { + (void)detail::is_sax_static_asserts {}; + const bool result = sax_parse_internal(sax); + + // strict mode: next byte must be EOF + if (result && strict && (get_token() != token_type::end_of_input)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); + } + + return result; + } + + private: + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse_internal(SAX* sax) + { + // stack to remember the hierarchy of structured values we are parsing + // true = array; false = object + std::vector states; + // value to avoid a goto (see comment where set to true) + bool skip_to_state_evaluation = false; + + while (true) + { + if (!skip_to_state_evaluation) + { + // invariant: get_token() was called before each iteration + switch (last_token) + { + case token_type::begin_object: + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + { + return false; + } + + // closing } -> we are done + if (get_token() == token_type::end_object) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) + { + return false; + } + break; + } + + // parse key + if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); + } + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); + } + + // remember we are now inside an object + states.push_back(false); + + // parse values + get_token(); + continue; + } + + case token_type::begin_array: + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + { + return false; + } + + // closing ] -> we are done + if (get_token() == token_type::end_array) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) + { + return false; + } + break; + } + + // remember we are now inside an array + states.push_back(true); + + // parse values (no need to call get_token) + continue; + } + + case token_type::value_float: + { + const auto res = m_lexer.get_number_float(); + + if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType())); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) + { + return false; + } + + break; + } + + case token_type::literal_false: + { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) + { + return false; + } + break; + } + + case token_type::literal_null: + { + if (JSON_HEDLEY_UNLIKELY(!sax->null())) + { + return false; + } + break; + } + + case token_type::literal_true: + { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) + { + return false; + } + break; + } + + case token_type::value_integer: + { + if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) + { + return false; + } + break; + } + + case token_type::value_string: + { + if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) + { + return false; + } + break; + } + + case token_type::value_unsigned: + { + if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) + { + return false; + } + break; + } + + case token_type::parse_error: + { + // using "uninitialized" to avoid "expected" message + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType())); + } + + case token_type::uninitialized: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::end_of_input: + case token_type::literal_or_value: + default: // the last token was unexpected + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType())); + } + } + } + else + { + skip_to_state_evaluation = false; + } + + // we reached this line after we successfully parsed a value + if (states.empty()) + { + // empty stack: we reached the end of the hierarchy: done + return true; + } + + if (states.back()) // array + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse a new value + get_token(); + continue; + } + + // closing ] + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) + { + return false; + } + + // We are done with this array. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType())); + } + + // states.back() is false -> object + + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse key + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); + } + + // parse values + get_token(); + continue; + } + + // closing } + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) + { + return false; + } + + // We are done with this object. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType())); + } + } + + /// get next token from lexer + token_type get_token() + { + return last_token = m_lexer.scan(); + } + + std::string exception_message(const token_type expected, const std::string& context) + { + std::string error_msg = "syntax error "; + + if (!context.empty()) + { + error_msg += "while parsing " + context + " "; + } + + error_msg += "- "; + + if (last_token == token_type::parse_error) + { + error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + + m_lexer.get_token_string() + "'"; + } + else + { + error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); + } + + if (expected != token_type::uninitialized) + { + error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); + } + + return error_msg; + } + + private: + /// callback function + const parser_callback_t callback = nullptr; + /// the type of the last read token + token_type last_token = token_type::uninitialized; + /// the lexer + lexer_t m_lexer; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +} // namespace detail +} // namespace nlohmann + +// #include + + +// #include + + +#include // ptrdiff_t +#include // numeric_limits + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/* +@brief an iterator for primitive JSON types + +This class models an iterator for primitive JSON types (boolean, number, +string). It's only purpose is to allow the iterator/const_iterator classes +to "iterate" over primitive values. Internally, the iterator is modeled by +a `difference_type` variable. Value begin_value (`0`) models the begin, +end_value (`1`) models past the end. +*/ +class primitive_iterator_t +{ + private: + using difference_type = std::ptrdiff_t; + static constexpr difference_type begin_value = 0; + static constexpr difference_type end_value = begin_value + 1; + + JSON_PRIVATE_UNLESS_TESTED: + /// iterator as signed integer type + difference_type m_it = (std::numeric_limits::min)(); + + public: + constexpr difference_type get_value() const noexcept + { + return m_it; + } + + /// set iterator to a defined beginning + void set_begin() noexcept + { + m_it = begin_value; + } + + /// set iterator to a defined past the end + void set_end() noexcept + { + m_it = end_value; + } + + /// return whether the iterator can be dereferenced + constexpr bool is_begin() const noexcept + { + return m_it == begin_value; + } + + /// return whether the iterator is at end + constexpr bool is_end() const noexcept + { + return m_it == end_value; + } + + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it == rhs.m_it; + } + + friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it < rhs.m_it; + } + + primitive_iterator_t operator+(difference_type n) noexcept + { + auto result = *this; + result += n; + return result; + } + + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it - rhs.m_it; + } + + primitive_iterator_t& operator++() noexcept + { + ++m_it; + return *this; + } + + primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type) + { + auto result = *this; + ++m_it; + return result; + } + + primitive_iterator_t& operator--() noexcept + { + --m_it; + return *this; + } + + primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type) + { + auto result = *this; + --m_it; + return result; + } + + primitive_iterator_t& operator+=(difference_type n) noexcept + { + m_it += n; + return *this; + } + + primitive_iterator_t& operator-=(difference_type n) noexcept + { + m_it -= n; + return *this; + } +}; +} // namespace detail +} // namespace nlohmann + + +namespace nlohmann +{ +namespace detail +{ +/*! +@brief an iterator value + +@note This structure could easily be a union, but MSVC currently does not allow +unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. +*/ +template struct internal_iterator +{ + /// iterator for JSON objects + typename BasicJsonType::object_t::iterator object_iterator {}; + /// iterator for JSON arrays + typename BasicJsonType::array_t::iterator array_iterator {}; + /// generic iterator for all other types + primitive_iterator_t primitive_iterator {}; +}; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next +#include // conditional, is_const, remove_const + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +// forward declare, to be able to friend it later on +template class iteration_proxy; +template class iteration_proxy_value; + +/*! +@brief a template for a bidirectional iterator for the @ref basic_json class +This class implements a both iterators (iterator and const_iterator) for the +@ref basic_json class. +@note An iterator is called *initialized* when a pointer to a JSON value has + been set (e.g., by a constructor or a copy assignment). If the iterator is + default-constructed, it is *uninitialized* and most methods are undefined. + **The library uses assertions to detect calls on uninitialized iterators.** +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +@since version 1.0.0, simplified in version 2.0.9, change to bidirectional + iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) +*/ +template +class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) +{ + /// the iterator with BasicJsonType of different const-ness + using other_iter_impl = iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + /// allow basic_json to access private members + friend other_iter_impl; + friend BasicJsonType; + friend iteration_proxy; + friend iteration_proxy_value; + + using object_t = typename BasicJsonType::object_t; + using array_t = typename BasicJsonType::array_t; + // make sure BasicJsonType is basic_json or const basic_json + static_assert(is_basic_json::type>::value, + "iter_impl only accepts (const) basic_json"); + + public: + + /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. + /// The C++ Standard has never required user-defined iterators to derive from std::iterator. + /// A user-defined iterator should provide publicly accessible typedefs named + /// iterator_category, value_type, difference_type, pointer, and reference. + /// Note that value_type is required to be non-const, even for constant iterators. + using iterator_category = std::bidirectional_iterator_tag; + + /// the type of the values when the iterator is dereferenced + using value_type = typename BasicJsonType::value_type; + /// a type to represent differences between iterators + using difference_type = typename BasicJsonType::difference_type; + /// defines a pointer to the type iterated over (value_type) + using pointer = typename std::conditional::value, + typename BasicJsonType::const_pointer, + typename BasicJsonType::pointer>::type; + /// defines a reference to the type iterated over (value_type) + using reference = + typename std::conditional::value, + typename BasicJsonType::const_reference, + typename BasicJsonType::reference>::type; + + iter_impl() = default; + ~iter_impl() = default; + iter_impl(iter_impl&&) noexcept = default; + iter_impl& operator=(iter_impl&&) noexcept = default; + + /*! + @brief constructor for a given JSON instance + @param[in] object pointer to a JSON object for this iterator + @pre object != nullptr + @post The iterator is initialized; i.e. `m_object != nullptr`. + */ + explicit iter_impl(pointer object) noexcept : m_object(object) + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = typename object_t::iterator(); + break; + } + + case value_t::array: + { + m_it.array_iterator = typename array_t::iterator(); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator = primitive_iterator_t(); + break; + } + } + } + + /*! + @note The conventional copy constructor and copy assignment are implicitly + defined. Combined with the following converting constructor and + assignment, they support: (1) copy from iterator to iterator, (2) + copy from const iterator to const iterator, and (3) conversion from + iterator to const iterator. However conversion from const iterator + to iterator is not defined. + */ + + /*! + @brief const copy constructor + @param[in] other const iterator to copy from + @note This copy constructor had to be defined explicitly to circumvent a bug + occurring on msvc v19.0 compiler (VS 2015) debug build. For more + information refer to: https://github.com/nlohmann/json/issues/1608 + */ + iter_impl(const iter_impl& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl& other) noexcept + { + if (&other != this) + { + m_object = other.m_object; + m_it = other.m_it; + } + return *this; + } + + /*! + @brief converting constructor + @param[in] other non-const iterator to copy from + @note It is not checked whether @a other is initialized. + */ + iter_impl(const iter_impl::type>& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other non-const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl::type>& other) noexcept // NOLINT(cert-oop54-cpp) + { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_begin() noexcept + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->begin(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->begin(); + break; + } + + case value_t::null: + { + // set to end so begin()==end() is true: null is empty + m_it.primitive_iterator.set_end(); + break; + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator.set_begin(); + break; + } + } + } + + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_end() noexcept + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->end(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->end(); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator.set_end(); + break; + } + } + } + + public: + /*! + @brief return a reference to the value pointed to by the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator*() const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + return m_it.object_iterator->second; + } + + case value_t::array: + { + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + return *m_it.array_iterator; + } + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + } + } + } + + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + pointer operator->() const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + return &(m_it.object_iterator->second); + } + + case value_t::array: + { + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + return &*m_it.array_iterator; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + } + } + } + + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator++(int) // NOLINT(readability-const-return-type) + { + auto result = *this; + ++(*this); + return result; + } + + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator++() + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, 1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, 1); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + ++m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator--(int) // NOLINT(readability-const-return-type) + { + auto result = *this; + --(*this); + return result; + } + + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator--() + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, -1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, -1); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + --m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief comparison: equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator==(const IterImpl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); + } + + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + return (m_it.object_iterator == other.m_it.object_iterator); + + case value_t::array: + return (m_it.array_iterator == other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator == other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator!=(const IterImpl& other) const + { + return !operator==(other); + } + + /*! + @brief comparison: smaller + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); + } + + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object)); + + case value_t::array: + return (m_it.array_iterator < other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator < other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<=(const iter_impl& other) const + { + return !other.operator < (*this); + } + + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>(const iter_impl& other) const + { + return !operator<=(other); + } + + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>=(const iter_impl& other) const + { + return !operator<(other); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator+=(difference_type i) + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); + + case value_t::array: + { + std::advance(m_it.array_iterator, i); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator += i; + break; + } + } + + return *this; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator-=(difference_type i) + { + return operator+=(-i); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator+(difference_type i) const + { + auto result = *this; + result += i; + return result; + } + + /*! + @brief addition of distance and iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + friend iter_impl operator+(difference_type i, const iter_impl& it) + { + auto result = it; + result += i; + return result; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator-(difference_type i) const + { + auto result = *this; + result -= i; + return result; + } + + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + difference_type operator-(const iter_impl& other) const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); + + case value_t::array: + return m_it.array_iterator - other.m_it.array_iterator; + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return m_it.primitive_iterator - other.m_it.primitive_iterator; + } + } + + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator[](difference_type n) const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object)); + + case value_t::array: + return *std::next(m_it.array_iterator, n); + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + } + } + } + + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + const typename object_t::key_type& key() const + { + JSON_ASSERT(m_object != nullptr); + + if (JSON_HEDLEY_LIKELY(m_object->is_object())) + { + return m_it.object_iterator->first; + } + + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object)); + } + + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference value() const + { + return operator*(); + } + + JSON_PRIVATE_UNLESS_TESTED: + /// associated JSON instance + pointer m_object = nullptr; + /// the actual iterator of the associated instance + internal_iterator::type> m_it {}; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // ptrdiff_t +#include // reverse_iterator +#include // declval + +namespace nlohmann +{ +namespace detail +{ +////////////////////// +// reverse_iterator // +////////////////////// + +/*! +@brief a template for a reverse iterator class + +@tparam Base the base iterator type to reverse. Valid types are @ref +iterator (to create @ref reverse_iterator) and @ref const_iterator (to +create @ref const_reverse_iterator). + +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): + It is possible to write to the pointed-to element (only if @a Base is + @ref iterator). + +@since version 1.0.0 +*/ +template +class json_reverse_iterator : public std::reverse_iterator +{ + public: + using difference_type = std::ptrdiff_t; + /// shortcut to the reverse iterator adapter + using base_iterator = std::reverse_iterator; + /// the reference type for the pointed-to element + using reference = typename Base::reference; + + /// create reverse iterator from iterator + explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept + : base_iterator(it) {} + + /// create reverse iterator from base class + explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} + + /// post-increment (it++) + json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type) + { + return static_cast(base_iterator::operator++(1)); + } + + /// pre-increment (++it) + json_reverse_iterator& operator++() + { + return static_cast(base_iterator::operator++()); + } + + /// post-decrement (it--) + json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type) + { + return static_cast(base_iterator::operator--(1)); + } + + /// pre-decrement (--it) + json_reverse_iterator& operator--() + { + return static_cast(base_iterator::operator--()); + } + + /// add to iterator + json_reverse_iterator& operator+=(difference_type i) + { + return static_cast(base_iterator::operator+=(i)); + } + + /// add to iterator + json_reverse_iterator operator+(difference_type i) const + { + return static_cast(base_iterator::operator+(i)); + } + + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const + { + return static_cast(base_iterator::operator-(i)); + } + + /// return difference + difference_type operator-(const json_reverse_iterator& other) const + { + return base_iterator(*this) - base_iterator(other); + } + + /// access to successor + reference operator[](difference_type n) const + { + return *(this->operator+(n)); + } + + /// return the key of an object iterator + auto key() const -> decltype(std::declval().key()) + { + auto it = --this->base(); + return it.key(); + } + + /// return the value of an iterator + reference value() const + { + auto it = --this->base(); + return it.operator * (); + } +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // all_of +#include // isdigit +#include // max +#include // accumulate +#include // string +#include // move +#include // vector + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ + +/// @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 +{ + // allow basic_json to access private members + NLOHMANN_BASIC_JSON_TPL_DECLARATION + friend class basic_json; + + public: + /// @brief create JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ + explicit json_pointer(const std::string& s = "") + : reference_tokens(split(s)) + {} + + /// @brief return a string representation of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ + std::string to_string() const + { + return std::accumulate(reference_tokens.begin(), reference_tokens.end(), + std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + detail::escape(b); + }); + } + + /// @brief return a string representation of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ + operator std::string() const + { + return to_string(); + } + + /// @brief append another JSON pointer at the end of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ + json_pointer& operator/=(const json_pointer& ptr) + { + reference_tokens.insert(reference_tokens.end(), + ptr.reference_tokens.begin(), + ptr.reference_tokens.end()); + return *this; + } + + /// @brief append an unescaped reference token at the end of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ + json_pointer& operator/=(std::string token) + { + push_back(std::move(token)); + return *this; + } + + /// @brief append an array index at the end of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ + json_pointer& operator/=(std::size_t array_idx) + { + return *this /= std::to_string(array_idx); + } + + /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ + friend json_pointer operator/(const json_pointer& lhs, + const json_pointer& rhs) + { + return json_pointer(lhs) /= rhs; + } + + /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ + friend json_pointer operator/(const json_pointer& lhs, std::string token) // NOLINT(performance-unnecessary-value-param) + { + return json_pointer(lhs) /= std::move(token); + } + + /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ + friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) + { + return json_pointer(lhs) /= array_idx; + } + + /// @brief returns the parent of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ + json_pointer parent_pointer() const + { + if (empty()) + { + return *this; + } + + json_pointer res = *this; + res.pop_back(); + return res; + } + + /// @brief remove last reference token + /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ + void pop_back() + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + } + + reference_tokens.pop_back(); + } + + /// @brief return last reference token + /// @sa https://json.nlohmann.me/api/json_pointer/back/ + const std::string& back() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + } + + return reference_tokens.back(); + } + + /// @brief append an unescaped token at the end of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ + void push_back(const std::string& token) + { + reference_tokens.push_back(token); + } + + /// @brief append an unescaped token at the end of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ + void push_back(std::string&& token) + { + reference_tokens.push_back(std::move(token)); + } + + /// @brief return whether pointer points to the root document + /// @sa https://json.nlohmann.me/api/json_pointer/empty/ + bool empty() const noexcept + { + return reference_tokens.empty(); + } + + private: + /*! + @param[in] s reference token to be converted into an array index + + @return integer representation of @a s + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index begins not with a digit + @throw out_of_range.404 if string @a s could not be converted to an integer + @throw out_of_range.410 if an array index exceeds size_type + */ + static typename BasicJsonType::size_type array_index(const std::string& s) + { + using size_type = typename BasicJsonType::size_type; + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType())); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType())); + } + + std::size_t processed_chars = 0; + unsigned long long res = 0; // NOLINT(runtime/int) + JSON_TRY + { + res = std::stoull(s, &processed_chars); + } + JSON_CATCH(std::out_of_range&) + { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + } + + // check if the string was completely read + if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) + { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + } + + // only triggered on special platforms (like 32bit), see also + // https://github.com/nlohmann/json/pull/2203 + if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int) + { + JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE + } + + return static_cast(res); + } + + JSON_PRIVATE_UNLESS_TESTED: + json_pointer top() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + } + + json_pointer result = *this; + result.reference_tokens = {reference_tokens[0]}; + return result; + } + + private: + /*! + @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. + + @throw parse_error.109 if array index is not a number + @throw type_error.313 if value cannot be unflattened + */ + BasicJsonType& get_and_create(BasicJsonType& j) const + { + auto* result = &j; + + // in case no reference tokens exist, return a reference to the JSON value + // j which will be overwritten by a primitive value + for (const auto& reference_token : reference_tokens) + { + switch (result->type()) + { + case detail::value_t::null: + { + if (reference_token == "0") + { + // start a new array if reference token is 0 + result = &result->operator[](0); + } + else + { + // start a new object otherwise + result = &result->operator[](reference_token); + } + break; + } + + case detail::value_t::object: + { + // create an entry in the object + result = &result->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // create an entry in the array + result = &result->operator[](array_index(reference_token)); + break; + } + + /* + The following code is only reached if there exists a reference + token _and_ the current value is primitive. In this case, we have + an error situation, because primitive values may only occur as + single value; that is, with an empty list of reference tokens. + */ + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j)); + } + } + + return *result; + } + + /*! + @brief return a reference to the pointed to value + + @note This version does not throw if a value is not present, but tries to + create nested values instead. For instance, calling this function + with pointer `"/this/that"` on a null value is equivalent to calling + `operator[]("this").operator[]("that")` on that value, effectively + changing the null value to an object. + + @param[in] ptr a JSON value + + @return reference to the JSON value pointed to by the JSON pointer + + @complexity Linear in the length of the JSON pointer. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_unchecked(BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + // convert null values to arrays or objects before continuing + if (ptr->is_null()) + { + // check if reference token is a number + const bool nums = + std::all_of(reference_token.begin(), reference_token.end(), + [](const unsigned char x) + { + return std::isdigit(x); + }); + + // change value to array for numbers or "-" or to object otherwise + *ptr = (nums || reference_token == "-") + ? detail::value_t::array + : detail::value_t::object; + } + + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (reference_token == "-") + { + // explicitly treat "-" as index beyond the end + ptr = &ptr->operator[](ptr->m_value.array->size()); + } + else + { + // convert array index to number; unchecked access + ptr = &ptr->operator[](array_index(reference_token)); + } + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_checked(BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range", *ptr)); + } + + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @brief return a const reference to the pointed to value + + @param[in] ptr a JSON value + + @return const reference to the JSON value pointed to by the JSON + pointer + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" cannot be used for const access + JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr)); + } + + // use unchecked array access + ptr = &ptr->operator[](array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_checked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range", *ptr)); + } + + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + */ + bool contains(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + if (!ptr->contains(reference_token)) + { + // we did not find the key in the object + return false; + } + + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) + { + // invalid char + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) + { + if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) + { + // first char should be between '1' and '9' + return false; + } + for (std::size_t i = 1; i < reference_token.size(); i++) + { + if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) + { + // other char should be between '0' and '9' + return false; + } + } + } + + const auto idx = array_index(reference_token); + if (idx >= ptr->size()) + { + // index out of range + return false; + } + + ptr = &ptr->operator[](idx); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + { + // we do not expect primitive values if there is still a + // reference token to process + return false; + } + } + } + + // no reference token left means we found a primitive value + return true; + } + + /*! + @brief split the string input to reference tokens + + @note This function is only called by the json_pointer constructor. + All exceptions below are documented there. + + @throw parse_error.107 if the pointer is not empty or begins with '/' + @throw parse_error.108 if character '~' is not followed by '0' or '1' + */ + static std::vector split(const std::string& reference_string) + { + std::vector result; + + // special case: empty reference string -> no reference tokens + if (reference_string.empty()) + { + return result; + } + + // check if nonempty reference string begins with slash + if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) + { + JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType())); + } + + // extract the reference tokens: + // - slash: position of the last read slash (or end of string) + // - start: position after the previous slash + for ( + // search for the first slash after the first character + std::size_t slash = reference_string.find_first_of('/', 1), + // set the beginning of the first reference token + start = 1; + // we can stop if start == 0 (if slash == std::string::npos) + start != 0; + // set the beginning of the next reference token + // (will eventually be 0 if slash == std::string::npos) + start = (slash == std::string::npos) ? 0 : slash + 1, + // find next slash + slash = reference_string.find_first_of('/', start)) + { + // use the text between the beginning of the reference token + // (start) and the last slash (slash). + auto reference_token = reference_string.substr(start, slash - start); + + // check reference tokens are properly escaped + for (std::size_t pos = reference_token.find_first_of('~'); + pos != std::string::npos; + pos = reference_token.find_first_of('~', pos + 1)) + { + JSON_ASSERT(reference_token[pos] == '~'); + + // ~ must be followed by 0 or 1 + if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || + (reference_token[pos + 1] != '0' && + reference_token[pos + 1] != '1'))) + { + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType())); + } + } + + // finally, store the reference token + detail::unescape(reference_token); + result.push_back(reference_token); + } + + return result; + } + + private: + /*! + @param[in] reference_string the reference string to the current value + @param[in] value the value to consider + @param[in,out] result the result object to insert values to + + @note Empty objects or arrays are flattened to `null`. + */ + static void flatten(const std::string& reference_string, + const BasicJsonType& value, + BasicJsonType& result) + { + switch (value.type()) + { + case detail::value_t::array: + { + if (value.m_value.array->empty()) + { + // flatten empty array as null + result[reference_string] = nullptr; + } + else + { + // iterate array and use index as reference string + for (std::size_t i = 0; i < value.m_value.array->size(); ++i) + { + flatten(reference_string + "/" + std::to_string(i), + value.m_value.array->operator[](i), result); + } + } + break; + } + + case detail::value_t::object: + { + if (value.m_value.object->empty()) + { + // flatten empty object as null + result[reference_string] = nullptr; + } + else + { + // iterate object and use keys as reference string + for (const auto& element : *value.m_value.object) + { + flatten(reference_string + "/" + detail::escape(element.first), element.second, result); + } + } + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + { + // add primitive value with its reference string + result[reference_string] = value; + break; + } + } + } + + /*! + @param[in] value flattened JSON + + @return unflattened JSON + + @throw parse_error.109 if array index is not a number + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + @throw type_error.313 if value cannot be unflattened + */ + static BasicJsonType + unflatten(const BasicJsonType& value) + { + if (JSON_HEDLEY_UNLIKELY(!value.is_object())) + { + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value)); + } + + BasicJsonType result; + + // iterate the JSON object values + for (const auto& element : *value.m_value.object) + { + if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) + { + JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second)); + } + + // assign value to reference pointed to by JSON pointer; Note that if + // the JSON pointer is "" (i.e., points to the whole value), function + // get_and_create returns a reference to result itself. An assignment + // will then create a primitive value. + json_pointer(element.first).get_and_create(result) = element.second; + } + + return result; + } + + /*! + @brief compares two JSON pointers for equality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is equal to @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return lhs.reference_tokens == rhs.reference_tokens; + } + + /*! + @brief compares two JSON pointers for inequality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is not equal @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return !(lhs == rhs); + } + + /// the reference tokens + std::vector reference_tokens; +}; +} // namespace nlohmann + +// #include + + +#include +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +class json_ref +{ + public: + using value_type = BasicJsonType; + + json_ref(value_type&& value) + : owned_value(std::move(value)) + {} + + json_ref(const value_type& value) + : value_ref(&value) + {} + + json_ref(std::initializer_list init) + : owned_value(init) + {} + + template < + class... Args, + enable_if_t::value, int> = 0 > + json_ref(Args && ... args) + : owned_value(std::forward(args)...) + {} + + // class should be movable only + json_ref(json_ref&&) noexcept = default; + json_ref(const json_ref&) = delete; + json_ref& operator=(const json_ref&) = delete; + json_ref& operator=(json_ref&&) = delete; + ~json_ref() = default; + + value_type moved_or_copied() const + { + if (value_ref == nullptr) + { + return std::move(owned_value); + } + return *value_ref; + } + + value_type const& operator*() const + { + return value_ref ? *value_ref : owned_value; + } + + value_type const* operator->() const + { + return &** this; + } + + private: + mutable value_type owned_value = nullptr; + value_type const* value_ref = nullptr; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + +// #include + +// #include + + +#include // reverse +#include // array +#include // isnan, isinf +#include // uint8_t, uint16_t, uint32_t, uint64_t +#include // memcpy +#include // numeric_limits +#include // string +#include // move + +// #include + +// #include + +// #include + + +#include // copy +#include // size_t +#include // back_inserter +#include // shared_ptr, make_shared +#include // basic_string +#include // vector + +#ifndef JSON_NO_IO + #include // streamsize + #include // basic_ostream +#endif // JSON_NO_IO + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/// abstract output adapter interface +template struct output_adapter_protocol +{ + virtual void write_character(CharType c) = 0; + virtual void write_characters(const CharType* s, std::size_t length) = 0; + virtual ~output_adapter_protocol() = default; + + output_adapter_protocol() = default; + output_adapter_protocol(const output_adapter_protocol&) = default; + output_adapter_protocol(output_adapter_protocol&&) noexcept = default; + output_adapter_protocol& operator=(const output_adapter_protocol&) = default; + output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; +}; + +/// a type to simplify interfaces +template +using output_adapter_t = std::shared_ptr>; + +/// output adapter for byte vectors +template> +class output_vector_adapter : public output_adapter_protocol +{ + public: + explicit output_vector_adapter(std::vector& vec) noexcept + : v(vec) + {} + + void write_character(CharType c) override + { + v.push_back(c); + } + + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType* s, std::size_t length) override + { + std::copy(s, s + length, std::back_inserter(v)); + } + + private: + std::vector& v; +}; + +#ifndef JSON_NO_IO +/// output adapter for output streams +template +class output_stream_adapter : public output_adapter_protocol +{ + public: + explicit output_stream_adapter(std::basic_ostream& s) noexcept + : stream(s) + {} + + void write_character(CharType c) override + { + stream.put(c); + } + + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType* s, std::size_t length) override + { + stream.write(s, static_cast(length)); + } + + private: + std::basic_ostream& stream; +}; +#endif // JSON_NO_IO + +/// output adapter for basic_string +template> +class output_string_adapter : public output_adapter_protocol +{ + public: + explicit output_string_adapter(StringType& s) noexcept + : str(s) + {} + + void write_character(CharType c) override + { + str.push_back(c); + } + + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType* s, std::size_t length) override + { + str.append(s, length); + } + + private: + StringType& str; +}; + +template> +class output_adapter +{ + public: + template> + output_adapter(std::vector& vec) + : oa(std::make_shared>(vec)) {} + +#ifndef JSON_NO_IO + output_adapter(std::basic_ostream& s) + : oa(std::make_shared>(s)) {} +#endif // JSON_NO_IO + + output_adapter(StringType& s) + : oa(std::make_shared>(s)) {} + + operator output_adapter_t() + { + return oa; + } + + private: + output_adapter_t oa = nullptr; +}; +} // namespace detail +} // namespace nlohmann + + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// binary writer // +/////////////////// + +/*! +@brief serialization to CBOR and MessagePack values +*/ +template +class binary_writer +{ + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using number_float_t = typename BasicJsonType::number_float_t; + + public: + /*! + @brief create a binary writer + + @param[in] adapter output adapter to write to + */ + explicit binary_writer(output_adapter_t adapter) : oa(std::move(adapter)) + { + JSON_ASSERT(oa); + } + + /*! + @param[in] j JSON value to serialize + @pre j.type() == value_t::object + */ + void write_bson(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::object: + { + write_bson_object(*j.m_value.object); + break; + } + + case value_t::null: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j)); + } + } + } + + /*! + @param[in] j JSON value to serialize + */ + void write_cbor(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::null: + { + oa->write_character(to_char_type(0xF6)); + break; + } + + case value_t::boolean: + { + oa->write_character(j.m_value.boolean + ? to_char_type(0xF5) + : to_char_type(0xF4)); + break; + } + + case value_t::number_integer: + { + if (j.m_value.number_integer >= 0) + { + // CBOR does not differentiate between positive signed + // integers and unsigned integers. Therefore, we used the + // code from the value_t::number_unsigned case here. + if (j.m_value.number_integer <= 0x17) + { + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x18)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x19)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x1A)); + write_number(static_cast(j.m_value.number_integer)); + } + else + { + oa->write_character(to_char_type(0x1B)); + write_number(static_cast(j.m_value.number_integer)); + } + } + else + { + // The conversions below encode the sign in the first + // byte, and the value is converted to a positive number. + const auto positive_number = -1 - j.m_value.number_integer; + if (j.m_value.number_integer >= -24) + { + write_number(static_cast(0x20 + positive_number)); + } + else if (positive_number <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x38)); + write_number(static_cast(positive_number)); + } + else if (positive_number <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x39)); + write_number(static_cast(positive_number)); + } + else if (positive_number <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x3A)); + write_number(static_cast(positive_number)); + } + else + { + oa->write_character(to_char_type(0x3B)); + write_number(static_cast(positive_number)); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned <= 0x17) + { + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x18)); + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x19)); + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x1A)); + write_number(static_cast(j.m_value.number_unsigned)); + } + else + { + oa->write_character(to_char_type(0x1B)); + write_number(static_cast(j.m_value.number_unsigned)); + } + break; + } + + case value_t::number_float: + { + if (std::isnan(j.m_value.number_float)) + { + // NaN is 0xf97e00 in CBOR + oa->write_character(to_char_type(0xF9)); + oa->write_character(to_char_type(0x7E)); + oa->write_character(to_char_type(0x00)); + } + else if (std::isinf(j.m_value.number_float)) + { + // Infinity is 0xf97c00, -Infinity is 0xf9fc00 + oa->write_character(to_char_type(0xf9)); + oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); + oa->write_character(to_char_type(0x00)); + } + else + { + write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); + } + break; + } + + case value_t::string: + { + // step 1: write control byte and the string length + const auto N = j.m_value.string->size(); + if (N <= 0x17) + { + write_number(static_cast(0x60 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x78)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x79)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x7A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x7B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write the string + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + // step 1: write control byte and the array size + const auto N = j.m_value.array->size(); + if (N <= 0x17) + { + write_number(static_cast(0x80 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x98)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x99)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x9A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x9B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto& el : *j.m_value.array) + { + write_cbor(el); + } + break; + } + + case value_t::binary: + { + if (j.m_value.binary->has_subtype()) + { + if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xd8)); + write_number(static_cast(j.m_value.binary->subtype())); + } + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xd9)); + write_number(static_cast(j.m_value.binary->subtype())); + } + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xda)); + write_number(static_cast(j.m_value.binary->subtype())); + } + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xdb)); + write_number(static_cast(j.m_value.binary->subtype())); + } + } + + // step 1: write control byte and the binary array size + const auto N = j.m_value.binary->size(); + if (N <= 0x17) + { + write_number(static_cast(0x40 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x58)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x59)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x5A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x5B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + N); + + break; + } + + case value_t::object: + { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 0x17) + { + write_number(static_cast(0xA0 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xB8)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xB9)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xBA)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xBB)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto& el : *j.m_value.object) + { + write_cbor(el.first); + write_cbor(el.second); + } + break; + } + + case value_t::discarded: + default: + break; + } + } + + /*! + @param[in] j JSON value to serialize + */ + void write_msgpack(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::null: // nil + { + oa->write_character(to_char_type(0xC0)); + break; + } + + case value_t::boolean: // true and false + { + oa->write_character(j.m_value.boolean + ? to_char_type(0xC3) + : to_char_type(0xC2)); + break; + } + + case value_t::number_integer: + { + if (j.m_value.number_integer >= 0) + { + // MessagePack does not differentiate between positive + // signed integers and unsigned integers. Therefore, we used + // the code from the value_t::number_unsigned case here. + if (j.m_value.number_unsigned < 128) + { + // positive fixnum + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 8 + oa->write_character(to_char_type(0xCC)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 16 + oa->write_character(to_char_type(0xCD)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 32 + oa->write_character(to_char_type(0xCE)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 64 + oa->write_character(to_char_type(0xCF)); + write_number(static_cast(j.m_value.number_integer)); + } + } + else + { + if (j.m_value.number_integer >= -32) + { + // negative fixnum + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 8 + oa->write_character(to_char_type(0xD0)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 16 + oa->write_character(to_char_type(0xD1)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 32 + oa->write_character(to_char_type(0xD2)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 64 + oa->write_character(to_char_type(0xD3)); + write_number(static_cast(j.m_value.number_integer)); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned < 128) + { + // positive fixnum + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 8 + oa->write_character(to_char_type(0xCC)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 16 + oa->write_character(to_char_type(0xCD)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 32 + oa->write_character(to_char_type(0xCE)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 64 + oa->write_character(to_char_type(0xCF)); + write_number(static_cast(j.m_value.number_integer)); + } + break; + } + + case value_t::number_float: + { + write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); + break; + } + + case value_t::string: + { + // step 1: write control byte and the string length + const auto N = j.m_value.string->size(); + if (N <= 31) + { + // fixstr + write_number(static_cast(0xA0 | N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // str 8 + oa->write_character(to_char_type(0xD9)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // str 16 + oa->write_character(to_char_type(0xDA)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // str 32 + oa->write_character(to_char_type(0xDB)); + write_number(static_cast(N)); + } + + // step 2: write the string + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + // step 1: write control byte and the array size + const auto N = j.m_value.array->size(); + if (N <= 15) + { + // fixarray + write_number(static_cast(0x90 | N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // array 16 + oa->write_character(to_char_type(0xDC)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // array 32 + oa->write_character(to_char_type(0xDD)); + write_number(static_cast(N)); + } + + // step 2: write each element + for (const auto& el : *j.m_value.array) + { + write_msgpack(el); + } + break; + } + + case value_t::binary: + { + // step 0: determine if the binary type has a set subtype to + // determine whether or not to use the ext or fixext types + const bool use_ext = j.m_value.binary->has_subtype(); + + // step 1: write control byte and the byte string length + const auto N = j.m_value.binary->size(); + if (N <= (std::numeric_limits::max)()) + { + std::uint8_t output_type{}; + bool fixed = true; + if (use_ext) + { + switch (N) + { + case 1: + output_type = 0xD4; // fixext 1 + break; + case 2: + output_type = 0xD5; // fixext 2 + break; + case 4: + output_type = 0xD6; // fixext 4 + break; + case 8: + output_type = 0xD7; // fixext 8 + break; + case 16: + output_type = 0xD8; // fixext 16 + break; + default: + output_type = 0xC7; // ext 8 + fixed = false; + break; + } + + } + else + { + output_type = 0xC4; // bin 8 + fixed = false; + } + + oa->write_character(to_char_type(output_type)); + if (!fixed) + { + write_number(static_cast(N)); + } + } + else if (N <= (std::numeric_limits::max)()) + { + std::uint8_t output_type = use_ext + ? 0xC8 // ext 16 + : 0xC5; // bin 16 + + oa->write_character(to_char_type(output_type)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + std::uint8_t output_type = use_ext + ? 0xC9 // ext 32 + : 0xC6; // bin 32 + + oa->write_character(to_char_type(output_type)); + write_number(static_cast(N)); + } + + // step 1.5: if this is an ext type, write the subtype + if (use_ext) + { + write_number(static_cast(j.m_value.binary->subtype())); + } + + // step 2: write the byte string + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + N); + + break; + } + + case value_t::object: + { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 15) + { + // fixmap + write_number(static_cast(0x80 | (N & 0xF))); + } + else if (N <= (std::numeric_limits::max)()) + { + // map 16 + oa->write_character(to_char_type(0xDE)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // map 32 + oa->write_character(to_char_type(0xDF)); + write_number(static_cast(N)); + } + + // step 2: write each element + for (const auto& el : *j.m_value.object) + { + write_msgpack(el.first); + write_msgpack(el.second); + } + break; + } + + case value_t::discarded: + default: + break; + } + } + + /*! + @param[in] j JSON value to serialize + @param[in] use_count whether to use '#' prefixes (optimized format) + @param[in] use_type whether to use '$' prefixes (optimized format) + @param[in] add_prefix whether prefixes need to be used for this value + */ + void write_ubjson(const BasicJsonType& j, const bool use_count, + const bool use_type, const bool add_prefix = true) + { + switch (j.type()) + { + case value_t::null: + { + if (add_prefix) + { + oa->write_character(to_char_type('Z')); + } + break; + } + + case value_t::boolean: + { + if (add_prefix) + { + oa->write_character(j.m_value.boolean + ? to_char_type('T') + : to_char_type('F')); + } + break; + } + + case value_t::number_integer: + { + write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); + break; + } + + case value_t::number_unsigned: + { + write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); + break; + } + + case value_t::number_float: + { + write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); + break; + } + + case value_t::string: + { + if (add_prefix) + { + oa->write_character(to_char_type('S')); + } + write_number_with_ubjson_prefix(j.m_value.string->size(), true); + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + if (add_prefix) + { + oa->write_character(to_char_type('[')); + } + + bool prefix_required = true; + if (use_type && !j.m_value.array->empty()) + { + JSON_ASSERT(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin() + 1, j.end(), + [this, first_prefix](const BasicJsonType & v) + { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) + { + prefix_required = false; + oa->write_character(to_char_type('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) + { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.array->size(), true); + } + + for (const auto& el : *j.m_value.array) + { + write_ubjson(el, use_count, use_type, prefix_required); + } + + if (!use_count) + { + oa->write_character(to_char_type(']')); + } + + break; + } + + case value_t::binary: + { + if (add_prefix) + { + oa->write_character(to_char_type('[')); + } + + if (use_type && !j.m_value.binary->empty()) + { + JSON_ASSERT(use_count); + oa->write_character(to_char_type('$')); + oa->write_character('U'); + } + + if (use_count) + { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.binary->size(), true); + } + + if (use_type) + { + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + j.m_value.binary->size()); + } + else + { + for (size_t i = 0; i < j.m_value.binary->size(); ++i) + { + oa->write_character(to_char_type('U')); + oa->write_character(j.m_value.binary->data()[i]); + } + } + + if (!use_count) + { + oa->write_character(to_char_type(']')); + } + + break; + } + + case value_t::object: + { + if (add_prefix) + { + oa->write_character(to_char_type('{')); + } + + bool prefix_required = true; + if (use_type && !j.m_value.object->empty()) + { + JSON_ASSERT(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin(), j.end(), + [this, first_prefix](const BasicJsonType & v) + { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) + { + prefix_required = false; + oa->write_character(to_char_type('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) + { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.object->size(), true); + } + + for (const auto& el : *j.m_value.object) + { + write_number_with_ubjson_prefix(el.first.size(), true); + oa->write_characters( + reinterpret_cast(el.first.c_str()), + el.first.size()); + write_ubjson(el.second, use_count, use_type, prefix_required); + } + + if (!use_count) + { + oa->write_character(to_char_type('}')); + } + + break; + } + + case value_t::discarded: + default: + break; + } + } + + private: + ////////// + // BSON // + ////////// + + /*! + @return The size of a BSON document entry header, including the id marker + and the entry name size (and its null-terminator). + */ + static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) + { + const auto it = name.find(static_cast(0)); + if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) + { + JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j)); + static_cast(j); + } + + return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; + } + + /*! + @brief Writes the given @a element_type and @a name to the output adapter + */ + void write_bson_entry_header(const string_t& name, + const std::uint8_t element_type) + { + oa->write_character(to_char_type(element_type)); // boolean + oa->write_characters( + reinterpret_cast(name.c_str()), + name.size() + 1u); + } + + /*! + @brief Writes a BSON element with key @a name and boolean value @a value + */ + void write_bson_boolean(const string_t& name, + const bool value) + { + write_bson_entry_header(name, 0x08); + oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); + } + + /*! + @brief Writes a BSON element with key @a name and double value @a value + */ + void write_bson_double(const string_t& name, + const double value) + { + write_bson_entry_header(name, 0x01); + write_number(value); + } + + /*! + @return The size of the BSON-encoded string in @a value + */ + static std::size_t calc_bson_string_size(const string_t& value) + { + return sizeof(std::int32_t) + value.size() + 1ul; + } + + /*! + @brief Writes a BSON element with key @a name and string value @a value + */ + void write_bson_string(const string_t& name, + const string_t& value) + { + write_bson_entry_header(name, 0x02); + + write_number(static_cast(value.size() + 1ul)); + oa->write_characters( + reinterpret_cast(value.c_str()), + value.size() + 1); + } + + /*! + @brief Writes a BSON element with key @a name and null value + */ + void write_bson_null(const string_t& name) + { + write_bson_entry_header(name, 0x0A); + } + + /*! + @return The size of the BSON-encoded integer @a value + */ + static std::size_t calc_bson_integer_size(const std::int64_t value) + { + return (std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)() + ? sizeof(std::int32_t) + : sizeof(std::int64_t); + } + + /*! + @brief Writes a BSON element with key @a name and integer @a value + */ + void write_bson_integer(const string_t& name, + const std::int64_t value) + { + if ((std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)()) + { + write_bson_entry_header(name, 0x10); // int32 + write_number(static_cast(value)); + } + else + { + write_bson_entry_header(name, 0x12); // int64 + write_number(static_cast(value)); + } + } + + /*! + @return The size of the BSON-encoded unsigned integer in @a j + */ + static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept + { + return (value <= static_cast((std::numeric_limits::max)())) + ? sizeof(std::int32_t) + : sizeof(std::int64_t); + } + + /*! + @brief Writes a BSON element with key @a name and unsigned @a value + */ + void write_bson_unsigned(const string_t& name, + const BasicJsonType& j) + { + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + write_bson_entry_header(name, 0x10 /* int32 */); + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + write_bson_entry_header(name, 0x12 /* int64 */); + write_number(static_cast(j.m_value.number_unsigned)); + } + else + { + JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j)); + } + } + + /*! + @brief Writes a BSON element with key @a name and object @a value + */ + void write_bson_object_entry(const string_t& name, + const typename BasicJsonType::object_t& value) + { + write_bson_entry_header(name, 0x03); // object + write_bson_object(value); + } + + /*! + @return The size of the BSON-encoded array @a value + */ + static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) + { + std::size_t array_index = 0ul; + + const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) + { + return result + calc_bson_element_size(std::to_string(array_index++), el); + }); + + return sizeof(std::int32_t) + embedded_document_size + 1ul; + } + + /*! + @return The size of the BSON-encoded binary array @a value + */ + static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) + { + return sizeof(std::int32_t) + value.size() + 1ul; + } + + /*! + @brief Writes a BSON element with key @a name and array @a value + */ + void write_bson_array(const string_t& name, + const typename BasicJsonType::array_t& value) + { + write_bson_entry_header(name, 0x04); // array + write_number(static_cast(calc_bson_array_size(value))); + + std::size_t array_index = 0ul; + + for (const auto& el : value) + { + write_bson_element(std::to_string(array_index++), el); + } + + oa->write_character(to_char_type(0x00)); + } + + /*! + @brief Writes a BSON element with key @a name and binary value @a value + */ + void write_bson_binary(const string_t& name, + const binary_t& value) + { + write_bson_entry_header(name, 0x05); + + write_number(static_cast(value.size())); + write_number(value.has_subtype() ? static_cast(value.subtype()) : static_cast(0x00)); + + oa->write_characters(reinterpret_cast(value.data()), value.size()); + } + + /*! + @brief Calculates the size necessary to serialize the JSON value @a j with its @a name + @return The calculated size for the BSON document entry for @a j with the given @a name. + */ + static std::size_t calc_bson_element_size(const string_t& name, + const BasicJsonType& j) + { + const auto header_size = calc_bson_entry_header_size(name, j); + switch (j.type()) + { + case value_t::object: + return header_size + calc_bson_object_size(*j.m_value.object); + + case value_t::array: + return header_size + calc_bson_array_size(*j.m_value.array); + + case value_t::binary: + return header_size + calc_bson_binary_size(*j.m_value.binary); + + case value_t::boolean: + return header_size + 1ul; + + case value_t::number_float: + return header_size + 8ul; + + case value_t::number_integer: + return header_size + calc_bson_integer_size(j.m_value.number_integer); + + case value_t::number_unsigned: + return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); + + case value_t::string: + return header_size + calc_bson_string_size(*j.m_value.string); + + case value_t::null: + return header_size + 0ul; + + // LCOV_EXCL_START + case value_t::discarded: + default: + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + return 0ul; + // LCOV_EXCL_STOP + } + } + + /*! + @brief Serializes the JSON value @a j to BSON and associates it with the + key @a name. + @param name The name to associate with the JSON entity @a j within the + current BSON document + */ + void write_bson_element(const string_t& name, + const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::object: + return write_bson_object_entry(name, *j.m_value.object); + + case value_t::array: + return write_bson_array(name, *j.m_value.array); + + case value_t::binary: + return write_bson_binary(name, *j.m_value.binary); + + case value_t::boolean: + return write_bson_boolean(name, j.m_value.boolean); + + case value_t::number_float: + return write_bson_double(name, j.m_value.number_float); + + case value_t::number_integer: + return write_bson_integer(name, j.m_value.number_integer); + + case value_t::number_unsigned: + return write_bson_unsigned(name, j); + + case value_t::string: + return write_bson_string(name, *j.m_value.string); + + case value_t::null: + return write_bson_null(name); + + // LCOV_EXCL_START + case value_t::discarded: + default: + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + return; + // LCOV_EXCL_STOP + } + } + + /*! + @brief Calculates the size of the BSON serialization of the given + JSON-object @a j. + @param[in] value JSON value to serialize + @pre value.type() == value_t::object + */ + static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) + { + std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast(0), + [](size_t result, const typename BasicJsonType::object_t::value_type & el) + { + return result += calc_bson_element_size(el.first, el.second); + }); + + return sizeof(std::int32_t) + document_size + 1ul; + } + + /*! + @param[in] value JSON value to serialize + @pre value.type() == value_t::object + */ + void write_bson_object(const typename BasicJsonType::object_t& value) + { + write_number(static_cast(calc_bson_object_size(value))); + + for (const auto& el : value) + { + write_bson_element(el.first, el.second); + } + + oa->write_character(to_char_type(0x00)); + } + + ////////// + // CBOR // + ////////// + + static constexpr CharType get_cbor_float_prefix(float /*unused*/) + { + return to_char_type(0xFA); // Single-Precision Float + } + + static constexpr CharType get_cbor_float_prefix(double /*unused*/) + { + return to_char_type(0xFB); // Double-Precision Float + } + + ///////////// + // MsgPack // + ///////////// + + static constexpr CharType get_msgpack_float_prefix(float /*unused*/) + { + return to_char_type(0xCA); // float 32 + } + + static constexpr CharType get_msgpack_float_prefix(double /*unused*/) + { + return to_char_type(0xCB); // float 64 + } + + //////////// + // UBJSON // + //////////// + + // UBJSON: write number (floating point) + template::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if (add_prefix) + { + oa->write_character(get_ubjson_float_prefix(n)); + } + write_number(n); + } + + // UBJSON: write number (unsigned integer) + template::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('i')); // int8 + } + write_number(static_cast(n)); + } + else if (n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('U')); // uint8 + } + write_number(static_cast(n)); + } + else if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('I')); // int16 + } + write_number(static_cast(n)); + } + else if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('l')); // int32 + } + write_number(static_cast(n)); + } + else if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('L')); // int64 + } + write_number(static_cast(n)); + } + else + { + if (add_prefix) + { + oa->write_character(to_char_type('H')); // high-precision number + } + + const auto number = BasicJsonType(n).dump(); + write_number_with_ubjson_prefix(number.size(), true); + for (std::size_t i = 0; i < number.size(); ++i) + { + oa->write_character(to_char_type(static_cast(number[i]))); + } + } + } + + // UBJSON: write number (signed integer) + template < typename NumberType, typename std::enable_if < + std::is_signed::value&& + !std::is_floating_point::value, int >::type = 0 > + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('i')); // int8 + } + write_number(static_cast(n)); + } + else if (static_cast((std::numeric_limits::min)()) <= n && n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('U')); // uint8 + } + write_number(static_cast(n)); + } + else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('I')); // int16 + } + write_number(static_cast(n)); + } + else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('l')); // int32 + } + write_number(static_cast(n)); + } + else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('L')); // int64 + } + write_number(static_cast(n)); + } + // LCOV_EXCL_START + else + { + if (add_prefix) + { + oa->write_character(to_char_type('H')); // high-precision number + } + + const auto number = BasicJsonType(n).dump(); + write_number_with_ubjson_prefix(number.size(), true); + for (std::size_t i = 0; i < number.size(); ++i) + { + oa->write_character(to_char_type(static_cast(number[i]))); + } + } + // LCOV_EXCL_STOP + } + + /*! + @brief determine the type prefix of container values + */ + CharType ubjson_prefix(const BasicJsonType& j) const noexcept + { + switch (j.type()) + { + case value_t::null: + return 'Z'; + + case value_t::boolean: + return j.m_value.boolean ? 'T' : 'F'; + + case value_t::number_integer: + { + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'i'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'U'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'I'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'l'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'L'; + } + // anything else is treated as high-precision number + return 'H'; // LCOV_EXCL_LINE + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'i'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'U'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'I'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'l'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'L'; + } + // anything else is treated as high-precision number + return 'H'; // LCOV_EXCL_LINE + } + + case value_t::number_float: + return get_ubjson_float_prefix(j.m_value.number_float); + + case value_t::string: + return 'S'; + + case value_t::array: // fallthrough + case value_t::binary: + return '['; + + case value_t::object: + return '{'; + + case value_t::discarded: + default: // discarded values + return 'N'; + } + } + + static constexpr CharType get_ubjson_float_prefix(float /*unused*/) + { + return 'd'; // float 32 + } + + static constexpr CharType get_ubjson_float_prefix(double /*unused*/) + { + return 'D'; // float 64 + } + + /////////////////////// + // Utility functions // + /////////////////////// + + /* + @brief write a number to output input + @param[in] n number of type @a NumberType + @tparam NumberType the type of the number + @tparam OutputIsLittleEndian Set to true if output data is + required to be little endian + + @note This function needs to respect the system's endianness, because bytes + in CBOR, MessagePack, and UBJSON are stored in network order (big + endian) and therefore need reordering on little endian systems. + */ + template + void write_number(const NumberType n) + { + // step 1: write number to array of length NumberType + std::array vec{}; + std::memcpy(vec.data(), &n, sizeof(NumberType)); + + // step 2: write array to output (with possible reordering) + if (is_little_endian != OutputIsLittleEndian) + { + // reverse byte order prior to conversion if necessary + std::reverse(vec.begin(), vec.end()); + } + + oa->write_characters(vec.data(), sizeof(NumberType)); + } + + void write_compact_float(const number_float_t n, detail::input_format_t format) + { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && + static_cast(n) <= static_cast((std::numeric_limits::max)()) && + static_cast(static_cast(n)) == static_cast(n)) + { + oa->write_character(format == detail::input_format_t::cbor + ? get_cbor_float_prefix(static_cast(n)) + : get_msgpack_float_prefix(static_cast(n))); + write_number(static_cast(n)); + } + else + { + oa->write_character(format == detail::input_format_t::cbor + ? get_cbor_float_prefix(n) + : get_msgpack_float_prefix(n)); + write_number(n); + } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + } + + public: + // The following to_char_type functions are implement the conversion + // between uint8_t and CharType. In case CharType is not unsigned, + // such a conversion is required to allow values greater than 128. + // See for a discussion. + template < typename C = CharType, + enable_if_t < std::is_signed::value && std::is_signed::value > * = nullptr > + static constexpr CharType to_char_type(std::uint8_t x) noexcept + { + return *reinterpret_cast(&x); + } + + template < typename C = CharType, + enable_if_t < std::is_signed::value && std::is_unsigned::value > * = nullptr > + static CharType to_char_type(std::uint8_t x) noexcept + { + static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); + static_assert(std::is_trivial::value, "CharType must be trivial"); + CharType result; + std::memcpy(&result, &x, sizeof(x)); + return result; + } + + template::value>* = nullptr> + static constexpr CharType to_char_type(std::uint8_t x) noexcept + { + return x; + } + + template < typename InputCharType, typename C = CharType, + enable_if_t < + std::is_signed::value && + std::is_signed::value && + std::is_same::type>::value + > * = nullptr > + static constexpr CharType to_char_type(InputCharType x) noexcept + { + return x; + } + + private: + /// whether we can assume little endianness + const bool is_little_endian = little_endianness(); + + /// the output + output_adapter_t oa = nullptr; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // reverse, remove, fill, find, none_of +#include // array +#include // localeconv, lconv +#include // labs, isfinite, isnan, signbit +#include // size_t, ptrdiff_t +#include // uint8_t +#include // snprintf +#include // numeric_limits +#include // string, char_traits +#include // setfill, setw +#include // is_same +#include // move + +// #include + + +#include // array +#include // signbit, isfinite +#include // intN_t, uintN_t +#include // memcpy, memmove +#include // numeric_limits +#include // conditional + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +/*! +@brief implements the Grisu2 algorithm for binary to decimal floating-point +conversion. + +This implementation is a slightly modified version of the reference +implementation which may be obtained from +http://florian.loitsch.com/publications (bench.tar.gz). + +The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. + +For a detailed description of the algorithm see: + +[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with + Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming + Language Design and Implementation, PLDI 2010 +[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", + Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language + Design and Implementation, PLDI 1996 +*/ +namespace dtoa_impl +{ + +template +Target reinterpret_bits(const Source source) +{ + static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); + + Target target; + std::memcpy(&target, &source, sizeof(Source)); + return target; +} + +struct diyfp // f * 2^e +{ + static constexpr int kPrecision = 64; // = q + + std::uint64_t f = 0; + int e = 0; + + constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} + + /*! + @brief returns x - y + @pre x.e == y.e and x.f >= y.f + */ + static diyfp sub(const diyfp& x, const diyfp& y) noexcept + { + JSON_ASSERT(x.e == y.e); + JSON_ASSERT(x.f >= y.f); + + return {x.f - y.f, x.e}; + } + + /*! + @brief returns x * y + @note The result is rounded. (Only the upper q bits are returned.) + */ + static diyfp mul(const diyfp& x, const diyfp& y) noexcept + { + static_assert(kPrecision == 64, "internal error"); + + // Computes: + // f = round((x.f * y.f) / 2^q) + // e = x.e + y.e + q + + // Emulate the 64-bit * 64-bit multiplication: + // + // p = u * v + // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) + // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) + // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) + // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) + // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) + // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) + // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) + // + // (Since Q might be larger than 2^32 - 1) + // + // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) + // + // (Q_hi + H does not overflow a 64-bit int) + // + // = p_lo + 2^64 p_hi + + const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; + const std::uint64_t u_hi = x.f >> 32u; + const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; + const std::uint64_t v_hi = y.f >> 32u; + + const std::uint64_t p0 = u_lo * v_lo; + const std::uint64_t p1 = u_lo * v_hi; + const std::uint64_t p2 = u_hi * v_lo; + const std::uint64_t p3 = u_hi * v_hi; + + const std::uint64_t p0_hi = p0 >> 32u; + const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; + const std::uint64_t p1_hi = p1 >> 32u; + const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; + const std::uint64_t p2_hi = p2 >> 32u; + + std::uint64_t Q = p0_hi + p1_lo + p2_lo; + + // The full product might now be computed as + // + // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) + // p_lo = p0_lo + (Q << 32) + // + // But in this particular case here, the full p_lo is not required. + // Effectively we only need to add the highest bit in p_lo to p_hi (and + // Q_hi + 1 does not overflow). + + Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up + + const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); + + return {h, x.e + y.e + 64}; + } + + /*! + @brief normalize x such that the significand is >= 2^(q-1) + @pre x.f != 0 + */ + static diyfp normalize(diyfp x) noexcept + { + JSON_ASSERT(x.f != 0); + + while ((x.f >> 63u) == 0) + { + x.f <<= 1u; + x.e--; + } + + return x; + } + + /*! + @brief normalize x such that the result has the exponent E + @pre e >= x.e and the upper e - x.e bits of x.f must be zero. + */ + static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept + { + const int delta = x.e - target_exponent; + + JSON_ASSERT(delta >= 0); + JSON_ASSERT(((x.f << delta) >> delta) == x.f); + + return {x.f << delta, target_exponent}; + } +}; + +struct boundaries +{ + diyfp w; + diyfp minus; + diyfp plus; +}; + +/*! +Compute the (normalized) diyfp representing the input number 'value' and its +boundaries. + +@pre value must be finite and positive +*/ +template +boundaries compute_boundaries(FloatType value) +{ + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); + + // Convert the IEEE representation into a diyfp. + // + // If v is denormal: + // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) + // If v is normalized: + // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) + + static_assert(std::numeric_limits::is_iec559, + "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + + constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) + constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); + constexpr int kMinExp = 1 - kBias; + constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) + + using bits_type = typename std::conditional::type; + + const auto bits = static_cast(reinterpret_bits(value)); + const std::uint64_t E = bits >> (kPrecision - 1); + const std::uint64_t F = bits & (kHiddenBit - 1); + + const bool is_denormal = E == 0; + const diyfp v = is_denormal + ? diyfp(F, kMinExp) + : diyfp(F + kHiddenBit, static_cast(E) - kBias); + + // Compute the boundaries m- and m+ of the floating-point value + // v = f * 2^e. + // + // Determine v- and v+, the floating-point predecessor and successor if v, + // respectively. + // + // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) + // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // + // v+ = v + 2^e + // + // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ + // between m- and m+ round to v, regardless of how the input rounding + // algorithm breaks ties. + // + // ---+-------------+-------------+-------------+-------------+--- (A) + // v- m- v m+ v+ + // + // -----------------+------+------+-------------+-------------+--- (B) + // v- m- v m+ v+ + + const bool lower_boundary_is_closer = F == 0 && E > 1; + const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_minus = lower_boundary_is_closer + ? diyfp(4 * v.f - 1, v.e - 2) // (B) + : diyfp(2 * v.f - 1, v.e - 1); // (A) + + // Determine the normalized w+ = m+. + const diyfp w_plus = diyfp::normalize(m_plus); + + // Determine w- = m- such that e_(w-) = e_(w+). + const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); + + return {diyfp::normalize(v), w_minus, w_plus}; +} + +// Given normalized diyfp w, Grisu needs to find a (normalized) cached +// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies +// within a certain range [alpha, gamma] (Definition 3.2 from [1]) +// +// alpha <= e = e_c + e_w + q <= gamma +// +// or +// +// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q +// <= f_c * f_w * 2^gamma +// +// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies +// +// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma +// +// or +// +// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) +// +// The choice of (alpha,gamma) determines the size of the table and the form of +// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well +// in practice: +// +// The idea is to cut the number c * w = f * 2^e into two parts, which can be +// processed independently: An integral part p1, and a fractional part p2: +// +// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e +// = (f div 2^-e) + (f mod 2^-e) * 2^e +// = p1 + p2 * 2^e +// +// The conversion of p1 into decimal form requires a series of divisions and +// modulos by (a power of) 10. These operations are faster for 32-bit than for +// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be +// achieved by choosing +// +// -e >= 32 or e <= -32 := gamma +// +// In order to convert the fractional part +// +// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... +// +// into decimal form, the fraction is repeatedly multiplied by 10 and the digits +// d[-i] are extracted in order: +// +// (10 * p2) div 2^-e = d[-1] +// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... +// +// The multiplication by 10 must not overflow. It is sufficient to choose +// +// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. +// +// Since p2 = f mod 2^-e < 2^-e, +// +// -e <= 60 or e >= -60 := alpha + +constexpr int kAlpha = -60; +constexpr int kGamma = -32; + +struct cached_power // c = f * 2^e ~= 10^k +{ + std::uint64_t f; + int e; + int k; +}; + +/*! +For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached +power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c +satisfies (Definition 3.2 from [1]) + + alpha <= e_c + e + q <= gamma. +*/ +inline cached_power get_cached_power_for_binary_exponent(int e) +{ + // Now + // + // alpha <= e_c + e + q <= gamma (1) + // ==> f_c * 2^alpha <= c * 2^e * 2^q + // + // and since the c's are normalized, 2^(q-1) <= f_c, + // + // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) + // ==> 2^(alpha - e - 1) <= c + // + // If c were an exact power of ten, i.e. c = 10^k, one may determine k as + // + // k = ceil( log_10( 2^(alpha - e - 1) ) ) + // = ceil( (alpha - e - 1) * log_10(2) ) + // + // From the paper: + // "In theory the result of the procedure could be wrong since c is rounded, + // and the computation itself is approximated [...]. In practice, however, + // this simple function is sufficient." + // + // For IEEE double precision floating-point numbers converted into + // normalized diyfp's w = f * 2^e, with q = 64, + // + // e >= -1022 (min IEEE exponent) + // -52 (p - 1) + // -52 (p - 1, possibly normalize denormal IEEE numbers) + // -11 (normalize the diyfp) + // = -1137 + // + // and + // + // e <= +1023 (max IEEE exponent) + // -52 (p - 1) + // -11 (normalize the diyfp) + // = 960 + // + // This binary exponent range [-1137,960] results in a decimal exponent + // range [-307,324]. One does not need to store a cached power for each + // k in this range. For each such k it suffices to find a cached power + // such that the exponent of the product lies in [alpha,gamma]. + // This implies that the difference of the decimal exponents of adjacent + // table entries must be less than or equal to + // + // floor( (gamma - alpha) * log_10(2) ) = 8. + // + // (A smaller distance gamma-alpha would require a larger table.) + + // NB: + // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. + + constexpr int kCachedPowersMinDecExp = -300; + constexpr int kCachedPowersDecStep = 8; + + static constexpr std::array kCachedPowers = + { + { + { 0xAB70FE17C79AC6CA, -1060, -300 }, + { 0xFF77B1FCBEBCDC4F, -1034, -292 }, + { 0xBE5691EF416BD60C, -1007, -284 }, + { 0x8DD01FAD907FFC3C, -980, -276 }, + { 0xD3515C2831559A83, -954, -268 }, + { 0x9D71AC8FADA6C9B5, -927, -260 }, + { 0xEA9C227723EE8BCB, -901, -252 }, + { 0xAECC49914078536D, -874, -244 }, + { 0x823C12795DB6CE57, -847, -236 }, + { 0xC21094364DFB5637, -821, -228 }, + { 0x9096EA6F3848984F, -794, -220 }, + { 0xD77485CB25823AC7, -768, -212 }, + { 0xA086CFCD97BF97F4, -741, -204 }, + { 0xEF340A98172AACE5, -715, -196 }, + { 0xB23867FB2A35B28E, -688, -188 }, + { 0x84C8D4DFD2C63F3B, -661, -180 }, + { 0xC5DD44271AD3CDBA, -635, -172 }, + { 0x936B9FCEBB25C996, -608, -164 }, + { 0xDBAC6C247D62A584, -582, -156 }, + { 0xA3AB66580D5FDAF6, -555, -148 }, + { 0xF3E2F893DEC3F126, -529, -140 }, + { 0xB5B5ADA8AAFF80B8, -502, -132 }, + { 0x87625F056C7C4A8B, -475, -124 }, + { 0xC9BCFF6034C13053, -449, -116 }, + { 0x964E858C91BA2655, -422, -108 }, + { 0xDFF9772470297EBD, -396, -100 }, + { 0xA6DFBD9FB8E5B88F, -369, -92 }, + { 0xF8A95FCF88747D94, -343, -84 }, + { 0xB94470938FA89BCF, -316, -76 }, + { 0x8A08F0F8BF0F156B, -289, -68 }, + { 0xCDB02555653131B6, -263, -60 }, + { 0x993FE2C6D07B7FAC, -236, -52 }, + { 0xE45C10C42A2B3B06, -210, -44 }, + { 0xAA242499697392D3, -183, -36 }, + { 0xFD87B5F28300CA0E, -157, -28 }, + { 0xBCE5086492111AEB, -130, -20 }, + { 0x8CBCCC096F5088CC, -103, -12 }, + { 0xD1B71758E219652C, -77, -4 }, + { 0x9C40000000000000, -50, 4 }, + { 0xE8D4A51000000000, -24, 12 }, + { 0xAD78EBC5AC620000, 3, 20 }, + { 0x813F3978F8940984, 30, 28 }, + { 0xC097CE7BC90715B3, 56, 36 }, + { 0x8F7E32CE7BEA5C70, 83, 44 }, + { 0xD5D238A4ABE98068, 109, 52 }, + { 0x9F4F2726179A2245, 136, 60 }, + { 0xED63A231D4C4FB27, 162, 68 }, + { 0xB0DE65388CC8ADA8, 189, 76 }, + { 0x83C7088E1AAB65DB, 216, 84 }, + { 0xC45D1DF942711D9A, 242, 92 }, + { 0x924D692CA61BE758, 269, 100 }, + { 0xDA01EE641A708DEA, 295, 108 }, + { 0xA26DA3999AEF774A, 322, 116 }, + { 0xF209787BB47D6B85, 348, 124 }, + { 0xB454E4A179DD1877, 375, 132 }, + { 0x865B86925B9BC5C2, 402, 140 }, + { 0xC83553C5C8965D3D, 428, 148 }, + { 0x952AB45CFA97A0B3, 455, 156 }, + { 0xDE469FBD99A05FE3, 481, 164 }, + { 0xA59BC234DB398C25, 508, 172 }, + { 0xF6C69A72A3989F5C, 534, 180 }, + { 0xB7DCBF5354E9BECE, 561, 188 }, + { 0x88FCF317F22241E2, 588, 196 }, + { 0xCC20CE9BD35C78A5, 614, 204 }, + { 0x98165AF37B2153DF, 641, 212 }, + { 0xE2A0B5DC971F303A, 667, 220 }, + { 0xA8D9D1535CE3B396, 694, 228 }, + { 0xFB9B7CD9A4A7443C, 720, 236 }, + { 0xBB764C4CA7A44410, 747, 244 }, + { 0x8BAB8EEFB6409C1A, 774, 252 }, + { 0xD01FEF10A657842C, 800, 260 }, + { 0x9B10A4E5E9913129, 827, 268 }, + { 0xE7109BFBA19C0C9D, 853, 276 }, + { 0xAC2820D9623BF429, 880, 284 }, + { 0x80444B5E7AA7CF85, 907, 292 }, + { 0xBF21E44003ACDD2D, 933, 300 }, + { 0x8E679C2F5E44FF8F, 960, 308 }, + { 0xD433179D9C8CB841, 986, 316 }, + { 0x9E19DB92B4E31BA9, 1013, 324 }, + } + }; + + // This computation gives exactly the same results for k as + // k = ceil((kAlpha - e - 1) * 0.30102999566398114) + // for |e| <= 1500, but doesn't require floating-point operations. + // NB: log_10(2) ~= 78913 / 2^18 + JSON_ASSERT(e >= -1500); + JSON_ASSERT(e <= 1500); + const int f = kAlpha - e - 1; + const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + + const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; + JSON_ASSERT(index >= 0); + JSON_ASSERT(static_cast(index) < kCachedPowers.size()); + + const cached_power cached = kCachedPowers[static_cast(index)]; + JSON_ASSERT(kAlpha <= cached.e + e + 64); + JSON_ASSERT(kGamma >= cached.e + e + 64); + + return cached; +} + +/*! +For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. +For n == 0, returns 1 and sets pow10 := 1. +*/ +inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) +{ + // LCOV_EXCL_START + if (n >= 1000000000) + { + pow10 = 1000000000; + return 10; + } + // LCOV_EXCL_STOP + if (n >= 100000000) + { + pow10 = 100000000; + return 9; + } + if (n >= 10000000) + { + pow10 = 10000000; + return 8; + } + if (n >= 1000000) + { + pow10 = 1000000; + return 7; + } + if (n >= 100000) + { + pow10 = 100000; + return 6; + } + if (n >= 10000) + { + pow10 = 10000; + return 5; + } + if (n >= 1000) + { + pow10 = 1000; + return 4; + } + if (n >= 100) + { + pow10 = 100; + return 3; + } + if (n >= 10) + { + pow10 = 10; + return 2; + } + + pow10 = 1; + return 1; +} + +inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, + std::uint64_t rest, std::uint64_t ten_k) +{ + JSON_ASSERT(len >= 1); + JSON_ASSERT(dist <= delta); + JSON_ASSERT(rest <= delta); + JSON_ASSERT(ten_k > 0); + + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // ten_k + // <------> + // <---- rest ----> + // --------------[------------------+----+--------------]-------------- + // w V + // = buf * 10^k + // + // ten_k represents a unit-in-the-last-place in the decimal representation + // stored in buf. + // Decrement buf by ten_k while this takes buf closer to w. + + // The tests are written in this order to avoid overflow in unsigned + // integer arithmetic. + + while (rest < dist + && delta - rest >= ten_k + && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) + { + JSON_ASSERT(buf[len - 1] != '0'); + buf[len - 1]--; + rest += ten_k; + } +} + +/*! +Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. +M- and M+ must be normalized and share the same exponent -60 <= e <= -32. +*/ +inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, + diyfp M_minus, diyfp w, diyfp M_plus) +{ + static_assert(kAlpha >= -60, "internal error"); + static_assert(kGamma <= -32, "internal error"); + + // Generates the digits (and the exponent) of a decimal floating-point + // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's + // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. + // + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // Grisu2 generates the digits of M+ from left to right and stops as soon as + // V is in [M-,M+]. + + JSON_ASSERT(M_plus.e >= kAlpha); + JSON_ASSERT(M_plus.e <= kGamma); + + std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) + std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) + + // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): + // + // M+ = f * 2^e + // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e + // = ((p1 ) * 2^-e + (p2 )) * 2^e + // = p1 + p2 * 2^e + + const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); + + auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) + std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e + + // 1) + // + // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] + + JSON_ASSERT(p1 > 0); + + std::uint32_t pow10{}; + const int k = find_largest_pow10(p1, pow10); + + // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) + // + // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) + // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) + // + // M+ = p1 + p2 * 2^e + // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e + // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e + // = d[k-1] * 10^(k-1) + ( rest) * 2^e + // + // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) + // + // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] + // + // but stop as soon as + // + // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e + + int n = k; + while (n > 0) + { + // Invariants: + // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) + // pow10 = 10^(n-1) <= p1 < 10^n + // + const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) + const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // + // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e + // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // + p1 = r; + n--; + // + // M+ = buffer * 10^n + (p1 + p2 * 2^e) + // pow10 = 10^n + // + + // Now check if enough digits have been generated. + // Compute + // + // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e + // + // Note: + // Since rest and delta share the same exponent e, it suffices to + // compare the significands. + const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; + if (rest <= delta) + { + // V = buffer * 10^n, with M- <= V <= M+. + + decimal_exponent += n; + + // We may now just stop. But instead look if the buffer could be + // decremented to bring V closer to w. + // + // pow10 = 10^n is now 1 ulp in the decimal representation V. + // The rounding procedure works with diyfp's with an implicit + // exponent of e. + // + // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // + const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; + grisu2_round(buffer, length, dist, delta, rest, ten_n); + + return; + } + + pow10 /= 10; + // + // pow10 = 10^(n-1) <= p1 < 10^n + // Invariants restored. + } + + // 2) + // + // The digits of the integral part have been generated: + // + // M+ = d[k-1]...d[1]d[0] + p2 * 2^e + // = buffer + p2 * 2^e + // + // Now generate the digits of the fractional part p2 * 2^e. + // + // Note: + // No decimal point is generated: the exponent is adjusted instead. + // + // p2 actually represents the fraction + // + // p2 * 2^e + // = p2 / 2^-e + // = d[-1] / 10^1 + d[-2] / 10^2 + ... + // + // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) + // + // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m + // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) + // + // using + // + // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) + // = ( d) * 2^-e + ( r) + // + // or + // 10^m * p2 * 2^e = d + r * 2^e + // + // i.e. + // + // M+ = buffer + p2 * 2^e + // = buffer + 10^-m * (d + r * 2^e) + // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e + // + // and stop as soon as 10^-m * r * 2^e <= delta * 2^e + + JSON_ASSERT(p2 > delta); + + int m = 0; + for (;;) + { + // Invariant: + // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e + // = buffer * 10^-m + 10^-m * (p2 ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e + // + JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); + p2 *= 10; + const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e + const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // + // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) + // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + p2 = r; + m++; + // + // M+ = buffer * 10^-m + 10^-m * p2 * 2^e + // Invariant restored. + + // Check if enough digits have been generated. + // + // 10^-m * p2 * 2^e <= delta * 2^e + // p2 * 2^e <= 10^m * delta * 2^e + // p2 <= 10^m * delta + delta *= 10; + dist *= 10; + if (p2 <= delta) + { + break; + } + } + + // V = buffer * 10^-m, with M- <= V <= M+. + + decimal_exponent -= m; + + // 1 ulp in the decimal representation is now 10^-m. + // Since delta and dist are now scaled by 10^m, we need to do the + // same with ulp in order to keep the units in sync. + // + // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e + // + const std::uint64_t ten_m = one.f; + grisu2_round(buffer, length, dist, delta, p2, ten_m); + + // By construction this algorithm generates the shortest possible decimal + // number (Loitsch, Theorem 6.2) which rounds back to w. + // For an input number of precision p, at least + // + // N = 1 + ceil(p * log_10(2)) + // + // decimal digits are sufficient to identify all binary floating-point + // numbers (Matula, "In-and-Out conversions"). + // This implies that the algorithm does not produce more than N decimal + // digits. + // + // N = 17 for p = 53 (IEEE double precision) + // N = 9 for p = 24 (IEEE single precision) +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +JSON_HEDLEY_NON_NULL(1) +inline void grisu2(char* buf, int& len, int& decimal_exponent, + diyfp m_minus, diyfp v, diyfp m_plus) +{ + JSON_ASSERT(m_plus.e == m_minus.e); + JSON_ASSERT(m_plus.e == v.e); + + // --------(-----------------------+-----------------------)-------- (A) + // m- v m+ + // + // --------------------(-----------+-----------------------)-------- (B) + // m- v m+ + // + // First scale v (and m- and m+) such that the exponent is in the range + // [alpha, gamma]. + + const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); + + const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k + + // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] + const diyfp w = diyfp::mul(v, c_minus_k); + const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); + const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); + + // ----(---+---)---------------(---+---)---------------(---+---)---- + // w- w w+ + // = c*m- = c*v = c*m+ + // + // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and + // w+ are now off by a small amount. + // In fact: + // + // w - v * 10^k < 1 ulp + // + // To account for this inaccuracy, add resp. subtract 1 ulp. + // + // --------+---[---------------(---+---)---------------]---+-------- + // w- M- w M+ w+ + // + // Now any number in [M-, M+] (bounds included) will round to w when input, + // regardless of how the input rounding algorithm breaks ties. + // + // And digit_gen generates the shortest possible such number in [M-, M+]. + // Note that this does not mean that Grisu2 always generates the shortest + // possible number in the interval (m-, m+). + const diyfp M_minus(w_minus.f + 1, w_minus.e); + const diyfp M_plus (w_plus.f - 1, w_plus.e ); + + decimal_exponent = -cached.k; // = -(-k) = k + + grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +template +JSON_HEDLEY_NON_NULL(1) +void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) +{ + static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, + "internal error: not enough precision"); + + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); + + // If the neighbors (and boundaries) of 'value' are always computed for double-precision + // numbers, all float's can be recovered using strtod (and strtof). However, the resulting + // decimal representations are not exactly "short". + // + // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) + // says "value is converted to a string as if by std::sprintf in the default ("C") locale" + // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' + // does. + // On the other hand, the documentation for 'std::to_chars' requires that "parsing the + // representation using the corresponding std::from_chars function recovers value exactly". That + // indicates that single precision floating-point numbers should be recovered using + // 'std::strtof'. + // + // NB: If the neighbors are computed for single-precision numbers, there is a single float + // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision + // value is off by 1 ulp. +#if 0 + const boundaries w = compute_boundaries(static_cast(value)); +#else + const boundaries w = compute_boundaries(value); +#endif + + grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); +} + +/*! +@brief appends a decimal representation of e to buf +@return a pointer to the element following the exponent. +@pre -1000 < e < 1000 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* append_exponent(char* buf, int e) +{ + JSON_ASSERT(e > -1000); + JSON_ASSERT(e < 1000); + + if (e < 0) + { + e = -e; + *buf++ = '-'; + } + else + { + *buf++ = '+'; + } + + auto k = static_cast(e); + if (k < 10) + { + // Always print at least two digits in the exponent. + // This is for compatibility with printf("%g"). + *buf++ = '0'; + *buf++ = static_cast('0' + k); + } + else if (k < 100) + { + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + else + { + *buf++ = static_cast('0' + k / 100); + k %= 100; + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + + return buf; +} + +/*! +@brief prettify v = buf * 10^decimal_exponent + +If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point +notation. Otherwise it will be printed in exponential notation. + +@pre min_exp < 0 +@pre max_exp > 0 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* format_buffer(char* buf, int len, int decimal_exponent, + int min_exp, int max_exp) +{ + JSON_ASSERT(min_exp < 0); + JSON_ASSERT(max_exp > 0); + + const int k = len; + const int n = len + decimal_exponent; + + // v = buf * 10^(n-k) + // k is the length of the buffer (number of decimal digits) + // n is the position of the decimal point relative to the start of the buffer. + + if (k <= n && n <= max_exp) + { + // digits[000] + // len <= max_exp + 2 + + std::memset(buf + k, '0', static_cast(n) - static_cast(k)); + // Make it look like a floating-point number (#362, #378) + buf[n + 0] = '.'; + buf[n + 1] = '0'; + return buf + (static_cast(n) + 2); + } + + if (0 < n && n <= max_exp) + { + // dig.its + // len <= max_digits10 + 1 + + JSON_ASSERT(k > n); + + std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); + buf[n] = '.'; + return buf + (static_cast(k) + 1U); + } + + if (min_exp < n && n <= 0) + { + // 0.[000]digits + // len <= 2 + (-min_exp - 1) + max_digits10 + + std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); + buf[0] = '0'; + buf[1] = '.'; + std::memset(buf + 2, '0', static_cast(-n)); + return buf + (2U + static_cast(-n) + static_cast(k)); + } + + if (k == 1) + { + // dE+123 + // len <= 1 + 5 + + buf += 1; + } + else + { + // d.igitsE+123 + // len <= max_digits10 + 1 + 5 + + std::memmove(buf + 2, buf + 1, static_cast(k) - 1); + buf[1] = '.'; + buf += 1 + static_cast(k); + } + + *buf++ = 'e'; + return append_exponent(buf, n - 1); +} + +} // namespace dtoa_impl + +/*! +@brief generates a decimal representation of the floating-point number value in [first, last). + +The format of the resulting decimal representation is similar to printf's %g +format. Returns an iterator pointing past-the-end of the decimal representation. + +@note The input number must be finite, i.e. NaN's and Inf's are not supported. +@note The buffer must be large enough. +@note The result is NOT null-terminated. +*/ +template +JSON_HEDLEY_NON_NULL(1, 2) +JSON_HEDLEY_RETURNS_NON_NULL +char* to_chars(char* first, const char* last, FloatType value) +{ + static_cast(last); // maybe unused - fix warning + JSON_ASSERT(std::isfinite(value)); + + // Use signbit(value) instead of (value < 0) since signbit works for -0. + if (std::signbit(value)) + { + value = -value; + *first++ = '-'; + } + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + if (value == 0) // +-0 + { + *first++ = '0'; + // Make it look like a floating-point number (#362, #378) + *first++ = '.'; + *first++ = '0'; + return first; + } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); + + // Compute v = buffer * 10^decimal_exponent. + // The decimal digits are stored in the buffer, which needs to be interpreted + // as an unsigned decimal integer. + // len is the length of the buffer, i.e. the number of decimal digits. + int len = 0; + int decimal_exponent = 0; + dtoa_impl::grisu2(first, len, decimal_exponent, value); + + JSON_ASSERT(len <= std::numeric_limits::max_digits10); + + // Format the buffer like printf("%.*g", prec, value) + constexpr int kMinExp = -4; + // Use digits10 here to increase compatibility with version 2. + constexpr int kMaxExp = std::numeric_limits::digits10; + + JSON_ASSERT(last - first >= kMaxExp + 2); + JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10 + 6); + + return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); +} + +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// serialization // +/////////////////// + +/// how to treat decoding errors +enum class error_handler_t +{ + strict, ///< throw a type_error exception in case of invalid UTF-8 + replace, ///< replace invalid UTF-8 sequences with U+FFFD + ignore ///< ignore invalid UTF-8 sequences +}; + +template +class serializer +{ + using string_t = typename BasicJsonType::string_t; + using number_float_t = typename BasicJsonType::number_float_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using binary_char_t = typename BasicJsonType::binary_t::value_type; + static constexpr std::uint8_t UTF8_ACCEPT = 0; + static constexpr std::uint8_t UTF8_REJECT = 1; + + public: + /*! + @param[in] s output stream to serialize to + @param[in] ichar indentation character to use + @param[in] error_handler_ how to react on decoding errors + */ + serializer(output_adapter_t s, const char ichar, + error_handler_t error_handler_ = error_handler_t::strict) + : o(std::move(s)) + , loc(std::localeconv()) + , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->thousands_sep))) + , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->decimal_point))) + , indent_char(ichar) + , indent_string(512, indent_char) + , error_handler(error_handler_) + {} + + // delete because of pointer members + serializer(const serializer&) = delete; + serializer& operator=(const serializer&) = delete; + serializer(serializer&&) = delete; + serializer& operator=(serializer&&) = delete; + ~serializer() = default; + + /*! + @brief internal implementation of the serialization function + + This function is called by the public member function dump and organizes + the serialization internally. The indentation level is propagated as + additional parameter. In case of arrays and objects, the function is + called recursively. + + - strings and object keys are escaped using `escape_string()` + - integer numbers are converted implicitly via `operator<<` + - floating-point numbers are converted to a string using `"%g"` format + - binary values are serialized as objects containing the subtype and the + byte array + + @param[in] val value to serialize + @param[in] pretty_print whether the output shall be pretty-printed + @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters + in the output are escaped with `\uXXXX` sequences, and the result consists + of ASCII characters only. + @param[in] indent_step the indent level + @param[in] current_indent the current indent level (only used internally) + */ + void dump(const BasicJsonType& val, + const bool pretty_print, + const bool ensure_ascii, + const unsigned int indent_step, + const unsigned int current_indent = 0) + { + switch (val.m_type) + { + case value_t::object: + { + if (val.m_value.object->empty()) + { + o->write_characters("{}", 2); + return; + } + + if (pretty_print) + { + o->write_characters("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character('}'); + } + else + { + o->write_character('{'); + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + o->write_character(','); + } + + // last element + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + + o->write_character('}'); + } + + return; + } + + case value_t::array: + { + if (val.m_value.array->empty()) + { + o->write_characters("[]", 2); + return; + } + + if (pretty_print) + { + o->write_characters("[\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) + { + o->write_characters(indent_string.c_str(), new_indent); + dump(*i, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + JSON_ASSERT(!val.m_value.array->empty()); + o->write_characters(indent_string.c_str(), new_indent); + dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character(']'); + } + else + { + o->write_character('['); + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) + { + dump(*i, false, ensure_ascii, indent_step, current_indent); + o->write_character(','); + } + + // last element + JSON_ASSERT(!val.m_value.array->empty()); + dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); + + o->write_character(']'); + } + + return; + } + + case value_t::string: + { + o->write_character('\"'); + dump_escaped(*val.m_value.string, ensure_ascii); + o->write_character('\"'); + return; + } + + case value_t::binary: + { + if (pretty_print) + { + o->write_characters("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + o->write_characters(indent_string.c_str(), new_indent); + + o->write_characters("\"bytes\": [", 10); + + if (!val.m_value.binary->empty()) + { + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) + { + dump_integer(*i); + o->write_characters(", ", 2); + } + dump_integer(val.m_value.binary->back()); + } + + o->write_characters("],\n", 3); + o->write_characters(indent_string.c_str(), new_indent); + + o->write_characters("\"subtype\": ", 11); + if (val.m_value.binary->has_subtype()) + { + dump_integer(val.m_value.binary->subtype()); + } + else + { + o->write_characters("null", 4); + } + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character('}'); + } + else + { + o->write_characters("{\"bytes\":[", 10); + + if (!val.m_value.binary->empty()) + { + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) + { + dump_integer(*i); + o->write_character(','); + } + dump_integer(val.m_value.binary->back()); + } + + o->write_characters("],\"subtype\":", 12); + if (val.m_value.binary->has_subtype()) + { + dump_integer(val.m_value.binary->subtype()); + o->write_character('}'); + } + else + { + o->write_characters("null}", 5); + } + } + return; + } + + case value_t::boolean: + { + if (val.m_value.boolean) + { + o->write_characters("true", 4); + } + else + { + o->write_characters("false", 5); + } + return; + } + + case value_t::number_integer: + { + dump_integer(val.m_value.number_integer); + return; + } + + case value_t::number_unsigned: + { + dump_integer(val.m_value.number_unsigned); + return; + } + + case value_t::number_float: + { + dump_float(val.m_value.number_float); + return; + } + + case value_t::discarded: + { + o->write_characters("", 11); + return; + } + + case value_t::null: + { + o->write_characters("null", 4); + return; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + } + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief dump escaped string + + Escape a string by replacing certain special characters by a sequence of an + escape character (backslash) and another character and other control + characters by a sequence of "\u" followed by a four-digit hex + representation. The escaped string is written to output stream @a o. + + @param[in] s the string to escape + @param[in] ensure_ascii whether to escape non-ASCII characters with + \uXXXX sequences + + @complexity Linear in the length of string @a s. + */ + void dump_escaped(const string_t& s, const bool ensure_ascii) + { + std::uint32_t codepoint{}; + std::uint8_t state = UTF8_ACCEPT; + std::size_t bytes = 0; // number of bytes written to string_buffer + + // number of bytes written at the point of the last valid byte + std::size_t bytes_after_last_accept = 0; + std::size_t undumped_chars = 0; + + for (std::size_t i = 0; i < s.size(); ++i) + { + const auto byte = static_cast(s[i]); + + switch (decode(state, codepoint, byte)) + { + case UTF8_ACCEPT: // decode found a new code point + { + switch (codepoint) + { + case 0x08: // backspace + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'b'; + break; + } + + case 0x09: // horizontal tab + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 't'; + break; + } + + case 0x0A: // newline + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'n'; + break; + } + + case 0x0C: // formfeed + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'f'; + break; + } + + case 0x0D: // carriage return + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'r'; + break; + } + + case 0x22: // quotation mark + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\"'; + break; + } + + case 0x5C: // reverse solidus + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\\'; + break; + } + + default: + { + // escape control characters (0x00..0x1F) or, if + // ensure_ascii parameter is used, non-ASCII characters + if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) + { + if (codepoint <= 0xFFFF) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + static_cast((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", + static_cast(codepoint))); + bytes += 6; + } + else + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + static_cast((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", + static_cast(0xD7C0u + (codepoint >> 10u)), + static_cast(0xDC00u + (codepoint & 0x3FFu)))); + bytes += 12; + } + } + else + { + // copy byte to buffer (all previous bytes + // been copied have in default case above) + string_buffer[bytes++] = s[i]; + } + break; + } + } + + // write buffer and reset index; there must be 13 bytes + // left, as this is the maximal number of bytes to be + // written ("\uxxxx\uxxxx\0") for one code point + if (string_buffer.size() - bytes < 13) + { + o->write_characters(string_buffer.data(), bytes); + bytes = 0; + } + + // remember the byte position of this accept + bytes_after_last_accept = bytes; + undumped_chars = 0; + break; + } + + case UTF8_REJECT: // decode found invalid UTF-8 byte + { + switch (error_handler) + { + case error_handler_t::strict: + { + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + hex_bytes(byte | 0), BasicJsonType())); + } + + case error_handler_t::ignore: + case error_handler_t::replace: + { + // in case we saw this character the first time, we + // would like to read it again, because the byte + // may be OK for itself, but just not OK for the + // previous sequence + if (undumped_chars > 0) + { + --i; + } + + // reset length buffer to the last accepted index; + // thus removing/ignoring the invalid characters + bytes = bytes_after_last_accept; + + if (error_handler == error_handler_t::replace) + { + // add a replacement character + if (ensure_ascii) + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'u'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'd'; + } + else + { + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xEF'); + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBF'); + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBD'); + } + + // write buffer and reset index; there must be 13 bytes + // left, as this is the maximal number of bytes to be + // written ("\uxxxx\uxxxx\0") for one code point + if (string_buffer.size() - bytes < 13) + { + o->write_characters(string_buffer.data(), bytes); + bytes = 0; + } + + bytes_after_last_accept = bytes; + } + + undumped_chars = 0; + + // continue processing the string + state = UTF8_ACCEPT; + break; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + break; + } + + default: // decode found yet incomplete multi-byte code point + { + if (!ensure_ascii) + { + // code point will not be escaped - copy byte to buffer + string_buffer[bytes++] = s[i]; + } + ++undumped_chars; + break; + } + } + } + + // we finished processing the string + if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) + { + // write buffer + if (bytes > 0) + { + o->write_characters(string_buffer.data(), bytes); + } + } + else + { + // we finish reading, but do not accept: string was incomplete + switch (error_handler) + { + case error_handler_t::strict: + { + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + hex_bytes(static_cast(s.back() | 0)), BasicJsonType())); + } + + case error_handler_t::ignore: + { + // write all accepted bytes + o->write_characters(string_buffer.data(), bytes_after_last_accept); + break; + } + + case error_handler_t::replace: + { + // write all accepted bytes + o->write_characters(string_buffer.data(), bytes_after_last_accept); + // add a replacement character + if (ensure_ascii) + { + o->write_characters("\\ufffd", 6); + } + else + { + o->write_characters("\xEF\xBF\xBD", 3); + } + break; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + } + } + + private: + /*! + @brief count digits + + Count the number of decimal (base 10) digits for an input unsigned integer. + + @param[in] x unsigned integer number to count its digits + @return number of decimal digits + */ + inline unsigned int count_digits(number_unsigned_t x) noexcept + { + unsigned int n_digits = 1; + for (;;) + { + if (x < 10) + { + return n_digits; + } + if (x < 100) + { + return n_digits + 1; + } + if (x < 1000) + { + return n_digits + 2; + } + if (x < 10000) + { + return n_digits + 3; + } + x = x / 10000u; + n_digits += 4; + } + } + + /*! + * @brief convert a byte to a uppercase hex representation + * @param[in] byte byte to represent + * @return representation ("00".."FF") + */ + static std::string hex_bytes(std::uint8_t byte) + { + std::string result = "FF"; + constexpr const char* nibble_to_hex = "0123456789ABCDEF"; + result[0] = nibble_to_hex[byte / 16]; + result[1] = nibble_to_hex[byte % 16]; + return result; + } + + // templates to avoid warnings about useless casts + template ::value, int> = 0> + bool is_negative_number(NumberType x) + { + return x < 0; + } + + template < typename NumberType, enable_if_t ::value, int > = 0 > + bool is_negative_number(NumberType /*unused*/) + { + return false; + } + + /*! + @brief dump an integer + + Dump a given integer to output stream @a o. Works internally with + @a number_buffer. + + @param[in] x integer number (signed or unsigned) to dump + @tparam NumberType either @a number_integer_t or @a number_unsigned_t + */ + template < typename NumberType, detail::enable_if_t < + std::is_integral::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + int > = 0 > + void dump_integer(NumberType x) + { + static constexpr std::array, 100> digits_to_99 + { + { + {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, + {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, + {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, + {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, + {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, + {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, + {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, + {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, + {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, + {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, + } + }; + + // special case for "0" + if (x == 0) + { + o->write_character('0'); + return; + } + + // use a pointer to fill the buffer + auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) + + number_unsigned_t abs_value; + + unsigned int n_chars{}; + + if (is_negative_number(x)) + { + *buffer_ptr = '-'; + abs_value = remove_sign(static_cast(x)); + + // account one more byte for the minus sign + n_chars = 1 + count_digits(abs_value); + } + else + { + abs_value = static_cast(x); + n_chars = count_digits(abs_value); + } + + // spare 1 byte for '\0' + JSON_ASSERT(n_chars < number_buffer.size() - 1); + + // jump to the end to generate the string from backward, + // so we later avoid reversing the result + buffer_ptr += n_chars; + + // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu + // See: https://www.youtube.com/watch?v=o4-CwDo2zpg + while (abs_value >= 100) + { + const auto digits_index = static_cast((abs_value % 100)); + abs_value /= 100; + *(--buffer_ptr) = digits_to_99[digits_index][1]; + *(--buffer_ptr) = digits_to_99[digits_index][0]; + } + + if (abs_value >= 10) + { + const auto digits_index = static_cast(abs_value); + *(--buffer_ptr) = digits_to_99[digits_index][1]; + *(--buffer_ptr) = digits_to_99[digits_index][0]; + } + else + { + *(--buffer_ptr) = static_cast('0' + abs_value); + } + + o->write_characters(number_buffer.data(), n_chars); + } + + /*! + @brief dump a floating-point number + + Dump a given floating-point number to output stream @a o. Works internally + with @a number_buffer. + + @param[in] x floating-point number to dump + */ + void dump_float(number_float_t x) + { + // NaN / inf + if (!std::isfinite(x)) + { + o->write_characters("null", 4); + return; + } + + // If number_float_t is an IEEE-754 single or double precision number, + // use the Grisu2 algorithm to produce short numbers which are + // guaranteed to round-trip, using strtof and strtod, resp. + // + // NB: The test below works if == . + static constexpr bool is_ieee_single_or_double + = (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 24 && std::numeric_limits::max_exponent == 128) || + (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 53 && std::numeric_limits::max_exponent == 1024); + + dump_float(x, std::integral_constant()); + } + + void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) + { + auto* begin = number_buffer.data(); + auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); + + o->write_characters(begin, static_cast(end - begin)); + } + + void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) + { + // get number of digits for a float -> text -> float round-trip + static constexpr auto d = std::numeric_limits::max_digits10; + + // the actual conversion + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); + + // negative value indicates an error + JSON_ASSERT(len > 0); + // check if buffer was large enough + JSON_ASSERT(static_cast(len) < number_buffer.size()); + + // erase thousands separator + if (thousands_sep != '\0') + { + // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 + const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep); + std::fill(end, number_buffer.end(), '\0'); + JSON_ASSERT((end - number_buffer.begin()) <= len); + len = (end - number_buffer.begin()); + } + + // convert decimal point to '.' + if (decimal_point != '\0' && decimal_point != '.') + { + // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 + const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); + if (dec_pos != number_buffer.end()) + { + *dec_pos = '.'; + } + } + + o->write_characters(number_buffer.data(), static_cast(len)); + + // determine if we need to append ".0" + const bool value_is_int_like = + std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, + [](char c) + { + return c == '.' || c == 'e'; + }); + + if (value_is_int_like) + { + o->write_characters(".0", 2); + } + } + + /*! + @brief check whether a string is UTF-8 encoded + + The function checks each byte of a string whether it is UTF-8 encoded. The + result of the check is stored in the @a state parameter. The function must + be called initially with state 0 (accept). State 1 means the string must + be rejected, because the current byte is not allowed. If the string is + completely processed, but the state is non-zero, the string ended + prematurely; that is, the last byte indicated more bytes should have + followed. + + @param[in,out] state the state of the decoding + @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) + @param[in] byte next byte to decode + @return new state + + @note The function has been edited: a std::array is used. + + @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann + @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + */ + static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept + { + static const std::array utf8d = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF + 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF + 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF + 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF + 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 + 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 + 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 + } + }; + + JSON_ASSERT(byte < utf8d.size()); + const std::uint8_t type = utf8d[byte]; + + codep = (state != UTF8_ACCEPT) + ? (byte & 0x3fu) | (codep << 6u) + : (0xFFu >> type) & (byte); + + std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); + JSON_ASSERT(index < 400); + state = utf8d[index]; + return state; + } + + /* + * Overload to make the compiler happy while it is instantiating + * dump_integer for number_unsigned_t. + * Must never be called. + */ + number_unsigned_t remove_sign(number_unsigned_t x) + { + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return x; // LCOV_EXCL_LINE + } + + /* + * Helper function for dump_integer + * + * This function takes a negative signed integer and returns its absolute + * value as unsigned integer. The plus/minus shuffling is necessary as we can + * not directly remove the sign of an arbitrary signed integer as the + * absolute values of INT_MIN and INT_MAX are usually not the same. See + * #1708 for details. + */ + inline number_unsigned_t remove_sign(number_integer_t x) noexcept + { + JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) + return static_cast(-(x + 1)) + 1; + } + + private: + /// the output of the serializer + output_adapter_t o = nullptr; + + /// a (hopefully) large enough character buffer + std::array number_buffer{{}}; + + /// the locale + const std::lconv* loc = nullptr; + /// the locale's thousand separator character + const char thousands_sep = '\0'; + /// the locale's decimal point character + const char decimal_point = '\0'; + + /// string buffer + std::array string_buffer{{}}; + + /// the indentation character + const char indent_char; + /// the indentation string + string_t indent_string; + + /// error_handler how to react on decoding errors + const error_handler_t error_handler; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include // less +#include // initializer_list +#include // input_iterator_tag, iterator_traits +#include // allocator +#include // for out_of_range +#include // enable_if, is_convertible +#include // pair +#include // vector + +// #include + + +namespace nlohmann +{ + +/// ordered_map: a minimal map-like container that preserves insertion order +/// for use within nlohmann::basic_json +template , + class Allocator = std::allocator>> + struct ordered_map : std::vector, Allocator> +{ + using key_type = Key; + using mapped_type = T; + using Container = std::vector, Allocator>; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + using size_type = typename Container::size_type; + using value_type = typename Container::value_type; + + // Explicit constructors instead of `using Container::Container` + // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) + ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {} + template + ordered_map(It first, It last, const Allocator& alloc = Allocator()) + : Container{first, last, alloc} {} + ordered_map(std::initializer_list init, const Allocator& alloc = Allocator() ) + : Container{init, alloc} {} + + template + std::pair emplace(const key_type& key, Args&&... args) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return {it, false}; + } + } + Container::emplace_back(key, std::forward(args)...); + return {--this->end(), true}; + } + + T& operator[](const Key& key) + { + return emplace(key, T{}).first->second; + } + + const T& operator[](const Key& key) const + { + return at(key); + } + + T& at(const Key& key) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it->second; + } + } + + JSON_THROW(std::out_of_range("key not found")); + } + + const T& at(const Key& key) const + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it->second; + } + } + + JSON_THROW(std::out_of_range("key not found")); + } + + size_type erase(const Key& key) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + // Since we cannot move const Keys, re-construct them in place + for (auto next = it; ++next != this->end(); ++it) + { + it->~value_type(); // Destroy but keep allocation + new (&*it) value_type{std::move(*next)}; + } + Container::pop_back(); + return 1; + } + } + return 0; + } + + iterator erase(iterator pos) + { + return erase(pos, std::next(pos)); + } + + iterator erase(iterator first, iterator last) + { + const auto elements_affected = std::distance(first, last); + const auto offset = std::distance(Container::begin(), first); + + // This is the start situation. We need to delete elements_affected + // elements (3 in this example: e, f, g), and need to return an + // iterator past the last deleted element (h in this example). + // Note that offset is the distance from the start of the vector + // to first. We will need this later. + + // [ a, b, c, d, e, f, g, h, i, j ] + // ^ ^ + // first last + + // Since we cannot move const Keys, we re-construct them in place. + // We start at first and re-construct (viz. copy) the elements from + // the back of the vector. Example for first iteration: + + // ,--------. + // v | destroy e and re-construct with h + // [ a, b, c, d, e, f, g, h, i, j ] + // ^ ^ + // it it + elements_affected + + for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) + { + it->~value_type(); // destroy but keep allocation + new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it + } + + // [ a, b, c, d, h, i, j, h, i, j ] + // ^ ^ + // first last + + // remove the unneeded elements at the end of the vector + Container::resize(this->size() - static_cast(elements_affected)); + + // [ a, b, c, d, h, i, j ] + // ^ ^ + // first last + + // first is now pointing past the last deleted element, but we cannot + // use this iterator, because it may have been invalidated by the + // resize call. Instead, we can return begin() + offset. + return Container::begin() + offset; + } + + size_type count(const Key& key) const + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return 1; + } + } + return 0; + } + + iterator find(const Key& key) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it; + } + } + return Container::end(); + } + + const_iterator find(const Key& key) const + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it; + } + } + return Container::end(); + } + + std::pair insert( value_type&& value ) + { + return emplace(value.first, std::move(value.second)); + } + + std::pair insert( const value_type& value ) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == value.first) + { + return {it, false}; + } + } + Container::push_back(value); + return {--this->end(), true}; + } + + template + using require_input_iter = typename std::enable_if::iterator_category, + std::input_iterator_tag>::value>::type; + + template> + void insert(InputIt first, InputIt last) + { + for (auto it = first; it != last; ++it) + { + insert(*it); + } + } +}; + +} // namespace nlohmann + + +#if defined(JSON_HAS_CPP_17) + #include +#endif + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ + +/*! +@brief a class to store JSON values + +@internal +@invariant The member variables @a m_value and @a m_type have the following +relationship: +- If `m_type == value_t::object`, then `m_value.object != nullptr`. +- If `m_type == value_t::array`, then `m_value.array != nullptr`. +- If `m_type == value_t::string`, then `m_value.string != nullptr`. +The invariants are checked by member function assert_invariant(). + +@note ObjectType trick from https://stackoverflow.com/a/9860911 +@endinternal + +@since version 1.0.0 + +@nosubgrouping +*/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) +{ + private: + template friend struct detail::external_constructor; + friend ::nlohmann::json_pointer; + + template + friend class ::nlohmann::detail::parser; + friend ::nlohmann::detail::serializer; + template + friend class ::nlohmann::detail::iter_impl; + template + friend class ::nlohmann::detail::binary_writer; + template + friend class ::nlohmann::detail::binary_reader; + template + friend class ::nlohmann::detail::json_sax_dom_parser; + template + friend class ::nlohmann::detail::json_sax_dom_callback_parser; + friend class ::nlohmann::detail::exception; + + /// workaround type for MSVC + using basic_json_t = NLOHMANN_BASIC_JSON_TPL; + + JSON_PRIVATE_UNLESS_TESTED: + // convenience aliases for types residing in namespace detail; + using lexer = ::nlohmann::detail::lexer_base; + + template + static ::nlohmann::detail::parser parser( + InputAdapterType adapter, + detail::parser_callback_tcb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false + ) + { + return ::nlohmann::detail::parser(std::move(adapter), + std::move(cb), allow_exceptions, ignore_comments); + } + + private: + using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; + template + using internal_iterator = ::nlohmann::detail::internal_iterator; + template + using iter_impl = ::nlohmann::detail::iter_impl; + template + using iteration_proxy = ::nlohmann::detail::iteration_proxy; + template using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator; + + template + using output_adapter_t = ::nlohmann::detail::output_adapter_t; + + template + using binary_reader = ::nlohmann::detail::binary_reader; + template using binary_writer = ::nlohmann::detail::binary_writer; + + JSON_PRIVATE_UNLESS_TESTED: + using serializer = ::nlohmann::detail::serializer; + + public: + using value_t = detail::value_t; + /// JSON Pointer, see @ref nlohmann::json_pointer + using json_pointer = ::nlohmann::json_pointer; + template + using json_serializer = JSONSerializer; + /// how to treat decoding errors + using error_handler_t = detail::error_handler_t; + /// how to treat CBOR tags + using cbor_tag_handler_t = detail::cbor_tag_handler_t; + /// helper type for initializer lists of basic_json values + using initializer_list_t = std::initializer_list>; + + using input_format_t = detail::input_format_t; + /// SAX interface type, see @ref nlohmann::json_sax + using json_sax_t = json_sax; + + //////////////// + // exceptions // + //////////////// + + /// @name exceptions + /// Classes to implement user-defined exceptions. + /// @{ + + using exception = detail::exception; + using parse_error = detail::parse_error; + using invalid_iterator = detail::invalid_iterator; + using type_error = detail::type_error; + using out_of_range = detail::out_of_range; + using other_error = detail::other_error; + + /// @} + + + ///////////////////// + // container types // + ///////////////////// + + /// @name container types + /// The canonic container types to use @ref basic_json like any other STL + /// container. + /// @{ + + /// the type of elements in a basic_json container + using value_type = basic_json; + + /// the type of an element reference + using reference = value_type&; + /// the type of an element const reference + using const_reference = const value_type&; + + /// a type to represent differences between iterators + using difference_type = std::ptrdiff_t; + /// a type to represent container sizes + using size_type = std::size_t; + + /// the allocator type + using allocator_type = AllocatorType; + + /// the type of an element pointer + using pointer = typename std::allocator_traits::pointer; + /// the type of an element const pointer + using const_pointer = typename std::allocator_traits::const_pointer; + + /// an iterator for a basic_json container + using iterator = iter_impl; + /// a const iterator for a basic_json container + using const_iterator = iter_impl; + /// a reverse iterator for a basic_json container + using reverse_iterator = json_reverse_iterator; + /// a const reverse iterator for a basic_json container + using const_reverse_iterator = json_reverse_iterator; + + /// @} + + + /// @brief returns the allocator associated with the container + /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ + static allocator_type get_allocator() + { + return allocator_type(); + } + + /// @brief returns version information on the library + /// @sa https://json.nlohmann.me/api/basic_json/meta/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json meta() + { + basic_json result; + + result["copyright"] = "(C) 2013-2022 Niels Lohmann"; + result["name"] = "JSON for Modern C++"; + result["url"] = "https://github.com/nlohmann/json"; + result["version"]["string"] = + std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_PATCH); + result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; + result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; + result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; + +#ifdef _WIN32 + result["platform"] = "win32"; +#elif defined __linux__ + result["platform"] = "linux"; +#elif defined __APPLE__ + result["platform"] = "apple"; +#elif defined __unix__ + result["platform"] = "unix"; +#else + result["platform"] = "unknown"; +#endif + +#if defined(__ICC) || defined(__INTEL_COMPILER) + result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; +#elif defined(__clang__) + result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; +#elif defined(__GNUC__) || defined(__GNUG__) + result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; +#elif defined(__HP_cc) || defined(__HP_aCC) + result["compiler"] = "hp" +#elif defined(__IBMCPP__) + result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; +#elif defined(_MSC_VER) + result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; +#elif defined(__PGI) + result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; +#elif defined(__SUNPRO_CC) + result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; +#else + result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; +#endif + +#ifdef __cplusplus + result["compiler"]["c++"] = std::to_string(__cplusplus); +#else + result["compiler"]["c++"] = "unknown"; +#endif + return result; + } + + + /////////////////////////// + // JSON value data types // + /////////////////////////// + + /// @name JSON value data types + /// The data types to store a JSON value. These types are derived from + /// the template arguments passed to class @ref basic_json. + /// @{ + + /// @brief object key comparator type + /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/ +#if defined(JSON_HAS_CPP_14) + // Use transparent comparator if possible, combined with perfect forwarding + // on find() and count() calls prevents unnecessary string construction. + using object_comparator_t = std::less<>; +#else + using object_comparator_t = std::less; +#endif + + /// @brief a type for an object + /// @sa https://json.nlohmann.me/api/basic_json/object_t/ + using object_t = ObjectType>>; + + /// @brief a type for an array + /// @sa https://json.nlohmann.me/api/basic_json/array_t/ + using array_t = ArrayType>; + + /// @brief a type for a string + /// @sa https://json.nlohmann.me/api/basic_json/string_t/ + using string_t = StringType; + + /// @brief a type for a boolean + /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/ + using boolean_t = BooleanType; + + /// @brief a type for a number (integer) + /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/ + using number_integer_t = NumberIntegerType; + + /// @brief a type for a number (unsigned) + /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/ + using number_unsigned_t = NumberUnsignedType; + + /// @brief a type for a number (floating-point) + /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/ + using number_float_t = NumberFloatType; + + /// @brief a type for a packed binary type + /// @sa https://json.nlohmann.me/api/basic_json/binary_t/ + using binary_t = nlohmann::byte_container_with_subtype; + + /// @} + + private: + + /// helper for exception-safe object creation + template + JSON_HEDLEY_RETURNS_NON_NULL + static T* create(Args&& ... args) + { + AllocatorType alloc; + using AllocatorTraits = std::allocator_traits>; + + auto deleter = [&](T * obj) + { + AllocatorTraits::deallocate(alloc, obj, 1); + }; + std::unique_ptr obj(AllocatorTraits::allocate(alloc, 1), deleter); + AllocatorTraits::construct(alloc, obj.get(), std::forward(args)...); + JSON_ASSERT(obj != nullptr); + return obj.release(); + } + + //////////////////////// + // JSON value storage // + //////////////////////// + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief a JSON value + + The actual storage for a JSON value of the @ref basic_json class. This + union combines the different storage types for the JSON value types + defined in @ref value_t. + + JSON type | value_t type | used type + --------- | --------------- | ------------------------ + object | object | pointer to @ref object_t + array | array | pointer to @ref array_t + string | string | pointer to @ref string_t + boolean | boolean | @ref boolean_t + number | number_integer | @ref number_integer_t + number | number_unsigned | @ref number_unsigned_t + number | number_float | @ref number_float_t + binary | binary | pointer to @ref binary_t + null | null | *no value is stored* + + @note Variable-length types (objects, arrays, and strings) are stored as + pointers. The size of the union should not exceed 64 bits if the default + value types are used. + + @since version 1.0.0 + */ + union json_value + { + /// object (stored with pointer to save storage) + object_t* object; + /// array (stored with pointer to save storage) + array_t* array; + /// string (stored with pointer to save storage) + string_t* string; + /// binary (stored with pointer to save storage) + binary_t* binary; + /// boolean + boolean_t boolean; + /// number (integer) + number_integer_t number_integer; + /// number (unsigned integer) + number_unsigned_t number_unsigned; + /// number (floating-point) + number_float_t number_float; + + /// default constructor (for null values) + json_value() = default; + /// constructor for booleans + json_value(boolean_t v) noexcept : boolean(v) {} + /// constructor for numbers (integer) + json_value(number_integer_t v) noexcept : number_integer(v) {} + /// constructor for numbers (unsigned) + json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} + /// constructor for numbers (floating-point) + json_value(number_float_t v) noexcept : number_float(v) {} + /// constructor for empty values of a given type + json_value(value_t t) + { + switch (t) + { + case value_t::object: + { + object = create(); + break; + } + + case value_t::array: + { + array = create(); + break; + } + + case value_t::string: + { + string = create(""); + break; + } + + case value_t::binary: + { + binary = create(); + break; + } + + case value_t::boolean: + { + boolean = static_cast(false); + break; + } + + case value_t::number_integer: + { + number_integer = static_cast(0); + break; + } + + case value_t::number_unsigned: + { + number_unsigned = static_cast(0); + break; + } + + case value_t::number_float: + { + number_float = static_cast(0.0); + break; + } + + case value_t::null: + { + object = nullptr; // silence warning, see #821 + break; + } + + case value_t::discarded: + default: + { + object = nullptr; // silence warning, see #821 + if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) + { + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE + } + break; + } + } + } + + /// constructor for strings + json_value(const string_t& value) : string(create(value)) {} + + /// constructor for rvalue strings + json_value(string_t&& value) : string(create(std::move(value))) {} + + /// constructor for objects + json_value(const object_t& value) : object(create(value)) {} + + /// constructor for rvalue objects + json_value(object_t&& value) : object(create(std::move(value))) {} + + /// constructor for arrays + json_value(const array_t& value) : array(create(value)) {} + + /// constructor for rvalue arrays + json_value(array_t&& value) : array(create(std::move(value))) {} + + /// constructor for binary arrays + json_value(const typename binary_t::container_type& value) : binary(create(value)) {} + + /// constructor for rvalue binary arrays + json_value(typename binary_t::container_type&& value) : binary(create(std::move(value))) {} + + /// constructor for binary arrays (internal type) + json_value(const binary_t& value) : binary(create(value)) {} + + /// constructor for rvalue binary arrays (internal type) + json_value(binary_t&& value) : binary(create(std::move(value))) {} + + void destroy(value_t t) + { + if (t == value_t::array || t == value_t::object) + { + // flatten the current json_value to a heap-allocated stack + std::vector stack; + + // move the top-level items to stack + if (t == value_t::array) + { + stack.reserve(array->size()); + std::move(array->begin(), array->end(), std::back_inserter(stack)); + } + else + { + stack.reserve(object->size()); + for (auto&& it : *object) + { + stack.push_back(std::move(it.second)); + } + } + + while (!stack.empty()) + { + // move the last item to local variable to be processed + basic_json current_item(std::move(stack.back())); + stack.pop_back(); + + // if current_item is array/object, move + // its children to the stack to be processed later + if (current_item.is_array()) + { + std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); + + current_item.m_value.array->clear(); + } + else if (current_item.is_object()) + { + for (auto&& it : *current_item.m_value.object) + { + stack.push_back(std::move(it.second)); + } + + current_item.m_value.object->clear(); + } + + // it's now safe that current_item get destructed + // since it doesn't have any children + } + } + + switch (t) + { + case value_t::object: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, object); + std::allocator_traits::deallocate(alloc, object, 1); + break; + } + + case value_t::array: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, array); + std::allocator_traits::deallocate(alloc, array, 1); + break; + } + + case value_t::string: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, string); + std::allocator_traits::deallocate(alloc, string, 1); + break; + } + + case value_t::binary: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, binary); + std::allocator_traits::deallocate(alloc, binary, 1); + break; + } + + case value_t::null: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::discarded: + default: + { + break; + } + } + } + }; + + private: + /*! + @brief checks the class invariants + + This function asserts the class invariants. It needs to be called at the + end of every constructor to make sure that created objects respect the + invariant. Furthermore, it has to be called each time the type of a JSON + value is changed, because the invariant expresses a relationship between + @a m_type and @a m_value. + + Furthermore, the parent relation is checked for arrays and objects: If + @a check_parents true and the value is an array or object, then the + container's elements must have the current value as parent. + + @param[in] check_parents whether the parent relation should be checked. + The value is true by default and should only be set to false + during destruction of objects when the invariant does not + need to hold. + */ + void assert_invariant(bool check_parents = true) const noexcept + { + JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); + JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); + JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); + JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); + +#if JSON_DIAGNOSTICS + JSON_TRY + { + // cppcheck-suppress assertWithSideEffect + JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) + { + return j.m_parent == this; + })); + } + JSON_CATCH(...) {} // LCOV_EXCL_LINE +#endif + static_cast(check_parents); + } + + void set_parents() + { +#if JSON_DIAGNOSTICS + switch (m_type) + { + case value_t::array: + { + for (auto& element : *m_value.array) + { + element.m_parent = this; + } + break; + } + + case value_t::object: + { + for (auto& element : *m_value.object) + { + element.second.m_parent = this; + } + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + break; + } +#endif + } + + iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) + { +#if JSON_DIAGNOSTICS + for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) + { + (it + i)->m_parent = this; + } +#else + static_cast(count_set_parents); +#endif + return it; + } + + reference set_parent(reference j, std::size_t old_capacity = static_cast(-1)) + { +#if JSON_DIAGNOSTICS + if (old_capacity != static_cast(-1)) + { + // see https://github.com/nlohmann/json/issues/2838 + JSON_ASSERT(type() == value_t::array); + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + return j; + } + } + + // ordered_json uses a vector internally, so pointers could have + // been invalidated; see https://github.com/nlohmann/json/issues/2962 +#ifdef JSON_HEDLEY_MSVC_VERSION +#pragma warning(push ) +#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr +#endif + if (detail::is_ordered_map::value) + { + set_parents(); + return j; + } +#ifdef JSON_HEDLEY_MSVC_VERSION +#pragma warning( pop ) +#endif + + j.m_parent = this; +#else + static_cast(j); + static_cast(old_capacity); +#endif + return j; + } + + public: + ////////////////////////// + // JSON parser callback // + ////////////////////////// + + /// @brief parser event types + /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/ + using parse_event_t = detail::parse_event_t; + + /// @brief per-element parser callback type + /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/ + using parser_callback_t = detail::parser_callback_t; + + ////////////////// + // constructors // + ////////////////// + + /// @name constructors and destructors + /// Constructors of class @ref basic_json, copy/move constructor, copy + /// assignment, static functions creating objects, and the destructor. + /// @{ + + /// @brief create an empty value with a given type + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(const value_t v) + : m_type(v), m_value(v) + { + assert_invariant(); + } + + /// @brief create a null object + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(std::nullptr_t = nullptr) noexcept + : basic_json(value_t::null) + { + assert_invariant(); + } + + /// @brief create a JSON value from compatible types + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + template < typename CompatibleType, + typename U = detail::uncvref_t, + detail::enable_if_t < + !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > + basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) + JSONSerializer::to_json(std::declval(), + std::forward(val)))) + { + JSONSerializer::to_json(*this, std::forward(val)); + set_parents(); + assert_invariant(); + } + + /// @brief create a JSON value from an existing one + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + template < typename BasicJsonType, + detail::enable_if_t < + detail::is_basic_json::value&& !std::is_same::value, int > = 0 > + basic_json(const BasicJsonType& val) + { + using other_boolean_t = typename BasicJsonType::boolean_t; + using other_number_float_t = typename BasicJsonType::number_float_t; + using other_number_integer_t = typename BasicJsonType::number_integer_t; + using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using other_string_t = typename BasicJsonType::string_t; + using other_object_t = typename BasicJsonType::object_t; + using other_array_t = typename BasicJsonType::array_t; + using other_binary_t = typename BasicJsonType::binary_t; + + switch (val.type()) + { + case value_t::boolean: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_float: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_integer: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_unsigned: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::string: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::object: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::array: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::binary: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::null: + *this = nullptr; + break; + case value_t::discarded: + m_type = value_t::discarded; + break; + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + set_parents(); + assert_invariant(); + } + + /// @brief create a container (array or object) from an initializer list + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(initializer_list_t init, + bool type_deduction = true, + value_t manual_type = value_t::array) + { + // check if each element is an array with two elements whose first + // element is a string + bool is_an_object = std::all_of(init.begin(), init.end(), + [](const detail::json_ref& element_ref) + { + return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); + }); + + // adjust type if type deduction is not wanted + if (!type_deduction) + { + // if array is wanted, do not create an object though possible + if (manual_type == value_t::array) + { + is_an_object = false; + } + + // if object is wanted but impossible, throw an exception + if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) + { + JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json())); + } + } + + if (is_an_object) + { + // the initializer list is a list of pairs -> create object + m_type = value_t::object; + m_value = value_t::object; + + for (auto& element_ref : init) + { + auto element = element_ref.moved_or_copied(); + m_value.object->emplace( + std::move(*((*element.m_value.array)[0].m_value.string)), + std::move((*element.m_value.array)[1])); + } + } + else + { + // the initializer list describes an array -> create array + m_type = value_t::array; + m_value.array = create(init.begin(), init.end()); + } + + set_parents(); + assert_invariant(); + } + + /// @brief explicitly create a binary array (without subtype) + /// @sa https://json.nlohmann.me/api/basic_json/binary/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(const typename binary_t::container_type& init) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = init; + return res; + } + + /// @brief explicitly create a binary array (with subtype) + /// @sa https://json.nlohmann.me/api/basic_json/binary/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = binary_t(init, subtype); + return res; + } + + /// @brief explicitly create a binary array + /// @sa https://json.nlohmann.me/api/basic_json/binary/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(typename binary_t::container_type&& init) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = std::move(init); + return res; + } + + /// @brief explicitly create a binary array (with subtype) + /// @sa https://json.nlohmann.me/api/basic_json/binary/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = binary_t(std::move(init), subtype); + return res; + } + + /// @brief explicitly create an array from an initializer list + /// @sa https://json.nlohmann.me/api/basic_json/array/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json array(initializer_list_t init = {}) + { + return basic_json(init, false, value_t::array); + } + + /// @brief explicitly create an object from an initializer list + /// @sa https://json.nlohmann.me/api/basic_json/object/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json object(initializer_list_t init = {}) + { + return basic_json(init, false, value_t::object); + } + + /// @brief construct an array with count copies of given value + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(size_type cnt, const basic_json& val) + : m_type(value_t::array) + { + m_value.array = create(cnt, val); + set_parents(); + assert_invariant(); + } + + /// @brief construct a JSON container given an iterator range + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + template < class InputIT, typename std::enable_if < + std::is_same::value || + std::is_same::value, int >::type = 0 > + basic_json(InputIT first, InputIT last) + { + JSON_ASSERT(first.m_object != nullptr); + JSON_ASSERT(last.m_object != nullptr); + + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json())); + } + + // copy type from first iterator + m_type = first.m_object->m_type; + + // check if iterator range is complete for primitive values + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + { + if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() + || !last.m_it.primitive_iterator.is_end())) + { + JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object)); + } + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::binary: + case value_t::discarded: + default: + break; + } + + switch (m_type) + { + case value_t::number_integer: + { + m_value.number_integer = first.m_object->m_value.number_integer; + break; + } + + case value_t::number_unsigned: + { + m_value.number_unsigned = first.m_object->m_value.number_unsigned; + break; + } + + case value_t::number_float: + { + m_value.number_float = first.m_object->m_value.number_float; + break; + } + + case value_t::boolean: + { + m_value.boolean = first.m_object->m_value.boolean; + break; + } + + case value_t::string: + { + m_value = *first.m_object->m_value.string; + break; + } + + case value_t::object: + { + m_value.object = create(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: + { + m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + case value_t::binary: + { + m_value = *first.m_object->m_value.binary; + break; + } + + case value_t::null: + case value_t::discarded: + default: + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object)); + } + + set_parents(); + assert_invariant(); + } + + + /////////////////////////////////////// + // other constructors and destructor // + /////////////////////////////////////// + + template, + std::is_same>::value, int> = 0 > + basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} + + /// @brief copy constructor + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(const basic_json& other) + : m_type(other.m_type) + { + // check of passed value is valid + other.assert_invariant(); + + switch (m_type) + { + case value_t::object: + { + m_value = *other.m_value.object; + break; + } + + case value_t::array: + { + m_value = *other.m_value.array; + break; + } + + case value_t::string: + { + m_value = *other.m_value.string; + break; + } + + case value_t::boolean: + { + m_value = other.m_value.boolean; + break; + } + + case value_t::number_integer: + { + m_value = other.m_value.number_integer; + break; + } + + case value_t::number_unsigned: + { + m_value = other.m_value.number_unsigned; + break; + } + + case value_t::number_float: + { + m_value = other.m_value.number_float; + break; + } + + case value_t::binary: + { + m_value = *other.m_value.binary; + break; + } + + case value_t::null: + case value_t::discarded: + default: + break; + } + + set_parents(); + assert_invariant(); + } + + /// @brief move constructor + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(basic_json&& other) noexcept + : m_type(std::move(other.m_type)), + m_value(std::move(other.m_value)) + { + // check that passed value is valid + other.assert_invariant(false); + + // invalidate payload + other.m_type = value_t::null; + other.m_value = {}; + + set_parents(); + assert_invariant(); + } + + /// @brief copy assignment + /// @sa https://json.nlohmann.me/api/basic_json/operator=/ + basic_json& operator=(basic_json other) noexcept ( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value + ) + { + // check that passed value is valid + other.assert_invariant(); + + using std::swap; + swap(m_type, other.m_type); + swap(m_value, other.m_value); + + set_parents(); + assert_invariant(); + return *this; + } + + /// @brief destructor + /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/ + ~basic_json() noexcept + { + assert_invariant(false); + m_value.destroy(m_type); + } + + /// @} + + public: + /////////////////////// + // object inspection // + /////////////////////// + + /// @name object inspection + /// Functions to inspect the type of a JSON value. + /// @{ + + /// @brief serialization + /// @sa https://json.nlohmann.me/api/basic_json/dump/ + string_t dump(const int indent = -1, + const char indent_char = ' ', + const bool ensure_ascii = false, + const error_handler_t error_handler = error_handler_t::strict) const + { + string_t result; + serializer s(detail::output_adapter(result), indent_char, error_handler); + + if (indent >= 0) + { + s.dump(*this, true, ensure_ascii, static_cast(indent)); + } + else + { + s.dump(*this, false, ensure_ascii, 0); + } + + return result; + } + + /// @brief return the type of the JSON value (explicit) + /// @sa https://json.nlohmann.me/api/basic_json/type/ + constexpr value_t type() const noexcept + { + return m_type; + } + + /// @brief return whether type is primitive + /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/ + constexpr bool is_primitive() const noexcept + { + return is_null() || is_string() || is_boolean() || is_number() || is_binary(); + } + + /// @brief return whether type is structured + /// @sa https://json.nlohmann.me/api/basic_json/is_structured/ + constexpr bool is_structured() const noexcept + { + return is_array() || is_object(); + } + + /// @brief return whether value is null + /// @sa https://json.nlohmann.me/api/basic_json/is_null/ + constexpr bool is_null() const noexcept + { + return m_type == value_t::null; + } + + /// @brief return whether value is a boolean + /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ + constexpr bool is_boolean() const noexcept + { + return m_type == value_t::boolean; + } + + /// @brief return whether value is a number + /// @sa https://json.nlohmann.me/api/basic_json/is_number/ + constexpr bool is_number() const noexcept + { + return is_number_integer() || is_number_float(); + } + + /// @brief return whether value is an integer number + /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ + constexpr bool is_number_integer() const noexcept + { + return m_type == value_t::number_integer || m_type == value_t::number_unsigned; + } + + /// @brief return whether value is an unsigned integer number + /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ + constexpr bool is_number_unsigned() const noexcept + { + return m_type == value_t::number_unsigned; + } + + /// @brief return whether value is a floating-point number + /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ + constexpr bool is_number_float() const noexcept + { + return m_type == value_t::number_float; + } + + /// @brief return whether value is an object + /// @sa https://json.nlohmann.me/api/basic_json/is_object/ + constexpr bool is_object() const noexcept + { + return m_type == value_t::object; + } + + /// @brief return whether value is an array + /// @sa https://json.nlohmann.me/api/basic_json/is_array/ + constexpr bool is_array() const noexcept + { + return m_type == value_t::array; + } + + /// @brief return whether value is a string + /// @sa https://json.nlohmann.me/api/basic_json/is_string/ + constexpr bool is_string() const noexcept + { + return m_type == value_t::string; + } + + /// @brief return whether value is a binary array + /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ + constexpr bool is_binary() const noexcept + { + return m_type == value_t::binary; + } + + /// @brief return whether value is discarded + /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ + constexpr bool is_discarded() const noexcept + { + return m_type == value_t::discarded; + } + + /// @brief return the type of the JSON value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ + constexpr operator value_t() const noexcept + { + return m_type; + } + + /// @} + + private: + ////////////////// + // value access // + ////////////////// + + /// get a boolean (explicit) + boolean_t get_impl(boolean_t* /*unused*/) const + { + if (JSON_HEDLEY_LIKELY(is_boolean())) + { + return m_value.boolean; + } + + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this)); + } + + /// get a pointer to the value (object) + object_t* get_impl_ptr(object_t* /*unused*/) noexcept + { + return is_object() ? m_value.object : nullptr; + } + + /// get a pointer to the value (object) + constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept + { + return is_object() ? m_value.object : nullptr; + } + + /// get a pointer to the value (array) + array_t* get_impl_ptr(array_t* /*unused*/) noexcept + { + return is_array() ? m_value.array : nullptr; + } + + /// get a pointer to the value (array) + constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept + { + return is_array() ? m_value.array : nullptr; + } + + /// get a pointer to the value (string) + string_t* get_impl_ptr(string_t* /*unused*/) noexcept + { + return is_string() ? m_value.string : nullptr; + } + + /// get a pointer to the value (string) + constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept + { + return is_string() ? m_value.string : nullptr; + } + + /// get a pointer to the value (boolean) + boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept + { + return is_boolean() ? &m_value.boolean : nullptr; + } + + /// get a pointer to the value (boolean) + constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept + { + return is_boolean() ? &m_value.boolean : nullptr; + } + + /// get a pointer to the value (integer number) + number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept + { + return is_number_integer() ? &m_value.number_integer : nullptr; + } + + /// get a pointer to the value (integer number) + constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept + { + return is_number_integer() ? &m_value.number_integer : nullptr; + } + + /// get a pointer to the value (unsigned number) + number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept + { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } + + /// get a pointer to the value (unsigned number) + constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept + { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } + + /// get a pointer to the value (floating-point number) + number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept + { + return is_number_float() ? &m_value.number_float : nullptr; + } + + /// get a pointer to the value (floating-point number) + constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept + { + return is_number_float() ? &m_value.number_float : nullptr; + } + + /// get a pointer to the value (binary) + binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept + { + return is_binary() ? m_value.binary : nullptr; + } + + /// get a pointer to the value (binary) + constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept + { + return is_binary() ? m_value.binary : nullptr; + } + + /*! + @brief helper function to implement get_ref() + + This function helps to implement get_ref() without code duplication for + const and non-const overloads + + @tparam ThisType will be deduced as `basic_json` or `const basic_json` + + @throw type_error.303 if ReferenceType does not match underlying value + type of the current JSON + */ + template + static ReferenceType get_ref_impl(ThisType& obj) + { + // delegate the call to get_ptr<>() + auto* ptr = obj.template get_ptr::type>(); + + if (JSON_HEDLEY_LIKELY(ptr != nullptr)) + { + return *ptr; + } + + JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj)); + } + + public: + /// @name value access + /// Direct access to the stored value of a JSON value. + /// @{ + + /// @brief get a pointer value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ + template::value, int>::type = 0> + auto get_ptr() noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) + { + // delegate the call to get_impl_ptr<>() + return get_impl_ptr(static_cast(nullptr)); + } + + /// @brief get a pointer value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ + template < typename PointerType, typename std::enable_if < + std::is_pointer::value&& + std::is_const::type>::value, int >::type = 0 > + constexpr auto get_ptr() const noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) + { + // delegate the call to get_impl_ptr<>() const + return get_impl_ptr(static_cast(nullptr)); + } + + private: + /*! + @brief get a value (explicit) + + Explicit type conversion between the JSON value and a compatible value + which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) + and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + ValueType ret; + JSONSerializer::from_json(*this, ret); + return ret; + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json, + - @ref json_serializer has a `from_json()` method of the form + `void from_json(const basic_json&, ValueType&)`, and + - @ref json_serializer does not have a `from_json()` method of + the form `ValueType from_json(const basic_json&)` + + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,get__ValueType_const} + + @since version 2.1.0 + */ + template < typename ValueType, + detail::enable_if_t < + detail::is_default_constructible::value&& + detail::has_from_json::value, + int > = 0 > + ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), std::declval()))) + { + auto ret = ValueType(); + JSONSerializer::from_json(*this, ret); + return ret; + } + + /*! + @brief get a value (explicit); special case + + Explicit type conversion between the JSON value and a compatible value + which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) + and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + return JSONSerializer::from_json(*this); + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json and + - @ref json_serializer has a `from_json()` method of the form + `ValueType from_json(const basic_json&)` + + @note If @ref json_serializer has both overloads of + `from_json()`, this one is chosen. + + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws + + @since version 2.1.0 + */ + template < typename ValueType, + detail::enable_if_t < + detail::has_non_default_from_json::value, + int > = 0 > + ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( + JSONSerializer::from_json(std::declval()))) + { + return JSONSerializer::from_json(*this); + } + + /*! + @brief get special-case overload + + This overloads converts the current @ref basic_json in a different + @ref basic_json type + + @tparam BasicJsonType == @ref basic_json + + @return a copy of *this, converted into @a BasicJsonType + + @complexity Depending on the implementation of the called `from_json()` + method. + + @since version 3.2.0 + */ + template < typename BasicJsonType, + detail::enable_if_t < + detail::is_basic_json::value, + int > = 0 > + BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const + { + return *this; + } + + /*! + @brief get special-case overload + + This overloads avoids a lot of template boilerplate, it can be seen as the + identity method + + @tparam BasicJsonType == @ref basic_json + + @return a copy of *this + + @complexity Constant. + + @since version 2.1.0 + */ + template::value, + int> = 0> + basic_json get_impl(detail::priority_tag<3> /*unused*/) const + { + return *this; + } + + /*! + @brief get a pointer value (explicit) + @copydoc get() + */ + template::value, + int> = 0> + constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept + -> decltype(std::declval().template get_ptr()) + { + // delegate the call to get_ptr + return get_ptr(); + } + + public: + /*! + @brief get a (pointer) value (explicit) + + Performs explicit type conversion between the JSON value and a compatible value if required. + + - If the requested type is a pointer to the internally stored JSON value that pointer is returned. + No copies are made. + + - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible + from the current @ref basic_json. + + - Otherwise the value is converted by calling the @ref json_serializer `from_json()` + method. + + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @tparam ValueType if necessary + + @throw what @ref json_serializer `from_json()` method throws if conversion is required + + @since version 2.1.0 + */ + template < typename ValueTypeCV, typename ValueType = detail::uncvref_t> +#if defined(JSON_HAS_CPP_14) + constexpr +#endif + auto get() const noexcept( + noexcept(std::declval().template get_impl(detail::priority_tag<4> {}))) + -> decltype(std::declval().template get_impl(detail::priority_tag<4> {})) + { + // we cannot static_assert on ValueTypeCV being non-const, because + // there is support for get(), which is why we + // still need the uncvref + static_assert(!std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + return get_impl(detail::priority_tag<4> {}); + } + + /*! + @brief get a pointer value (explicit) + + Explicit pointer access to the internally stored JSON value. No copies are + made. + + @warning The pointer becomes invalid if the underlying JSON object + changes. + + @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref + object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, + @ref number_unsigned_t, or @ref number_float_t. + + @return pointer to the internally stored JSON value if the requested + pointer type @a PointerType fits to the JSON value; `nullptr` otherwise + + @complexity Constant. + + @liveexample{The example below shows how pointers to internal values of a + JSON value can be requested. Note that no type conversions are made and a + `nullptr` is returned if the value and the requested pointer type does not + match.,get__PointerType} + + @sa see @ref get_ptr() for explicit pointer-member access + + @since version 1.0.0 + */ + template::value, int>::type = 0> + auto get() noexcept -> decltype(std::declval().template get_ptr()) + { + // delegate the call to get_ptr + return get_ptr(); + } + + /// @brief get a value (explicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_to/ + template < typename ValueType, + detail::enable_if_t < + !detail::is_basic_json::value&& + detail::has_from_json::value, + int > = 0 > + ValueType & get_to(ValueType& v) const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), v))) + { + JSONSerializer::from_json(*this, v); + return v; + } + + // specialization to allow calling get_to with a basic_json value + // see https://github.com/nlohmann/json/issues/2175 + template::value, + int> = 0> + ValueType & get_to(ValueType& v) const + { + v = *this; + return v; + } + + template < + typename T, std::size_t N, + typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + detail::enable_if_t < + detail::has_from_json::value, int > = 0 > + Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + noexcept(noexcept(JSONSerializer::from_json( + std::declval(), v))) + { + JSONSerializer::from_json(*this, v); + return v; + } + + /// @brief get a reference value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ + template::value, int>::type = 0> + ReferenceType get_ref() + { + // delegate call to get_ref_impl + return get_ref_impl(*this); + } + + /// @brief get a reference value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ + template < typename ReferenceType, typename std::enable_if < + std::is_reference::value&& + std::is_const::type>::value, int >::type = 0 > + ReferenceType get_ref() const + { + // delegate call to get_ref_impl + return get_ref_impl(*this); + } + + /*! + @brief get a value (implicit) + + Implicit type conversion between the JSON value and a compatible value. + The call is realized by calling @ref get() const. + + @tparam ValueType non-pointer type compatible to the JSON value, for + instance `int` for JSON integer numbers, `bool` for JSON booleans, or + `std::vector` types for JSON arrays. The character type of @ref string_t + as well as an initializer list of this type is excluded to avoid + ambiguities as these types implicitly convert to `std::string`. + + @return copy of the JSON value, converted to type @a ValueType + + @throw type_error.302 in case passed type @a ValueType is incompatible + to the JSON value type (e.g., the JSON value is of type boolean, but a + string is requested); see example below + + @complexity Linear in the size of the JSON value. + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,operator__ValueType} + + @since version 1.0.0 + */ + template < typename ValueType, typename std::enable_if < + detail::conjunction < + detail::negation>, + detail::negation>>, + detail::negation>, + detail::negation>, + detail::negation>>, + +#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) + detail::negation>, +#endif + detail::is_detected_lazy + >::value, int >::type = 0 > + JSON_EXPLICIT operator ValueType() const + { + // delegate the call to get<>() const + return get(); + } + + /// @brief get a binary value + /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ + binary_t& get_binary() + { + if (!is_binary()) + { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); + } + + return *get_ptr(); + } + + /// @brief get a binary value + /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ + const binary_t& get_binary() const + { + if (!is_binary()) + { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); + } + + return *get_ptr(); + } + + /// @} + + + //////////////////// + // element access // + //////////////////// + + /// @name element access + /// Access to the JSON value. + /// @{ + + /// @brief access specified array element with bounds checking + /// @sa https://json.nlohmann.me/api/basic_json/at/ + reference at(size_type idx) + { + // at only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + JSON_TRY + { + return set_parent(m_value.array->at(idx)); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /// @brief access specified array element with bounds checking + /// @sa https://json.nlohmann.me/api/basic_json/at/ + const_reference at(size_type idx) const + { + // at only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + JSON_TRY + { + return m_value.array->at(idx); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /// @brief access specified object element with bounds checking + /// @sa https://json.nlohmann.me/api/basic_json/at/ + reference at(const typename object_t::key_type& key) + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_TRY + { + return set_parent(m_value.object->at(key)); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /// @brief access specified object element with bounds checking + /// @sa https://json.nlohmann.me/api/basic_json/at/ + const_reference at(const typename object_t::key_type& key) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_TRY + { + return m_value.object->at(key); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /// @brief access specified array element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + reference operator[](size_type idx) + { + // implicitly convert null value to an empty array + if (is_null()) + { + m_type = value_t::array; + m_value.array = create(); + assert_invariant(); + } + + // operator[] only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + // fill up array with null values if given idx is outside range + if (idx >= m_value.array->size()) + { +#if JSON_DIAGNOSTICS + // remember array size & capacity before resizing + const auto old_size = m_value.array->size(); + const auto old_capacity = m_value.array->capacity(); +#endif + m_value.array->resize(idx + 1); + +#if JSON_DIAGNOSTICS + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + } + else + { + // set parent for values added above + set_parents(begin() + static_cast(old_size), static_cast(idx + 1 - old_size)); + } +#endif + assert_invariant(); + } + + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified array element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + const_reference operator[](size_type idx) const + { + // const operator[] only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + reference operator[](const typename object_t::key_type& key) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + // operator[] only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + return set_parent(m_value.object->operator[](key)); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + const_reference operator[](const typename object_t::key_type& key) const + { + // const operator[] only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + template + JSON_HEDLEY_NON_NULL(2) + reference operator[](T* key) + { + // implicitly convert null to object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + return set_parent(m_value.object->operator[](key)); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + template + JSON_HEDLEY_NON_NULL(2) + const_reference operator[](T* key) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + /// using std::is_convertible in a std::enable_if will fail when using explicit conversions + template < class ValueType, typename std::enable_if < + detail::is_getable::value + && !std::is_same::value, int >::type = 0 > + ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if key is found, return value and given default value otherwise + const auto it = find(key); + if (it != end()) + { + return it->template get(); + } + + return default_value; + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + /// overload for a default value of type const char* + string_t value(const typename object_t::key_type& key, const char* default_value) const + { + return value(key, string_t(default_value)); + } + + /// @brief access specified object element via JSON Pointer with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + template::value, int>::type = 0> + ValueType value(const json_pointer& ptr, const ValueType& default_value) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if pointer resolves a value, return it or use default value + JSON_TRY + { + return ptr.get_checked(this).template get(); + } + JSON_INTERNAL_CATCH (out_of_range&) + { + return default_value; + } + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element via JSON Pointer with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + /// overload for a default value of type const char* + JSON_HEDLEY_NON_NULL(3) + string_t value(const json_pointer& ptr, const char* default_value) const + { + return value(ptr, string_t(default_value)); + } + + /// @brief access the first element + /// @sa https://json.nlohmann.me/api/basic_json/front/ + reference front() + { + return *begin(); + } + + /// @brief access the first element + /// @sa https://json.nlohmann.me/api/basic_json/front/ + const_reference front() const + { + return *cbegin(); + } + + /// @brief access the last element + /// @sa https://json.nlohmann.me/api/basic_json/back/ + reference back() + { + auto tmp = end(); + --tmp; + return *tmp; + } + + /// @brief access the last element + /// @sa https://json.nlohmann.me/api/basic_json/back/ + const_reference back() const + { + auto tmp = cend(); + --tmp; + return *tmp; + } + + /// @brief remove element given an iterator + /// @sa https://json.nlohmann.me/api/basic_json/erase/ + template < class IteratorType, typename std::enable_if < + std::is_same::value || + std::is_same::value, int >::type + = 0 > + IteratorType erase(IteratorType pos) + { + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + IteratorType result = end(); + + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + case value_t::binary: + { + if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) + { + JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this)); + } + + if (is_string()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; + } + else if (is_binary()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: + { + result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); + break; + } + + case value_t::array: + { + result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); + break; + } + + case value_t::null: + case value_t::discarded: + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + + return result; + } + + /// @brief remove elements given an iterator range + /// @sa https://json.nlohmann.me/api/basic_json/erase/ + template < class IteratorType, typename std::enable_if < + std::is_same::value || + std::is_same::value, int >::type + = 0 > + IteratorType erase(IteratorType first, IteratorType last) + { + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) + { + JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this)); + } + + IteratorType result = end(); + + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + case value_t::binary: + { + if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() + || !last.m_it.primitive_iterator.is_end())) + { + JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this)); + } + + if (is_string()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; + } + else if (is_binary()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: + { + result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: + { + result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + case value_t::null: + case value_t::discarded: + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + + return result; + } + + /// @brief remove element from a JSON object given a key + /// @sa https://json.nlohmann.me/api/basic_json/erase/ + size_type erase(const typename object_t::key_type& key) + { + // this erase only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + return m_value.object->erase(key); + } + + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + + /// @brief remove element from a JSON array given an index + /// @sa https://json.nlohmann.me/api/basic_json/erase/ + void erase(const size_type idx) + { + // this erase only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + if (JSON_HEDLEY_UNLIKELY(idx >= size())) + { + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); + } + + m_value.array->erase(m_value.array->begin() + static_cast(idx)); + } + else + { + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + } + + /// @} + + + //////////// + // lookup // + //////////// + + /// @name lookup + /// @{ + + /// @brief find an element in a JSON object + /// @sa https://json.nlohmann.me/api/basic_json/find/ + template + iterator find(KeyT&& key) + { + auto result = end(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; + } + + /// @brief find an element in a JSON object + /// @sa https://json.nlohmann.me/api/basic_json/find/ + template + const_iterator find(KeyT&& key) const + { + auto result = cend(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; + } + + /// @brief returns the number of occurrences of a key in a JSON object + /// @sa https://json.nlohmann.me/api/basic_json/count/ + template + size_type count(KeyT&& key) const + { + // return 0 for all nonobject types + return is_object() ? m_value.object->count(std::forward(key)) : 0; + } + + /// @brief check the existence of an element in a JSON object + /// @sa https://json.nlohmann.me/api/basic_json/contains/ + template < typename KeyT, typename std::enable_if < + !std::is_same::type, json_pointer>::value, int >::type = 0 > + bool contains(KeyT && key) const + { + return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); + } + + /// @brief check the existence of an element in a JSON object given a JSON pointer + /// @sa https://json.nlohmann.me/api/basic_json/contains/ + bool contains(const json_pointer& ptr) const + { + return ptr.contains(this); + } + + /// @} + + + /////////////// + // iterators // + /////////////// + + /// @name iterators + /// @{ + + /// @brief returns an iterator to the first element + /// @sa https://json.nlohmann.me/api/basic_json/begin/ + iterator begin() noexcept + { + iterator result(this); + result.set_begin(); + return result; + } + + /// @brief returns an iterator to the first element + /// @sa https://json.nlohmann.me/api/basic_json/begin/ + const_iterator begin() const noexcept + { + return cbegin(); + } + + /// @brief returns a const iterator to the first element + /// @sa https://json.nlohmann.me/api/basic_json/cbegin/ + const_iterator cbegin() const noexcept + { + const_iterator result(this); + result.set_begin(); + return result; + } + + /// @brief returns an iterator to one past the last element + /// @sa https://json.nlohmann.me/api/basic_json/end/ + iterator end() noexcept + { + iterator result(this); + result.set_end(); + return result; + } + + /// @brief returns an iterator to one past the last element + /// @sa https://json.nlohmann.me/api/basic_json/end/ + const_iterator end() const noexcept + { + return cend(); + } + + /// @brief returns an iterator to one past the last element + /// @sa https://json.nlohmann.me/api/basic_json/cend/ + const_iterator cend() const noexcept + { + const_iterator result(this); + result.set_end(); + return result; + } + + /// @brief returns an iterator to the reverse-beginning + /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ + reverse_iterator rbegin() noexcept + { + return reverse_iterator(end()); + } + + /// @brief returns an iterator to the reverse-beginning + /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ + const_reverse_iterator rbegin() const noexcept + { + return crbegin(); + } + + /// @brief returns an iterator to the reverse-end + /// @sa https://json.nlohmann.me/api/basic_json/rend/ + reverse_iterator rend() noexcept + { + return reverse_iterator(begin()); + } + + /// @brief returns an iterator to the reverse-end + /// @sa https://json.nlohmann.me/api/basic_json/rend/ + const_reverse_iterator rend() const noexcept + { + return crend(); + } + + /// @brief returns a const reverse iterator to the last element + /// @sa https://json.nlohmann.me/api/basic_json/crbegin/ + const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator(cend()); + } + + /// @brief returns a const reverse iterator to one before the first + /// @sa https://json.nlohmann.me/api/basic_json/crend/ + const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator(cbegin()); + } + + public: + /// @brief wrapper to access iterator member functions in range-based for + /// @sa https://json.nlohmann.me/api/basic_json/items/ + /// @deprecated This function is deprecated since 3.1.0 and will be removed in + /// version 4.0.0 of the library. Please use @ref items() instead; + /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. + JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) + static iteration_proxy iterator_wrapper(reference ref) noexcept + { + return ref.items(); + } + + /// @brief wrapper to access iterator member functions in range-based for + /// @sa https://json.nlohmann.me/api/basic_json/items/ + /// @deprecated This function is deprecated since 3.1.0 and will be removed in + /// version 4.0.0 of the library. Please use @ref items() instead; + /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. + JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) + static iteration_proxy iterator_wrapper(const_reference ref) noexcept + { + return ref.items(); + } + + /// @brief helper to access iterator member functions in range-based for + /// @sa https://json.nlohmann.me/api/basic_json/items/ + iteration_proxy items() noexcept + { + return iteration_proxy(*this); + } + + /// @brief helper to access iterator member functions in range-based for + /// @sa https://json.nlohmann.me/api/basic_json/items/ + iteration_proxy items() const noexcept + { + return iteration_proxy(*this); + } + + /// @} + + + ////////////// + // capacity // + ////////////// + + /// @name capacity + /// @{ + + /// @brief checks whether the container is empty. + /// @sa https://json.nlohmann.me/api/basic_json/empty/ + bool empty() const noexcept + { + switch (m_type) + { + case value_t::null: + { + // null values are empty + return true; + } + + case value_t::array: + { + // delegate call to array_t::empty() + return m_value.array->empty(); + } + + case value_t::object: + { + // delegate call to object_t::empty() + return m_value.object->empty(); + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // all other types are nonempty + return false; + } + } + } + + /// @brief returns the number of elements + /// @sa https://json.nlohmann.me/api/basic_json/size/ + size_type size() const noexcept + { + switch (m_type) + { + case value_t::null: + { + // null values are empty + return 0; + } + + case value_t::array: + { + // delegate call to array_t::size() + return m_value.array->size(); + } + + case value_t::object: + { + // delegate call to object_t::size() + return m_value.object->size(); + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // all other types have size 1 + return 1; + } + } + } + + /// @brief returns the maximum possible number of elements + /// @sa https://json.nlohmann.me/api/basic_json/max_size/ + size_type max_size() const noexcept + { + switch (m_type) + { + case value_t::array: + { + // delegate call to array_t::max_size() + return m_value.array->max_size(); + } + + case value_t::object: + { + // delegate call to object_t::max_size() + return m_value.object->max_size(); + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // all other types have max_size() == size() + return size(); + } + } + } + + /// @} + + + /////////////// + // modifiers // + /////////////// + + /// @name modifiers + /// @{ + + /// @brief clears the contents + /// @sa https://json.nlohmann.me/api/basic_json/clear/ + void clear() noexcept + { + switch (m_type) + { + case value_t::number_integer: + { + m_value.number_integer = 0; + break; + } + + case value_t::number_unsigned: + { + m_value.number_unsigned = 0; + break; + } + + case value_t::number_float: + { + m_value.number_float = 0.0; + break; + } + + case value_t::boolean: + { + m_value.boolean = false; + break; + } + + case value_t::string: + { + m_value.string->clear(); + break; + } + + case value_t::binary: + { + m_value.binary->clear(); + break; + } + + case value_t::array: + { + m_value.array->clear(); + break; + } + + case value_t::object: + { + m_value.object->clear(); + break; + } + + case value_t::null: + case value_t::discarded: + default: + break; + } + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/push_back/ + void push_back(basic_json&& val) + { + // push_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array (move semantics) + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(std::move(val)); + set_parent(m_value.array->back(), old_capacity); + // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ + reference operator+=(basic_json&& val) + { + push_back(std::move(val)); + return *this; + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/push_back/ + void push_back(const basic_json& val) + { + // push_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(val); + set_parent(m_value.array->back(), old_capacity); + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ + reference operator+=(const basic_json& val) + { + push_back(val); + return *this; + } + + /// @brief add an object to an object + /// @sa https://json.nlohmann.me/api/basic_json/push_back/ + void push_back(const typename object_t::value_type& val) + { + // push_back only works for null objects or objects + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to object + auto res = m_value.object->insert(val); + set_parent(res.first->second); + } + + /// @brief add an object to an object + /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ + reference operator+=(const typename object_t::value_type& val) + { + push_back(val); + return *this; + } + + /// @brief add an object to an object + /// @sa https://json.nlohmann.me/api/basic_json/push_back/ + void push_back(initializer_list_t init) + { + if (is_object() && init.size() == 2 && (*init.begin())->is_string()) + { + basic_json&& key = init.begin()->moved_or_copied(); + push_back(typename object_t::value_type( + std::move(key.get_ref()), (init.begin() + 1)->moved_or_copied())); + } + else + { + push_back(basic_json(init)); + } + } + + /// @brief add an object to an object + /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ + reference operator+=(initializer_list_t init) + { + push_back(init); + return *this; + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/ + template + reference emplace_back(Args&& ... args) + { + // emplace_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) + { + JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array (perfect forwarding) + const auto old_capacity = m_value.array->capacity(); + m_value.array->emplace_back(std::forward(args)...); + return set_parent(m_value.array->back(), old_capacity); + } + + /// @brief add an object to an object if key does not exist + /// @sa https://json.nlohmann.me/api/basic_json/emplace/ + template + std::pair emplace(Args&& ... args) + { + // emplace only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) + { + JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this)); + } + + // transform null object into an object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to array (perfect forwarding) + auto res = m_value.object->emplace(std::forward(args)...); + set_parent(res.first->second); + + // create result iterator and set iterator to the result of emplace + auto it = begin(); + it.m_it.object_iterator = res.first; + + // return pair of iterator and boolean + return {it, res.second}; + } + + /// Helper for insertion of an iterator + /// @note: This uses std::distance to support GCC 4.8, + /// see https://github.com/nlohmann/json/pull/1257 + template + iterator insert_iterator(const_iterator pos, Args&& ... args) + { + iterator result(this); + JSON_ASSERT(m_value.array != nullptr); + + auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); + m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); + result.m_it.array_iterator = m_value.array->begin() + insert_pos; + + // This could have been written as: + // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); + // but the return value of insert is missing in GCC 4.8, so it is written this way instead. + + set_parents(); + return result; + } + + /// @brief inserts element into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, const basic_json& val) + { + // insert only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, val); + } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + /// @brief inserts element into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, basic_json&& val) + { + return insert(pos, val); + } + + /// @brief inserts copies of element into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, size_type cnt, const basic_json& val) + { + // insert only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, cnt, val); + } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + /// @brief inserts range of elements into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, const_iterator first, const_iterator last) + { + // insert only works for arrays + if (JSON_HEDLEY_UNLIKELY(!is_array())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); + } + + if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) + { + JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); + } + + /// @brief inserts elements from initializer list into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, initializer_list_t ilist) + { + // insert only works for arrays + if (JSON_HEDLEY_UNLIKELY(!is_array())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, ilist.begin(), ilist.end()); + } + + /// @brief inserts range of elements into object + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + void insert(const_iterator first, const_iterator last) + { + // insert only works for objects + if (JSON_HEDLEY_UNLIKELY(!is_object())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); + } + + // passed iterators must belong to objects + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); + } + + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + } + + /// @brief updates a JSON object from another object, overwriting existing keys + /// @sa https://json.nlohmann.me/api/basic_json/update/ + void update(const_reference j, bool merge_objects = false) + { + update(j.begin(), j.end(), merge_objects); + } + + /// @brief updates a JSON object from another object, overwriting existing keys + /// @sa https://json.nlohmann.me/api/basic_json/update/ + void update(const_iterator first, const_iterator last, bool merge_objects = false) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + if (JSON_HEDLEY_UNLIKELY(!is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); + } + + // passed iterators must belong to objects + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object)); + } + + for (auto it = first; it != last; ++it) + { + if (merge_objects && it.value().is_object()) + { + auto it2 = m_value.object->find(it.key()); + if (it2 != m_value.object->end()) + { + it2->second.update(it.value(), true); + continue; + } + } + m_value.object->operator[](it.key()) = it.value(); +#if JSON_DIAGNOSTICS + m_value.object->operator[](it.key()).m_parent = this; +#endif + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(reference other) noexcept ( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value + ) + { + std::swap(m_type, other.m_type); + std::swap(m_value, other.m_value); + + set_parents(); + other.set_parents(); + assert_invariant(); + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + friend void swap(reference left, reference right) noexcept ( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value + ) + { + left.swap(right); + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(array_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + std::swap(*(m_value.array), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(object_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + std::swap(*(m_value.object), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(string_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_string())) + { + std::swap(*(m_value.string), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(binary_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_binary())) + { + std::swap(*(m_value.binary), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_binary())) + { + std::swap(*(m_value.binary), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @} + + public: + ////////////////////////////////////////// + // lexicographical comparison operators // + ////////////////////////////////////////// + + /// @name lexicographical comparison operators + /// @{ + + /// @brief comparison: equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ + friend bool operator==(const_reference lhs, const_reference rhs) noexcept + { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case value_t::array: + return *lhs.m_value.array == *rhs.m_value.array; + + case value_t::object: + return *lhs.m_value.object == *rhs.m_value.object; + + case value_t::null: + return true; + + case value_t::string: + return *lhs.m_value.string == *rhs.m_value.string; + + case value_t::boolean: + return lhs.m_value.boolean == rhs.m_value.boolean; + + case value_t::number_integer: + return lhs.m_value.number_integer == rhs.m_value.number_integer; + + case value_t::number_unsigned: + return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; + + case value_t::number_float: + return lhs.m_value.number_float == rhs.m_value.number_float; + + case value_t::binary: + return *lhs.m_value.binary == *rhs.m_value.binary; + + case value_t::discarded: + default: + return false; + } + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) + { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); + } + + return false; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + } + + /// @brief comparison: equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ + template::value, int>::type = 0> + friend bool operator==(const_reference lhs, ScalarType rhs) noexcept + { + return lhs == basic_json(rhs); + } + + /// @brief comparison: equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ + template::value, int>::type = 0> + friend bool operator==(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) == rhs; + } + + /// @brief comparison: not equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ + friend bool operator!=(const_reference lhs, const_reference rhs) noexcept + { + return !(lhs == rhs); + } + + /// @brief comparison: not equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ + template::value, int>::type = 0> + friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept + { + return lhs != basic_json(rhs); + } + + /// @brief comparison: not equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ + template::value, int>::type = 0> + friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) != rhs; + } + + /// @brief comparison: less than + /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ + friend bool operator<(const_reference lhs, const_reference rhs) noexcept + { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case value_t::array: + // note parentheses are necessary, see + // https://github.com/nlohmann/json/issues/1530 + return (*lhs.m_value.array) < (*rhs.m_value.array); + + case value_t::object: + return (*lhs.m_value.object) < (*rhs.m_value.object); + + case value_t::null: + return false; + + case value_t::string: + return (*lhs.m_value.string) < (*rhs.m_value.string); + + case value_t::boolean: + return (lhs.m_value.boolean) < (rhs.m_value.boolean); + + case value_t::number_integer: + return (lhs.m_value.number_integer) < (rhs.m_value.number_integer); + + case value_t::number_unsigned: + return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned); + + case value_t::number_float: + return (lhs.m_value.number_float) < (rhs.m_value.number_float); + + case value_t::binary: + return (*lhs.m_value.binary) < (*rhs.m_value.binary); + + case value_t::discarded: + default: + return false; + } + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) + { + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; + } + + // We only reach this line if we cannot compare values. In that case, + // we compare types. Note we have to call the operator explicitly, + // because MSVC has problems otherwise. + return operator<(lhs_type, rhs_type); + } + + /// @brief comparison: less than + /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ + template::value, int>::type = 0> + friend bool operator<(const_reference lhs, ScalarType rhs) noexcept + { + return lhs < basic_json(rhs); + } + + /// @brief comparison: less than + /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ + template::value, int>::type = 0> + friend bool operator<(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) < rhs; + } + + /// @brief comparison: less than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ + friend bool operator<=(const_reference lhs, const_reference rhs) noexcept + { + return !(rhs < lhs); + } + + /// @brief comparison: less than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ + template::value, int>::type = 0> + friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept + { + return lhs <= basic_json(rhs); + } + + /// @brief comparison: less than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ + template::value, int>::type = 0> + friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) <= rhs; + } + + /// @brief comparison: greater than + /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ + friend bool operator>(const_reference lhs, const_reference rhs) noexcept + { + return !(lhs <= rhs); + } + + /// @brief comparison: greater than + /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ + template::value, int>::type = 0> + friend bool operator>(const_reference lhs, ScalarType rhs) noexcept + { + return lhs > basic_json(rhs); + } + + /// @brief comparison: greater than + /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ + template::value, int>::type = 0> + friend bool operator>(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) > rhs; + } + + /// @brief comparison: greater than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ + friend bool operator>=(const_reference lhs, const_reference rhs) noexcept + { + return !(lhs < rhs); + } + + /// @brief comparison: greater than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ + template::value, int>::type = 0> + friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept + { + return lhs >= basic_json(rhs); + } + + /// @brief comparison: greater than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ + template::value, int>::type = 0> + friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) >= rhs; + } + + /// @} + + /////////////////// + // serialization // + /////////////////// + + /// @name serialization + /// @{ +#ifndef JSON_NO_IO + /// @brief serialize to stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ + friend std::ostream& operator<<(std::ostream& o, const basic_json& j) + { + // read width member and use it as indentation parameter if nonzero + const bool pretty_print = o.width() > 0; + const auto indentation = pretty_print ? o.width() : 0; + + // reset width to 0 for subsequent calls to this stream + o.width(0); + + // do the actual serialization + serializer s(detail::output_adapter(o), o.fill()); + s.dump(j, pretty_print, false, static_cast(indentation)); + return o; + } + + /// @brief serialize to stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ + /// @deprecated This function is deprecated since 3.0.0 and will be removed in + /// version 4.0.0 of the library. Please use + /// operator<<(std::ostream&, const basic_json&) instead; that is, + /// replace calls like `j >> o;` with `o << j;`. + JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) + friend std::ostream& operator>>(const basic_json& j, std::ostream& o) + { + return o << j; + } +#endif // JSON_NO_IO + /// @} + + + ///////////////////// + // deserialization // + ///////////////////// + + /// @name deserialization + /// @{ + + /// @brief deserialize from a compatible input + /// @sa https://json.nlohmann.me/api/basic_json/parse/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json parse(InputType&& i, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) + { + basic_json result; + parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } + + /// @brief deserialize from a pair of character iterators + /// @sa https://json.nlohmann.me/api/basic_json/parse/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json parse(IteratorType first, + IteratorType last, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) + { + basic_json result; + parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) + static basic_json parse(detail::span_input_adapter&& i, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) + { + basic_json result; + parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } + + /// @brief check if the input is valid JSON + /// @sa https://json.nlohmann.me/api/basic_json/accept/ + template + static bool accept(InputType&& i, + const bool ignore_comments = false) + { + return parser(detail::input_adapter(std::forward(i)), nullptr, false, ignore_comments).accept(true); + } + + /// @brief check if the input is valid JSON + /// @sa https://json.nlohmann.me/api/basic_json/accept/ + template + static bool accept(IteratorType first, IteratorType last, + const bool ignore_comments = false) + { + return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) + static bool accept(detail::span_input_adapter&& i, + const bool ignore_comments = false) + { + return parser(i.get(), nullptr, false, ignore_comments).accept(true); + } + + /// @brief generate SAX events + /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ + template + JSON_HEDLEY_NON_NULL(2) + static bool sax_parse(InputType&& i, SAX* sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) + { + auto ia = detail::input_adapter(std::forward(i)); + return format == input_format_t::json + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } + + /// @brief generate SAX events + /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ + template + JSON_HEDLEY_NON_NULL(3) + static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) + { + auto ia = detail::input_adapter(std::move(first), std::move(last)); + return format == input_format_t::json + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } + + /// @brief generate SAX events + /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ + /// @deprecated This function is deprecated since 3.8.0 and will be removed in + /// version 4.0.0 of the library. Please use + /// sax_parse(ptr, ptr + len) instead. + template + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) + JSON_HEDLEY_NON_NULL(2) + static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) + { + auto ia = i.get(); + return format == input_format_t::json + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } +#ifndef JSON_NO_IO + /// @brief deserialize from stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ + /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in + /// version 4.0.0 of the library. Please use + /// operator>>(std::istream&, basic_json&) instead; that is, + /// replace calls like `j << i;` with `i >> j;`. + JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) + friend std::istream& operator<<(basic_json& j, std::istream& i) + { + return operator>>(i, j); + } + + /// @brief deserialize from stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ + friend std::istream& operator>>(std::istream& i, basic_json& j) + { + parser(detail::input_adapter(i)).parse(false, j); + return i; + } +#endif // JSON_NO_IO + /// @} + + /////////////////////////// + // convenience functions // + /////////////////////////// + + /// @brief return the type as string + /// @sa https://json.nlohmann.me/api/basic_json/type_name/ + JSON_HEDLEY_RETURNS_NON_NULL + const char* type_name() const noexcept + { + switch (m_type) + { + case value_t::null: + return "null"; + case value_t::object: + return "object"; + case value_t::array: + return "array"; + case value_t::string: + return "string"; + case value_t::boolean: + return "boolean"; + case value_t::binary: + return "binary"; + case value_t::discarded: + return "discarded"; + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + default: + return "number"; + } + } + + + JSON_PRIVATE_UNLESS_TESTED: + ////////////////////// + // member variables // + ////////////////////// + + /// the type of the current element + value_t m_type = value_t::null; + + /// the value of the current element + json_value m_value = {}; + +#if JSON_DIAGNOSTICS + /// a pointer to a parent value (for debugging purposes) + basic_json* m_parent = nullptr; +#endif + + ////////////////////////////////////////// + // binary serialization/deserialization // + ////////////////////////////////////////// + + /// @name binary serialization/deserialization support + /// @{ + + public: + /// @brief create a CBOR serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ + static std::vector to_cbor(const basic_json& j) + { + std::vector result; + to_cbor(j, result); + return result; + } + + /// @brief create a CBOR serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ + static void to_cbor(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_cbor(j); + } + + /// @brief create a CBOR serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ + static void to_cbor(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_cbor(j); + } + + /// @brief create a MessagePack serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ + static std::vector to_msgpack(const basic_json& j) + { + std::vector result; + to_msgpack(j, result); + return result; + } + + /// @brief create a MessagePack serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ + static void to_msgpack(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_msgpack(j); + } + + /// @brief create a MessagePack serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ + static void to_msgpack(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_msgpack(j); + } + + /// @brief create a UBJSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ + static std::vector to_ubjson(const basic_json& j, + const bool use_size = false, + const bool use_type = false) + { + std::vector result; + to_ubjson(j, result, use_size, use_type); + return result; + } + + /// @brief create a UBJSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ + static void to_ubjson(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false) + { + binary_writer(o).write_ubjson(j, use_size, use_type); + } + + /// @brief create a UBJSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ + static void to_ubjson(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false) + { + binary_writer(o).write_ubjson(j, use_size, use_type); + } + + /// @brief create a BSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ + static std::vector to_bson(const basic_json& j) + { + std::vector result; + to_bson(j, result); + return result; + } + + /// @brief create a BSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ + static void to_bson(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_bson(j); + } + + /// @brief create a BSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ + static void to_bson(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_bson(j); + } + + /// @brief create a JSON value from an input in CBOR format + /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_cbor(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in CBOR format + /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_cbor(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) + static basic_json from_cbor(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); + } + + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) + static basic_json from_cbor(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in MessagePack format + /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_msgpack(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in MessagePack format + /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_msgpack(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) + static basic_json from_msgpack(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_msgpack(ptr, ptr + len, strict, allow_exceptions); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) + static basic_json from_msgpack(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in UBJSON format + /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_ubjson(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in UBJSON format + /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_ubjson(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) + static basic_json from_ubjson(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_ubjson(ptr, ptr + len, strict, allow_exceptions); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) + static basic_json from_ubjson(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in BSON format + /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_bson(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in BSON format + /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_bson(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) + static basic_json from_bson(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_bson(ptr, ptr + len, strict, allow_exceptions); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) + static basic_json from_bson(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + /// @} + + ////////////////////////// + // JSON Pointer support // + ////////////////////////// + + /// @name JSON Pointer functions + /// @{ + + /// @brief access specified element via JSON Pointer + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + reference operator[](const json_pointer& ptr) + { + return ptr.get_unchecked(this); + } + + /// @brief access specified element via JSON Pointer + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + const_reference operator[](const json_pointer& ptr) const + { + return ptr.get_unchecked(this); + } + + /// @brief access specified element via JSON Pointer + /// @sa https://json.nlohmann.me/api/basic_json/at/ + reference at(const json_pointer& ptr) + { + return ptr.get_checked(this); + } + + /// @brief access specified element via JSON Pointer + /// @sa https://json.nlohmann.me/api/basic_json/at/ + const_reference at(const json_pointer& ptr) const + { + return ptr.get_checked(this); + } + + /// @brief return flattened JSON value + /// @sa https://json.nlohmann.me/api/basic_json/flatten/ + basic_json flatten() const + { + basic_json result(value_t::object); + json_pointer::flatten("", *this, result); + return result; + } + + /// @brief unflatten a previously flattened JSON value + /// @sa https://json.nlohmann.me/api/basic_json/unflatten/ + basic_json unflatten() const + { + return json_pointer::unflatten(*this); + } + + /// @} + + ////////////////////////// + // JSON Patch functions // + ////////////////////////// + + /// @name JSON Patch functions + /// @{ + + /// @brief applies a JSON patch + /// @sa https://json.nlohmann.me/api/basic_json/patch/ + basic_json patch(const basic_json& json_patch) const + { + // make a working copy to apply the patch to + basic_json result = *this; + + // the valid JSON Patch operations + enum class patch_operations {add, remove, replace, move, copy, test, invalid}; + + const auto get_op = [](const std::string & op) + { + if (op == "add") + { + return patch_operations::add; + } + if (op == "remove") + { + return patch_operations::remove; + } + if (op == "replace") + { + return patch_operations::replace; + } + if (op == "move") + { + return patch_operations::move; + } + if (op == "copy") + { + return patch_operations::copy; + } + if (op == "test") + { + return patch_operations::test; + } + + return patch_operations::invalid; + }; + + // wrapper for "add" operation; add value at ptr + const auto operation_add = [&result](json_pointer & ptr, basic_json val) + { + // adding to the root of the target document means replacing it + if (ptr.empty()) + { + result = val; + return; + } + + // make sure the top element of the pointer exists + json_pointer top_pointer = ptr.top(); + if (top_pointer != ptr) + { + result.at(top_pointer); + } + + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.back(); + ptr.pop_back(); + basic_json& parent = result[ptr]; + + switch (parent.m_type) + { + case value_t::null: + case value_t::object: + { + // use operator[] to add value + parent[last_path] = val; + break; + } + + case value_t::array: + { + if (last_path == "-") + { + // special case: append to back + parent.push_back(val); + } + else + { + const auto idx = json_pointer::array_index(last_path); + if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) + { + // avoid undefined behavior + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent)); + } + + // default case: insert add offset + parent.insert(parent.begin() + static_cast(idx), val); + } + break; + } + + // if there exists a parent it cannot be primitive + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + }; + + // wrapper for "remove" operation; remove value at ptr + const auto operation_remove = [this, &result](json_pointer & ptr) + { + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.back(); + ptr.pop_back(); + basic_json& parent = result.at(ptr); + + // remove child + if (parent.is_object()) + { + // perform range check + auto it = parent.find(last_path); + if (JSON_HEDLEY_LIKELY(it != parent.end())) + { + parent.erase(it); + } + else + { + JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this)); + } + } + else if (parent.is_array()) + { + // note erase performs range check + parent.erase(json_pointer::array_index(last_path)); + } + }; + + // type check: top level value must be an array + if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) + { + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch)); + } + + // iterate and apply the operations + for (const auto& val : json_patch) + { + // wrapper to get a value for an operation + const auto get_value = [&val](const std::string & op, + const std::string & member, + bool string_type) -> basic_json & + { + // find value + auto it = val.m_value.object->find(member); + + // context-sensitive error message + const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; + + // check if desired value is present + if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) + { + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val)); + } + + // check if result is of type string + if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) + { + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val)); + } + + // no error: return value + return it->second; + }; + + // type check: every element of the array must be an object + if (JSON_HEDLEY_UNLIKELY(!val.is_object())) + { + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val)); + } + + // collect mandatory members + const auto op = get_value("op", "op", true).template get(); + const auto path = get_value(op, "path", true).template get(); + json_pointer ptr(path); + + switch (get_op(op)) + { + case patch_operations::add: + { + operation_add(ptr, get_value("add", "value", false)); + break; + } + + case patch_operations::remove: + { + operation_remove(ptr); + break; + } + + case patch_operations::replace: + { + // the "path" location must exist - use at() + result.at(ptr) = get_value("replace", "value", false); + break; + } + + case patch_operations::move: + { + const auto from_path = get_value("move", "from", true).template get(); + json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The move operation is functionally identical to a + // "remove" operation on the "from" location, followed + // immediately by an "add" operation at the target + // location with the value that was just removed. + operation_remove(from_ptr); + operation_add(ptr, v); + break; + } + + case patch_operations::copy: + { + const auto from_path = get_value("copy", "from", true).template get(); + const json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The copy is functionally identical to an "add" + // operation at the target location using the value + // specified in the "from" member. + operation_add(ptr, v); + break; + } + + case patch_operations::test: + { + bool success = false; + JSON_TRY + { + // check if "value" matches the one at "path" + // the "path" location must exist - use at() + success = (result.at(ptr) == get_value("test", "value", false)); + } + JSON_INTERNAL_CATCH (out_of_range&) + { + // ignore out of range errors: success remains false + } + + // throw an exception if test fails + if (JSON_HEDLEY_UNLIKELY(!success)) + { + JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val)); + } + + break; + } + + case patch_operations::invalid: + default: + { + // op must be "add", "remove", "replace", "move", "copy", or + // "test" + JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val)); + } + } + } + + return result; + } + + /// @brief creates a diff as a JSON patch + /// @sa https://json.nlohmann.me/api/basic_json/diff/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json diff(const basic_json& source, const basic_json& target, + const std::string& path = "") + { + // the patch + basic_json result(value_t::array); + + // if the values are the same, return empty patch + if (source == target) + { + return result; + } + + if (source.type() != target.type()) + { + // different types: replace value + result.push_back( + { + {"op", "replace"}, {"path", path}, {"value", target} + }); + return result; + } + + switch (source.type()) + { + case value_t::array: + { + // first pass: traverse common elements + std::size_t i = 0; + while (i < source.size() && i < target.size()) + { + // recursive call to compare array values at index i + auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + ++i; + } + + // We now reached the end of at least one array + // in a second pass, traverse the remaining elements + + // remove my remaining elements + const auto end_index = static_cast(result.size()); + while (i < source.size()) + { + // add operations in reverse order to avoid invalid + // indices + result.insert(result.begin() + end_index, object( + { + {"op", "remove"}, + {"path", path + "/" + std::to_string(i)} + })); + ++i; + } + + // add other remaining elements + while (i < target.size()) + { + result.push_back( + { + {"op", "add"}, + {"path", path + "/-"}, + {"value", target[i]} + }); + ++i; + } + + break; + } + + case value_t::object: + { + // first pass: traverse this object's elements + for (auto it = source.cbegin(); it != source.cend(); ++it) + { + // escape the key name to be used in a JSON patch + const auto path_key = path + "/" + detail::escape(it.key()); + + if (target.find(it.key()) != target.end()) + { + // recursive call to compare object values at key it + auto temp_diff = diff(it.value(), target[it.key()], path_key); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + } + else + { + // found a key that is not in o -> remove it + result.push_back(object( + { + {"op", "remove"}, {"path", path_key} + })); + } + } + + // second pass: traverse other object's elements + for (auto it = target.cbegin(); it != target.cend(); ++it) + { + if (source.find(it.key()) == source.end()) + { + // found a key that is not in this -> add it + const auto path_key = path + "/" + detail::escape(it.key()); + result.push_back( + { + {"op", "add"}, {"path", path_key}, + {"value", it.value()} + }); + } + } + + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // both primitive type: replace value + result.push_back( + { + {"op", "replace"}, {"path", path}, {"value", target} + }); + break; + } + } + + return result; + } + + /// @} + + //////////////////////////////// + // JSON Merge Patch functions // + //////////////////////////////// + + /// @name JSON Merge Patch functions + /// @{ + + /// @brief applies a JSON Merge Patch + /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/ + void merge_patch(const basic_json& apply_patch) + { + if (apply_patch.is_object()) + { + if (!is_object()) + { + *this = object(); + } + for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) + { + if (it.value().is_null()) + { + erase(it.key()); + } + else + { + operator[](it.key()).merge_patch(it.value()); + } + } + } + else + { + *this = apply_patch; + } + } + + /// @} +}; + +/// @brief user-defined to_string function for JSON values +/// @sa https://json.nlohmann.me/api/basic_json/to_string/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) +{ + return j.dump(); +} + +} // namespace nlohmann + +/////////////////////// +// nonmember support // +/////////////////////// + +namespace std // NOLINT(cert-dcl58-cpp) +{ + +/// @brief hash value for JSON objects +/// @sa https://json.nlohmann.me/api/basic_json/std_hash/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct hash +{ + std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const + { + return nlohmann::detail::hash(j); + } +}; + +// specialization for std::less +template<> +struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679 +{ + /*! + @brief compare two value_t enum values + @since version 3.0.0 + */ + bool operator()(nlohmann::detail::value_t lhs, + nlohmann::detail::value_t rhs) const noexcept + { + return nlohmann::detail::operator<(lhs, rhs); + } +}; + +// C++20 prohibit function specialization in the std namespace. +#ifndef JSON_HAS_CPP_20 + +/// @brief exchanges the values of two JSON objects +/// @sa https://json.nlohmann.me/api/basic_json/std_swap/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name) + is_nothrow_move_constructible::value&& // NOLINT(misc-redundant-expression) + is_nothrow_move_assignable::value) +{ + j1.swap(j2); +} + +#endif + +} // namespace std + +/// @brief user-defined string literal for JSON values +/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json operator "" _json(const char* s, std::size_t n) +{ + return nlohmann::json::parse(s, s + n); +} + +/// @brief user-defined string literal for JSON pointer +/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) +{ + return nlohmann::json::json_pointer(std::string(s, n)); +} + +// #include + + +// restore clang diagnostic settings +#if defined(__clang__) + #pragma clang diagnostic pop +#endif + +// clean up +#undef JSON_ASSERT +#undef JSON_INTERNAL_CATCH +#undef JSON_CATCH +#undef JSON_THROW +#undef JSON_TRY +#undef JSON_PRIVATE_UNLESS_TESTED +#undef JSON_HAS_CPP_11 +#undef JSON_HAS_CPP_14 +#undef JSON_HAS_CPP_17 +#undef JSON_HAS_CPP_20 +#undef JSON_HAS_FILESYSTEM +#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM +#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION +#undef NLOHMANN_BASIC_JSON_TPL +#undef JSON_EXPLICIT +#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL + +// #include + + +#undef JSON_HEDLEY_ALWAYS_INLINE +#undef JSON_HEDLEY_ARM_VERSION +#undef JSON_HEDLEY_ARM_VERSION_CHECK +#undef JSON_HEDLEY_ARRAY_PARAM +#undef JSON_HEDLEY_ASSUME +#undef JSON_HEDLEY_BEGIN_C_DECLS +#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#undef JSON_HEDLEY_CLANG_HAS_FEATURE +#undef JSON_HEDLEY_CLANG_HAS_WARNING +#undef JSON_HEDLEY_COMPCERT_VERSION +#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#undef JSON_HEDLEY_CONCAT +#undef JSON_HEDLEY_CONCAT3 +#undef JSON_HEDLEY_CONCAT3_EX +#undef JSON_HEDLEY_CONCAT_EX +#undef JSON_HEDLEY_CONST +#undef JSON_HEDLEY_CONSTEXPR +#undef JSON_HEDLEY_CONST_CAST +#undef JSON_HEDLEY_CPP_CAST +#undef JSON_HEDLEY_CRAY_VERSION +#undef JSON_HEDLEY_CRAY_VERSION_CHECK +#undef JSON_HEDLEY_C_DECL +#undef JSON_HEDLEY_DEPRECATED +#undef JSON_HEDLEY_DEPRECATED_FOR +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#undef JSON_HEDLEY_DIAGNOSTIC_POP +#undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#undef JSON_HEDLEY_DMC_VERSION +#undef JSON_HEDLEY_DMC_VERSION_CHECK +#undef JSON_HEDLEY_EMPTY_BASES +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#undef JSON_HEDLEY_END_C_DECLS +#undef JSON_HEDLEY_FLAGS +#undef JSON_HEDLEY_FLAGS_CAST +#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_BUILTIN +#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_EXTENSION +#undef JSON_HEDLEY_GCC_HAS_FEATURE +#undef JSON_HEDLEY_GCC_HAS_WARNING +#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#undef JSON_HEDLEY_GCC_VERSION +#undef JSON_HEDLEY_GCC_VERSION_CHECK +#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#undef JSON_HEDLEY_GNUC_HAS_FEATURE +#undef JSON_HEDLEY_GNUC_HAS_WARNING +#undef JSON_HEDLEY_GNUC_VERSION +#undef JSON_HEDLEY_GNUC_VERSION_CHECK +#undef JSON_HEDLEY_HAS_ATTRIBUTE +#undef JSON_HEDLEY_HAS_BUILTIN +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_HAS_EXTENSION +#undef JSON_HEDLEY_HAS_FEATURE +#undef JSON_HEDLEY_HAS_WARNING +#undef JSON_HEDLEY_IAR_VERSION +#undef JSON_HEDLEY_IAR_VERSION_CHECK +#undef JSON_HEDLEY_IBM_VERSION +#undef JSON_HEDLEY_IBM_VERSION_CHECK +#undef JSON_HEDLEY_IMPORT +#undef JSON_HEDLEY_INLINE +#undef JSON_HEDLEY_INTEL_CL_VERSION +#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#undef JSON_HEDLEY_INTEL_VERSION +#undef JSON_HEDLEY_INTEL_VERSION_CHECK +#undef JSON_HEDLEY_IS_CONSTANT +#undef JSON_HEDLEY_IS_CONSTEXPR_ +#undef JSON_HEDLEY_LIKELY +#undef JSON_HEDLEY_MALLOC +#undef JSON_HEDLEY_MCST_LCC_VERSION +#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#undef JSON_HEDLEY_MESSAGE +#undef JSON_HEDLEY_MSVC_VERSION +#undef JSON_HEDLEY_MSVC_VERSION_CHECK +#undef JSON_HEDLEY_NEVER_INLINE +#undef JSON_HEDLEY_NON_NULL +#undef JSON_HEDLEY_NO_ESCAPE +#undef JSON_HEDLEY_NO_RETURN +#undef JSON_HEDLEY_NO_THROW +#undef JSON_HEDLEY_NULL +#undef JSON_HEDLEY_PELLES_VERSION +#undef JSON_HEDLEY_PELLES_VERSION_CHECK +#undef JSON_HEDLEY_PGI_VERSION +#undef JSON_HEDLEY_PGI_VERSION_CHECK +#undef JSON_HEDLEY_PREDICT +#undef JSON_HEDLEY_PRINTF_FORMAT +#undef JSON_HEDLEY_PRIVATE +#undef JSON_HEDLEY_PUBLIC +#undef JSON_HEDLEY_PURE +#undef JSON_HEDLEY_REINTERPRET_CAST +#undef JSON_HEDLEY_REQUIRE +#undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#undef JSON_HEDLEY_REQUIRE_MSG +#undef JSON_HEDLEY_RESTRICT +#undef JSON_HEDLEY_RETURNS_NON_NULL +#undef JSON_HEDLEY_SENTINEL +#undef JSON_HEDLEY_STATIC_ASSERT +#undef JSON_HEDLEY_STATIC_CAST +#undef JSON_HEDLEY_STRINGIFY +#undef JSON_HEDLEY_STRINGIFY_EX +#undef JSON_HEDLEY_SUNPRO_VERSION +#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#undef JSON_HEDLEY_TINYC_VERSION +#undef JSON_HEDLEY_TINYC_VERSION_CHECK +#undef JSON_HEDLEY_TI_ARMCL_VERSION +#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL2000_VERSION +#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL430_VERSION +#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL6X_VERSION +#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL7X_VERSION +#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#undef JSON_HEDLEY_TI_CLPRU_VERSION +#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#undef JSON_HEDLEY_TI_VERSION +#undef JSON_HEDLEY_TI_VERSION_CHECK +#undef JSON_HEDLEY_UNAVAILABLE +#undef JSON_HEDLEY_UNLIKELY +#undef JSON_HEDLEY_UNPREDICTABLE +#undef JSON_HEDLEY_UNREACHABLE +#undef JSON_HEDLEY_UNREACHABLE_RETURN +#undef JSON_HEDLEY_VERSION +#undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#undef JSON_HEDLEY_VERSION_DECODE_MINOR +#undef JSON_HEDLEY_VERSION_DECODE_REVISION +#undef JSON_HEDLEY_VERSION_ENCODE +#undef JSON_HEDLEY_WARNING +#undef JSON_HEDLEY_WARN_UNUSED_RESULT +#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#undef JSON_HEDLEY_FALL_THROUGH + + + +#endif // INCLUDE_NLOHMANN_JSON_HPP_ diff --git a/deps/include/yaml-cpp/anchor.h b/deps/include/yaml-cpp/anchor.h new file mode 100644 index 000000000..f46d1d79d --- /dev/null +++ b/deps/include/yaml-cpp/anchor.h @@ -0,0 +1,17 @@ +#ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include + +namespace YAML { +using anchor_t = std::size_t; +const anchor_t NullAnchor = 0; +} + +#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/binary.h b/deps/include/yaml-cpp/binary.h new file mode 100644 index 000000000..1050dae98 --- /dev/null +++ b/deps/include/yaml-cpp/binary.h @@ -0,0 +1,71 @@ +#ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include + +#include "yaml-cpp/dll.h" + +namespace YAML { +YAML_CPP_API std::string EncodeBase64(const unsigned char *data, + std::size_t size); +YAML_CPP_API std::vector DecodeBase64(const std::string &input); + +class YAML_CPP_API Binary { + public: + Binary(const unsigned char *data_, std::size_t size_) + : m_data{}, m_unownedData(data_), m_unownedSize(size_) {} + Binary() : Binary(nullptr, 0) {} + Binary(const Binary &) = default; + Binary(Binary &&) = default; + Binary &operator=(const Binary &) = default; + Binary &operator=(Binary &&) = default; + + bool owned() const { return !m_unownedData; } + std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; } + const unsigned char *data() const { + return owned() ? &m_data[0] : m_unownedData; + } + + void swap(std::vector &rhs) { + if (m_unownedData) { + m_data.swap(rhs); + rhs.clear(); + rhs.resize(m_unownedSize); + std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin()); + m_unownedData = nullptr; + m_unownedSize = 0; + } else { + m_data.swap(rhs); + } + } + + bool operator==(const Binary &rhs) const { + const std::size_t s = size(); + if (s != rhs.size()) + return false; + const unsigned char *d1 = data(); + const unsigned char *d2 = rhs.data(); + for (std::size_t i = 0; i < s; i++) { + if (*d1++ != *d2++) + return false; + } + return true; + } + + bool operator!=(const Binary &rhs) const { return !(*this == rhs); } + + private: + std::vector m_data; + const unsigned char *m_unownedData; + std::size_t m_unownedSize; +}; +} // namespace YAML + +#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/contrib/anchordict.h b/deps/include/yaml-cpp/contrib/anchordict.h new file mode 100644 index 000000000..1b7809b87 --- /dev/null +++ b/deps/include/yaml-cpp/contrib/anchordict.h @@ -0,0 +1,40 @@ +#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include + +#include "../anchor.h" + +namespace YAML { +/** + * An object that stores and retrieves values correlating to {@link anchor_t} + * values. + * + *

Efficient implementation that can make assumptions about how + * {@code anchor_t} values are assigned by the {@link Parser} class. + */ +template +class AnchorDict { + public: + AnchorDict() : m_data{} {} + void Register(anchor_t anchor, T value) { + if (anchor > m_data.size()) { + m_data.resize(anchor); + } + m_data[anchor - 1] = value; + } + + T Get(anchor_t anchor) const { return m_data[anchor - 1]; } + + private: + std::vector m_data; +}; +} // namespace YAML + +#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/contrib/graphbuilder.h b/deps/include/yaml-cpp/contrib/graphbuilder.h new file mode 100644 index 000000000..dbffd921e --- /dev/null +++ b/deps/include/yaml-cpp/contrib/graphbuilder.h @@ -0,0 +1,149 @@ +#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/mark.h" +#include + +namespace YAML { +class Parser; + +// GraphBuilderInterface +// . Abstraction of node creation +// . pParentNode is always nullptr or the return value of one of the NewXXX() +// functions. +class GraphBuilderInterface { + public: + virtual ~GraphBuilderInterface() = 0; + + // Create and return a new node with a null value. + virtual void *NewNull(const Mark &mark, void *pParentNode) = 0; + + // Create and return a new node with the given tag and value. + virtual void *NewScalar(const Mark &mark, const std::string &tag, + void *pParentNode, const std::string &value) = 0; + + // Create and return a new sequence node + virtual void *NewSequence(const Mark &mark, const std::string &tag, + void *pParentNode) = 0; + + // Add pNode to pSequence. pNode was created with one of the NewXxx() + // functions and pSequence with NewSequence(). + virtual void AppendToSequence(void *pSequence, void *pNode) = 0; + + // Note that no moew entries will be added to pSequence + virtual void SequenceComplete(void *pSequence) { (void)pSequence; } + + // Create and return a new map node + virtual void *NewMap(const Mark &mark, const std::string &tag, + void *pParentNode) = 0; + + // Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode + // were created with one of the NewXxx() methods and pMap with NewMap(). + virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0; + + // Note that no more assignments will be made in pMap + virtual void MapComplete(void *pMap) { (void)pMap; } + + // Return the node that should be used in place of an alias referencing + // pNode (pNode by default) + virtual void *AnchorReference(const Mark &mark, void *pNode) { + (void)mark; + return pNode; + } +}; + +// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines +// Node, Sequence, and Map types. Sequence and Map must derive from Node +// (unless Node is defined as void). Impl must also implement function with +// all of the same names as the virtual functions in GraphBuilderInterface +// -- including the ones with default implementations -- but with the +// prototypes changed to accept an explicit Node*, Sequence*, or Map* where +// appropriate. +template +class GraphBuilder : public GraphBuilderInterface { + public: + typedef typename Impl::Node Node; + typedef typename Impl::Sequence Sequence; + typedef typename Impl::Map Map; + + GraphBuilder(Impl &impl) : m_impl(impl) { + Map *pMap = nullptr; + Sequence *pSeq = nullptr; + Node *pNode = nullptr; + + // Type consistency checks + pNode = pMap; + pNode = pSeq; + } + + GraphBuilderInterface &AsBuilderInterface() { return *this; } + + virtual void *NewNull(const Mark &mark, void *pParentNode) { + return CheckType(m_impl.NewNull(mark, AsNode(pParentNode))); + } + + virtual void *NewScalar(const Mark &mark, const std::string &tag, + void *pParentNode, const std::string &value) { + return CheckType( + m_impl.NewScalar(mark, tag, AsNode(pParentNode), value)); + } + + virtual void *NewSequence(const Mark &mark, const std::string &tag, + void *pParentNode) { + return CheckType( + m_impl.NewSequence(mark, tag, AsNode(pParentNode))); + } + virtual void AppendToSequence(void *pSequence, void *pNode) { + m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode)); + } + virtual void SequenceComplete(void *pSequence) { + m_impl.SequenceComplete(AsSequence(pSequence)); + } + + virtual void *NewMap(const Mark &mark, const std::string &tag, + void *pParentNode) { + return CheckType(m_impl.NewMap(mark, tag, AsNode(pParentNode))); + } + virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) { + m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode)); + } + virtual void MapComplete(void *pMap) { m_impl.MapComplete(AsMap(pMap)); } + + virtual void *AnchorReference(const Mark &mark, void *pNode) { + return CheckType(m_impl.AnchorReference(mark, AsNode(pNode))); + } + + private: + Impl &m_impl; + + // Static check for pointer to T + template + static T *CheckType(U *p) { + return p; + } + + static Node *AsNode(void *pNode) { return static_cast(pNode); } + static Sequence *AsSequence(void *pSeq) { + return static_cast(pSeq); + } + static Map *AsMap(void *pMap) { return static_cast(pMap); } +}; + +void *BuildGraphOfNextDocument(Parser &parser, + GraphBuilderInterface &graphBuilder); + +template +typename Impl::Node *BuildGraphOfNextDocument(Parser &parser, Impl &impl) { + GraphBuilder graphBuilder(impl); + return static_cast( + BuildGraphOfNextDocument(parser, graphBuilder)); +} +} + +#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/depthguard.h b/deps/include/yaml-cpp/depthguard.h new file mode 100644 index 000000000..8ca61ac6c --- /dev/null +++ b/deps/include/yaml-cpp/depthguard.h @@ -0,0 +1,77 @@ +#ifndef DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000 +#define DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "exceptions.h" + +namespace YAML { + +/** + * @brief The DeepRecursion class + * An exception class which is thrown by DepthGuard. Ideally it should be + * a member of DepthGuard. However, DepthGuard is a templated class which means + * that any catch points would then need to know the template parameters. It is + * simpler for clients to not have to know at the catch point what was the + * maximum depth. + */ +class DeepRecursion : public ParserException { +public: + virtual ~DeepRecursion() = default; + + DeepRecursion(int depth, const Mark& mark_, const std::string& msg_); + + // Returns the recursion depth when the exception was thrown + int depth() const { + return m_depth; + } + +private: + int m_depth = 0; +}; + +/** + * @brief The DepthGuard class + * DepthGuard takes a reference to an integer. It increments the integer upon + * construction of DepthGuard and decrements the integer upon destruction. + * + * If the integer would be incremented past max_depth, then an exception is + * thrown. This is ideally geared toward guarding against deep recursion. + * + * @param max_depth + * compile-time configurable maximum depth. + */ +template +class DepthGuard final { +public: + DepthGuard(int & depth_, const Mark& mark_, const std::string& msg_) : m_depth(depth_) { + ++m_depth; + if ( max_depth <= m_depth ) { + throw DeepRecursion{m_depth, mark_, msg_}; + } + } + + DepthGuard(const DepthGuard & copy_ctor) = delete; + DepthGuard(DepthGuard && move_ctor) = delete; + DepthGuard & operator=(const DepthGuard & copy_assign) = delete; + DepthGuard & operator=(DepthGuard && move_assign) = delete; + + ~DepthGuard() { + --m_depth; + } + + int current_depth() const { + return m_depth; + } + +private: + int & m_depth; +}; + +} // namespace YAML + +#endif // DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000 diff --git a/deps/include/yaml-cpp/dll.h b/deps/include/yaml-cpp/dll.h new file mode 100644 index 000000000..eabdda1d9 --- /dev/null +++ b/deps/include/yaml-cpp/dll.h @@ -0,0 +1,61 @@ +#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +// Definition YAML_CPP_STATIC_DEFINE using to building YAML-CPP as static +// library (definition created by CMake or defined manually) + +// Definition yaml_cpp_EXPORTS using to building YAML-CPP as dll/so library +// (definition created by CMake or defined manually) + +#ifdef YAML_CPP_STATIC_DEFINE +# define YAML_CPP_API +# define YAML_CPP_NO_EXPORT +#else +# if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) +# ifndef YAML_CPP_API +# ifdef yaml_cpp_EXPORTS + /* We are building this library */ +# pragma message( "Defining YAML_CPP_API for DLL export" ) +# define YAML_CPP_API __declspec(dllexport) +# else + /* We are using this library */ +# pragma message( "Defining YAML_CPP_API for DLL import" ) +# define YAML_CPP_API __declspec(dllimport) +# endif +# endif +# ifndef YAML_CPP_NO_EXPORT +# define YAML_CPP_NO_EXPORT +# endif +# else /* No _MSC_VER */ +# ifndef YAML_CPP_API +# ifdef yaml_cpp_EXPORTS + /* We are building this library */ +# define YAML_CPP_API __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define YAML_CPP_API __attribute__((visibility("default"))) +# endif +# endif +# ifndef YAML_CPP_NO_EXPORT +# define YAML_CPP_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +# endif /* _MSC_VER */ +#endif /* YAML_CPP_STATIC_DEFINE */ + +#ifndef YAML_CPP_DEPRECATED +# ifdef _MSC_VER +# define YAML_CPP_DEPRECATED __declspec(deprecated) +# else +# define YAML_CPP_DEPRECATED __attribute__ ((__deprecated__)) +# endif +#endif + +#ifndef YAML_CPP_DEPRECATED_EXPORT +# define YAML_CPP_DEPRECATED_EXPORT YAML_CPP_API YAML_CPP_DEPRECATED +#endif + +#ifndef YAML_CPP_DEPRECATED_NO_EXPORT +# define YAML_CPP_DEPRECATED_NO_EXPORT YAML_CPP_NO_EXPORT YAML_CPP_DEPRECATED +#endif + +#endif /* DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 */ diff --git a/deps/include/yaml-cpp/emitfromevents.h b/deps/include/yaml-cpp/emitfromevents.h new file mode 100644 index 000000000..1f389c5a1 --- /dev/null +++ b/deps/include/yaml-cpp/emitfromevents.h @@ -0,0 +1,57 @@ +#ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include + +#include "yaml-cpp/anchor.h" +#include "yaml-cpp/emitterstyle.h" +#include "yaml-cpp/eventhandler.h" + +namespace YAML { +struct Mark; +} // namespace YAML + +namespace YAML { +class Emitter; + +class EmitFromEvents : public EventHandler { + public: + EmitFromEvents(Emitter& emitter); + + void OnDocumentStart(const Mark& mark) override; + void OnDocumentEnd() override; + + void OnNull(const Mark& mark, anchor_t anchor) override; + void OnAlias(const Mark& mark, anchor_t anchor) override; + void OnScalar(const Mark& mark, const std::string& tag, + anchor_t anchor, const std::string& value) override; + + void OnSequenceStart(const Mark& mark, const std::string& tag, + anchor_t anchor, EmitterStyle::value style) override; + void OnSequenceEnd() override; + + void OnMapStart(const Mark& mark, const std::string& tag, + anchor_t anchor, EmitterStyle::value style) override; + void OnMapEnd() override; + + private: + void BeginNode(); + void EmitProps(const std::string& tag, anchor_t anchor); + + private: + Emitter& m_emitter; + + struct State { + enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue }; + }; + std::stack m_stateStack; +}; +} + +#endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/emitter.h b/deps/include/yaml-cpp/emitter.h new file mode 100644 index 000000000..210b1ec97 --- /dev/null +++ b/deps/include/yaml-cpp/emitter.h @@ -0,0 +1,281 @@ +#ifndef EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "yaml-cpp/binary.h" +#include "yaml-cpp/dll.h" +#include "yaml-cpp/emitterdef.h" +#include "yaml-cpp/emittermanip.h" +#include "yaml-cpp/null.h" +#include "yaml-cpp/ostream_wrapper.h" + +namespace YAML { +class Binary; +struct _Null; +} // namespace YAML + +namespace YAML { +class EmitterState; + +class YAML_CPP_API Emitter { + public: + Emitter(); + explicit Emitter(std::ostream& stream); + Emitter(const Emitter&) = delete; + Emitter& operator=(const Emitter&) = delete; + ~Emitter(); + + // output + const char* c_str() const; + std::size_t size() const; + + // state checking + bool good() const; + const std::string GetLastError() const; + + // global setters + bool SetOutputCharset(EMITTER_MANIP value); + bool SetStringFormat(EMITTER_MANIP value); + bool SetBoolFormat(EMITTER_MANIP value); + bool SetNullFormat(EMITTER_MANIP value); + bool SetIntBase(EMITTER_MANIP value); + bool SetSeqFormat(EMITTER_MANIP value); + bool SetMapFormat(EMITTER_MANIP value); + bool SetIndent(std::size_t n); + bool SetPreCommentIndent(std::size_t n); + bool SetPostCommentIndent(std::size_t n); + bool SetFloatPrecision(std::size_t n); + bool SetDoublePrecision(std::size_t n); + void RestoreGlobalModifiedSettings(); + + // local setters + Emitter& SetLocalValue(EMITTER_MANIP value); + Emitter& SetLocalIndent(const _Indent& indent); + Emitter& SetLocalPrecision(const _Precision& precision); + + // overloads of write + Emitter& Write(const std::string& str); + Emitter& Write(bool b); + Emitter& Write(char ch); + Emitter& Write(const _Alias& alias); + Emitter& Write(const _Anchor& anchor); + Emitter& Write(const _Tag& tag); + Emitter& Write(const _Comment& comment); + Emitter& Write(const _Null& n); + Emitter& Write(const Binary& binary); + + template + Emitter& WriteIntegralType(T value); + + template + Emitter& WriteStreamable(T value); + + private: + template + void SetStreamablePrecision(std::stringstream&) {} + std::size_t GetFloatPrecision() const; + std::size_t GetDoublePrecision() const; + + void PrepareIntegralStream(std::stringstream& stream) const; + void StartedScalar(); + + private: + void EmitBeginDoc(); + void EmitEndDoc(); + void EmitBeginSeq(); + void EmitEndSeq(); + void EmitBeginMap(); + void EmitEndMap(); + void EmitNewline(); + void EmitKindTag(); + void EmitTag(bool verbatim, const _Tag& tag); + + void PrepareNode(EmitterNodeType::value child); + void PrepareTopNode(EmitterNodeType::value child); + void FlowSeqPrepareNode(EmitterNodeType::value child); + void BlockSeqPrepareNode(EmitterNodeType::value child); + + void FlowMapPrepareNode(EmitterNodeType::value child); + + void FlowMapPrepareLongKey(EmitterNodeType::value child); + void FlowMapPrepareLongKeyValue(EmitterNodeType::value child); + void FlowMapPrepareSimpleKey(EmitterNodeType::value child); + void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child); + + void BlockMapPrepareNode(EmitterNodeType::value child); + + void BlockMapPrepareLongKey(EmitterNodeType::value child); + void BlockMapPrepareLongKeyValue(EmitterNodeType::value child); + void BlockMapPrepareSimpleKey(EmitterNodeType::value child); + void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child); + + void SpaceOrIndentTo(bool requireSpace, std::size_t indent); + + const char* ComputeFullBoolName(bool b) const; + const char* ComputeNullName() const; + bool CanEmitNewline() const; + + private: + std::unique_ptr m_pState; + ostream_wrapper m_stream; +}; + +template +inline Emitter& Emitter::WriteIntegralType(T value) { + if (!good()) + return *this; + + PrepareNode(EmitterNodeType::Scalar); + + std::stringstream stream; + PrepareIntegralStream(stream); + stream << value; + m_stream << stream.str(); + + StartedScalar(); + + return *this; +} + +template +inline Emitter& Emitter::WriteStreamable(T value) { + if (!good()) + return *this; + + PrepareNode(EmitterNodeType::Scalar); + + std::stringstream stream; + SetStreamablePrecision(stream); + + bool special = false; + if (std::is_floating_point::value) { + if ((std::numeric_limits::has_quiet_NaN || + std::numeric_limits::has_signaling_NaN) && + std::isnan(value)) { + special = true; + stream << ".nan"; + } else if (std::numeric_limits::has_infinity && std::isinf(value)) { + special = true; + if (std::signbit(value)) { + stream << "-.inf"; + } else { + stream << ".inf"; + } + } + } + + if (!special) { + stream << value; + } + m_stream << stream.str(); + + StartedScalar(); + + return *this; +} + +template <> +inline void Emitter::SetStreamablePrecision(std::stringstream& stream) { + stream.precision(static_cast(GetFloatPrecision())); +} + +template <> +inline void Emitter::SetStreamablePrecision(std::stringstream& stream) { + stream.precision(static_cast(GetDoublePrecision())); +} + +// overloads of insertion +inline Emitter& operator<<(Emitter& emitter, const std::string& v) { + return emitter.Write(v); +} +inline Emitter& operator<<(Emitter& emitter, bool v) { + return emitter.Write(v); +} +inline Emitter& operator<<(Emitter& emitter, char v) { + return emitter.Write(v); +} +inline Emitter& operator<<(Emitter& emitter, unsigned char v) { + return emitter.Write(static_cast(v)); +} +inline Emitter& operator<<(Emitter& emitter, const _Alias& v) { + return emitter.Write(v); +} +inline Emitter& operator<<(Emitter& emitter, const _Anchor& v) { + return emitter.Write(v); +} +inline Emitter& operator<<(Emitter& emitter, const _Tag& v) { + return emitter.Write(v); +} +inline Emitter& operator<<(Emitter& emitter, const _Comment& v) { + return emitter.Write(v); +} +inline Emitter& operator<<(Emitter& emitter, const _Null& v) { + return emitter.Write(v); +} +inline Emitter& operator<<(Emitter& emitter, const Binary& b) { + return emitter.Write(b); +} + +inline Emitter& operator<<(Emitter& emitter, const char* v) { + return emitter.Write(std::string(v)); +} + +inline Emitter& operator<<(Emitter& emitter, int v) { + return emitter.WriteIntegralType(v); +} +inline Emitter& operator<<(Emitter& emitter, unsigned int v) { + return emitter.WriteIntegralType(v); +} +inline Emitter& operator<<(Emitter& emitter, short v) { + return emitter.WriteIntegralType(v); +} +inline Emitter& operator<<(Emitter& emitter, unsigned short v) { + return emitter.WriteIntegralType(v); +} +inline Emitter& operator<<(Emitter& emitter, long v) { + return emitter.WriteIntegralType(v); +} +inline Emitter& operator<<(Emitter& emitter, unsigned long v) { + return emitter.WriteIntegralType(v); +} +inline Emitter& operator<<(Emitter& emitter, long long v) { + return emitter.WriteIntegralType(v); +} +inline Emitter& operator<<(Emitter& emitter, unsigned long long v) { + return emitter.WriteIntegralType(v); +} + +inline Emitter& operator<<(Emitter& emitter, float v) { + return emitter.WriteStreamable(v); +} +inline Emitter& operator<<(Emitter& emitter, double v) { + return emitter.WriteStreamable(v); +} + +inline Emitter& operator<<(Emitter& emitter, EMITTER_MANIP value) { + return emitter.SetLocalValue(value); +} + +inline Emitter& operator<<(Emitter& emitter, _Indent indent) { + return emitter.SetLocalIndent(indent); +} + +inline Emitter& operator<<(Emitter& emitter, _Precision precision) { + return emitter.SetLocalPrecision(precision); +} +} // namespace YAML + +#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/emitterdef.h b/deps/include/yaml-cpp/emitterdef.h new file mode 100644 index 000000000..0b426957f --- /dev/null +++ b/deps/include/yaml-cpp/emitterdef.h @@ -0,0 +1,16 @@ +#ifndef EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +namespace YAML { +struct EmitterNodeType { + enum value { NoType, Property, Scalar, FlowSeq, BlockSeq, FlowMap, BlockMap }; +}; +} + +#endif // EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/emittermanip.h b/deps/include/yaml-cpp/emittermanip.h new file mode 100644 index 000000000..976d14950 --- /dev/null +++ b/deps/include/yaml-cpp/emittermanip.h @@ -0,0 +1,144 @@ +#ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include + +namespace YAML { +enum EMITTER_MANIP { + // general manipulators + Auto, + TagByKind, + Newline, + + // output character set + EmitNonAscii, + EscapeNonAscii, + EscapeAsJson, + + // string manipulators + // Auto, // duplicate + SingleQuoted, + DoubleQuoted, + Literal, + + // null manipulators + LowerNull, + UpperNull, + CamelNull, + TildeNull, + + // bool manipulators + YesNoBool, // yes, no + TrueFalseBool, // true, false + OnOffBool, // on, off + UpperCase, // TRUE, N + LowerCase, // f, yes + CamelCase, // No, Off + LongBool, // yes, On + ShortBool, // y, t + + // int manipulators + Dec, + Hex, + Oct, + + // document manipulators + BeginDoc, + EndDoc, + + // sequence manipulators + BeginSeq, + EndSeq, + Flow, + Block, + + // map manipulators + BeginMap, + EndMap, + Key, + Value, + // Flow, // duplicate + // Block, // duplicate + // Auto, // duplicate + LongKey +}; + +struct _Indent { + _Indent(int value_) : value(value_) {} + int value; +}; + +inline _Indent Indent(int value) { return _Indent(value); } + +struct _Alias { + _Alias(const std::string& content_) : content(content_) {} + std::string content; +}; + +inline _Alias Alias(const std::string& content) { return _Alias(content); } + +struct _Anchor { + _Anchor(const std::string& content_) : content(content_) {} + std::string content; +}; + +inline _Anchor Anchor(const std::string& content) { return _Anchor(content); } + +struct _Tag { + struct Type { + enum value { Verbatim, PrimaryHandle, NamedHandle }; + }; + + explicit _Tag(const std::string& prefix_, const std::string& content_, + Type::value type_) + : prefix(prefix_), content(content_), type(type_) {} + std::string prefix; + std::string content; + Type::value type; +}; + +inline _Tag VerbatimTag(const std::string& content) { + return _Tag("", content, _Tag::Type::Verbatim); +} + +inline _Tag LocalTag(const std::string& content) { + return _Tag("", content, _Tag::Type::PrimaryHandle); +} + +inline _Tag LocalTag(const std::string& prefix, const std::string content) { + return _Tag(prefix, content, _Tag::Type::NamedHandle); +} + +inline _Tag SecondaryTag(const std::string& content) { + return _Tag("", content, _Tag::Type::NamedHandle); +} + +struct _Comment { + _Comment(const std::string& content_) : content(content_) {} + std::string content; +}; + +inline _Comment Comment(const std::string& content) { return _Comment(content); } + +struct _Precision { + _Precision(int floatPrecision_, int doublePrecision_) + : floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {} + + int floatPrecision; + int doublePrecision; +}; + +inline _Precision FloatPrecision(int n) { return _Precision(n, -1); } + +inline _Precision DoublePrecision(int n) { return _Precision(-1, n); } + +inline _Precision Precision(int n) { return _Precision(n, n); } +} + +#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/emitterstyle.h b/deps/include/yaml-cpp/emitterstyle.h new file mode 100644 index 000000000..67bb3981b --- /dev/null +++ b/deps/include/yaml-cpp/emitterstyle.h @@ -0,0 +1,16 @@ +#ifndef EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +namespace YAML { +struct EmitterStyle { + enum value { Default, Block, Flow }; +}; +} + +#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/eventhandler.h b/deps/include/yaml-cpp/eventhandler.h new file mode 100644 index 000000000..7242fe1f5 --- /dev/null +++ b/deps/include/yaml-cpp/eventhandler.h @@ -0,0 +1,45 @@ +#ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include + +#include "yaml-cpp/anchor.h" +#include "yaml-cpp/emitterstyle.h" + +namespace YAML { +struct Mark; + +class EventHandler { + public: + virtual ~EventHandler() = default; + + virtual void OnDocumentStart(const Mark& mark) = 0; + virtual void OnDocumentEnd() = 0; + + virtual void OnNull(const Mark& mark, anchor_t anchor) = 0; + virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0; + virtual void OnScalar(const Mark& mark, const std::string& tag, + anchor_t anchor, const std::string& value) = 0; + + virtual void OnSequenceStart(const Mark& mark, const std::string& tag, + anchor_t anchor, EmitterStyle::value style) = 0; + virtual void OnSequenceEnd() = 0; + + virtual void OnMapStart(const Mark& mark, const std::string& tag, + anchor_t anchor, EmitterStyle::value style) = 0; + virtual void OnMapEnd() = 0; + + virtual void OnAnchor(const Mark& /*mark*/, + const std::string& /*anchor_name*/) { + // empty default implementation for compatibility + } +}; +} // namespace YAML + +#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/exceptions.h b/deps/include/yaml-cpp/exceptions.h new file mode 100644 index 000000000..f6b2602ae --- /dev/null +++ b/deps/include/yaml-cpp/exceptions.h @@ -0,0 +1,303 @@ +#ifndef EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/mark.h" +#include "yaml-cpp/noexcept.h" +#include "yaml-cpp/traits.h" +#include +#include +#include + +namespace YAML { +// error messages +namespace ErrorMsg { +const char* const YAML_DIRECTIVE_ARGS = + "YAML directives must have exactly one argument"; +const char* const YAML_VERSION = "bad YAML version: "; +const char* const YAML_MAJOR_VERSION = "YAML major version too large"; +const char* const REPEATED_YAML_DIRECTIVE = "repeated YAML directive"; +const char* const TAG_DIRECTIVE_ARGS = + "TAG directives must have exactly two arguments"; +const char* const REPEATED_TAG_DIRECTIVE = "repeated TAG directive"; +const char* const CHAR_IN_TAG_HANDLE = + "illegal character found while scanning tag handle"; +const char* const TAG_WITH_NO_SUFFIX = "tag handle with no suffix"; +const char* const END_OF_VERBATIM_TAG = "end of verbatim tag not found"; +const char* const END_OF_MAP = "end of map not found"; +const char* const END_OF_MAP_FLOW = "end of map flow not found"; +const char* const END_OF_SEQ = "end of sequence not found"; +const char* const END_OF_SEQ_FLOW = "end of sequence flow not found"; +const char* const MULTIPLE_TAGS = + "cannot assign multiple tags to the same node"; +const char* const MULTIPLE_ANCHORS = + "cannot assign multiple anchors to the same node"; +const char* const MULTIPLE_ALIASES = + "cannot assign multiple aliases to the same node"; +const char* const ALIAS_CONTENT = + "aliases can't have any content, *including* tags"; +const char* const INVALID_HEX = "bad character found while scanning hex number"; +const char* const INVALID_UNICODE = "invalid unicode: "; +const char* const INVALID_ESCAPE = "unknown escape character: "; +const char* const UNKNOWN_TOKEN = "unknown token"; +const char* const DOC_IN_SCALAR = "illegal document indicator in scalar"; +const char* const EOF_IN_SCALAR = "illegal EOF in scalar"; +const char* const CHAR_IN_SCALAR = "illegal character in scalar"; +const char* const TAB_IN_INDENTATION = + "illegal tab when looking for indentation"; +const char* const FLOW_END = "illegal flow end"; +const char* const BLOCK_ENTRY = "illegal block entry"; +const char* const MAP_KEY = "illegal map key"; +const char* const MAP_VALUE = "illegal map value"; +const char* const ALIAS_NOT_FOUND = "alias not found after *"; +const char* const ANCHOR_NOT_FOUND = "anchor not found after &"; +const char* const CHAR_IN_ALIAS = + "illegal character found while scanning alias"; +const char* const CHAR_IN_ANCHOR = + "illegal character found while scanning anchor"; +const char* const ZERO_INDENT_IN_BLOCK = + "cannot set zero indentation for a block scalar"; +const char* const CHAR_IN_BLOCK = "unexpected character in block scalar"; +const char* const AMBIGUOUS_ANCHOR = + "cannot assign the same alias to multiple nodes"; +const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined: "; + +const char* const INVALID_NODE = + "invalid node; this may result from using a map iterator as a sequence " + "iterator, or vice-versa"; +const char* const INVALID_SCALAR = "invalid scalar"; +const char* const KEY_NOT_FOUND = "key not found"; +const char* const BAD_CONVERSION = "bad conversion"; +const char* const BAD_DEREFERENCE = "bad dereference"; +const char* const BAD_SUBSCRIPT = "operator[] call on a scalar"; +const char* const BAD_PUSHBACK = "appending to a non-sequence"; +const char* const BAD_INSERT = "inserting in a non-convertible-to-map"; + +const char* const UNMATCHED_GROUP_TAG = "unmatched group tag"; +const char* const UNEXPECTED_END_SEQ = "unexpected end sequence token"; +const char* const UNEXPECTED_END_MAP = "unexpected end map token"; +const char* const SINGLE_QUOTED_CHAR = + "invalid character in single-quoted string"; +const char* const INVALID_ANCHOR = "invalid anchor"; +const char* const INVALID_ALIAS = "invalid alias"; +const char* const INVALID_TAG = "invalid tag"; +const char* const BAD_FILE = "bad file"; + +template +inline const std::string KEY_NOT_FOUND_WITH_KEY( + const T&, typename disable_if>::type* = 0) { + return KEY_NOT_FOUND; +} + +inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) { + std::stringstream stream; + stream << KEY_NOT_FOUND << ": " << key; + return stream.str(); +} + +inline const std::string KEY_NOT_FOUND_WITH_KEY(const char* key) { + std::stringstream stream; + stream << KEY_NOT_FOUND << ": " << key; + return stream.str(); +} + +template +inline const std::string KEY_NOT_FOUND_WITH_KEY( + const T& key, typename enable_if>::type* = 0) { + std::stringstream stream; + stream << KEY_NOT_FOUND << ": " << key; + return stream.str(); +} + +template +inline const std::string BAD_SUBSCRIPT_WITH_KEY( + const T&, typename disable_if>::type* = nullptr) { + return BAD_SUBSCRIPT; +} + +inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& key) { + std::stringstream stream; + stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")"; + return stream.str(); +} + +inline const std::string BAD_SUBSCRIPT_WITH_KEY(const char* key) { + std::stringstream stream; + stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")"; + return stream.str(); +} + +template +inline const std::string BAD_SUBSCRIPT_WITH_KEY( + const T& key, typename enable_if>::type* = nullptr) { + std::stringstream stream; + stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")"; + return stream.str(); +} + +inline const std::string INVALID_NODE_WITH_KEY(const std::string& key) { + std::stringstream stream; + if (key.empty()) { + return INVALID_NODE; + } + stream << "invalid node; first invalid key: \"" << key << "\""; + return stream.str(); +} +} // namespace ErrorMsg + +class YAML_CPP_API Exception : public std::runtime_error { + public: + Exception(const Mark& mark_, const std::string& msg_) + : std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {} + ~Exception() YAML_CPP_NOEXCEPT override; + + Exception(const Exception&) = default; + + Mark mark; + std::string msg; + + private: + static const std::string build_what(const Mark& mark, + const std::string& msg) { + if (mark.is_null()) { + return msg; + } + + std::stringstream output; + output << "yaml-cpp: error at line " << mark.line + 1 << ", column " + << mark.column + 1 << ": " << msg; + return output.str(); + } +}; + +class YAML_CPP_API ParserException : public Exception { + public: + ParserException(const Mark& mark_, const std::string& msg_) + : Exception(mark_, msg_) {} + ParserException(const ParserException&) = default; + ~ParserException() YAML_CPP_NOEXCEPT override; +}; + +class YAML_CPP_API RepresentationException : public Exception { + public: + RepresentationException(const Mark& mark_, const std::string& msg_) + : Exception(mark_, msg_) {} + RepresentationException(const RepresentationException&) = default; + ~RepresentationException() YAML_CPP_NOEXCEPT override; +}; + +// representation exceptions +class YAML_CPP_API InvalidScalar : public RepresentationException { + public: + InvalidScalar(const Mark& mark_) + : RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {} + InvalidScalar(const InvalidScalar&) = default; + ~InvalidScalar() YAML_CPP_NOEXCEPT override; +}; + +class YAML_CPP_API KeyNotFound : public RepresentationException { + public: + template + KeyNotFound(const Mark& mark_, const T& key_) + : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) { + } + KeyNotFound(const KeyNotFound&) = default; + ~KeyNotFound() YAML_CPP_NOEXCEPT override; +}; + +template +class YAML_CPP_API TypedKeyNotFound : public KeyNotFound { + public: + TypedKeyNotFound(const Mark& mark_, const T& key_) + : KeyNotFound(mark_, key_), key(key_) {} + ~TypedKeyNotFound() YAML_CPP_NOEXCEPT override = default; + + T key; +}; + +template +inline TypedKeyNotFound MakeTypedKeyNotFound(const Mark& mark, + const T& key) { + return TypedKeyNotFound(mark, key); +} + +class YAML_CPP_API InvalidNode : public RepresentationException { + public: + InvalidNode(const std::string& key) + : RepresentationException(Mark::null_mark(), + ErrorMsg::INVALID_NODE_WITH_KEY(key)) {} + InvalidNode(const InvalidNode&) = default; + ~InvalidNode() YAML_CPP_NOEXCEPT override; +}; + +class YAML_CPP_API BadConversion : public RepresentationException { + public: + explicit BadConversion(const Mark& mark_) + : RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {} + BadConversion(const BadConversion&) = default; + ~BadConversion() YAML_CPP_NOEXCEPT override; +}; + +template +class TypedBadConversion : public BadConversion { + public: + explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {} +}; + +class YAML_CPP_API BadDereference : public RepresentationException { + public: + BadDereference() + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {} + BadDereference(const BadDereference&) = default; + ~BadDereference() YAML_CPP_NOEXCEPT override; +}; + +class YAML_CPP_API BadSubscript : public RepresentationException { + public: + template + BadSubscript(const Mark& mark_, const Key& key) + : RepresentationException(mark_, ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {} + BadSubscript(const BadSubscript&) = default; + ~BadSubscript() YAML_CPP_NOEXCEPT override; +}; + +class YAML_CPP_API BadPushback : public RepresentationException { + public: + BadPushback() + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {} + BadPushback(const BadPushback&) = default; + ~BadPushback() YAML_CPP_NOEXCEPT override; +}; + +class YAML_CPP_API BadInsert : public RepresentationException { + public: + BadInsert() + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {} + BadInsert(const BadInsert&) = default; + ~BadInsert() YAML_CPP_NOEXCEPT override; +}; + +class YAML_CPP_API EmitterException : public Exception { + public: + EmitterException(const std::string& msg_) + : Exception(Mark::null_mark(), msg_) {} + EmitterException(const EmitterException&) = default; + ~EmitterException() YAML_CPP_NOEXCEPT override; +}; + +class YAML_CPP_API BadFile : public Exception { + public: + explicit BadFile(const std::string& filename) + : Exception(Mark::null_mark(), + std::string(ErrorMsg::BAD_FILE) + ": " + filename) {} + BadFile(const BadFile&) = default; + ~BadFile() YAML_CPP_NOEXCEPT override; +}; +} // namespace YAML + +#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/mark.h b/deps/include/yaml-cpp/mark.h new file mode 100644 index 000000000..bf94b4f41 --- /dev/null +++ b/deps/include/yaml-cpp/mark.h @@ -0,0 +1,29 @@ +#ifndef MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/dll.h" + +namespace YAML { +struct YAML_CPP_API Mark { + Mark() : pos(0), line(0), column(0) {} + + static const Mark null_mark() { return Mark(-1, -1, -1); } + + bool is_null() const { return pos == -1 && line == -1 && column == -1; } + + int pos; + int line, column; + + private: + Mark(int pos_, int line_, int column_) + : pos(pos_), line(line_), column(column_) {} +}; +} + +#endif // MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/convert.h b/deps/include/yaml-cpp/node/convert.h new file mode 100644 index 000000000..21619a455 --- /dev/null +++ b/deps/include/yaml-cpp/node/convert.h @@ -0,0 +1,419 @@ +#ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "yaml-cpp/binary.h" +#include "yaml-cpp/node/impl.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/type.h" +#include "yaml-cpp/null.h" + + +namespace YAML { +class Binary; +struct _Null; +template +struct convert; +} // namespace YAML + +namespace YAML { +namespace conversion { +inline bool IsInfinity(const std::string& input) { + return input == ".inf" || input == ".Inf" || input == ".INF" || + input == "+.inf" || input == "+.Inf" || input == "+.INF"; +} + +inline bool IsNegativeInfinity(const std::string& input) { + return input == "-.inf" || input == "-.Inf" || input == "-.INF"; +} + +inline bool IsNaN(const std::string& input) { + return input == ".nan" || input == ".NaN" || input == ".NAN"; +} +} + +// Node +template <> +struct convert { + static Node encode(const Node& rhs) { return rhs; } + + static bool decode(const Node& node, Node& rhs) { + rhs.reset(node); + return true; + } +}; + +// std::string +template <> +struct convert { + static Node encode(const std::string& rhs) { return Node(rhs); } + + static bool decode(const Node& node, std::string& rhs) { + if (!node.IsScalar()) + return false; + rhs = node.Scalar(); + return true; + } +}; + +// C-strings can only be encoded +template <> +struct convert { + static Node encode(const char* rhs) { return Node(rhs); } +}; + +template <> +struct convert { + static Node encode(const char* rhs) { return Node(rhs); } +}; + +template +struct convert { + static Node encode(const char* rhs) { return Node(rhs); } +}; + +template <> +struct convert<_Null> { + static Node encode(const _Null& /* rhs */) { return Node(); } + + static bool decode(const Node& node, _Null& /* rhs */) { + return node.IsNull(); + } +}; + +namespace conversion { +template +typename std::enable_if< std::is_floating_point::value, void>::type +inner_encode(const T& rhs, std::stringstream& stream){ + if (std::isnan(rhs)) { + stream << ".nan"; + } else if (std::isinf(rhs)) { + if (std::signbit(rhs)) { + stream << "-.inf"; + } else { + stream << ".inf"; + } + } else { + stream << rhs; + } +} + +template +typename std::enable_if::value, void>::type +inner_encode(const T& rhs, std::stringstream& stream){ + stream << rhs; +} + +template +typename std::enable_if<(std::is_same::value || + std::is_same::value), bool>::type +ConvertStreamTo(std::stringstream& stream, T& rhs) { + int num; + if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) { + if (num >= (std::numeric_limits::min)() && + num <= (std::numeric_limits::max)()) { + rhs = (T)num; + return true; + } + } + return false; +} + +template +typename std::enable_if::value || + std::is_same::value), bool>::type +ConvertStreamTo(std::stringstream& stream, T& rhs) { + if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) { + return true; + } + return false; +} +} + +#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \ + template <> \ + struct convert { \ + \ + static Node encode(const type& rhs) { \ + std::stringstream stream; \ + stream.precision(std::numeric_limits::max_digits10); \ + conversion::inner_encode(rhs, stream); \ + return Node(stream.str()); \ + } \ + \ + static bool decode(const Node& node, type& rhs) { \ + if (node.Type() != NodeType::Scalar) { \ + return false; \ + } \ + const std::string& input = node.Scalar(); \ + std::stringstream stream(input); \ + stream.unsetf(std::ios::dec); \ + if ((stream.peek() == '-') && std::is_unsigned::value) { \ + return false; \ + } \ + if (conversion::ConvertStreamTo(stream, rhs)) { \ + return true; \ + } \ + if (std::numeric_limits::has_infinity) { \ + if (conversion::IsInfinity(input)) { \ + rhs = std::numeric_limits::infinity(); \ + return true; \ + } else if (conversion::IsNegativeInfinity(input)) { \ + rhs = negative_op std::numeric_limits::infinity(); \ + return true; \ + } \ + } \ + \ + if (std::numeric_limits::has_quiet_NaN) { \ + if (conversion::IsNaN(input)) { \ + rhs = std::numeric_limits::quiet_NaN(); \ + return true; \ + } \ + } \ + \ + return false; \ + } \ + } + +#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \ + YAML_DEFINE_CONVERT_STREAMABLE(type, -) + +#define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type) \ + YAML_DEFINE_CONVERT_STREAMABLE(type, +) + +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long); + +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(signed char); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char); + +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double); + +#undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED +#undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED +#undef YAML_DEFINE_CONVERT_STREAMABLE + +// bool +template <> +struct convert { + static Node encode(bool rhs) { return rhs ? Node("true") : Node("false"); } + + YAML_CPP_API static bool decode(const Node& node, bool& rhs); +}; + +// std::map +template +struct convert> { + static Node encode(const std::map& rhs) { + Node node(NodeType::Map); + for (const auto& element : rhs) + node.force_insert(element.first, element.second); + return node; + } + + static bool decode(const Node& node, std::map& rhs) { + if (!node.IsMap()) + return false; + + rhs.clear(); + for (const auto& element : node) +#if defined(__GNUC__) && __GNUC__ < 4 + // workaround for GCC 3: + rhs[element.first.template as()] = element.second.template as(); +#else + rhs[element.first.as()] = element.second.as(); +#endif + return true; + } +}; + +// std::unordered_map +template +struct convert> { + static Node encode(const std::unordered_map& rhs) { + Node node(NodeType::Map); + for (const auto& element : rhs) + node.force_insert(element.first, element.second); + return node; + } + + static bool decode(const Node& node, std::unordered_map& rhs) { + if (!node.IsMap()) + return false; + + rhs.clear(); + for (const auto& element : node) +#if defined(__GNUC__) && __GNUC__ < 4 + // workaround for GCC 3: + rhs[element.first.template as()] = element.second.template as(); +#else + rhs[element.first.as()] = element.second.as(); +#endif + return true; + } +}; + +// std::vector +template +struct convert> { + static Node encode(const std::vector& rhs) { + Node node(NodeType::Sequence); + for (const auto& element : rhs) + node.push_back(element); + return node; + } + + static bool decode(const Node& node, std::vector& rhs) { + if (!node.IsSequence()) + return false; + + rhs.clear(); + for (const auto& element : node) +#if defined(__GNUC__) && __GNUC__ < 4 + // workaround for GCC 3: + rhs.push_back(element.template as()); +#else + rhs.push_back(element.as()); +#endif + return true; + } +}; + +// std::list +template +struct convert> { + static Node encode(const std::list& rhs) { + Node node(NodeType::Sequence); + for (const auto& element : rhs) + node.push_back(element); + return node; + } + + static bool decode(const Node& node, std::list& rhs) { + if (!node.IsSequence()) + return false; + + rhs.clear(); + for (const auto& element : node) +#if defined(__GNUC__) && __GNUC__ < 4 + // workaround for GCC 3: + rhs.push_back(element.template as()); +#else + rhs.push_back(element.as()); +#endif + return true; + } +}; + +// std::array +template +struct convert> { + static Node encode(const std::array& rhs) { + Node node(NodeType::Sequence); + for (const auto& element : rhs) { + node.push_back(element); + } + return node; + } + + static bool decode(const Node& node, std::array& rhs) { + if (!isNodeValid(node)) { + return false; + } + + for (auto i = 0u; i < node.size(); ++i) { +#if defined(__GNUC__) && __GNUC__ < 4 + // workaround for GCC 3: + rhs[i] = node[i].template as(); +#else + rhs[i] = node[i].as(); +#endif + } + return true; + } + + private: + static bool isNodeValid(const Node& node) { + return node.IsSequence() && node.size() == N; + } +}; + +// std::pair +template +struct convert> { + static Node encode(const std::pair& rhs) { + Node node(NodeType::Sequence); + node.push_back(rhs.first); + node.push_back(rhs.second); + return node; + } + + static bool decode(const Node& node, std::pair& rhs) { + if (!node.IsSequence()) + return false; + if (node.size() != 2) + return false; + +#if defined(__GNUC__) && __GNUC__ < 4 + // workaround for GCC 3: + rhs.first = node[0].template as(); +#else + rhs.first = node[0].as(); +#endif +#if defined(__GNUC__) && __GNUC__ < 4 + // workaround for GCC 3: + rhs.second = node[1].template as(); +#else + rhs.second = node[1].as(); +#endif + return true; + } +}; + +// binary +template <> +struct convert { + static Node encode(const Binary& rhs) { + return Node(EncodeBase64(rhs.data(), rhs.size())); + } + + static bool decode(const Node& node, Binary& rhs) { + if (!node.IsScalar()) + return false; + + std::vector data = DecodeBase64(node.Scalar()); + if (data.empty() && !node.Scalar().empty()) + return false; + + rhs.swap(data); + return true; + } +}; +} + +#endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/detail/impl.h b/deps/include/yaml-cpp/node/detail/impl.h new file mode 100644 index 000000000..b38038dfd --- /dev/null +++ b/deps/include/yaml-cpp/node/detail/impl.h @@ -0,0 +1,235 @@ +#ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/node/detail/node.h" +#include "yaml-cpp/node/detail/node_data.h" + +#include +#include + +namespace YAML { +namespace detail { +template +struct get_idx { + static node* get(const std::vector& /* sequence */, + const Key& /* key */, shared_memory_holder /* pMemory */) { + return nullptr; + } +}; + +template +struct get_idx::value && + !std::is_same::value>::type> { + static node* get(const std::vector& sequence, const Key& key, + shared_memory_holder /* pMemory */) { + return key < sequence.size() ? sequence[key] : nullptr; + } + + static node* get(std::vector& sequence, const Key& key, + shared_memory_holder pMemory) { + if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined())) + return nullptr; + if (key == sequence.size()) + sequence.push_back(&pMemory->create_node()); + return sequence[key]; + } +}; + +template +struct get_idx::value>::type> { + static node* get(const std::vector& sequence, const Key& key, + shared_memory_holder pMemory) { + return key >= 0 ? get_idx::get( + sequence, static_cast(key), pMemory) + : nullptr; + } + static node* get(std::vector& sequence, const Key& key, + shared_memory_holder pMemory) { + return key >= 0 ? get_idx::get( + sequence, static_cast(key), pMemory) + : nullptr; + } +}; + +template +struct remove_idx { + static bool remove(std::vector&, const Key&, std::size_t&) { + return false; + } +}; + +template +struct remove_idx< + Key, typename std::enable_if::value && + !std::is_same::value>::type> { + + static bool remove(std::vector& sequence, const Key& key, + std::size_t& seqSize) { + if (key >= sequence.size()) { + return false; + } else { + sequence.erase(sequence.begin() + key); + if (seqSize > key) { + --seqSize; + } + return true; + } + } +}; + +template +struct remove_idx::value>::type> { + + static bool remove(std::vector& sequence, const Key& key, + std::size_t& seqSize) { + return key >= 0 ? remove_idx::remove( + sequence, static_cast(key), seqSize) + : false; + } +}; + +template +inline bool node::equals(const T& rhs, shared_memory_holder pMemory) { + T lhs; + if (convert::decode(Node(*this, pMemory), lhs)) { + return lhs == rhs; + } + return false; +} + +inline bool node::equals(const char* rhs, shared_memory_holder pMemory) { + std::string lhs; + if (convert::decode(Node(*this, std::move(pMemory)), lhs)) { + return lhs == rhs; + } + return false; +} + +// indexing +template +inline node* node_data::get(const Key& key, + shared_memory_holder pMemory) const { + switch (m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + return nullptr; + case NodeType::Sequence: + if (node* pNode = get_idx::get(m_sequence, key, pMemory)) + return pNode; + return nullptr; + case NodeType::Scalar: + throw BadSubscript(m_mark, key); + } + + auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) { + return m.first->equals(key, pMemory); + }); + + return it != m_map.end() ? it->second : nullptr; +} + +template +inline node& node_data::get(const Key& key, shared_memory_holder pMemory) { + switch (m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + if (node* pNode = get_idx::get(m_sequence, key, pMemory)) { + m_type = NodeType::Sequence; + return *pNode; + } + + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadSubscript(m_mark, key); + } + + auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) { + return m.first->equals(key, pMemory); + }); + + if (it != m_map.end()) { + return *it->second; + } + + node& k = convert_to_node(key, pMemory); + node& v = pMemory->create_node(); + insert_map_pair(k, v); + return v; +} + +template +inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) { + if (m_type == NodeType::Sequence) { + return remove_idx::remove(m_sequence, key, m_seqSize); + } + + if (m_type == NodeType::Map) { + kv_pairs::iterator it = m_undefinedPairs.begin(); + while (it != m_undefinedPairs.end()) { + kv_pairs::iterator jt = std::next(it); + if (it->first->equals(key, pMemory)) { + m_undefinedPairs.erase(it); + } + it = jt; + } + + auto iter = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) { + return m.first->equals(key, pMemory); + }); + + if (iter != m_map.end()) { + m_map.erase(iter); + return true; + } + } + + return false; +} + +// map +template +inline void node_data::force_insert(const Key& key, const Value& value, + shared_memory_holder pMemory) { + switch (m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadInsert(); + } + + node& k = convert_to_node(key, pMemory); + node& v = convert_to_node(value, pMemory); + insert_map_pair(k, v); +} + +template +inline node& node_data::convert_to_node(const T& rhs, + shared_memory_holder pMemory) { + Node value = convert::encode(rhs); + value.EnsureNodeExists(); + pMemory->merge(*value.m_pMemory); + return *value.m_pNode; +} +} +} + +#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/detail/iterator.h b/deps/include/yaml-cpp/node/detail/iterator.h new file mode 100644 index 000000000..997c69a14 --- /dev/null +++ b/deps/include/yaml-cpp/node/detail/iterator.h @@ -0,0 +1,96 @@ +#ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/detail/node_iterator.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/ptr.h" +#include +#include + + +namespace YAML { +namespace detail { +struct iterator_value; + +template +class iterator_base { + + private: + template + friend class iterator_base; + struct enabler {}; + using base_type = node_iterator; + + struct proxy { + explicit proxy(const V& x) : m_ref(x) {} + V* operator->() { return std::addressof(m_ref); } + operator V*() { return std::addressof(m_ref); } + + V m_ref; + }; + + public: + using iterator_category = std::forward_iterator_tag; + using value_type = V; + using difference_type = std::ptrdiff_t; + using pointer = V*; + using reference = V; + + public: + iterator_base() : m_iterator(), m_pMemory() {} + explicit iterator_base(base_type rhs, shared_memory_holder pMemory) + : m_iterator(rhs), m_pMemory(pMemory) {} + + template + iterator_base(const iterator_base& rhs, + typename std::enable_if::value, + enabler>::type = enabler()) + : m_iterator(rhs.m_iterator), m_pMemory(rhs.m_pMemory) {} + + iterator_base& operator++() { + ++m_iterator; + return *this; + } + + iterator_base operator++(int) { + iterator_base iterator_pre(*this); + ++(*this); + return iterator_pre; + } + + template + bool operator==(const iterator_base& rhs) const { + return m_iterator == rhs.m_iterator; + } + + template + bool operator!=(const iterator_base& rhs) const { + return m_iterator != rhs.m_iterator; + } + + value_type operator*() const { + const typename base_type::value_type& v = *m_iterator; + if (v.pNode) + return value_type(Node(*v, m_pMemory)); + if (v.first && v.second) + return value_type(Node(*v.first, m_pMemory), Node(*v.second, m_pMemory)); + return value_type(); + } + + proxy operator->() const { return proxy(**this); } + + private: + base_type m_iterator; + shared_memory_holder m_pMemory; +}; +} // namespace detail +} // namespace YAML + +#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/detail/iterator_fwd.h b/deps/include/yaml-cpp/node/detail/iterator_fwd.h new file mode 100644 index 000000000..75c9de086 --- /dev/null +++ b/deps/include/yaml-cpp/node/detail/iterator_fwd.h @@ -0,0 +1,27 @@ +#ifndef VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/dll.h" +#include +#include +#include + +namespace YAML { + +namespace detail { +struct iterator_value; +template +class iterator_base; +} + +using iterator = detail::iterator_base; +using const_iterator = detail::iterator_base; +} + +#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/detail/memory.h b/deps/include/yaml-cpp/node/detail/memory.h new file mode 100644 index 000000000..e881545bf --- /dev/null +++ b/deps/include/yaml-cpp/node/detail/memory.h @@ -0,0 +1,47 @@ +#ifndef VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/ptr.h" + +namespace YAML { +namespace detail { +class node; +} // namespace detail +} // namespace YAML + +namespace YAML { +namespace detail { +class YAML_CPP_API memory { + public: + memory() : m_nodes{} {} + node& create_node(); + void merge(const memory& rhs); + + private: + using Nodes = std::set; + Nodes m_nodes; +}; + +class YAML_CPP_API memory_holder { + public: + memory_holder() : m_pMemory(new memory) {} + + node& create_node() { return m_pMemory->create_node(); } + void merge(memory_holder& rhs); + + private: + shared_memory m_pMemory; +}; +} // namespace detail +} // namespace YAML + +#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/detail/node.h b/deps/include/yaml-cpp/node/detail/node.h new file mode 100644 index 000000000..acf60ffb6 --- /dev/null +++ b/deps/include/yaml-cpp/node/detail/node.h @@ -0,0 +1,177 @@ +#ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/emitterstyle.h" +#include "yaml-cpp/node/detail/node_ref.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/type.h" +#include +#include + +namespace YAML { +namespace detail { +class node { + private: + struct less { + bool operator ()(const node* l, const node* r) const {return l->m_index < r->m_index;} + }; + + public: + node() : m_pRef(new node_ref), m_dependencies{}, m_index{} {} + node(const node&) = delete; + node& operator=(const node&) = delete; + + bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; } + const node_ref* ref() const { return m_pRef.get(); } + + bool is_defined() const { return m_pRef->is_defined(); } + const Mark& mark() const { return m_pRef->mark(); } + NodeType::value type() const { return m_pRef->type(); } + + const std::string& scalar() const { return m_pRef->scalar(); } + const std::string& tag() const { return m_pRef->tag(); } + EmitterStyle::value style() const { return m_pRef->style(); } + + template + bool equals(const T& rhs, shared_memory_holder pMemory); + bool equals(const char* rhs, shared_memory_holder pMemory); + + void mark_defined() { + if (is_defined()) + return; + + m_pRef->mark_defined(); + for (node* dependency : m_dependencies) + dependency->mark_defined(); + m_dependencies.clear(); + } + + void add_dependency(node& rhs) { + if (is_defined()) + rhs.mark_defined(); + else + m_dependencies.insert(&rhs); + } + + void set_ref(const node& rhs) { + if (rhs.is_defined()) + mark_defined(); + m_pRef = rhs.m_pRef; + } + void set_data(const node& rhs) { + if (rhs.is_defined()) + mark_defined(); + m_pRef->set_data(*rhs.m_pRef); + } + + void set_mark(const Mark& mark) { m_pRef->set_mark(mark); } + + void set_type(NodeType::value type) { + if (type != NodeType::Undefined) + mark_defined(); + m_pRef->set_type(type); + } + void set_null() { + mark_defined(); + m_pRef->set_null(); + } + void set_scalar(const std::string& scalar) { + mark_defined(); + m_pRef->set_scalar(scalar); + } + void set_tag(const std::string& tag) { + mark_defined(); + m_pRef->set_tag(tag); + } + + // style + void set_style(EmitterStyle::value style) { + mark_defined(); + m_pRef->set_style(style); + } + + // size/iterator + std::size_t size() const { return m_pRef->size(); } + + const_node_iterator begin() const { + return static_cast(*m_pRef).begin(); + } + node_iterator begin() { return m_pRef->begin(); } + + const_node_iterator end() const { + return static_cast(*m_pRef).end(); + } + node_iterator end() { return m_pRef->end(); } + + // sequence + void push_back(node& input, shared_memory_holder pMemory) { + m_pRef->push_back(input, pMemory); + input.add_dependency(*this); + m_index = m_amount.fetch_add(1); + } + void insert(node& key, node& value, shared_memory_holder pMemory) { + m_pRef->insert(key, value, pMemory); + key.add_dependency(*this); + value.add_dependency(*this); + } + + // indexing + template + node* get(const Key& key, shared_memory_holder pMemory) const { + // NOTE: this returns a non-const node so that the top-level Node can wrap + // it, and returns a pointer so that it can be nullptr (if there is no such + // key). + return static_cast(*m_pRef).get(key, pMemory); + } + template + node& get(const Key& key, shared_memory_holder pMemory) { + node& value = m_pRef->get(key, pMemory); + value.add_dependency(*this); + return value; + } + template + bool remove(const Key& key, shared_memory_holder pMemory) { + return m_pRef->remove(key, pMemory); + } + + node* get(node& key, shared_memory_holder pMemory) const { + // NOTE: this returns a non-const node so that the top-level Node can wrap + // it, and returns a pointer so that it can be nullptr (if there is no such + // key). + return static_cast(*m_pRef).get(key, pMemory); + } + node& get(node& key, shared_memory_holder pMemory) { + node& value = m_pRef->get(key, pMemory); + key.add_dependency(*this); + value.add_dependency(*this); + return value; + } + bool remove(node& key, shared_memory_holder pMemory) { + return m_pRef->remove(key, pMemory); + } + + // map + template + void force_insert(const Key& key, const Value& value, + shared_memory_holder pMemory) { + m_pRef->force_insert(key, value, pMemory); + } + + private: + shared_node_ref m_pRef; + using nodes = std::set; + nodes m_dependencies; + size_t m_index; + static YAML_CPP_API std::atomic m_amount; +}; +} // namespace detail +} // namespace YAML + +#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/detail/node_data.h b/deps/include/yaml-cpp/node/detail/node_data.h new file mode 100644 index 000000000..07cf81aa0 --- /dev/null +++ b/deps/include/yaml-cpp/node/detail/node_data.h @@ -0,0 +1,127 @@ +#ifndef VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include +#include +#include +#include + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/detail/node_iterator.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/type.h" + +namespace YAML { +namespace detail { +class node; +} // namespace detail +} // namespace YAML + +namespace YAML { +namespace detail { +class YAML_CPP_API node_data { + public: + node_data(); + node_data(const node_data&) = delete; + node_data& operator=(const node_data&) = delete; + + void mark_defined(); + void set_mark(const Mark& mark); + void set_type(NodeType::value type); + void set_tag(const std::string& tag); + void set_null(); + void set_scalar(const std::string& scalar); + void set_style(EmitterStyle::value style); + + bool is_defined() const { return m_isDefined; } + const Mark& mark() const { return m_mark; } + NodeType::value type() const { + return m_isDefined ? m_type : NodeType::Undefined; + } + const std::string& scalar() const { return m_scalar; } + const std::string& tag() const { return m_tag; } + EmitterStyle::value style() const { return m_style; } + + // size/iterator + std::size_t size() const; + + const_node_iterator begin() const; + node_iterator begin(); + + const_node_iterator end() const; + node_iterator end(); + + // sequence + void push_back(node& node, const shared_memory_holder& pMemory); + void insert(node& key, node& value, const shared_memory_holder& pMemory); + + // indexing + template + node* get(const Key& key, shared_memory_holder pMemory) const; + template + node& get(const Key& key, shared_memory_holder pMemory); + template + bool remove(const Key& key, shared_memory_holder pMemory); + + node* get(node& key, const shared_memory_holder& pMemory) const; + node& get(node& key, const shared_memory_holder& pMemory); + bool remove(node& key, const shared_memory_holder& pMemory); + + // map + template + void force_insert(const Key& key, const Value& value, + shared_memory_holder pMemory); + + public: + static const std::string& empty_scalar(); + + private: + void compute_seq_size() const; + void compute_map_size() const; + + void reset_sequence(); + void reset_map(); + + void insert_map_pair(node& key, node& value); + void convert_to_map(const shared_memory_holder& pMemory); + void convert_sequence_to_map(const shared_memory_holder& pMemory); + + template + static node& convert_to_node(const T& rhs, shared_memory_holder pMemory); + + private: + bool m_isDefined; + Mark m_mark; + NodeType::value m_type; + std::string m_tag; + EmitterStyle::value m_style; + + // scalar + std::string m_scalar; + + // sequence + using node_seq = std::vector; + node_seq m_sequence; + + mutable std::size_t m_seqSize; + + // map + using node_map = std::vector>; + node_map m_map; + + using kv_pair = std::pair; + using kv_pairs = std::list; + mutable kv_pairs m_undefinedPairs; +}; +} +} + +#endif // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/detail/node_iterator.h b/deps/include/yaml-cpp/node/detail/node_iterator.h new file mode 100644 index 000000000..49dcf958d --- /dev/null +++ b/deps/include/yaml-cpp/node/detail/node_iterator.h @@ -0,0 +1,181 @@ +#ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/ptr.h" +#include +#include +#include +#include +#include +#include + +namespace YAML { +namespace detail { +struct iterator_type { + enum value { NoneType, Sequence, Map }; +}; + +template +struct node_iterator_value : public std::pair { + using kv = std::pair; + + node_iterator_value() : kv(), pNode(nullptr) {} + explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {} + explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(nullptr) {} + + V& operator*() const { return *pNode; } + V& operator->() const { return *pNode; } + + V* pNode; +}; + +using node_seq = std::vector; +using node_map = std::vector>; + +template +struct node_iterator_type { + using seq = node_seq::iterator; + using map = node_map::iterator; +}; + +template +struct node_iterator_type { + using seq = node_seq::const_iterator; + using map = node_map::const_iterator; +}; + +template +class node_iterator_base { + private: + struct enabler {}; + + struct proxy { + explicit proxy(const node_iterator_value& x) : m_ref(x) {} + node_iterator_value* operator->() { return std::addressof(m_ref); } + operator node_iterator_value*() { return std::addressof(m_ref); } + + node_iterator_value m_ref; + }; + + public: + using iterator_category = std::forward_iterator_tag; + using value_type = node_iterator_value; + using difference_type = std::ptrdiff_t; + using pointer = node_iterator_value*; + using reference = node_iterator_value; + using SeqIter = typename node_iterator_type::seq; + using MapIter = typename node_iterator_type::map; + + node_iterator_base() + : m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {} + explicit node_iterator_base(SeqIter seqIt) + : m_type(iterator_type::Sequence), + m_seqIt(seqIt), + m_mapIt(), + m_mapEnd() {} + explicit node_iterator_base(MapIter mapIt, MapIter mapEnd) + : m_type(iterator_type::Map), + m_seqIt(), + m_mapIt(mapIt), + m_mapEnd(mapEnd) { + m_mapIt = increment_until_defined(m_mapIt); + } + + template + node_iterator_base(const node_iterator_base& rhs, + typename std::enable_if::value, + enabler>::type = enabler()) + : m_type(rhs.m_type), + m_seqIt(rhs.m_seqIt), + m_mapIt(rhs.m_mapIt), + m_mapEnd(rhs.m_mapEnd) {} + + template + friend class node_iterator_base; + + template + bool operator==(const node_iterator_base& rhs) const { + if (m_type != rhs.m_type) + return false; + + switch (m_type) { + case iterator_type::NoneType: + return true; + case iterator_type::Sequence: + return m_seqIt == rhs.m_seqIt; + case iterator_type::Map: + return m_mapIt == rhs.m_mapIt; + } + return true; + } + + template + bool operator!=(const node_iterator_base& rhs) const { + return !(*this == rhs); + } + + node_iterator_base& operator++() { + switch (m_type) { + case iterator_type::NoneType: + break; + case iterator_type::Sequence: + ++m_seqIt; + break; + case iterator_type::Map: + ++m_mapIt; + m_mapIt = increment_until_defined(m_mapIt); + break; + } + return *this; + } + + node_iterator_base operator++(int) { + node_iterator_base iterator_pre(*this); + ++(*this); + return iterator_pre; + } + + value_type operator*() const { + switch (m_type) { + case iterator_type::NoneType: + return value_type(); + case iterator_type::Sequence: + return value_type(**m_seqIt); + case iterator_type::Map: + return value_type(*m_mapIt->first, *m_mapIt->second); + } + return value_type(); + } + + proxy operator->() const { return proxy(**this); } + + MapIter increment_until_defined(MapIter it) { + while (it != m_mapEnd && !is_defined(it)) + ++it; + return it; + } + + bool is_defined(MapIter it) const { + return it->first->is_defined() && it->second->is_defined(); + } + + private: + typename iterator_type::value m_type; + + SeqIter m_seqIt; + MapIter m_mapIt, m_mapEnd; +}; + +using node_iterator = node_iterator_base; +using const_node_iterator = node_iterator_base; +} +} + +#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/detail/node_ref.h b/deps/include/yaml-cpp/node/detail/node_ref.h new file mode 100644 index 000000000..d8a94f8b8 --- /dev/null +++ b/deps/include/yaml-cpp/node/detail/node_ref.h @@ -0,0 +1,98 @@ +#ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/type.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/detail/node_data.h" + +namespace YAML { +namespace detail { +class node_ref { + public: + node_ref() : m_pData(new node_data) {} + node_ref(const node_ref&) = delete; + node_ref& operator=(const node_ref&) = delete; + + bool is_defined() const { return m_pData->is_defined(); } + const Mark& mark() const { return m_pData->mark(); } + NodeType::value type() const { return m_pData->type(); } + const std::string& scalar() const { return m_pData->scalar(); } + const std::string& tag() const { return m_pData->tag(); } + EmitterStyle::value style() const { return m_pData->style(); } + + void mark_defined() { m_pData->mark_defined(); } + void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; } + + void set_mark(const Mark& mark) { m_pData->set_mark(mark); } + void set_type(NodeType::value type) { m_pData->set_type(type); } + void set_tag(const std::string& tag) { m_pData->set_tag(tag); } + void set_null() { m_pData->set_null(); } + void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); } + void set_style(EmitterStyle::value style) { m_pData->set_style(style); } + + // size/iterator + std::size_t size() const { return m_pData->size(); } + + const_node_iterator begin() const { + return static_cast(*m_pData).begin(); + } + node_iterator begin() { return m_pData->begin(); } + + const_node_iterator end() const { + return static_cast(*m_pData).end(); + } + node_iterator end() { return m_pData->end(); } + + // sequence + void push_back(node& node, shared_memory_holder pMemory) { + m_pData->push_back(node, pMemory); + } + void insert(node& key, node& value, shared_memory_holder pMemory) { + m_pData->insert(key, value, pMemory); + } + + // indexing + template + node* get(const Key& key, shared_memory_holder pMemory) const { + return static_cast(*m_pData).get(key, pMemory); + } + template + node& get(const Key& key, shared_memory_holder pMemory) { + return m_pData->get(key, pMemory); + } + template + bool remove(const Key& key, shared_memory_holder pMemory) { + return m_pData->remove(key, pMemory); + } + + node* get(node& key, shared_memory_holder pMemory) const { + return static_cast(*m_pData).get(key, pMemory); + } + node& get(node& key, shared_memory_holder pMemory) { + return m_pData->get(key, pMemory); + } + bool remove(node& key, shared_memory_holder pMemory) { + return m_pData->remove(key, pMemory); + } + + // map + template + void force_insert(const Key& key, const Value& value, + shared_memory_holder pMemory) { + m_pData->force_insert(key, value, pMemory); + } + + private: + shared_node_data m_pData; +}; +} +} + +#endif // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/emit.h b/deps/include/yaml-cpp/node/emit.h new file mode 100644 index 000000000..032268c5d --- /dev/null +++ b/deps/include/yaml-cpp/node/emit.h @@ -0,0 +1,32 @@ +#ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include + +#include "yaml-cpp/dll.h" + +namespace YAML { +class Emitter; +class Node; + +/** + * Emits the node to the given {@link Emitter}. If there is an error in writing, + * {@link Emitter#good} will return false. + */ +YAML_CPP_API Emitter& operator<<(Emitter& out, const Node& node); + +/** Emits the node to the given output stream. */ +YAML_CPP_API std::ostream& operator<<(std::ostream& out, const Node& node); + +/** Converts the node to a YAML string. */ +YAML_CPP_API std::string Dump(const Node& node); +} // namespace YAML + +#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/impl.h b/deps/include/yaml-cpp/node/impl.h new file mode 100644 index 000000000..312281f18 --- /dev/null +++ b/deps/include/yaml-cpp/node/impl.h @@ -0,0 +1,385 @@ +#ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/exceptions.h" +#include "yaml-cpp/node/detail/memory.h" +#include "yaml-cpp/node/detail/node.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/node.h" +#include +#include + +namespace YAML { +inline Node::Node() + : m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {} + +inline Node::Node(NodeType::value type) + : m_isValid(true), + m_invalidKey{}, + m_pMemory(new detail::memory_holder), + m_pNode(&m_pMemory->create_node()) { + m_pNode->set_type(type); +} + +template +inline Node::Node(const T& rhs) + : m_isValid(true), + m_invalidKey{}, + m_pMemory(new detail::memory_holder), + m_pNode(&m_pMemory->create_node()) { + Assign(rhs); +} + +inline Node::Node(const detail::iterator_value& rhs) + : m_isValid(rhs.m_isValid), + m_invalidKey(rhs.m_invalidKey), + m_pMemory(rhs.m_pMemory), + m_pNode(rhs.m_pNode) {} + +inline Node::Node(const Node&) = default; + +inline Node::Node(Zombie) + : m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {} + +inline Node::Node(Zombie, const std::string& key) + : m_isValid(false), m_invalidKey(key), m_pMemory{}, m_pNode(nullptr) {} + +inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory) + : m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {} + +inline Node::~Node() = default; + +inline void Node::EnsureNodeExists() const { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + if (!m_pNode) { + m_pMemory.reset(new detail::memory_holder); + m_pNode = &m_pMemory->create_node(); + m_pNode->set_null(); + } +} + +inline bool Node::IsDefined() const { + if (!m_isValid) { + return false; + } + return m_pNode ? m_pNode->is_defined() : true; +} + +inline Mark Node::Mark() const { + if (!m_isValid) { + throw InvalidNode(m_invalidKey); + } + return m_pNode ? m_pNode->mark() : Mark::null_mark(); +} + +inline NodeType::value Node::Type() const { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + return m_pNode ? m_pNode->type() : NodeType::Null; +} + +// access + +// template helpers +template +struct as_if { + explicit as_if(const Node& node_) : node(node_) {} + const Node& node; + + T operator()(const S& fallback) const { + if (!node.m_pNode) + return fallback; + + T t; + if (convert::decode(node, t)) + return t; + return fallback; + } +}; + +template +struct as_if { + explicit as_if(const Node& node_) : node(node_) {} + const Node& node; + + std::string operator()(const S& fallback) const { + if (node.Type() == NodeType::Null) + return "null"; + if (node.Type() != NodeType::Scalar) + return fallback; + return node.Scalar(); + } +}; + +template +struct as_if { + explicit as_if(const Node& node_) : node(node_) {} + const Node& node; + + T operator()() const { + if (!node.m_pNode) + throw TypedBadConversion(node.Mark()); + + T t; + if (convert::decode(node, t)) + return t; + throw TypedBadConversion(node.Mark()); + } +}; + +template <> +struct as_if { + explicit as_if(const Node& node_) : node(node_) {} + const Node& node; + + std::string operator()() const { + if (node.Type() == NodeType::Null) + return "null"; + if (node.Type() != NodeType::Scalar) + throw TypedBadConversion(node.Mark()); + return node.Scalar(); + } +}; + +// access functions +template +inline T Node::as() const { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + return as_if(*this)(); +} + +template +inline T Node::as(const S& fallback) const { + if (!m_isValid) + return fallback; + return as_if(*this)(fallback); +} + +inline const std::string& Node::Scalar() const { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar(); +} + +inline const std::string& Node::Tag() const { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar(); +} + +inline void Node::SetTag(const std::string& tag) { + EnsureNodeExists(); + m_pNode->set_tag(tag); +} + +inline EmitterStyle::value Node::Style() const { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + return m_pNode ? m_pNode->style() : EmitterStyle::Default; +} + +inline void Node::SetStyle(EmitterStyle::value style) { + EnsureNodeExists(); + m_pNode->set_style(style); +} + +// assignment +inline bool Node::is(const Node& rhs) const { + if (!m_isValid || !rhs.m_isValid) + throw InvalidNode(m_invalidKey); + if (!m_pNode || !rhs.m_pNode) + return false; + return m_pNode->is(*rhs.m_pNode); +} + +template +inline Node& Node::operator=(const T& rhs) { + Assign(rhs); + return *this; +} + +inline Node& Node::operator=(const Node& rhs) { + if (is(rhs)) + return *this; + AssignNode(rhs); + return *this; +} + +inline void Node::reset(const YAML::Node& rhs) { + if (!m_isValid || !rhs.m_isValid) + throw InvalidNode(m_invalidKey); + m_pMemory = rhs.m_pMemory; + m_pNode = rhs.m_pNode; +} + +template +inline void Node::Assign(const T& rhs) { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + AssignData(convert::encode(rhs)); +} + +template <> +inline void Node::Assign(const std::string& rhs) { + EnsureNodeExists(); + m_pNode->set_scalar(rhs); +} + +inline void Node::Assign(const char* rhs) { + EnsureNodeExists(); + m_pNode->set_scalar(rhs); +} + +inline void Node::Assign(char* rhs) { + EnsureNodeExists(); + m_pNode->set_scalar(rhs); +} + +inline void Node::AssignData(const Node& rhs) { + EnsureNodeExists(); + rhs.EnsureNodeExists(); + + m_pNode->set_data(*rhs.m_pNode); + m_pMemory->merge(*rhs.m_pMemory); +} + +inline void Node::AssignNode(const Node& rhs) { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + rhs.EnsureNodeExists(); + + if (!m_pNode) { + m_pNode = rhs.m_pNode; + m_pMemory = rhs.m_pMemory; + return; + } + + m_pNode->set_ref(*rhs.m_pNode); + m_pMemory->merge(*rhs.m_pMemory); + m_pNode = rhs.m_pNode; +} + +// size/iterator +inline std::size_t Node::size() const { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + return m_pNode ? m_pNode->size() : 0; +} + +inline const_iterator Node::begin() const { + if (!m_isValid) + return const_iterator(); + return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory) + : const_iterator(); +} + +inline iterator Node::begin() { + if (!m_isValid) + return iterator(); + return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator(); +} + +inline const_iterator Node::end() const { + if (!m_isValid) + return const_iterator(); + return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator(); +} + +inline iterator Node::end() { + if (!m_isValid) + return iterator(); + return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator(); +} + +// sequence +template +inline void Node::push_back(const T& rhs) { + if (!m_isValid) + throw InvalidNode(m_invalidKey); + push_back(Node(rhs)); +} + +inline void Node::push_back(const Node& rhs) { + EnsureNodeExists(); + rhs.EnsureNodeExists(); + + m_pNode->push_back(*rhs.m_pNode, m_pMemory); + m_pMemory->merge(*rhs.m_pMemory); +} + +template +std::string key_to_string(const Key& key) { + return streamable_to_string::value>().impl(key); +} + +// indexing +template +inline const Node Node::operator[](const Key& key) const { + EnsureNodeExists(); + detail::node* value = + static_cast(*m_pNode).get(key, m_pMemory); + if (!value) { + return Node(ZombieNode, key_to_string(key)); + } + return Node(*value, m_pMemory); +} + +template +inline Node Node::operator[](const Key& key) { + EnsureNodeExists(); + detail::node& value = m_pNode->get(key, m_pMemory); + return Node(value, m_pMemory); +} + +template +inline bool Node::remove(const Key& key) { + EnsureNodeExists(); + return m_pNode->remove(key, m_pMemory); +} + +inline const Node Node::operator[](const Node& key) const { + EnsureNodeExists(); + key.EnsureNodeExists(); + m_pMemory->merge(*key.m_pMemory); + detail::node* value = + static_cast(*m_pNode).get(*key.m_pNode, m_pMemory); + if (!value) { + return Node(ZombieNode, key_to_string(key)); + } + return Node(*value, m_pMemory); +} + +inline Node Node::operator[](const Node& key) { + EnsureNodeExists(); + key.EnsureNodeExists(); + m_pMemory->merge(*key.m_pMemory); + detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory); + return Node(value, m_pMemory); +} + +inline bool Node::remove(const Node& key) { + EnsureNodeExists(); + key.EnsureNodeExists(); + return m_pNode->remove(*key.m_pNode, m_pMemory); +} + +// map +template +inline void Node::force_insert(const Key& key, const Value& value) { + EnsureNodeExists(); + m_pNode->force_insert(key, value, m_pMemory); +} + +// free functions +inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); } +} // namespace YAML + +#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/iterator.h b/deps/include/yaml-cpp/node/iterator.h new file mode 100644 index 000000000..1fcf6e400 --- /dev/null +++ b/deps/include/yaml-cpp/node/iterator.h @@ -0,0 +1,34 @@ +#ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/detail/iterator_fwd.h" +#include "yaml-cpp/node/detail/iterator.h" +#include +#include +#include + +// Assert in place so gcc + libc++ combination properly builds +static_assert(std::is_constructible::value, "Node must be copy constructable"); + +namespace YAML { +namespace detail { +struct iterator_value : public Node, std::pair { + iterator_value() = default; + explicit iterator_value(const Node& rhs) + : Node(rhs), + std::pair(Node(Node::ZombieNode), Node(Node::ZombieNode)) {} + explicit iterator_value(const Node& key, const Node& value) + : Node(Node::ZombieNode), std::pair(key, value) {} +}; +} +} + +#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/node.h b/deps/include/yaml-cpp/node/node.h new file mode 100644 index 000000000..c9e9a0a4b --- /dev/null +++ b/deps/include/yaml-cpp/node/node.h @@ -0,0 +1,148 @@ +#ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/emitterstyle.h" +#include "yaml-cpp/mark.h" +#include "yaml-cpp/node/detail/iterator_fwd.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/type.h" + +namespace YAML { +namespace detail { +class node; +class node_data; +struct iterator_value; +} // namespace detail +} // namespace YAML + +namespace YAML { +class YAML_CPP_API Node { + public: + friend class NodeBuilder; + friend class NodeEvents; + friend struct detail::iterator_value; + friend class detail::node; + friend class detail::node_data; + template + friend class detail::iterator_base; + template + friend struct as_if; + + using iterator = YAML::iterator; + using const_iterator = YAML::const_iterator; + + Node(); + explicit Node(NodeType::value type); + template + explicit Node(const T& rhs); + explicit Node(const detail::iterator_value& rhs); + Node(const Node& rhs); + ~Node(); + + YAML::Mark Mark() const; + NodeType::value Type() const; + bool IsDefined() const; + bool IsNull() const { return Type() == NodeType::Null; } + bool IsScalar() const { return Type() == NodeType::Scalar; } + bool IsSequence() const { return Type() == NodeType::Sequence; } + bool IsMap() const { return Type() == NodeType::Map; } + + // bool conversions + explicit operator bool() const { return IsDefined(); } + bool operator!() const { return !IsDefined(); } + + // access + template + T as() const; + template + T as(const S& fallback) const; + const std::string& Scalar() const; + + const std::string& Tag() const; + void SetTag(const std::string& tag); + + // style + // WARNING: This API might change in future releases. + EmitterStyle::value Style() const; + void SetStyle(EmitterStyle::value style); + + // assignment + bool is(const Node& rhs) const; + template + Node& operator=(const T& rhs); + Node& operator=(const Node& rhs); + void reset(const Node& rhs = Node()); + + // size/iterator + std::size_t size() const; + + const_iterator begin() const; + iterator begin(); + + const_iterator end() const; + iterator end(); + + // sequence + template + void push_back(const T& rhs); + void push_back(const Node& rhs); + + // indexing + template + const Node operator[](const Key& key) const; + template + Node operator[](const Key& key); + template + bool remove(const Key& key); + + const Node operator[](const Node& key) const; + Node operator[](const Node& key); + bool remove(const Node& key); + + // map + template + void force_insert(const Key& key, const Value& value); + + private: + enum Zombie { ZombieNode }; + explicit Node(Zombie); + explicit Node(Zombie, const std::string&); + explicit Node(detail::node& node, detail::shared_memory_holder pMemory); + + void EnsureNodeExists() const; + + template + void Assign(const T& rhs); + void Assign(const char* rhs); + void Assign(char* rhs); + + void AssignData(const Node& rhs); + void AssignNode(const Node& rhs); + + private: + bool m_isValid; + // String representation of invalid key, if the node is invalid. + std::string m_invalidKey; + mutable detail::shared_memory_holder m_pMemory; + mutable detail::node* m_pNode; +}; + +YAML_CPP_API bool operator==(const Node& lhs, const Node& rhs); + +YAML_CPP_API Node Clone(const Node& node); + +template +struct convert; +} + +#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/parse.h b/deps/include/yaml-cpp/node/parse.h new file mode 100644 index 000000000..7745fd724 --- /dev/null +++ b/deps/include/yaml-cpp/node/parse.h @@ -0,0 +1,78 @@ +#ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include +#include + +#include "yaml-cpp/dll.h" + +namespace YAML { +class Node; + +/** + * Loads the input string as a single YAML document. + * + * @throws {@link ParserException} if it is malformed. + */ +YAML_CPP_API Node Load(const std::string& input); + +/** + * Loads the input string as a single YAML document. + * + * @throws {@link ParserException} if it is malformed. + */ +YAML_CPP_API Node Load(const char* input); + +/** + * Loads the input stream as a single YAML document. + * + * @throws {@link ParserException} if it is malformed. + */ +YAML_CPP_API Node Load(std::istream& input); + +/** + * Loads the input file as a single YAML document. + * + * @throws {@link ParserException} if it is malformed. + * @throws {@link BadFile} if the file cannot be loaded. + */ +YAML_CPP_API Node LoadFile(const std::string& filename); + +/** + * Loads the input string as a list of YAML documents. + * + * @throws {@link ParserException} if it is malformed. + */ +YAML_CPP_API std::vector LoadAll(const std::string& input); + +/** + * Loads the input string as a list of YAML documents. + * + * @throws {@link ParserException} if it is malformed. + */ +YAML_CPP_API std::vector LoadAll(const char* input); + +/** + * Loads the input stream as a list of YAML documents. + * + * @throws {@link ParserException} if it is malformed. + */ +YAML_CPP_API std::vector LoadAll(std::istream& input); + +/** + * Loads the input file as a list of YAML documents. + * + * @throws {@link ParserException} if it is malformed. + * @throws {@link BadFile} if the file cannot be loaded. + */ +YAML_CPP_API std::vector LoadAllFromFile(const std::string& filename); +} // namespace YAML + +#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/ptr.h b/deps/include/yaml-cpp/node/ptr.h new file mode 100644 index 000000000..062d77ea0 --- /dev/null +++ b/deps/include/yaml-cpp/node/ptr.h @@ -0,0 +1,29 @@ +#ifndef VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/dll.h" +#include + +namespace YAML { +namespace detail { +class node; +class node_ref; +class node_data; +class memory; +class memory_holder; + +using shared_node = std::shared_ptr; +using shared_node_ref = std::shared_ptr; +using shared_node_data = std::shared_ptr; +using shared_memory_holder = std::shared_ptr; +using shared_memory = std::shared_ptr; +} +} + +#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/node/type.h b/deps/include/yaml-cpp/node/type.h new file mode 100644 index 000000000..9d55ca966 --- /dev/null +++ b/deps/include/yaml-cpp/node/type.h @@ -0,0 +1,16 @@ +#ifndef VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +namespace YAML { +struct NodeType { + enum value { Undefined, Null, Scalar, Sequence, Map }; +}; +} + +#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/noexcept.h b/deps/include/yaml-cpp/noexcept.h new file mode 100644 index 000000000..6aac63516 --- /dev/null +++ b/deps/include/yaml-cpp/noexcept.h @@ -0,0 +1,18 @@ +#ifndef NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8 +#define NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +// This is here for compatibility with older versions of Visual Studio +// which don't support noexcept. +#if defined(_MSC_VER) && _MSC_VER < 1900 + #define YAML_CPP_NOEXCEPT _NOEXCEPT +#else + #define YAML_CPP_NOEXCEPT noexcept +#endif + +#endif diff --git a/deps/include/yaml-cpp/null.h b/deps/include/yaml-cpp/null.h new file mode 100644 index 000000000..b9521d488 --- /dev/null +++ b/deps/include/yaml-cpp/null.h @@ -0,0 +1,26 @@ +#ifndef NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/dll.h" +#include + +namespace YAML { +class Node; + +struct YAML_CPP_API _Null {}; +inline bool operator==(const _Null&, const _Null&) { return true; } +inline bool operator!=(const _Null&, const _Null&) { return false; } + +YAML_CPP_API bool IsNull(const Node& node); // old API only +YAML_CPP_API bool IsNullString(const std::string& str); + +extern YAML_CPP_API _Null Null; +} + +#endif // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/ostream_wrapper.h b/deps/include/yaml-cpp/ostream_wrapper.h new file mode 100644 index 000000000..cf89741d0 --- /dev/null +++ b/deps/include/yaml-cpp/ostream_wrapper.h @@ -0,0 +1,76 @@ +#ifndef OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include + +#include "yaml-cpp/dll.h" + +namespace YAML { +class YAML_CPP_API ostream_wrapper { + public: + ostream_wrapper(); + explicit ostream_wrapper(std::ostream& stream); + ostream_wrapper(const ostream_wrapper&) = delete; + ostream_wrapper(ostream_wrapper&&) = delete; + ostream_wrapper& operator=(const ostream_wrapper&) = delete; + ostream_wrapper& operator=(ostream_wrapper&&) = delete; + ~ostream_wrapper(); + + void write(const std::string& str); + void write(const char* str, std::size_t size); + + void set_comment() { m_comment = true; } + + const char* str() const { + if (m_pStream) { + return nullptr; + } else { + m_buffer[m_pos] = '\0'; + return &m_buffer[0]; + } + } + + std::size_t row() const { return m_row; } + std::size_t col() const { return m_col; } + std::size_t pos() const { return m_pos; } + bool comment() const { return m_comment; } + + private: + void update_pos(char ch); + + private: + mutable std::vector m_buffer; + std::ostream* const m_pStream; + + std::size_t m_pos; + std::size_t m_row, m_col; + bool m_comment; +}; + +template +inline ostream_wrapper& operator<<(ostream_wrapper& stream, + const char (&str)[N]) { + stream.write(str, N - 1); + return stream; +} + +inline ostream_wrapper& operator<<(ostream_wrapper& stream, + const std::string& str) { + stream.write(str); + return stream; +} + +inline ostream_wrapper& operator<<(ostream_wrapper& stream, char ch) { + stream.write(&ch, 1); + return stream; +} +} // namespace YAML + +#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/parser.h b/deps/include/yaml-cpp/parser.h new file mode 100644 index 000000000..2f403c350 --- /dev/null +++ b/deps/include/yaml-cpp/parser.h @@ -0,0 +1,90 @@ +#ifndef PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include + +#include "yaml-cpp/dll.h" + +namespace YAML { +class EventHandler; +class Node; +class Scanner; +struct Directives; +struct Token; + +/** + * A parser turns a stream of bytes into one stream of "events" per YAML + * document in the input stream. + */ +class YAML_CPP_API Parser { + public: + /** Constructs an empty parser (with no input. */ + Parser(); + + Parser(const Parser&) = delete; + Parser(Parser&&) = delete; + Parser& operator=(const Parser&) = delete; + Parser& operator=(Parser&&) = delete; + + /** + * Constructs a parser from the given input stream. The input stream must + * live as long as the parser. + */ + explicit Parser(std::istream& in); + + ~Parser(); + + /** Evaluates to true if the parser has some valid input to be read. */ + explicit operator bool() const; + + /** + * Resets the parser with the given input stream. Any existing state is + * erased. + */ + void Load(std::istream& in); + + /** + * Handles the next document by calling events on the {@code eventHandler}. + * + * @throw a ParserException on error. + * @return false if there are no more documents + */ + bool HandleNextDocument(EventHandler& eventHandler); + + void PrintTokens(std::ostream& out); + + private: + /** + * Reads any directives that are next in the queue, setting the internal + * {@code m_pDirectives} state. + */ + void ParseDirectives(); + + void HandleDirective(const Token& token); + + /** + * Handles a "YAML" directive, which should be of the form 'major.minor' (like + * a version number). + */ + void HandleYamlDirective(const Token& token); + + /** + * Handles a "TAG" directive, which should be of the form 'handle prefix', + * where 'handle' is converted to 'prefix' in the file. + */ + void HandleTagDirective(const Token& token); + + private: + std::unique_ptr m_pScanner; + std::unique_ptr m_pDirectives; +}; +} // namespace YAML + +#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/stlemitter.h b/deps/include/yaml-cpp/stlemitter.h new file mode 100644 index 000000000..210a2f64e --- /dev/null +++ b/deps/include/yaml-cpp/stlemitter.h @@ -0,0 +1,50 @@ +#ifndef STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include +#include +#include + +namespace YAML { +template +inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) { + emitter << BeginSeq; + for (const auto& v : seq) + emitter << v; + emitter << EndSeq; + return emitter; +} + +template +inline Emitter& operator<<(Emitter& emitter, const std::vector& v) { + return EmitSeq(emitter, v); +} + +template +inline Emitter& operator<<(Emitter& emitter, const std::list& v) { + return EmitSeq(emitter, v); +} + +template +inline Emitter& operator<<(Emitter& emitter, const std::set& v) { + return EmitSeq(emitter, v); +} + +template +inline Emitter& operator<<(Emitter& emitter, const std::map& m) { + emitter << BeginMap; + for (const auto& v : m) + emitter << Key << v.first << Value << v.second; + emitter << EndMap; + return emitter; +} +} + +#endif // STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/traits.h b/deps/include/yaml-cpp/traits.h new file mode 100644 index 000000000..9a62db257 --- /dev/null +++ b/deps/include/yaml-cpp/traits.h @@ -0,0 +1,135 @@ +#ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include +#include +#include + +namespace YAML { +template +struct is_numeric { + enum { value = false }; +}; + +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +#if defined(_MSC_VER) && (_MSC_VER < 1310) +template <> +struct is_numeric<__int64> { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +#else +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +#endif +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; +template <> +struct is_numeric { + enum { value = true }; +}; + +template +struct enable_if_c { + using type = T; +}; + +template +struct enable_if_c {}; + +template +struct enable_if : public enable_if_c {}; + +template +struct disable_if_c { + using type = T; +}; + +template +struct disable_if_c {}; + +template +struct disable_if : public disable_if_c {}; +} + +template +struct is_streamable { + template + static auto test(int) + -> decltype(std::declval() << std::declval(), std::true_type()); + + template + static auto test(...) -> std::false_type; + + static const bool value = decltype(test(0))::value; +}; + +template +struct streamable_to_string { + static std::string impl(const Key& key) { + std::stringstream ss; + ss << key; + return ss.str(); + } +}; + +template +struct streamable_to_string { + static std::string impl(const Key&) { + return ""; + } +}; +#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/include/yaml-cpp/yaml.h b/deps/include/yaml-cpp/yaml.h new file mode 100644 index 000000000..7f515efb9 --- /dev/null +++ b/deps/include/yaml-cpp/yaml.h @@ -0,0 +1,24 @@ +#ifndef YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/parser.h" +#include "yaml-cpp/emitter.h" +#include "yaml-cpp/emitterstyle.h" +#include "yaml-cpp/stlemitter.h" +#include "yaml-cpp/exceptions.h" + +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/impl.h" +#include "yaml-cpp/node/convert.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/detail/impl.h" +#include "yaml-cpp/node/parse.h" +#include "yaml-cpp/node/emit.h" + +#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/deps/lib/yaml-cpp-d.lib b/deps/lib/yaml-cpp-d.lib new file mode 100644 index 000000000..81f7fed7b Binary files /dev/null and b/deps/lib/yaml-cpp-d.lib differ diff --git a/deps/lib/yaml-cpp.lib b/deps/lib/yaml-cpp.lib new file mode 100644 index 000000000..65bc7dacc Binary files /dev/null and b/deps/lib/yaml-cpp.lib differ diff --git a/legion/engine/application/window/windowsystem.cpp b/legion/engine/application/window/windowsystem.cpp index 5db797845..6fac22018 100644 --- a/legion/engine/application/window/windowsystem.cpp +++ b/legion/engine/application/window/windowsystem.cpp @@ -270,7 +270,7 @@ namespace legion::application using namespace filesystem::literals; m_exit = false; - m_defaultIcon = assets::load("Legion Icon", "engine://resources/legion/icon"_view, assets::import_settings{ true, true, false }); + m_defaultIcon = *assets::load("Legion Icon", "engine://resources/legion/icon"_view, assets::import_settings{ true, true, false }); bindToEvent(); diff --git a/legion/engine/audio/data/audio_segment.cpp b/legion/engine/audio/data/audio_segment.cpp index 36c7bbc0e..01eae841c 100644 --- a/legion/engine/audio/data/audio_segment.cpp +++ b/legion/engine/audio/data/audio_segment.cpp @@ -145,7 +145,7 @@ namespace legion::audio if (result != common::valid) { //log::error("Audio file wrong!"); - log::error("Error while loading file: {}, {}", static_cast(file.get_filename()), result.error()); + log::error("Error while loading file: {}, {}", *file.get_filename(), result.error()); return invalid_audio_segment_handle; } @@ -155,7 +155,7 @@ namespace legion::audio if (settings.channel_processing == audio_import_settings::channel_processing_setting::split_channels) { - audio_segment as = static_cast(result); + audio_segment as = *result; int amount = 1; audio_segment* segment = &as; log::debug("next is nullptr: {}", as.getNextAudioSegment() == nullptr); @@ -170,7 +170,7 @@ namespace legion::audio } auto* pairPointer = new std::pair(); - pairPointer->second = static_cast(result); + pairPointer->second = *result; m_segments.emplace(std::make_pair(id, std::unique_ptr>(pairPointer))); } diff --git a/legion/engine/core/assets/assets.inl b/legion/engine/core/assets/assets.inl index 6b88ec4df..6ce52984f 100644 --- a/legion/engine/core/assets/assets.inl +++ b/legion/engine/core/assets/assets.inl @@ -444,7 +444,7 @@ namespace legion::core::assets template inline L_ALWAYS_INLINE asset AssetLoader::create(id_type nameHash, Args&&...args) const { - return AssetCache::createInternal(nameHash, std::forward(args)...); + return *AssetCache::createInternal(nameHash, std::forward(args)...); } template diff --git a/legion/engine/core/common/hash.cpp b/legion/engine/core/common/hash.cpp index dc08b6986..02da74012 100644 --- a/legion/engine/core/common/hash.cpp +++ b/legion/engine/core/common/hash.cpp @@ -2,19 +2,12 @@ namespace legion::core { - id_type local_cast(id_type global) + namespace detail { - return detail::global_to_local.at(global); - } - - id_type global_cast(id_type local) - { - return detail::local_to_global.at(local); - } - - type_reference type_ref_cast(id_type hash) - { - return detail::hash_to_reference.at(hash); + void type_data::onInit() + { + create(); + } } name_hash::name_hash(const name_hash& src) noexcept { value = src.value; } @@ -33,55 +26,39 @@ namespace legion::core return *this; } - type_reference::type_reference(std::nullptr_t) - : value(nullptr) {} - - type_reference::type_reference(const type_hash_base& src) - : value(src.copy()) - { - detail::hash_to_reference.emplace(value->local(), *this); - } + type_hash::type_hash(const type_hash& src) noexcept : m_name(src.m_name), m_value(src.m_value) {} - type_reference::type_reference(const type_reference& src) - : value(src.value->copy()) {} + type_hash::type_hash(type_hash&& src) noexcept : m_name(src.m_name), m_value(src.m_value) {} - type_reference::type_reference(type_reference&& src) - : value(std::move(src.value)) {} - - type_reference& type_reference::operator=(const type_reference& src) + type_hash& type_hash::operator=(const type_hash& src) noexcept { - value = std::unique_ptr(src.value->copy()); + m_value = src.m_value; + m_name = src.m_name; return *this; } - type_reference& type_reference::operator=(type_reference&& src) + type_hash& type_hash::operator=(type_hash&& src) noexcept { - value = std::move(src.value); + m_value = src.m_value; + m_name = src.m_name; return *this; } - id_type type_reference::local() const - { - return value->local(); - } + type_hash::operator id_type() const noexcept { return id(); } - id_type type_reference::global() const - { - return value->global(); - } + L_NODISCARD id_type type_hash::id() const noexcept { return m_value; } - std::string_view type_reference::local_name() const - { - return value->local_name(); - } + L_NODISCARD std::string_view type_hash::name() const noexcept { return m_name; } + + type_hash::type_hash(id_type id, std::string_view name) noexcept : m_name(name), m_value(id) {} - std::string_view type_reference::global_name() const + L_NODISCARD type_hash type_hash::from_name(std::string_view name) { - return value->global_name(); + return type_hash(nameHash(name), name); } - type_reference::operator id_type() const + L_NODISCARD type_hash type_hash::from_id(id_type id) { - return value->local(); + return type_hash(id, detail::type_data::getInstance().id_to_name[id]); } } diff --git a/legion/engine/core/common/hash.hpp b/legion/engine/core/common/hash.hpp index 4b19f2795..a647cde4f 100644 --- a/legion/engine/core/common/hash.hpp +++ b/legion/engine/core/common/hash.hpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include namespace legion::core { @@ -35,141 +37,61 @@ namespace legion::core namespace detail { - static std::unordered_map local_to_global; - static std::unordered_map global_to_local; - } - - id_type local_cast(id_type global); - id_type global_cast(id_type local); - - struct type_hash_base - { - friend struct type_reference; - - virtual id_type local() const noexcept LEGION_PURE; - virtual std::string_view local_name() const noexcept LEGION_PURE; - virtual id_type global() const noexcept LEGION_PURE; - virtual std::string_view global_name() const noexcept LEGION_PURE; - - protected: - virtual type_hash_base* copy() const LEGION_PURE; - }; - - template - struct type_hash : public type_hash_base - { - std::string_view name; - id_type value = invalid_id; - - constexpr operator id_type () const noexcept; - - constexpr type_hash() noexcept : value(localTypeHash()), name(localNameOfType()) {} - - type_hash(const type_hash& src) noexcept : value(src.value), name(src.name) {} - type_hash(type_hash&& src) noexcept : value(src.value), name(src.name) {} - - type_hash& operator=(const type_hash& src) noexcept - { - value = src.value; - name = src.name; - return *this; - } - - type_hash& operator=(type_hash&& src) noexcept - { - value = src.value; - name = src.name; - return *this; - } - - virtual id_type local() const noexcept + struct type_data : public EngineSubSystem { - return value; - } + std::unordered_map id_to_name; - virtual std::string_view local_name() const noexcept - { - return name; - } + AllowPrivateOnInit; + SubSystemInstance(type_data); + private: + static void onInit(); + }; - virtual id_type global() const noexcept - { - if (!detail::local_to_global.count(value)) - { - auto global = typeHash(); - detail::local_to_global.emplace(value, global); - detail::global_to_local.emplace(global, value); - } - return typeHash(); - } + OnEngineInit(type_data, &type_data::init); + OnEngineShutdown(type_data, &type_data::shutdown); - virtual std::string_view global_name() const noexcept - { - if (!detail::local_to_global.count(value)) - { - auto global = typeHash(); - detail::local_to_global.emplace(value, global); - detail::global_to_local.emplace(global, value); - } - return nameOfType(); - } - - protected: - virtual type_hash_base* copy() const + template + std::string_view register_name(id_type id) { - if (!detail::local_to_global.count(value)) - { - auto global = typeHash(); - detail::local_to_global.emplace(value, global); - detail::global_to_local.emplace(global, value); - } - return new type_hash(); + auto [iterator, emplaced] = type_data::getInstance().id_to_name.emplace(id, std::string(nameOfType())); + return iterator->second; } - }; - - LEGION_CLANG_SUPPRESS_WARNING_PUSH - LEGION_GCC_SUPPRESS_WARNING_PUSH - LEGION_CLANG_SUPPRESS_WARNING("-Wdelete-abstract-non-virtual-dtor") - LEGION_GCC_SUPPRESS_WARNING("-Wdelete-abstract-non-virtual-dtor") + } - struct type_reference + struct type_hash { - private: - std::unique_ptr value; + template + friend type_hash make_hash() noexcept; - public: - type_reference() = default; - type_reference(std::nullptr_t); - type_reference(const type_hash_base& src); + L_NODISCARD static type_hash from_name(std::string_view name); + L_NODISCARD static type_hash from_id(id_type id); - type_reference(const type_reference& src); - type_reference(type_reference&& src); + type_hash(const type_hash& src) noexcept; + type_hash(type_hash&& src) noexcept; - type_reference& operator=(const type_reference& src); - type_reference& operator=(type_reference&& src); + type_hash& operator=(const type_hash& src) noexcept; - id_type local() const; - id_type global() const; - std::string_view local_name() const; - std::string_view global_name() const; + type_hash& operator=(type_hash&& src) noexcept; - operator id_type() const; - }; + operator id_type() const noexcept; - LEGION_GCC_SUPPRESS_WARNING_POP - LEGION_CLANG_SUPPRESS_WARNING_POP + L_NODISCARD id_type id() const noexcept; + L_NODISCARD std::string_view name() const noexcept; - namespace detail - { - static std::unordered_map hash_to_reference; - } + protected: + type_hash(id_type id, std::string_view name) noexcept; - type_reference type_ref_cast(id_type hash); + std::string_view m_name; + id_type m_value = invalid_id; + }; template - constexpr type_hash make_hash() noexcept + type_hash make_hash() noexcept { - return type_hash{}; + static id_type id = typeHash(); + static std::string_view name = detail::register_name(id); + + return type_hash{ id, name }; } template @@ -188,11 +110,11 @@ namespace legion::core #if !defined(DOXY_EXCLUDE) namespace std { - template<> struct hash + template<> struct hash { - std::size_t operator()(legion::core::type_reference const& handle) const noexcept + std::size_t operator()(legion::core::type_hash const& handle) const noexcept { - return handle.local(); + return handle.id(); } }; } diff --git a/legion/engine/core/common/hash.inl b/legion/engine/core/common/hash.inl index cf9d7fbcc..78369ab8f 100644 --- a/legion/engine/core/common/hash.inl +++ b/legion/engine/core/common/hash.inl @@ -8,12 +8,6 @@ namespace legion::core return value; } - template - constexpr type_hash::operator id_type() const noexcept - { - return value; - } - constexpr id_type combine_hash(id_type seed, id_type value) { value += 0x9e3779b9 + (seed << 6) + (seed >> 2); diff --git a/legion/engine/core/common/result.hpp b/legion/engine/core/common/result.hpp index 7de477efc..03baaf841 100644 --- a/legion/engine/core/common/result.hpp +++ b/legion/engine/core/common/result.hpp @@ -65,7 +65,7 @@ namespace legion::core::common if (m_succeeded) m_success.~success_type(); else if (!m_handled) - throw m_error; + throw m_error; } L_NODISCARD success_type& value() @@ -110,11 +110,6 @@ namespace legion::core::common void mark_handled() const noexcept { m_handled = true; } - L_NODISCARD operator success_type() { return value(); } - L_NODISCARD operator success_type() const { return value(); } - L_NODISCARD operator error_type() { return error(); } - L_NODISCARD operator error_type() const { return error(); } - L_NODISCARD success_type& operator*() { return m_success; } L_NODISCARD const success_type& operator*() const { return m_success; } L_NODISCARD success_type* operator->() { return &m_success; } @@ -157,12 +152,33 @@ namespace legion::core::common using warning_type = Warning; using warning_list = std::vector; - result(const result& src) = default; - result(result&& src) = default; + result(const result& src) : m_handled(src.m_handled), m_error(src.m_error), m_warnings(src.m_warnings) {} + result(result&& src) : m_handled(src.m_handled), m_error(src.m_error), m_warnings(src.m_warnings) { src.m_handled = true; } ~result() noexcept(false) { if (m_error && !m_handled) - throw *m_error; + throw* m_error; + } + + result& operator=(const result& src) + { + if (m_error && !m_handled) + throw* m_error; + + m_handled = src.m_handled; + m_error = src.m_error; + m_warnings = src.m_warnings; + } + + result& operator=(result&& src) + { + if (m_error && !m_handled) + throw* m_error; + + m_handled = src.m_handled; + m_error = src.m_error; + m_warnings = src.m_warnings; + src.m_handled = true; } result(success_t) {} @@ -204,9 +220,6 @@ namespace legion::core::common void mark_handled() const noexcept { m_handled = true; } - L_NODISCARD operator error_type() { return error(); } - L_NODISCARD operator error_type() const { return error(); } - L_NODISCARD bool has_warnings() const noexcept { return !m_warnings.empty(); } L_NODISCARD size_t warning_count() const noexcept { return m_warnings.size(); } L_NODISCARD const Warning& warning_at(size_t i) const { return m_warnings[i]; } @@ -271,9 +284,6 @@ namespace legion::core::common throw legion_exception_msg("this result is invalid!"); } - L_NODISCARD operator success_type() { return value(); } - L_NODISCARD operator success_type() const { return value(); } - L_NODISCARD success_type& operator*() { return *m_success; } L_NODISCARD const success_type& operator*() const { return *m_success; } L_NODISCARD success_type* operator->() { return &*m_success; } @@ -350,4 +360,10 @@ namespace legion::core::common warning_list m_warnings; }; +#define PropagateErrors(result, warnings) \ +{ \ + warnings.insert(warnings.end(), result.warnings().begin(), result.warnings().end()); \ + if (result.has_error()) { return { result.error(), warnings }; } \ +} + } diff --git a/legion/engine/core/containers/hashed_sparse_set.hpp b/legion/engine/core/containers/hashed_sparse_set.hpp index f2984863c..0d791c239 100644 --- a/legion/engine/core/containers/hashed_sparse_set.hpp +++ b/legion/engine/core/containers/hashed_sparse_set.hpp @@ -24,18 +24,25 @@ namespace legion::core * @note With default container parameters iterators may be invalidated upon resize. See reference of std::vector. * @note Removing item might invalidate the iterator of the last item in the dense container. */ - template , template typename dense_type = std::vector, template typename sparse_type = std::unordered_map> + template , template typename Dense = std::vector, template typename Sparse = std::unordered_map> class hashed_sparse_set { public: - using self_type = hashed_sparse_set; - using self_reference = self_type&; - using self_const_reference = const self_type&; + using value_type = Value; + using hash_type = Hash; + template + using dense_type = Dense; + template + using sparse_type = Sparse; using value_reference = value_type&; using value_const_reference = const value_type&; using value_pointer = value_type*; + using self_type = hashed_sparse_set; + using self_reference = self_type&; + using self_const_reference = const self_type&; + using sparse_container = sparse_type; using dense_container = dense_type; diff --git a/legion/engine/core/core.hpp b/legion/engine/core/core.hpp index ffb5938bc..8806c8245 100644 --- a/legion/engine/core/core.hpp +++ b/legion/engine/core/core.hpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -28,6 +27,7 @@ #include #include +#include namespace legion { diff --git a/legion/engine/core/core.vcxproj b/legion/engine/core/core.vcxproj index b90b52552..8d6dccad5 100644 --- a/legion/engine/core/core.vcxproj +++ b/legion/engine/core/core.vcxproj @@ -76,7 +76,7 @@ OpenCL.lib;%(AdditionalDependencies) - xcopy "$(OutDir)$(TargetName).lib" "$(SolutionDir)lib\" /y /i /r + xcopy "$(OutDir)$(TargetName).lib" "$(SolutionDir)lib\" /y /i /r copy /Y "$(SolutionDir)deps\dll\" "$(OutDir)" @@ -110,7 +110,7 @@ del /q ".\xcopyexclude" OpenCL.lib;%(AdditionalDependencies) - xcopy "$(OutDir)$(TargetName).lib" "$(SolutionDir)lib\" /y /i /r + xcopy "$(OutDir)$(TargetName).lib" "$(SolutionDir)lib\" /y /i /r copy /Y "$(SolutionDir)deps\dll\" "$(OutDir)" @@ -189,14 +189,17 @@ del /q ".\xcopyexclude" - - + + + + + @@ -519,12 +522,14 @@ del /q ".\xcopyexclude" - + + + + - @@ -573,6 +578,11 @@ del /q ".\xcopyexclude" + + + + + @@ -592,7 +602,6 @@ del /q ".\xcopyexclude" - @@ -739,7 +748,11 @@ del /q ".\xcopyexclude" + + + + diff --git a/legion/engine/core/core.vcxproj.filters b/legion/engine/core/core.vcxproj.filters index cac60e094..28888fcc3 100644 --- a/legion/engine/core/core.vcxproj.filters +++ b/legion/engine/core/core.vcxproj.filters @@ -41,6 +41,11 @@ + + + + + @@ -395,7 +400,6 @@ - @@ -411,10 +415,8 @@ - - @@ -422,7 +424,7 @@ - + @@ -432,6 +434,7 @@ + @@ -448,7 +451,14 @@ + + + + + + + @@ -593,7 +603,6 @@ - @@ -614,5 +623,9 @@ + + + + \ No newline at end of file diff --git a/legion/engine/core/ecs/containers/component_pool.hpp b/legion/engine/core/ecs/containers/component_pool.hpp index 040792d3e..c6f3b8f79 100644 --- a/legion/engine/core/ecs/containers/component_pool.hpp +++ b/legion/engine/core/ecs/containers/component_pool.hpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -30,11 +29,10 @@ namespace legion::core::ecs /**@brief Creates a component attached to a certain entity. (uses a prototype to serialize the component) * @param target Entity ID to create the component for. - * @param prototype Prototype used to serialize the component. + * @param src Pointer to component to copy from. * @return Pointer to the created component. */ - //virtual void* create_component(entity target, const serialization::component_prototype_base& prototype) LEGION_PURE; - //virtual void* create_component(entity target, serialization::component_prototype_base&& prototype) LEGION_PURE; + virtual void* create_component(entity target, const void* src) LEGION_PURE; /**@brief Check if a certain entity has the type of component managed by this pool. * @param target Entity ID of the entity to check for. @@ -53,12 +51,6 @@ namespace legion::core::ecs */ virtual void destroy_component(entity target) LEGION_PURE; - /**@brief Serialize a certain component into a prototype. - * @param target Entity ID of the entity the component is attached to. - * @return `std::unique_ptr` with the prototype. - */ - //L_NODISCARD virtual std::unique_ptr create_prototype(entity target) const LEGION_PURE; - virtual ~component_pool_base() = default; }; @@ -86,11 +78,10 @@ namespace legion::core::ecs /**@brief Creates a component attached to a certain entity. (uses a prototype to serialize the component) * @param target Entity ID to create the component for. - * @param prototype Prototype used to serialize the component. + * @param src Pointer to component to copy from. * @return Pointer to the created component. */ - //virtual void* create_component(entity target, const serialization::component_prototype_base& prototype); - //virtual void* create_component(entity target, serialization::component_prototype_base&& prototype); + virtual void* create_component(entity target, const void* src); /**@brief Check if a certain entity has the type of component managed by this pool. * @param target Entity ID of the entity to check for. @@ -109,14 +100,6 @@ namespace legion::core::ecs */ virtual void destroy_component(entity target); - /**@brief Serialize a certain component into a prototype. - * @param target Entity ID of the entity the component is attached to. - * @return `std::unique_ptr` with the prototype. - */ - //L_NODISCARD virtual std::unique_ptr create_prototype(entity target) const; - - //L_NODISCARD static serialization::component_prototype create_prototype_direct(entity target); - /**@brief Creates a component attached to a certain entity. * @note This is a more optimized direct variant, but it requires compile time info about what the component type is. * @param target Entity ID to create the component for. @@ -132,15 +115,6 @@ namespace legion::core::ecs static component_type& create_component_direct(entity target, component_type&& value); static component_type& create_component_direct(entity target, const component_type& value); - /**@brief Creates a component attached to a certain entity. (uses a prototype to serialize the component) - * @note This is a more optimized direct variant, but it requires compile time info about what the component type is. - * @param target Entity ID to create the component for. - * @param prototype Prototype used to serialize the component. - * @return Reference to the component. - */ - //static component_type& create_component_direct(entity target, const serialization::component_prototype_base& prototype); - //static component_type& create_component_direct(entity target, serialization::component_prototype_base&& prototype); - /**@brief Check if a certain entity has the type of component managed by this pool. * @note This is a more optimized direct variant, but it requires compile time info about what the component type is. * @param target Entity ID of the entity to check for. diff --git a/legion/engine/core/ecs/containers/component_pool.inl b/legion/engine/core/ecs/containers/component_pool.inl index becc664d9..9800d786c 100644 --- a/legion/engine/core/ecs/containers/component_pool.inl +++ b/legion/engine/core/ecs/containers/component_pool.inl @@ -41,47 +41,24 @@ namespace legion::core::ecs return &ret; } - //template - //inline L_ALWAYS_INLINE void* component_pool::create_component(entity target, const serialization::component_prototype_base& prototype) - //{ - // auto& ret = m_components.try_emplace(target, - // from_reflector(static_cast&>(prototype)) - // ).first.value(); - - // if constexpr (has_static_init_v) - // { - // component_type::init(ret, target); - // } - // else if constexpr (has_static_init_v) - // { - // component_type::init(ret); - // } - - // events::EventBus::raiseEvent>(target); - - // return &ret; - //} - - //template - //inline L_ALWAYS_INLINE void* component_pool::create_component(entity target, serialization::component_prototype_base&& prototype) - //{ - // auto& ret = m_components.try_emplace(target, - // from_reflector(static_cast&&>(prototype)) - // ).first.value(); - - // if constexpr (has_static_init_v) - // { - // component_type::init(ret, target); - // } - // else if constexpr (has_static_init_v) - // { - // component_type::init(ret); - // } - - // events::EventBus::raiseEvent>(target); - - // return &ret; - //} + template + inline L_ALWAYS_INLINE void* component_pool::create_component(entity target, const void* src) + { + auto& ret = m_components.try_emplace(target, *static_cast(src)).first.value(); + + if constexpr (has_static_init_v) + { + component_type::init(ret, target); + } + else if constexpr (has_static_init_v) + { + component_type::init(ret); + } + + events::EventBus::raiseEvent>(target); + + return &ret; + } template inline L_ALWAYS_INLINE bool component_pool::contains(entity target) const @@ -106,20 +83,6 @@ namespace legion::core::ecs m_components.erase(target->id); } - //template - //inline L_ALWAYS_INLINE std::unique_ptr component_pool::create_prototype(entity target) const - //{ - // return std::unique_ptr( - // new serialization::component_prototype(m_components.at(target)) - // ); - //} - - //template - //inline L_ALWAYS_INLINE serialization::component_prototype component_pool::create_prototype_direct(entity target) - //{ - // return serialization::component_prototype(m_components.at(target)); - //} - template inline L_ALWAYS_INLINE void* component_pool::get_component(entity target) const { @@ -183,48 +146,6 @@ namespace legion::core::ecs return ret; } - //template - //inline L_ALWAYS_INLINE component_type& component_pool::create_component_direct(entity target, const serialization::component_prototype_base& prototype) - //{ - // auto& ret = m_components.try_emplace(target, - // from_reflector(static_cast&>(prototype)) - // ).first.value(); - - // if constexpr (has_static_init_v) - // { - // component_type::init(ret, target); - // } - // else if constexpr (has_static_init_v) - // { - // component_type::init(ret); - // } - - // events::EventBus::raiseEvent>(target); - - // return ret; - //} - - //template - //inline L_ALWAYS_INLINE component_type& component_pool::create_component_direct(entity target, serialization::component_prototype_base&& prototype) - //{ - // auto& ret = m_components.try_emplace(target, - // from_reflector(static_cast&&>(prototype)) - // ).first.value(); - - // if constexpr (has_static_init_v) - // { - // component_type::init(ret, target); - // } - // else if constexpr (has_static_init_v) - // { - // component_type::init(ret); - // } - - // events::EventBus::raiseEvent>(target); - - // return ret; - //} - template inline L_ALWAYS_INLINE bool component_pool::contains_direct(entity target) { diff --git a/legion/engine/core/ecs/ecs.hpp b/legion/engine/core/ecs/ecs.hpp index 0b3b50905..999aac417 100644 --- a/legion/engine/core/ecs/ecs.hpp +++ b/legion/engine/core/ecs/ecs.hpp @@ -6,5 +6,3 @@ #include #include #include -#include -#include diff --git a/legion/engine/core/ecs/filters/filter_info.hpp b/legion/engine/core/ecs/filters/filter_info.hpp index 51ea15502..6e8a157d1 100644 --- a/legion/engine/core/ecs/filters/filter_info.hpp +++ b/legion/engine/core/ecs/filters/filter_info.hpp @@ -58,11 +58,11 @@ namespace legion::core::ecs public: /**@brief The actual id of the filter variant. */ - static constexpr id_type filter_id = generateId(); + static const id_type filter_id; /**@brief Array of the individual component type ids. */ - static constexpr std::array composition = { make_hash()... }; + static const std::array composition; virtual id_type id(); diff --git a/legion/engine/core/ecs/filters/filter_info.inl b/legion/engine/core/ecs/filters/filter_info.inl index 3b39bf5c0..82b65aab4 100644 --- a/legion/engine/core/ecs/filters/filter_info.inl +++ b/legion/engine/core/ecs/filters/filter_info.inl @@ -3,6 +3,12 @@ namespace legion::core::ecs { + template + const id_type filter_info::filter_id = filter_info::generateId(); + + template + const std::array filter_info::composition = { make_hash().id()... }; + template inline L_ALWAYS_INLINE id_type filter_info::id() { diff --git a/legion/engine/core/ecs/filters/filterregistry.cpp b/legion/engine/core/ecs/filters/filterregistry.cpp index 4b4f897c2..2e746c919 100644 --- a/legion/engine/core/ecs/filters/filterregistry.cpp +++ b/legion/engine/core/ecs/filters/filterregistry.cpp @@ -50,8 +50,9 @@ namespace legion::core::ecs void FilterRegistry::onInit() { - create(); + reportDependency<::legion::core::detail::type_data>(); reportDependency(); + create(); } void FilterRegistry::onShutdown() diff --git a/legion/engine/core/ecs/filters/filterregistry.hpp b/legion/engine/core/ecs/filters/filterregistry.hpp index 54d7c71f8..9240753f1 100644 --- a/legion/engine/core/ecs/filters/filterregistry.hpp +++ b/legion/engine/core/ecs/filters/filterregistry.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/legion/engine/core/ecs/filters/filterregistry.inl b/legion/engine/core/ecs/filters/filterregistry.inl index e63ce1fb5..1bd6e9035 100644 --- a/legion/engine/core/ecs/filters/filterregistry.inl +++ b/legion/engine/core/ecs/filters/filterregistry.inl @@ -42,7 +42,7 @@ namespace legion::core::ecs { init(); // Get the id. - constexpr id_type id = generateId(); + static const id_type id = generateId(); // Register the component types if it they aren't yet. Registry::registerComponentType(); diff --git a/legion/engine/core/ecs/handles/component.hpp b/legion/engine/core/ecs/handles/component.hpp index c7ea9dcd9..732e84e3a 100644 --- a/legion/engine/core/ecs/handles/component.hpp +++ b/legion/engine/core/ecs/handles/component.hpp @@ -25,7 +25,7 @@ namespace legion::core::ecs template struct component : public component_base { - static constexpr type_hash typeId = make_hash(); + static const type_hash typeId; entity owner; diff --git a/legion/engine/core/ecs/handles/component.inl b/legion/engine/core/ecs/handles/component.inl index 363c55f70..a886049cd 100644 --- a/legion/engine/core/ecs/handles/component.inl +++ b/legion/engine/core/ecs/handles/component.inl @@ -4,6 +4,9 @@ namespace legion::core::ecs { + template + const type_hash component::typeId = make_hash(); + template inline L_ALWAYS_INLINE component& component::operator=(const component_type& src) { diff --git a/legion/engine/core/ecs/handles/entity.cpp b/legion/engine/core/ecs/handles/entity.cpp index 3dce63662..c9dd99a40 100644 --- a/legion/engine/core/ecs/handles/entity.cpp +++ b/legion/engine/core/ecs/handles/entity.cpp @@ -1,5 +1,4 @@ #include - #include namespace legion::core::ecs diff --git a/legion/engine/core/ecs/handles/entity.hpp b/legion/engine/core/ecs/handles/entity.hpp index 2e96e3bc1..0ada1fa6a 100644 --- a/legion/engine/core/ecs/handles/entity.hpp +++ b/legion/engine/core/ecs/handles/entity.hpp @@ -22,12 +22,6 @@ namespace legion::core struct entity; } - - namespace serialization - { - template - struct prototype; - } } #if !defined(DOXY_EXCLUDE) @@ -297,16 +291,6 @@ namespace legion::core::ecs template typename archetype_type::handle_group add_component(component_type0&& value0, component_type1&& value1, component_typeN&&... valueN); - /**@brief Creates and adds a new component of a certain type to this entity. Component is serialized from a prototype. - * @tparam component_type Type of the component to add. - * @param prot Prototype to serialize component from. - * @return Component handle to the component. - */ - template - component add_component(const serialization::prototype>& prot); - template - component add_component(serialization::prototype>&& prot); - /**@brief Checks whether this entity has a certain component. * @tparam component_type Type of the component to check for. * @return True if the entity has the component, false if not. diff --git a/legion/engine/core/ecs/handles/entity.inl b/legion/engine/core/ecs/handles/entity.inl index 3034896b1..bdf38d005 100644 --- a/legion/engine/core/ecs/handles/entity.inl +++ b/legion/engine/core/ecs/handles/entity.inl @@ -138,20 +138,6 @@ namespace legion::core::ecs return std::make_tuple(component>{ {}, entity{ data } }, component>{ {}, entity{ data } }, component>{ {}, entity{ data } }...); } - template - inline L_ALWAYS_INLINE component entity::add_component(const serialization::prototype>& prot) - { - Registry::createComponent(*this, prot); - return { {}, entity{data} }; - } - - template - inline L_ALWAYS_INLINE component entity::add_component(serialization::prototype>&& prot) - { - Registry::createComponent(*this, std::move(prot)); - return { {}, entity{data} }; - } - template inline L_ALWAYS_INLINE bool entity::has_component() const { diff --git a/legion/engine/core/ecs/prototypes/component_prototype.hpp b/legion/engine/core/ecs/prototypes/component_prototype.hpp deleted file mode 100644 index 15199a16b..000000000 --- a/legion/engine/core/ecs/prototypes/component_prototype.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include - -#include - -/** - * @file component_prototype.hpp - */ - -namespace legion::core::serialization -{ - /**@struct prototype - * @brief Prototype specialization base class for component specializations. - */ - - /**@struct prototype> - * @brief Prototype specialization components. Makes use of reflectors. - * @ref legion::core::reflector - */ - - - /**@class component_prototype_base - * @brief Type alias for `prototype`. Base class for component specializations. - */ - - - /**@class component_prototype - * @brief Type alias for `prototype>`. Can be used to serialize and deserialize components. - */ - -} diff --git a/legion/engine/core/ecs/prototypes/entity_prototype.hpp b/legion/engine/core/ecs/prototypes/entity_prototype.hpp deleted file mode 100644 index 1781a7e6d..000000000 --- a/legion/engine/core/ecs/prototypes/entity_prototype.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include -#include - - -#include -#include - -/** - * @file entity_prototype.hpp - */ - -namespace legion::core::serialization -{ - /**@struct prototype - * @brief Prototype specialization for entities. - */ - - - - /**@struct entity_prototype - * @brief Type alias for `prototype`. Can be used to serialize and deserialize entities. - */ - -} diff --git a/legion/engine/core/ecs/prototypes/entity_prototype.inl b/legion/engine/core/ecs/prototypes/entity_prototype.inl deleted file mode 100644 index 6be2faa75..000000000 --- a/legion/engine/core/ecs/prototypes/entity_prototype.inl +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#pragma once - -namespace legion::core::serialization -{ - //inline prototype::prototype(ecs::entity src) : active(src->active) - //{ - // children.reserve(src->children.size()); - // for (size_type i = 0; i < src->children.size(); i++) - // { - // children.emplace_back(src->children[i]); - // } - - // for (auto typeId : ecs::Registry::entityComposition(src)) - // composition.emplace(typeId, ecs::Registry::getFamily(typeId)->create_prototype(src)); - //} - - //inline prototype::prototype(const prototype& src) : active(src.active), children(src.children) - //{ - // for (auto& [typeId, compPrototype] : src.composition) - // composition.emplace(typeId, compPrototype->copy()); - //} - - //inline prototype& prototype::operator=(ecs::entity src) - //{ - // active = src->active; - // children.clear(); - // children.reserve(src->children.size()); - // for (size_type i = 0; i < src->children.size(); i++) - // { - // children.emplace_back(src->children[i]); - // } - - // composition.clear(); - // for (auto typeId : ecs::Registry::entityComposition(src)) - // composition.emplace(typeId, ecs::Registry::getFamily(typeId)->create_prototype(src)); - - // return *this; - //} - - //inline prototype& prototype::operator=(const prototype& src) - //{ - // active = src.active; - // children = src.children; - - // for (auto& [typeId, compPrototype] : src.composition) - // composition.emplace(typeId, compPrototype->copy()); - - // return *this; - //} -} diff --git a/legion/engine/core/ecs/registry.cpp b/legion/engine/core/ecs/registry.cpp index 412335a28..b10aa968e 100644 --- a/legion/engine/core/ecs/registry.cpp +++ b/legion/engine/core/ecs/registry.cpp @@ -41,9 +41,9 @@ namespace legion::core::ecs void Registry::onInit() { + reportDependency(); create(); world = getWorld(); - reportDependency(); } void Registry::onShutdown() @@ -265,27 +265,16 @@ namespace legion::core::ecs return getFamily(typeId)->create_component(target); } - //void* Registry::createComponent(id_type typeId, entity target, const serialization::component_prototype_base& prototype) - //{ - // OPTICK_EVENT(); - // // Update entity composition. - // instance.m_entityCompositions.at(target).insert(typeId); - // // Update filters. - // FilterRegistry::markComponentAdd(typeId, target); - // // Actually create and return the component using the prototype. - // return getFamily(typeId)->create_component(target, prototype); - //} + void* Registry::createComponent(id_type typeId, entity target, const void* component) + { + OPTICK_EVENT(); + instance.m_entityCompositions.at(target).insert(typeId); + + FilterRegistry::markComponentAdd(typeId, target); + + return getFamily(typeId)->create_component(target, component); + } - //void* Registry::createComponent(id_type typeId, entity target, serialization::component_prototype_base&& prototype) - //{ - // OPTICK_EVENT(); - // // Update entity composition. - // instance.m_entityCompositions.at(target).insert(typeId); - // // Update filters. - // FilterRegistry::markComponentAdd(typeId, target); - // // Actually create and return the component using the prototype. - // return getFamily(typeId)->create_component(target, std::move(prototype)); - //} void Registry::destroyComponent(id_type typeId, entity target) { diff --git a/legion/engine/core/ecs/registry.hpp b/legion/engine/core/ecs/registry.hpp index 0edfa1260..ff1878c46 100644 --- a/legion/engine/core/ecs/registry.hpp +++ b/legion/engine/core/ecs/registry.hpp @@ -16,7 +16,6 @@ #include #include #include -#include #include /** @@ -94,7 +93,7 @@ namespace legion::core::ecs L_NODISCARD static component_pool* getFamily(Args&&... args); /**@brief Non templated way to get a pointer to the family of a certain component type. - * @note Will throw an exception if non of the templated functions have been called + * @note Will throw an exception if none of the templated functions have been called * before for this component type due to the type not being registered yet. * @param typeId Local type hash of the component type. */ @@ -205,6 +204,8 @@ namespace legion::core::ecs //template //static component_type& createComponent(entity target, serialization::component_prototype&& prototype); + static void* createComponent(id_type typeId, entity target, const void* component); + /**@brief Creates a new component of a certain type for a specific entity. * @param typeId Type hash of component type to create. * @param target Entity to create the component for. @@ -287,6 +288,5 @@ namespace legion::core::ecs #include #include #include -#include #include diff --git a/legion/engine/core/engine/engine.hpp b/legion/engine/core/engine/engine.hpp index 492346c58..f34b21534 100644 --- a/legion/engine/core/engine/engine.hpp +++ b/legion/engine/core/engine/engine.hpp @@ -1,14 +1,15 @@ #pragma once +#include +#include +#include + +#include + #include #include #include #include #include -#include - -#include -#include -#include /** * @file engine.hpp diff --git a/legion/engine/core/engine/system.hpp b/legion/engine/core/engine/system.hpp index 5ac19c1a8..b7de98a6d 100644 --- a/legion/engine/core/engine/system.hpp +++ b/legion/engine/core/engine/system.hpp @@ -4,10 +4,8 @@ #include #include #include -#include #include #include -#include namespace legion::core { @@ -17,7 +15,7 @@ namespace legion::core { friend class Engine; public: - const type_reference id; + const id_type id; virtual ~SystemBase() = default; @@ -25,7 +23,7 @@ namespace legion::core std::unordered_map> m_processes; std::unordered_map> m_bindings; - SystemBase(type_reference&& id) : id(id) {} + SystemBase(id_type&& id) : id(id) {} // TODO: Inline all the things @@ -105,7 +103,7 @@ namespace legion::core static auto queueJobs(size_type count, Func&& func); public: - System() : SystemBase(make_hash()) {} + System() : SystemBase(typeHash()) {} virtual ~System() = default; diff --git a/legion/engine/core/filesystem/assetimporter.hpp b/legion/engine/core/filesystem/assetimporter.hpp index 6454d0fa5..5593c2aff 100644 --- a/legion/engine/core/filesystem/assetimporter.hpp +++ b/legion/engine/core/filesystem/assetimporter.hpp @@ -111,7 +111,7 @@ namespace legion::core::filesystem if (result != common::valid) return result.error(); - for (auto& base : m_converters[nameHash(view.get_extension())]) + for (auto& base : m_converters[nameHash(*view.get_extension())]) { // Do a safety check if the cast was valid before we call any functions on it. if (typeHash() == base->result_type()) @@ -120,7 +120,7 @@ namespace legion::core::filesystem auto* converter = static_cast*>(base.get()); // Attempt the conversion and return the result. - return converter->load(result, std::forward(settings)...); + return converter->load(*result, std::forward(settings)...); } } diff --git a/legion/engine/core/filesystem/view.cpp b/legion/engine/core/filesystem/view.cpp index 2f559184d..665fc4e8d 100644 --- a/legion/engine/core/filesystem/view.cpp +++ b/legion/engine/core/filesystem/view.cpp @@ -324,7 +324,6 @@ namespace legion::core::filesystem } - void view::make_inheritance() const { OPTICK_EVENT(); diff --git a/legion/engine/core/math/glm/detail/type_mat3x3.inl b/legion/engine/core/math/glm/detail/type_mat3x3.inl index 0b5aa64e4..811d03a4f 100644 --- a/legion/engine/core/math/glm/detail/type_mat3x3.inl +++ b/legion/engine/core/math/glm/detail/type_mat3x3.inl @@ -1,5 +1,4 @@ #include "../matrix.hpp" -#include namespace legion::core::math { @@ -236,13 +235,6 @@ namespace legion::core::math # endif } - - template - template - inline void mat<3, 3, T, Q>::serialize(Archive& archive) - { - //archive(CEREAL_NVP(value[0])); - } // -- Accesses -- template diff --git a/legion/engine/core/math/glm/detail/type_quat.inl b/legion/engine/core/math/glm/detail/type_quat.inl index d96aa6a49..4838e21b4 100644 --- a/legion/engine/core/math/glm/detail/type_quat.inl +++ b/legion/engine/core/math/glm/detail/type_quat.inl @@ -2,7 +2,6 @@ #include "../exponential.hpp" #include "../ext/quaternion_geometric.hpp" #include -#include namespace legion::core::math{ namespace detail @@ -151,13 +150,6 @@ namespace detail // -- Conversion constructors -- - template - template - void qua::serialize(Archive& archive) - { - archive(CEREAL_NVP(x), CEREAL_NVP(y), CEREAL_NVP(z), CEREAL_NVP(w)); - } - template template GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(qua const& q) diff --git a/legion/engine/core/math/glm/detail/type_vec3.hpp b/legion/engine/core/math/glm/detail/type_vec3.hpp index 548211fbd..fa4eb8b98 100644 --- a/legion/engine/core/math/glm/detail/type_vec3.hpp +++ b/legion/engine/core/math/glm/detail/type_vec3.hpp @@ -10,7 +10,6 @@ # include "_swizzle_func.hpp" #endif #include -#include namespace legion::core::math { diff --git a/legion/engine/core/math/glm/detail/type_vec3.inl b/legion/engine/core/math/glm/detail/type_vec3.inl index e4773f71a..23a793524 100644 --- a/legion/engine/core/math/glm/detail/type_vec3.inl +++ b/legion/engine/core/math/glm/detail/type_vec3.inl @@ -66,13 +66,6 @@ namespace legion::core::math , z(static_cast(v.x)) {} - template - template - inline void vec<3, T, Q>::serialize(Archive& archive) - { - archive(CEREAL_NVP(x), CEREAL_NVP(y), CEREAL_NVP(z)); - } - template template GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, Y _y, Z _z) diff --git a/legion/engine/core/math/glm/detail/type_vec4.inl b/legion/engine/core/math/glm/detail/type_vec4.inl index 137cfbbe9..85d7ffe45 100644 --- a/legion/engine/core/math/glm/detail/type_vec4.inl +++ b/legion/engine/core/math/glm/detail/type_vec4.inl @@ -312,13 +312,6 @@ namespace detail // -- Conversion vector constructors -- - template - template - inline void vec<4, T, Q>::serialize(Archive& archive) - { - archive(CEREAL_NVP(x), CEREAL_NVP(y), CEREAL_NVP(z), CEREAL_NVP(w)); - } - template template GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, B _z, C _w) diff --git a/legion/engine/core/scenemanagement/components/scene.hpp b/legion/engine/core/scenemanagement/components/scene.hpp index 3ec5a4fad..a5a25f0f9 100644 --- a/legion/engine/core/scenemanagement/components/scene.hpp +++ b/legion/engine/core/scenemanagement/components/scene.hpp @@ -8,17 +8,5 @@ namespace legion::core::scenemanagement { public: id_type id = invalid_id; - - template - void serialize(Archive& archive); }; - - template - inline void scene::serialize(Archive& archive) - { - std::string name = SceneManager::sceneNames[id]; - archive(cereal::make_nvp("NAME", name)); - id = nameHash(name); - SceneManager::sceneNames[id] = name; - } } diff --git a/legion/engine/core/scenemanagement/scenemanager.cpp b/legion/engine/core/scenemanagement/scenemanager.cpp index 7c937c817..aaea52f1d 100644 --- a/legion/engine/core/scenemanagement/scenemanager.cpp +++ b/legion/engine/core/scenemanagement/scenemanager.cpp @@ -1,5 +1,4 @@ #include -#include #include #include //#include diff --git a/legion/engine/core/scenemanagement/scenemanager.hpp b/legion/engine/core/scenemanagement/scenemanager.hpp index 4071cf07f..d2a241293 100644 --- a/legion/engine/core/scenemanagement/scenemanager.hpp +++ b/legion/engine/core/scenemanagement/scenemanager.hpp @@ -3,7 +3,6 @@ #include #include #include -#include /** *@file scenemanager.hpp diff --git a/legion/engine/core/scheduling/process.hpp b/legion/engine/core/scheduling/process.hpp index 49ea25574..e62503bd7 100644 --- a/legion/engine/core/scheduling/process.hpp +++ b/legion/engine/core/scheduling/process.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include diff --git a/legion/engine/core/serialization/serialization.hpp b/legion/engine/core/serialization/serialization.hpp new file mode 100644 index 000000000..8cec23ad1 --- /dev/null +++ b/legion/engine/core/serialization/serialization.hpp @@ -0,0 +1,38 @@ +#pragma once +#include +#include + +#include +#include + +namespace legion::core::serialization +{ + template + common::result serialize(ViewType& s_view, Type&& data, std::string_view name); + + template + common::result write(fs::view file, Type&& data, std::string_view name); + + template + common::result write(Type&& data, fs::view file, std::string_view name); + + template + common::result deserialize(ViewType& s_view, std::string_view name); + + template + common::result load(const fs::view& file, std::string_view name); + + template + common::result load(std::vector data, std::string_view name); + + template + common::result load(Iterator begin, Iterator end, std::string_view name); +} + +#include +#include + +namespace legion::core +{ + namespace srl = serialization; +} diff --git a/legion/engine/core/serialization/serialization.inl b/legion/engine/core/serialization/serialization.inl new file mode 100644 index 000000000..c19f7514d --- /dev/null +++ b/legion/engine/core/serialization/serialization.inl @@ -0,0 +1,132 @@ +#include +#pragma once + +namespace legion::core::serialization +{ + template + inline common::result serialize(ViewType& s_view, Type&& data, std::string_view name) + { + std::vector warnings{}; + + auto serializer = SerializerRegistry::getSerializer>(); + auto result = serializer->serialize(&data, s_view, name); + PropagateErrors(result, warnings); + + return { common::success, warnings }; + } + + template + inline common::result write(fs::view file, Type&& data, std::string_view name) + { + ViewType view{}; + std::vector warnings{}; + + { + auto serializer = SerializerRegistry::getSerializer>(); + auto result = serializer->serialize(&data, view, name); + PropagateErrors(result, warnings); + } + + { + auto result = view.write(file); + PropagateErrors(result, warnings); + } + + return { common::success, warnings }; + } + + template + inline L_ALWAYS_INLINE common::result write(Type&& data, fs::view file, std::string_view name) + { + return write(file, std::forward(data), name); + } + + template + common::result deserialize(ViewType& s_view, std::string_view name) + { + byte rawData[sizeof(Type)]; + Type* data = reinterpret_cast(rawData); + std::vector warnings{}; + + auto serializer = SerializerRegistry::getSerializer>(); + auto result = serializer->deserialize(data, s_view, name); + PropagateErrors(result, warnings); + + return { *data, warnings }; + } + + template + inline common::result load(const fs::view& file, std::string_view name) + { + static_assert(!std::is_pointer_v && !std::is_reference_v, "Type to load must be a value type."); + static_assert(!std::is_abstract_v, "Type to load must be a constructible type."); + + ViewType view{}; + byte rawData[sizeof(Type)]; + Type* data = reinterpret_cast(rawData); + std::vector warnings{}; + + { + auto result = view.read(file); + PropagateErrors(result, warnings); + } + + { + auto serializer = SerializerRegistry::getSerializer>(); + auto result = serializer->deserialize(data, view, name); + PropagateErrors(result, warnings); + } + + return { *data, warnings }; + } + + template + inline common::result load(const byte_vec& bytes, std::string_view name) + { + static_assert(!std::is_pointer_v && !std::is_reference_v, "Type to load must be a value type."); + static_assert(!std::is_abstract_v, "Type to load must be a constructible type."); + + ViewType view{}; + byte rawData[sizeof(Type)]; + Type* data = reinterpret_cast(rawData); + std::vector warnings{}; + + { + auto result = view.read(bytes); + PropagateErrors(result, warnings); + } + + { + auto serializer = SerializerRegistry::getSerializer>(); + auto result = serializer->deserialize(data, view, name); + PropagateErrors(result, warnings); + } + + return { *data, warnings }; + } + + template + common::result load(Iterator begin, Iterator end, std::string_view name) + { + static_assert(!std::is_pointer_v && !std::is_reference_v, "Type to load must be a value type."); + static_assert(!std::is_abstract_v, "Type to load must be a constructible type."); + + ViewType view{}; + byte rawData[sizeof(Type)]; + Type* data = reinterpret_cast(rawData); + std::vector warnings{}; + + { + auto result = view.read(begin, end); + PropagateErrors(result, warnings); + } + + { + auto serializer = SerializerRegistry::getSerializer>(); + auto result = serializer->deserialize(data, view, name); + PropagateErrors(result, warnings); + } + + return { *data, warnings }; + } +} diff --git a/legion/engine/core/serialization/serializationmeta.hpp b/legion/engine/core/serialization/serializationmeta.hpp deleted file mode 100644 index 493ac7131..000000000 --- a/legion/engine/core/serialization/serializationmeta.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once -#include - -namespace legion::core::serialization -{ - template - struct has_serialize - { - static_assert( - std::integral_constant::value, - "Second template param needs to be of function type."); - }; - - template - struct has_serialize - { - private: - template - static constexpr auto check(T*) - -> typename std::is_same().serialize(std::declval()...)), Ret>::type; - - template - static constexpr auto check(...) - ->std::false_type; - - typedef decltype(check(nullptr)) type; - public: - static constexpr bool value = type::value; - }; - - - template - struct has_save - { - static_assert( - std::integral_constant::value, - "Second template param needs to be of function type."); - }; - - template - struct has_save - { - private: - template - static constexpr auto check(T*) - -> typename std::is_same().save(std::declval()...)), Ret>::type; - - template - static constexpr auto check(...) - ->std::false_type; - - typedef decltype(check(nullptr)) type; - public: - static constexpr bool value = type::value; - }; - - template - struct has_load - { - static_assert( - std::integral_constant::value, - "Second template param needs to be of function type."); - }; - - template - struct has_load - { - private: - template - static constexpr auto check(T*) - -> typename std::is_same< decltype(std::declval().load(std::declval()...)), Ret>::type; - - template - static constexpr auto check(...) - ->std::false_type; - - typedef decltype(check(nullptr)) type; - public: - static constexpr bool value = type::value; - }; - -} diff --git a/legion/engine/core/serialization/serializationregistry.cpp b/legion/engine/core/serialization/serializationregistry.cpp new file mode 100644 index 000000000..b09adea40 --- /dev/null +++ b/legion/engine/core/serialization/serializationregistry.cpp @@ -0,0 +1,6 @@ +#include + +namespace legion::core::serialization +{ + std::unordered_map> SerializerRegistry::serializers; +} diff --git a/legion/engine/core/serialization/serializationregistry.hpp b/legion/engine/core/serialization/serializationregistry.hpp new file mode 100644 index 000000000..4454288c7 --- /dev/null +++ b/legion/engine/core/serialization/serializationregistry.hpp @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include + +#include + +namespace legion::core::serialization +{ + class SerializerRegistry + { + private: + static std::unordered_map> serializers; + public: + template + static pointer> registerSerializer(Args&&... args); + + template + static pointer> getSerializer(); + static pointer getSerializer(id_type typeId); + }; +} + +#include +#include + diff --git a/legion/engine/core/serialization/serializationregistry.inl b/legion/engine/core/serialization/serializationregistry.inl new file mode 100644 index 000000000..85bc97e8c --- /dev/null +++ b/legion/engine/core/serialization/serializationregistry.inl @@ -0,0 +1,31 @@ +#include +#pragma once + +namespace legion::core::serialization +{ + template + inline pointer> SerializerRegistry::registerSerializer(Args&&... args) + { + auto [iterator, emplaced] = serializers.try_emplace(make_hash().id(), std::make_unique>(std::forward(args)...)); + return { dynamic_cast*>(iterator->second.get()) }; + } + + template + inline pointer> SerializerRegistry::getSerializer() + { + static const id_type typeId = make_hash().id(); + if (serializers.count(typeId)) + return { dynamic_cast*>(serializers.at(typeId).get()) }; + return { nullptr }; + } + + inline pointer SerializerRegistry::getSerializer(id_type typeId) + { + if (serializers.count(typeId)) + return { serializers.at(typeId).get() }; + return { nullptr }; + } + +} + + diff --git a/legion/engine/core/serialization/serializationutil.hpp b/legion/engine/core/serialization/serializationutil.hpp deleted file mode 100644 index 67f2e5b25..000000000 --- a/legion/engine/core/serialization/serializationutil.hpp +++ /dev/null @@ -1,164 +0,0 @@ -#pragma once -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -//Some testing objects for serialization -#pragma region TestObjects -struct MyRecord -{ - - uint8_t x, y; - float z; - MyRecord() - { - - } - - MyRecord(uint8_t _x, uint8_t _y, float _z) - { - x = _x; - y = _y; - z = _z; - } - - template - void serialize(Archive& ar) - { - ar(CEREAL_NVP(x), CEREAL_NVP(y), CEREAL_NVP(z)); - } -}; - - -struct Records -{ - MyRecord records[20]; - - template - void serialize(Archive& ar) - { - ar(CEREAL_NVP(records)); - } -}; -#pragma endregion - -namespace legion::core::serialization -{ - - class SerializationUtil - { - public: - /**@brief JSON serialization from a stringstream - * @param os stringstream the ouput for the serialized object - * @param serializable template type that represents the object that needs to be serialized - */ - template - static void JSONSerialize(std::stringstream os, T serializable) - { - cereal::JSONOutputArchive archive(os); // Create an output archive, Output as outputing to a string stream - archive(CEREAL_NVP(serializable)); // Read the data into the archive - } - - /**@brief JSON deserialization from a stringstream - * @param is stringstream the input of a serialized object - * @returns the the deserialized object as type T - */ - template - static T JSONDeserialize(std::stringstream is) - { - cereal::JSONInputArchive iarchive(is); // Create an input archive, Input as inputing to memory - T t; - iarchive(t); // Read the data from the archive - return t; - } - - /**@brief Binary serialization from a stringstream - * @param os stringstream the ouput for the serialized object - * @param serializable template type that represents the object that needs to be serialized - */ - template - static void BinarySerialize(std::stringstream os, T serializable) - { - cereal::BinaryOutputArchive archive(os); // Create an output archive, Output as outputing to a string stream - archive(CEREAL_NVP(serializable)); // Read the data into the archive - } - - /**@brief Binary deserialization from a stringstream - * @param is stringstream the input of a serialized object - * @returns the the deserialized object as type T - */ - template - static T BinaryDeserialize(std::stringstream is) - { - cereal::BinaryInputArchive iarchive(is); // Create an input archive, Input as inputing to memory - T t; - iarchive(t); // Read the data from the archive - return t; - } - - /**@brief JSON serialization from a filestream - * @param os filestream the ouput for the serialized object - * @param serializable template type that represents the object that needs to be serialized - */ - template - static void JSONSerialize(std::ofstream& os, T serializable) - { - log::debug("[CEREAL] Started Serializing"); - time::timer timer; - cereal::JSONOutputArchive archive(os);// Create an output archive, Output as outputing to a filestream - archive(cereal::make_nvp(typeid(T).name(), serializable)); // Read the data to the archive - log::debug("[CEREAL] Finished Serializing in : {}s", timer.end().seconds()); - } - - /**@brief JSON deserialization from a filestream - * @param is filestream the input of a serialized object - * @returns the the deserialized object as type T - */ - template - static T JSONDeserialize(std::ifstream& is) - { - cereal::JSONInputArchive iarchive(is); // Create an input archive, Input as inputing to memory - T t; - iarchive(t); // Read the data from the archive - return t; - } - - /**@brief Binary serialization from a filestream - * @param os filestream the ouput for the serialized object - * @param serializable template type that represents the object that needs to be serialized - */ - template - static void BinarySerialize(std::ofstream& os, T serializable) - { - cereal::BinaryOutputArchive archive(os);// Create an output archive, Output as outputing to a string stream - archive(CEREAL_NVP(serializable)); // Read the data to the archive - } - - /**@brief Binary deserialization from a filestream - * @param is filestream the input of a serialized object - * @returns the the deserialized object as type T - */ - template - static T BinaryDeserialize(std::ifstream& is) - { - cereal::BinaryInputArchive iarchive(is); // Create an input archive, Input as inputing to memory - T t; - iarchive(t); // Read the data from the archive - return t; - } - }; -} diff --git a/legion/engine/core/serialization/serializer.hpp b/legion/engine/core/serialization/serializer.hpp new file mode 100644 index 000000000..224e94ac7 --- /dev/null +++ b/legion/engine/core/serialization/serializer.hpp @@ -0,0 +1,63 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace legion::core::serialization +{ + struct serializer_base + { + NO_DTOR_RULE5_NOEXCEPT(serializer_base); + virtual ~serializer_base() = default; + + virtual common::result serialize(const void* serializable, serializer_view& view, std::string_view name) LEGION_PURE; + virtual common::result deserialize(void* target, serializer_view& view, std::string_view name) LEGION_PURE; + virtual id_type type_size() LEGION_PURE; + }; + + template + struct serializer : serializer_base + { + NO_DTOR_RULE5_NOEXCEPT(serializer); + virtual ~serializer() = default; + + virtual common::result serialize(const void* serializable, serializer_view& s_view, std::string_view name) override; + virtual common::result deserialize(void* target, serializer_view& s_view, std::string_view name) override; + virtual id_type type_size() override { return sizeof(serializable_type); } + }; + + template<> + struct serializer : serializer_base + { + NO_DTOR_RULE5_NOEXCEPT(serializer); + virtual ~serializer() = default; + + virtual common::result serialize(const void* serializable, serializer_view& view, std::string_view name) override; + virtual common::result deserialize(void* target, serializer_view& s_view, std::string_view name) override; + virtual id_type type_size() override { return sizeof(ecs::entity_data); } + }; + + template<> + struct serializer : serializer_base + { + NO_DTOR_RULE5_NOEXCEPT(serializer); + virtual ~serializer() = default; + + virtual common::result serialize(const void* serializable, serializer_view& view, std::string_view name) override; + virtual common::result deserialize(void* target, serializer_view& s_view, std::string_view name) override; + virtual id_type type_size() override { return sizeof(ecs::entity); } + }; + +} + + + + + diff --git a/legion/engine/core/serialization/serializer.inl b/legion/engine/core/serialization/serializer.inl new file mode 100644 index 000000000..a8831335b --- /dev/null +++ b/legion/engine/core/serialization/serializer.inl @@ -0,0 +1,434 @@ +#include +#pragma once + +#define EndReadPropagate(_result, _warnings, _view) \ + _warnings.insert(_warnings.end(), _result.warnings().begin(), _result.warnings().end()); \ + if (_result.has_error()) { _view.end_read(); return { _result.error(), _warnings }; } + +#define EndObjectPropagate(_result, _warnings, _view) \ + _warnings.insert(_warnings.end(), _result.warnings().begin(), _result.warnings().end()); \ + if (_result.has_error()) { _view.end_object(); return { _result.error(), _warnings }; } + +namespace legion::core::serialization +{ + namespace detail + { + template + inline common::result serialize_container(type&& container, serializer_view& s_view, std::string_view name) + { + using container_type = remove_cvr_t; + using value_type = remove_cvr_t; + + s_view.start_container(std::string(name)); + + std::vector warnings{}; + size_type i = 0; + for (auto it = container.begin(); it != container.end(); ++it, i++) + { + if constexpr (is_serializable_v) + { + if (!s_view.serialize("", *it)) + { + s_view.end_container(); + return { legion_fs_error("Type was not a primitive serializable type."), warnings }; + } + } + else if constexpr (is_container_v) + { + auto result = detail::serialize_container(*it, s_view, ""); + warnings.insert(warnings.end(), result.warnings().begin(), result.warnings().end()); + + if (result.has_error()) + { + s_view.end_container(); + return { result.error(), warnings }; + } + } + else + { + auto _serializer = SerializerRegistry::getSerializer(); + + auto result = _serializer->serialize(&(*it), s_view, ""); + warnings.insert(warnings.end(), result.warnings().begin(), result.warnings().end()); + + if (result.has_error()) + { + s_view.end_container(); + return { result.error(), warnings }; + } + } + } + + s_view.end_container(); + + return { common::success, warnings }; + } + + template + inline common::result deserialize_container(type& container, serializer_view& s_view, std::string_view name) + { + using container_type = remove_cvr_t; + using value_type = remove_cvr_t; + std::vector warnings{}; + + { + auto result = s_view.start_read(std::string(name)); + PropagateErrors(result, warnings); + } + + size_type size = s_view.current_item_size(); + + std::vector tempContainer{}; + tempContainer.reserve(size); + + byte buffer[sizeof(value_type)]; + value_type* itemPtr = reinterpret_cast(buffer); + + for (size_type i = 0; i < size; i++) + { + if constexpr (is_serializable_v) + { + auto result = s_view.deserialize(""); + warnings.insert(warnings.end(), result.warnings().begin(), result.warnings().end()); + + if (result.has_error()) + { + s_view.end_read(); + return { result.error(), warnings }; + } + new(itemPtr) value_type(*result); + } + else if constexpr (is_container_v) + { + auto result = detail::deserialize_container(*itemPtr, s_view, ""); + warnings.insert(warnings.end(), result.warnings().begin(), result.warnings().end()); + + if (result.has_error()) + { + s_view.end_read(); + return { result.error(), warnings }; + } + } + else + { + auto _serializer = SerializerRegistry::getSerializer(); + + auto result = _serializer->deserialize(buffer, s_view, ""); + warnings.insert(warnings.end(), result.warnings().begin(), result.warnings().end()); + + if (result.has_error()) + { + s_view.end_read(); + return { result.error(), warnings }; + } + } + + tempContainer.push_back(*itemPtr); + } + + s_view.end_read(); + + using iterator = typename container_type::iterator; + using const_iterator = typename container_type::const_iterator; + using input_iterator = typename std::vector::iterator; + + if constexpr (has_insert_v) + container.insert(container.begin(), tempContainer.begin(), tempContainer.end()); + else if constexpr (has_insert_v) + container.insert(tempContainer.begin(), tempContainer.end()); + else if constexpr (has_size_v && has_at_v) + { + for (size_type i = 0; i < tempContainer.size(); i++) + container[i] = tempContainer[i]; + } + + return { common::success, warnings }; + } + + inline common::result serialize_ent_data(const ecs::entity_data& ent_data, serializer_view& s_view, std::string_view name) + { + if (!ent_data.alive) + return legion_fs_error("Entity does not exist."); + + std::vector warnings{}; + + s_view.start_object(std::string(name)); + s_view.serialize("type_name", nameOfType()); + s_view.serialize("name", ent_data.name); + s_view.serialize("active", ent_data.active); + std::vector children{ ent_data.children.begin(), ent_data.children.end() }; + auto result = detail::serialize_container(children, s_view, "children"); + EndObjectPropagate(result, warnings, s_view); + + s_view.start_container("components"); + + auto ent = ecs::Registry::getEntity(ent_data.id); + auto ent_composition = ent.component_composition(); + + for (id_type typeId : ent_composition) + { + auto compName = std::string(type_hash::from_id(typeId).name()); + if (compName.empty()) + { + s_view.end_container(); + s_view.end_object(); + return { legion_fs_error("Component type " + std::to_string(typeId) + " has no type data."), warnings }; + } + + auto _serializer = SerializerRegistry::getSerializer(typeId); + if (!_serializer) + { + warnings.push_back("Could not find existing serializer for " + compName); + continue; + } + + auto result = _serializer->serialize(ecs::Registry::getComponent(typeId, ent), s_view, compName); + warnings.insert(warnings.end(), result.warnings().begin(), result.warnings().end()); + + if (result.has_error()) + { + s_view.end_container(); + s_view.end_object(); + return { result.error(), warnings }; + } + } + + s_view.end_container(); + s_view.end_object(); + return { common::success, warnings }; + } + + inline common::result deserialize_ent_data(ecs::entity_data* target, serializer_view& s_view, std::string_view name) + { + std::vector warnings{}; + + { + auto result = s_view.start_read(std::string(name)); // Object + PropagateErrors(result, warnings); + } + + { + auto result = s_view.deserialize("type_name"); + EndReadPropagate(result, warnings, s_view); + + if (*result != nameOfType()) + { + s_view.end_read(); + return { legion_fs_error("Item of name " + std::string(name) + " is not of type " + std::string(nameOfType()) + " but of type " + *result + "."), warnings }; + } + } + + // Entity + auto ent = ecs::Registry::createEntity(); + + { + auto result = s_view.deserialize("name"); + EndReadPropagate(result, warnings, s_view); + ent->name = *result; + } + + { + auto result = s_view.deserialize("active"); + EndReadPropagate(result, warnings, s_view); + ent->active = *result; + } + + // Children + std::vector children{}; + { + auto result = deserialize_container(children, s_view, "children"); + EndReadPropagate(result, warnings, s_view); + } + + for (auto& child : children) + ent.add_child(child); + + // Components + { + auto result = s_view.start_read("components"); + EndReadPropagate(result, warnings, s_view); + } + + for (size_type i = 0; i < s_view.current_item_size(); i++) + { + s_view.peak_ahead(""); + id_type typeId; + + { + auto result = s_view.deserialize("type_name"); + warnings.insert(warnings.end(), result.warnings().begin(), result.warnings().end()); + + if (result.has_error()) + { + s_view.end_read(); // Components + s_view.end_read(); // Object + return { result.error(), warnings }; + } + + typeId = nameHash(*result); + } + + auto _serializer = SerializerRegistry::getSerializer(typeId); + + byte_vec buffer{}; + buffer.resize(_serializer->type_size()); + + { + auto result = _serializer->deserialize(buffer.data(), s_view, ""); + + warnings.insert(warnings.end(), result.warnings().begin(), result.warnings().end()); + + if (result.has_error()) + { + s_view.end_read(); // Components + s_view.end_read(); // Object + return { result.error(), warnings }; + } + } + + ecs::Registry::createComponent(typeId, ent, buffer.data()); + } + + s_view.end_read(); // Components + s_view.end_read(); // Object + + new(target) ecs::entity_data(*ent.data); + + return { common::success, warnings }; + } + } + + inline common::result serializer::serialize(const void* ent, serializer_view& s_view, std::string_view name) + { + return detail::serialize_ent_data(*static_cast(ent), s_view, name); + } + + inline common::result serializer::deserialize(void* target, serializer_view& view, std::string_view name) + { + return detail::deserialize_ent_data(reinterpret_cast(target), view, name); + } + + inline common::result serializer::serialize(const void* ent, serializer_view& s_view, std::string_view name) + { + return detail::serialize_ent_data(*static_cast(ent)->data, s_view, name); + } + + inline common::result serializer::deserialize(void* target, serializer_view& view, std::string_view name) + { + byte rawData[sizeof(ecs::entity_data)]; + ecs::entity_data* data = reinterpret_cast(rawData); + auto result = detail::deserialize_ent_data(data, view, name); + *static_cast(target) = ecs::Registry::getEntity(data->id); + return result; + } + + template + inline common::result serializer::serialize(const void* serializable, serializer_view& s_view, std::string_view name) + { + using serializable_type = remove_cvr_t; + + auto* ptr = static_cast(serializable); + + if constexpr (is_serializable_v) + { + return s_view.serialize(std::string(name), *ptr) ? common::success : legion_fs_error("Type was not a primitive serializable type."); + } + else if constexpr (is_container_v) + { + return detail::serialize_container(*ptr, s_view, name); + } + else + { + auto refl = make_reflector(*ptr); + std::vector warnings{}; + + s_view.start_object(std::string(name)); + s_view.serialize("type_name", nameOfType()); + + for (auto& var : refl.members) + { + if (var.is_object) + { + auto _serializer = SerializerRegistry::getSerializer(var.object.typeId); + auto result = _serializer->serialize(var.object.data, s_view, var.name); + EndObjectPropagate(result, warnings, s_view); + } + else + { + if (!s_view.serialize(std::string(var.name), var.primitive.data, var.primitive.typeId)) + { + s_view.end_object(); + return { legion_fs_error("Type was not a primitive serializable type."), warnings }; + } + } + } + + s_view.end_object(); + return { common::success, warnings }; + } + } + + template + inline common::result serializer::deserialize(void* target, serializer_view& s_view, std::string_view name) + { + using serializable_type = remove_cvr_t; + auto* ptr = static_cast(target); + + if constexpr (is_serializable_v) + { + auto result = s_view.deserialize(std::string(name)); + if (result.has_error()) + return { result.error(), result.warnings() }; + else + new(ptr) serializable_type(result.value()); + } + else if constexpr (is_container_v) + { + new(ptr) serializable_type(); + return detail::deserialize_container(*ptr, s_view, name); + } + else + { + new(ptr) serializable_type(); + reflector refl = make_reflector(*ptr); + std::vector warnings{}; + + { + auto result = s_view.start_read(std::string(name)); + PropagateErrors(result, warnings); + } + + { + auto result = s_view.deserialize("type_name"); + EndReadPropagate(result, warnings, s_view); + + if (*result != nameOfType()) + { + s_view.end_read(); + return { legion_fs_error("Item of name " + std::string(name) + " is not of type " + std::string(nameOfType()) + " but of type " + *result + "."), warnings }; + } + } + + for (auto& var : refl.members) + { + if (var.is_object) + { + auto _serializer = SerializerRegistry::getSerializer(var.object.typeId); + auto result = _serializer->deserialize(var.object.data, s_view, var.name); + EndReadPropagate(result, warnings, s_view); + } + else + { + auto result = s_view.deserialize(std::string(var.name), var.primitive.data, var.primitive.typeId); + EndReadPropagate(result, warnings, s_view); + } + } + s_view.end_read(); + + return { common::success, warnings }; + } + } +} + +#undef EndReadPropagate +#undef EndObjectPropagate diff --git a/legion/engine/core/serialization/serializer_views/bson.cpp b/legion/engine/core/serialization/serializer_views/bson.cpp new file mode 100644 index 000000000..0bace1798 --- /dev/null +++ b/legion/engine/core/serialization/serializer_views/bson.cpp @@ -0,0 +1,42 @@ +#include + +namespace legion::core::serialization +{ + + common::result bson::write(fs::view& file) + { + return file.set(fs::basic_resource(nlohmann::ordered_json::to_bson(root.item))); + } + + common::result bson::read(const fs::view& file) + { + auto result = file.get(); + if (!result.valid()) + { + log::error(result.error().what()); + return result.error(); + } + + root.key = "root"; + root.item = nlohmann::ordered_json::from_bson(result->get()); + root.currentReadIndex = 0; + return common::success; + } + + common::result bson::read(const byte_vec& data) + { + root.key = "root"; + root.item = nlohmann::ordered_json::from_bson(data); + root.currentReadIndex = 0; + return common::success; + } + + common::result bson::read(byte_vec::iterator begin, byte_vec::iterator end) + { + root.key = "root"; + root.item = nlohmann::ordered_json::from_bson(begin, end); + root.currentReadIndex = 0; + return common::success; + } +} + diff --git a/legion/engine/core/serialization/serializer_views/bson.hpp b/legion/engine/core/serialization/serializer_views/bson.hpp new file mode 100644 index 000000000..93d12b285 --- /dev/null +++ b/legion/engine/core/serialization/serializer_views/bson.hpp @@ -0,0 +1,16 @@ +#pragma once +#include + +namespace legion::core::serialization +{ + struct bson : public json + { + bson() = default; + virtual ~bson() = default; + + L_NODISCARD virtual common::result write(fs::view& file) override; + L_NODISCARD virtual common::result read(const fs::view& file) override; + L_NODISCARD virtual common::result read(const byte_vec& data) override; + L_NODISCARD virtual common::result read(byte_vec::iterator begin, byte_vec::iterator end) override; + }; +} diff --git a/legion/engine/core/serialization/serializer_views/json.cpp b/legion/engine/core/serialization/serializer_views/json.cpp new file mode 100644 index 000000000..fdb3f5a96 --- /dev/null +++ b/legion/engine/core/serialization/serializer_views/json.cpp @@ -0,0 +1,449 @@ +#include + +namespace legion::core::serialization +{ + json::entry& json::current_item() + { + if (isPeaking) + return peakObject; + return active_stack.top(); + } + + void json::serialize_int(const std::string& name, int serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.is_object()) + item.emplace(name, serializable); + else if (item.is_array()) + item.emplace_back(serializable); + } + + void json::serialize_float(const std::string& name, float serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.is_object()) + item.emplace(name, serializable); + else if (item.is_array()) + item.emplace_back(serializable); + } + + void json::serialize_double(const std::string& name, double serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.is_object()) + item.emplace(name, serializable); + else if (item.is_array()) + item.emplace_back(serializable); + } + + void json::serialize_bool(const std::string& name, bool serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.is_object()) + item.emplace(name, serializable); + else if (item.is_array()) + item.emplace_back(serializable); + } + + void json::serialize_string(const std::string& name, const std::string& serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.is_object()) + item.emplace(name, serializable); + else if (item.is_array()) + item.emplace_back(serializable); + } + + void json::serialize_id_type(const std::string& name, id_type serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.is_object()) + item.emplace(name, serializable); + else if (item.is_array()) + item.emplace_back(serializable); + } + + + common::result json::deserialize_int(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.is_object()) + { + auto iterator = current.find(name); + if (iterator == current.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_number_integer()) + return legion_fs_error("Item with name: " + name + " is not an integer number."); + + return iterator->get(); + } + else if (current.is_array()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading json beyond the size of the array."); + auto& item = current.at(readIndex); + + if (!item.is_number_integer()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in json array " + currentName + " is not an integer number."); + + readIndex++; + return item.get(); + } + return legion_fs_error("Current json object is invalid."); + } + + common::result json::deserialize_float(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.is_object()) + { + auto iterator = current.find(name); + if (iterator == current.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_number_float()) + return legion_fs_error("Item with name: " + name + " is not a floating point number."); + + return iterator->get(); + } + else if (current.is_array()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading json beyond the size of the array."); + auto& item = current.at(readIndex); + + if (!item.is_number_float()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in json array " + currentName + " is not a floating point number."); + + readIndex++; + return item.get(); + } + return legion_fs_error("Current json object is invalid."); + } + + common::result json::deserialize_double(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.is_object()) + { + auto iterator = current.find(name); + if (iterator == current.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_number_float()) + return legion_fs_error("Item with name: " + name + " is not a floating point number."); + + return iterator->get(); + } + else if (current.is_array()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading json beyond the size of the array."); + auto& item = current.at(readIndex); + + if (!item.is_number_float()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in json array " + currentName + " is not a floating point number."); + + readIndex++; + return item.get(); + } + return legion_fs_error("Current json object is invalid."); + } + + common::result json::deserialize_bool(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.is_object()) + { + auto iterator = current.find(name); + if (iterator == current.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_boolean()) + return legion_fs_error("Item with name: " + name + " is not a boolean."); + + return iterator->get(); + } + else if (current.is_array()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading json beyond the size of the array."); + auto& item = current.at(readIndex); + + if (!item.is_boolean()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in json array " + currentName + " is not a boolean."); + + readIndex++; + return item.get(); + } + return legion_fs_error("Current json object is invalid."); + } + + common::result json::deserialize_string(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.is_object()) + { + auto iterator = current.find(name); + if (iterator == current.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_string()) + return legion_fs_error("Item with name: " + name + " is not a string."); + + return iterator->get(); + } + else if (current.is_array()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading json beyond the size of the array."); + auto& item = current.at(readIndex); + + if (!item.is_string()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in json array " + currentName + " is not a string."); + + readIndex++; + return item.get(); + } + return legion_fs_error("Current json object is invalid."); + } + + common::result json::deserialize_id_type(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.is_object()) + { + auto iterator = current.find(name); + if (iterator == current.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_number_integer()) + return legion_fs_error("Item with name: " + name + " is not an integer number."); + + return iterator->get(); + } + else if (current.is_array()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading json beyond the size of the array."); + auto& item = current.at(readIndex); + + if (!item.is_number_integer()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in json array " + currentName + " is not an integer number."); + + readIndex++; + return item.get(); + } + return legion_fs_error("Current json object is invalid."); + } + + void json::start_object() + { + active_stack.emplace("item_" + std::to_string(current_item().item.size()), nlohmann::ordered_json::object()); + } + + void json::start_object(const std::string& name) + { + active_stack.emplace(name, nlohmann::ordered_json::object()); + } + + void json::end_object() + { + if (active_stack.empty()) + return; + + auto& [name, object, readIndex] = current_item(); + + if (!object.is_object()) + return; + + if (active_stack.size() == 1) + { + root.item.emplace(name, object); + active_stack.pop(); + } + else + { + entry cpy{ name, object, readIndex }; + active_stack.pop(); + auto& [nxtName, next, nxtRdIdx] = current_item(); + + if (next.is_array()) + next.push_back(cpy.item); + else if (next.is_object()) + next.emplace(cpy.key, cpy.item); + } + } + + void json::start_container(const std::string& name) + { + active_stack.emplace(name, nlohmann::ordered_json::array()); + } + + void json::end_container() + { + if (active_stack.empty()) + return; + + auto& [name, arr, readIndex] = current_item(); + + if (!arr.is_array()) + return; + + if (active_stack.size() == 1) + { + root.item.emplace(name, arr); + active_stack.pop(); + } + else + { + entry cpy{ name, arr, readIndex }; + active_stack.pop(); + auto& [nxtName, next, nxtRdIdx] = current_item(); + + if (next.is_array()) + next.push_back(arr); + else if (next.is_object()) + next.emplace(cpy.key, cpy.item); + } + } + + common::result json::start_read(const std::string& name) + { + isPeaking = false; + if (active_stack.empty()) + { + auto iterator = root.item.find(name); + if (iterator == root.item.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_object() && !iterator->is_array()) + return legion_fs_error("Item with name: " + name + " is not an object or array."); + + active_stack.emplace(name, *iterator); + } + else + { + auto& [curName, current, readIndex] = active_stack.top(); + + if (current.is_array()) + { + active_stack.emplace("item_" + std::to_string(readIndex), current[readIndex]); + readIndex++; + } + else if (current.is_object()) + { + auto iterator = current.find(name); + if (iterator == current.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_object() && !iterator->is_array()) + return legion_fs_error("Item with name: " + name + " is not an object or array."); + + active_stack.emplace(name, *iterator); + } + } + return common::success; + } + + common::result json::peak_ahead(const std::string& name) + { + if (active_stack.empty()) + { + auto iterator = root.item.find(name); + if (iterator == root.item.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_object() && !iterator->is_array()) + return legion_fs_error("Item with name: " + name + " is not an object or array."); + + peakObject = entry{ iterator.key(), *iterator }; + } + else + { + auto& [curName, current, readIndex] = active_stack.top(); + + if (current.is_array()) + { + peakObject = entry{ "item_" + std::to_string(readIndex), current[readIndex] }; + } + else if (current.is_object()) + { + auto iterator = current.find(name); + if (iterator == current.end()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!iterator->is_object() && !iterator->is_array()) + return legion_fs_error("Item with name: " + name + " is not an object or array."); + + peakObject = entry{ iterator.key(), *iterator }; + } + } + isPeaking = true; + return common::success; + } + + void json::end_read() + { + if (active_stack.empty()) + return; + + active_stack.pop(); + } + + bool json::is_current_array() + { + return current_item().item.is_array(); + } + + bool json::is_current_object() + { + return current_item().item.is_object(); + } + + size_type json::current_item_size() + { + return current_item().item.size(); + } + + std::string json::get_key() + { + return current_item().key; + } + + common::result json::write(fs::view& file) + { + return file.set(fs::basic_resource(root.item.dump(4))); + } + + common::result json::read(const fs::view& file) + { + auto result = file.get(); + if (!result.valid()) + { + log::error(result.error().what()); + return result.error(); + } + root.key = "root"; + root.item = nlohmann::ordered_json::parse(result->to_string()); + root.currentReadIndex = 0; + return common::success; + } + + common::result json::read(const byte_vec& data) + { + root.key = "root"; + root.item = nlohmann::ordered_json::parse(data); + root.currentReadIndex = 0; + return common::success; + } + + common::result json::read(byte_vec::iterator begin, byte_vec::iterator end) + { + root.key = "root"; + root.item = nlohmann::ordered_json::parse(begin, end); + root.currentReadIndex = 0; + return common::success; + } +} diff --git a/legion/engine/core/serialization/serializer_views/json.hpp b/legion/engine/core/serialization/serializer_views/json.hpp new file mode 100644 index 000000000..7bbe7858e --- /dev/null +++ b/legion/engine/core/serialization/serializer_views/json.hpp @@ -0,0 +1,71 @@ +#pragma once +#include + +#include + +#include + +namespace legion::core::serialization +{ + struct json : public serializer_view + { + protected: + struct entry + { + std::string key; + nlohmann::ordered_json item; + size_type currentReadIndex = 0; + + RULE_OF_5_NOEXCEPT(entry); + + entry(const std::string& k, const nlohmann::ordered_json& j, size_type idx = 0) : key(k), item(j), currentReadIndex(idx) {} + }; + + entry root; + bool isPeaking; + entry peakObject; + std::stack active_stack; + + entry& current_item(); + + public: + json() = default; + virtual ~json() = default; + + virtual void serialize_int(const std::string& name, int serializable) override; + virtual void serialize_float(const std::string& name, float serializable) override; + virtual void serialize_double(const std::string& name, double serializable) override; + virtual void serialize_bool(const std::string& name, bool serializable) override; + virtual void serialize_string(const std::string& name, const std::string& serializable) override; + virtual void serialize_id_type(const std::string& name, id_type serializable) override; + + L_NODISCARD virtual common::result deserialize_int(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_float(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_double(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_bool(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_string(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_id_type(const std::string& name) override; + + virtual void start_object() override; + virtual void start_object(const std::string& name) override; + virtual void end_object() override; + + virtual void start_container(const std::string& name) override; + virtual void end_container() override; + + L_NODISCARD virtual common::result start_read(const std::string& name) override; + L_NODISCARD virtual common::result peak_ahead(const std::string& name) override; + virtual void end_read() override; + + L_NODISCARD virtual bool is_current_array() override; + L_NODISCARD virtual bool is_current_object() override; + L_NODISCARD virtual size_type current_item_size() override; + + L_NODISCARD virtual std::string get_key() override; + + L_NODISCARD virtual common::result write(fs::view& file) override; + L_NODISCARD virtual common::result read(const fs::view& file) override; + L_NODISCARD virtual common::result read(const byte_vec& data) override; + L_NODISCARD virtual common::result read(byte_vec::iterator begin, byte_vec::iterator end) override; + }; +} diff --git a/legion/engine/core/serialization/serializer_views/serializer_view.cpp b/legion/engine/core/serialization/serializer_views/serializer_view.cpp new file mode 100644 index 000000000..c07dc9fab --- /dev/null +++ b/legion/engine/core/serialization/serializer_views/serializer_view.cpp @@ -0,0 +1,111 @@ +#include + +namespace legion::core::serialization +{ + bool serializer_view::serialize(const std::string& name, const void* value, id_type typeId) + { + if (typeId == typeHash()) + { + serialize_int(name, *static_cast(value)); + return true; + } + else if (typeId == typeHash()) + { + serialize_float(name, *static_cast(value)); + return true; + } + else if (typeId == typeHash()) + { + serialize_double(name, *static_cast(value)); + return true; + } + else if (typeId == typeHash()) + { + serialize_bool(name, *static_cast(value)); + return true; + } + else if (typeId == typeHash()) + { + serialize_string(name, *static_cast(value)); + return true; + } + else if (typeId == typeHash()) + { + serialize_id_type(name, *static_cast(value)); + return true; + } + return false; + } + + common::result serializer_view::deserialize(const std::string& name, void* value, id_type typeId) + { + if (typeId == typeHash()) + { + auto result = deserialize_int(name); + if (result.has_error()) + return { result.error(), result.warnings() }; + else + { + *static_cast(value) = result.value(); + return { common::success, result.warnings() }; + } + } + else if (typeId == typeHash()) + { + auto result = deserialize_float(name); + if (result.has_error()) + return { result.error(), result.warnings() }; + else + { + *static_cast(value) = result.value(); + return { common::success, result.warnings() }; + } + } + else if (typeId == typeHash()) + { + auto result = deserialize_double(name); + if (result.has_error()) + return { result.error(), result.warnings() }; + else + { + *static_cast(value) = result.value(); + return { common::success, result.warnings() }; + } + } + else if (typeId == typeHash()) + { + auto result = deserialize_bool(name); + if (result.has_error()) + return { result.error(), result.warnings() }; + else + { + *static_cast(value) = result.value(); + return { common::success, result.warnings() }; + } + } + else if (typeId == typeHash()) + { + auto result = deserialize_string(name); + if (result.has_error()) + return { result.error(), result.warnings() }; + else + { + *static_cast(value) = result.value(); + return { common::success, result.warnings() }; + } + } + else if (typeId == typeHash()) + { + auto result = deserialize_id_type(name); + if (result.has_error()) + return { result.error(), result.warnings() }; + else + { + *static_cast(value) = result.value(); + return { common::success, result.warnings() }; + } + } + + return legion_fs_error("Type was not a primitive serializable type."); + } +} diff --git a/legion/engine/core/serialization/serializer_views/serializer_view.hpp b/legion/engine/core/serialization/serializer_views/serializer_view.hpp new file mode 100644 index 000000000..44217a0a4 --- /dev/null +++ b/legion/engine/core/serialization/serializer_views/serializer_view.hpp @@ -0,0 +1,63 @@ +#pragma once +#include +#include +#include + +#include + +namespace legion::core::serialization +{ + struct serializer_view + { + serializer_view() = default; + virtual ~serializer_view() = default; + + template + bool serialize(const std::string& name, Type&& value); + bool serialize(const std::string& name, const void* value, id_type typeId); + + virtual void serialize_int(const std::string& name, int serializable) LEGION_PURE; + virtual void serialize_float(const std::string& name, float serializable) LEGION_PURE; + virtual void serialize_double(const std::string& name, double serializable) LEGION_PURE; + virtual void serialize_bool(const std::string& name, bool serializable) LEGION_PURE; + virtual void serialize_string(const std::string& name, const std::string& serializable) LEGION_PURE; + virtual void serialize_id_type(const std::string& name, id_type serializable) LEGION_PURE; + + template + L_NODISCARD common::result deserialize(const std::string& name); + common::result deserialize(const std::string& name, void* value, id_type typeId); + + L_NODISCARD virtual common::result deserialize_int(const std::string& name) LEGION_PURE; + L_NODISCARD virtual common::result deserialize_float(const std::string& name) LEGION_PURE; + L_NODISCARD virtual common::result deserialize_double(const std::string& name) LEGION_PURE; + L_NODISCARD virtual common::result deserialize_bool(const std::string& name) LEGION_PURE; + L_NODISCARD virtual common::result deserialize_string(const std::string& name) LEGION_PURE; + L_NODISCARD virtual common::result deserialize_id_type(const std::string& name) LEGION_PURE; + + virtual void start_object() LEGION_PURE; + virtual void start_object(const std::string& name) LEGION_PURE; + virtual void end_object() LEGION_PURE; + + virtual void start_container(const std::string& name) LEGION_PURE; + virtual void end_container() LEGION_PURE; + + virtual common::result start_read(const std::string& name) LEGION_PURE; + virtual common::result peak_ahead(const std::string& name) LEGION_PURE; + virtual void end_read() LEGION_PURE; + + L_NODISCARD virtual bool is_current_array() LEGION_PURE; + L_NODISCARD virtual bool is_current_object() LEGION_PURE; + L_NODISCARD virtual size_type current_item_size() LEGION_PURE; + + L_NODISCARD virtual std::string get_key() LEGION_PURE; + + virtual common::result write(fs::view& file) LEGION_PURE; + + virtual common::result read(const fs::view& file) LEGION_PURE; + virtual common::result read(const byte_vec& data) LEGION_PURE; + virtual common::result read(byte_vec::iterator begin, byte_vec::iterator end) LEGION_PURE; + }; +} + +#include + diff --git a/legion/engine/core/serialization/serializer_views/serializer_view.inl b/legion/engine/core/serialization/serializer_views/serializer_view.inl new file mode 100644 index 000000000..9f54ddadb --- /dev/null +++ b/legion/engine/core/serialization/serializer_views/serializer_view.inl @@ -0,0 +1,75 @@ +#include +#pragma once + +namespace legion::core::serialization +{ + template + inline bool serializer_view::serialize(const std::string& name, Type&& value) + { + using raw_type = std::decay_t; + + if constexpr (std::is_same_v) + { + serialize_int(name, value); + return true; + } + else if constexpr (std::is_same_v) + { + serialize_float(name, value); + return true; + } + else if constexpr (std::is_same_v) + { + serialize_double(name, value); + return true; + } + else if constexpr (std::is_same_v) + { + serialize_bool(name, value); + return true; + } + else if constexpr (std::is_same_v) + { + serialize_string(name, value); + return true; + } + else if constexpr (std::is_same_v) + { + serialize_id_type(name, value); + return true; + } + return false; + } + + template + inline common::result serializer_view::deserialize(const std::string& name) + { + using raw_type = std::decay_t; + + if constexpr (std::is_same_v) + { + return deserialize_int(name); + } + else if constexpr (std::is_same_v) + { + return deserialize_float(name); + } + else if constexpr (std::is_same_v) + { + return deserialize_double(name); + } + else if constexpr (std::is_same_v) + { + return deserialize_bool(name); + } + else if constexpr (std::is_same_v) + { + return deserialize_string(name); + } + else if constexpr (std::is_same_v) + { + return deserialize_id_type(name); + } + return legion_fs_error("Type was not a primitive serializable type."); + } +} diff --git a/legion/engine/core/serialization/serializer_views/yaml.cpp b/legion/engine/core/serialization/serializer_views/yaml.cpp new file mode 100644 index 000000000..67469f9e0 --- /dev/null +++ b/legion/engine/core/serialization/serializer_views/yaml.cpp @@ -0,0 +1,454 @@ +#include + +namespace legion::core::serialization +{ + yaml::entry& yaml::current_item() + { + if (isPeaking) + return peakObject; + return active_stack.top(); + } + + void yaml::serialize_int(const std::string& name, int serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.IsMap()) + item[name] = serializable; + else if (item.IsSequence()) + item.push_back(serializable); + } + + void yaml::serialize_float(const std::string& name, float serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.IsMap()) + item[name] = serializable; + else if (item.IsSequence()) + item.push_back(serializable); + } + + void yaml::serialize_double(const std::string& name, double serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.IsMap()) + item[name] = serializable; + else if (item.IsSequence()) + item.push_back(serializable); + } + + void yaml::serialize_bool(const std::string& name, bool serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.IsMap()) + item[name] = serializable; + else if (item.IsSequence()) + item.push_back(serializable); + } + + void yaml::serialize_string(const std::string& name, const std::string& serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.IsMap()) + item[name] = serializable; + else if (item.IsSequence()) + item.push_back(serializable); + } + + void yaml::serialize_id_type(const std::string& name, id_type serializable) + { + auto& [key, item, rdIdx] = current_item(); + if (item.IsMap()) + item[name] = serializable; + else if (item.IsSequence()) + item.push_back(serializable); + } + + common::result yaml::deserialize_int(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.IsMap()) + { + auto node = current[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsScalar()) + return legion_fs_error("Item with name: " + name + " is not an integer number."); + + return node.as(); + } + else if (current.IsSequence()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading yaml beyond the size of the array."); + auto item = current[readIndex]; + + if (!item.IsScalar()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in yaml array " + currentName + " is not an integer number."); + + readIndex++; + return item.as(); + } + return legion_fs_error("Current yaml object is invalid."); + } + + common::result yaml::deserialize_float(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.IsMap()) + { + auto node = current[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsScalar()) + return legion_fs_error("Item with name: " + name + " is not a floating point number."); + + return node.as(); + } + else if (current.IsSequence()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading yaml beyond the size of the array."); + auto item = current[readIndex]; + + if (!item.IsScalar()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in yaml array " + currentName + " is not a floating point number."); + + readIndex++; + return item.as(); + } + return legion_fs_error("Current yaml object is invalid."); + } + + common::result yaml::deserialize_double(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.IsMap()) + { + auto node = current[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsScalar()) + return legion_fs_error("Item with name: " + name + " is not a floating point number."); + + return node.as(); + } + else if (current.IsSequence()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading yaml beyond the size of the array."); + auto item = current[readIndex]; + + if (!item.IsScalar()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in yaml array " + currentName + " is not a floating point number."); + + readIndex++; + return item.as(); + } + return legion_fs_error("Current yaml object is invalid."); + } + + common::result yaml::deserialize_bool(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.IsMap()) + { + auto node = current[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsScalar()) + return legion_fs_error("Item with name: " + name + " is not a boolean."); + + return node.as(); + } + else if (current.IsSequence()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading yaml beyond the size of the array."); + auto item = current[readIndex]; + + if (!item.IsScalar()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in yaml array " + currentName + " is not a boolean."); + + readIndex++; + return item.as(); + } + return legion_fs_error("Current yaml object is invalid."); + } + + common::result yaml::deserialize_string(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.IsMap()) + { + auto node = current[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsScalar()) + return legion_fs_error("Item with name: " + name + " is not a string."); + + return node.as(); + } + else if (current.IsSequence()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading yaml beyond the size of the array."); + auto item = current[readIndex]; + + if (!item.IsScalar()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in yaml array " + currentName + " is not a string."); + + readIndex++; + return item.as(); + } + return legion_fs_error("Current yaml object is invalid."); + } + + common::result yaml::deserialize_id_type(const std::string& name) + { + auto& [currentName, current, readIndex] = current_item(); + if (current.IsMap()) + { + auto node = current[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsScalar()) + return legion_fs_error("Item with name: " + name + " is not an integer number."); + + return node.as(); + } + else if (current.IsSequence()) + { + if (readIndex >= current.size()) + return legion_fs_error("Tried reading yaml beyond the size of the array."); + auto item = current[readIndex]; + + if (!item.IsScalar()) + return legion_fs_error("Item #" + std::to_string(readIndex) + " in yaml array " + currentName + " is not an integer number."); + + readIndex++; + return item.as(); + } + return legion_fs_error("Current yaml object is invalid."); + } + + void yaml::start_object() + { + active_stack.emplace("item_" + std::to_string(current_item().item.size()), YAML::Node(YAML::NodeType::Map)); + } + + void yaml::start_object(const std::string& name) + { + active_stack.emplace(name, YAML::Node(YAML::NodeType::Map)); + } + + void yaml::end_object() + { + if (active_stack.empty()) + return; + + auto& [name, object, readIndex] = current_item(); + + if (!object.IsMap()) + return; + + if (active_stack.size() == 1) + { + root.item[name] = object; + active_stack.pop(); + } + else + { + entry cpy{ name, object, readIndex }; + active_stack.pop(); + auto& [nxtName, next, nxtRdIdx] = current_item(); + + if (next.IsSequence()) + next.push_back(cpy.item); + else if (next.IsMap()) + next[cpy.key] = cpy.item; + } + } + + void yaml::start_container(const std::string& name) + { + active_stack.emplace(name, YAML::Node(YAML::NodeType::Sequence)); + } + + void yaml::end_container() + { + if (active_stack.empty()) + return; + + auto& [name, arr, readIndex] = current_item(); + + if (!arr.IsSequence()) + return; + + if (active_stack.size() == 1) + { + root.item[name] = arr; + active_stack.pop(); + } + else + { + entry cpy{ name, arr, readIndex }; + active_stack.pop(); + auto& [nxtName, next, nxtRdIdx] = current_item(); + + if (next.IsSequence()) + next.push_back(arr); + else if (next.IsMap()) + next[cpy.key] = cpy.item; + } + } + + common::result yaml::start_read(const std::string& name) + { + isPeaking = false; + if (active_stack.empty()) + { + auto node = root.item[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsMap() && !node.IsSequence()) + return legion_fs_error("Item with name: " + name + " is not an object or array."); + + active_stack.emplace(name, node); + } + else + { + auto& [curName, current, readIndex] = active_stack.top(); + + if (current.IsSequence()) + { + active_stack.emplace("item_" + std::to_string(readIndex), current[readIndex]); + readIndex++; + } + else if (current.IsMap()) + { + auto node = current[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsMap() && !node.IsSequence()) + return legion_fs_error("Item with name: " + name + " is not an object or array."); + + active_stack.emplace(name, node); + } + } + return common::success; + } + + common::result yaml::peak_ahead(const std::string& name) + { + if (active_stack.empty()) + { + auto node = root.item[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsMap() && !node.IsSequence()) + return legion_fs_error("Item with name: " + name + " is not an object or array."); + + peakObject = entry{ name, node }; + } + else + { + auto& [curName, current, readIndex] = active_stack.top(); + + if (current.IsSequence()) + { + peakObject = entry{ "item_" + std::to_string(readIndex), current[readIndex] }; + } + else if (current.IsMap()) + { + auto node = current[name]; + if (node.IsNull()) + return legion_fs_error("Item with name: " + name + " is not in current object."); + + if (!node.IsMap() && !node.IsSequence()) + return legion_fs_error("Item with name: " + name + " is not an object or array."); + + peakObject = entry{ name, node }; + } + } + isPeaking = true; + return common::success; + } + + void yaml::end_read() + { + if (active_stack.empty()) + return; + + active_stack.pop(); + } + + bool yaml::is_current_array() + { + return current_item().item.IsSequence(); + } + + bool yaml::is_current_object() + { + return current_item().item.IsSequence(); + } + + size_type yaml::current_item_size() + { + return current_item().item.size(); + } + + std::string yaml::get_key() + { + return current_item().key; + } + + common::result yaml::write(fs::view& file) + { + YAML::Emitter output; + output.SetIndent(4); + output << root.item; + return file.set(fs::basic_resource(output.c_str())); + } + + common::result yaml::read(const fs::view& file) + { + auto result = file.get(); + if (!result.valid()) + { + log::error(result.error().what()); + return result.error(); + } + root.key = "root"; + root.item = YAML::Load(result->to_string()); + root.currentReadIndex = 0; + return common::success; + } + + common::result yaml::read(const byte_vec& data) + { + root.key = "root"; + std::string str(data.begin(), data.end()); + root.item = YAML::Load(str); + root.currentReadIndex = 0; + return common::success; + } + + common::result yaml::read(byte_vec::iterator begin, byte_vec::iterator end) + { + root.key = "root"; + std::string str(begin, end); + root.item = YAML::Load(str); + root.currentReadIndex = 0; + return common::success; + } + +} diff --git a/legion/engine/core/serialization/serializer_views/yaml.hpp b/legion/engine/core/serialization/serializer_views/yaml.hpp new file mode 100644 index 000000000..062c3c8c9 --- /dev/null +++ b/legion/engine/core/serialization/serializer_views/yaml.hpp @@ -0,0 +1,71 @@ +#pragma once +#include +#define YAML_CPP_STATIC_DEFINE +#include +#include + +namespace legion::core::serialization +{ + + struct yaml : public serializer_view + { + protected: + struct entry + { + std::string key; + YAML::Node item; + size_type currentReadIndex = 0; + + RULE_OF_5_NOEXCEPT(entry); + + entry(const std::string& k, const YAML::Node& j, size_type idx = 0) : key(k), item(j), currentReadIndex(idx) {} + }; + + entry root; + bool isPeaking; + entry peakObject; + std::stack active_stack; + + entry& current_item(); + + public: + yaml() = default; + virtual ~yaml() = default; + + virtual void serialize_int(const std::string& name, int serializable) override; + virtual void serialize_float(const std::string& name, float serializable) override; + virtual void serialize_double(const std::string& name, double serializable) override; + virtual void serialize_bool(const std::string& name, bool serializable) override; + virtual void serialize_string(const std::string& name, const std::string& serializable) override; + virtual void serialize_id_type(const std::string& name, id_type serializable) override; + + L_NODISCARD virtual common::result deserialize_int(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_float(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_double(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_bool(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_string(const std::string& name) override; + L_NODISCARD virtual common::result deserialize_id_type(const std::string& name) override; + + virtual void start_object() override; + virtual void start_object(const std::string& name) override; + virtual void end_object() override; + + virtual void start_container(const std::string& name) override; + virtual void end_container() override; + + L_NODISCARD virtual common::result start_read(const std::string& name) override; + L_NODISCARD virtual common::result peak_ahead(const std::string& name) override; + virtual void end_read() override; + + L_NODISCARD virtual bool is_current_array() override; + L_NODISCARD virtual bool is_current_object() override; + L_NODISCARD virtual size_type current_item_size() override; + + L_NODISCARD virtual std::string get_key() override; + + L_NODISCARD virtual common::result write(fs::view& file) override; + L_NODISCARD virtual common::result read(const fs::view& file) override; + L_NODISCARD virtual common::result read(const byte_vec& data) override; + L_NODISCARD virtual common::result read(byte_vec::iterator begin, byte_vec::iterator end) override; + }; +} diff --git a/legion/engine/core/serialization/use_embedded_material.hpp b/legion/engine/core/serialization/use_embedded_material.hpp deleted file mode 100644 index 0087d8cd1..000000000 --- a/legion/engine/core/serialization/use_embedded_material.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include -#include - -namespace legion::core -{ - struct use_embedded_material - { - use_embedded_material(const std::string& matName, const std::string& str) : embedded_material_path(str), materialName(matName) {} - use_embedded_material() = default; - use_embedded_material(const use_embedded_material& other) = default; - use_embedded_material(use_embedded_material&& other) noexcept = default; - use_embedded_material& operator=(const use_embedded_material& other) = default; - use_embedded_material& operator=(use_embedded_material&& other) noexcept = default; - std::string embedded_material_path; - std::string materialName; - - template - void serialize(Archive& oa) - { - oa(cereal::make_nvp("EmbeddedMaterialPath",embedded_material_path), cereal::make_nvp("MaterialName", materialName)); - } - }; -} diff --git a/legion/engine/core/types/meta.hpp b/legion/engine/core/types/meta.hpp index 09164718c..97aa2bbdd 100644 --- a/legion/engine/core/types/meta.hpp +++ b/legion/engine/core/types/meta.hpp @@ -37,7 +37,7 @@ namespace legion::core }; \ \ template \ - constexpr bool CONCAT(has_, CONCAT(x, _v)) = CONCAT(has_, x)::value; \ + constexpr bool CONCAT(has_, CONCAT(x, _v)) = CONCAT(has_, x)::value; \ \ template \ struct CONCAT(has_static_, x) { \ @@ -70,7 +70,7 @@ namespace legion::core }; \ \ template \ - constexpr bool CONCAT(has_, CONCAT(x, _v)) = CONCAT(has_, x)::value; \ + constexpr bool CONCAT(has_, CONCAT(x, _v)) = CONCAT(has_, x)::value; \ \ template \ struct CONCAT(has_static_, x) { \ @@ -122,20 +122,51 @@ namespace legion::core }; \ \ template \ - constexpr bool CONCAT(name, _v) = name::value; + constexpr bool CONCAT(name, _v) = name::value; + + HAS_FUNC(setup); + HAS_FUNC(shutdown); + HAS_FUNC(update); HAS_FUNC(begin); HAS_FUNC(end); + HAS_FUNC(at); - COMBINE_SFINAE(is_container, has_begin_v&& has_end_v, T); - + HAS_FUNC(size); HAS_FUNC(resize); + HAS_FUNC(push_back); + HAS_FUNC(emplace); + HAS_FUNC(insert); + + COMBINE_SFINAE(is_container, has_begin_v&& has_end_v, T); COMBINE_SFINAE(is_resizable_container, has_begin_v&& has_end_v&& has_resize_v, T); + COMBINE_SFINAE(is_any_castable, std::is_constructible::value, T); - HAS_FUNC(setup); - HAS_FUNC(shutdown); - HAS_FUNC(update); + template + struct is_serializable + { + private: + template + static constexpr auto check(T*) + -> typename std::conditional || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v, std::true_type, std::false_type > ::type; + + template + static constexpr auto check(...) + ->std::false_type; + + typedef decltype(check(nullptr)) type; + public: + static constexpr bool value = type::value; + }; + + template + constexpr bool is_serializable_v = is_serializable::value; template using inherits_from = typename std::enable_if::value, int>::type; diff --git a/legion/engine/core/types/prototype.hpp b/legion/engine/core/types/prototype.hpp index cbf1a350a..22648b865 100644 --- a/legion/engine/core/types/prototype.hpp +++ b/legion/engine/core/types/prototype.hpp @@ -96,6 +96,6 @@ namespace legion::core template L_NODISCARD prototype make_prototype(const T& obj) { - return prototype{ localTypeHash(), localNameOfType(),std::vector() }; + return prototype{ typeHash(), nameOfType(), std::vector() }; } } diff --git a/legion/engine/core/types/reflector.hpp b/legion/engine/core/types/reflector.hpp index 0f5ce488f..a9dfdc5f5 100644 --- a/legion/engine/core/types/reflector.hpp +++ b/legion/engine/core/types/reflector.hpp @@ -12,25 +12,42 @@ namespace legion::core id_type typeId; std::string_view typeName; std::vector members; + void* data; reflector() = default; - reflector(id_type id, std::string_view name, std::vector _members) : typeId(id), typeName(name), members(_members) {} - reflector(const reflector& refl) : typeId(refl.typeId), typeName(refl.typeName), members(refl.members) {} + reflector(id_type id, std::string_view name, std::vector _members, void* _adress) + : typeId(id), typeName(name), members(_members), data(_adress) {} + + reflector(id_type id, std::string_view name, std::vector _members, const void* _adress) + : typeId(id), typeName(name), members(_members) + { + ptr_type adress = reinterpret_cast(_adress); + data = reinterpret_cast(adress); + } + + reflector(const reflector& refl) : typeId(refl.typeId), typeName(refl.typeName), members(refl.members), data(refl.data) {} reflector& operator=(const reflector& rhs) { typeId = rhs.typeId; typeName = rhs.typeName; members = rhs.members; + data = rhs.data; return *this; } }; + struct primitive_reference { id_type typeId; void* data = nullptr; + RULE_OF_5_NOEXCEPT(primitive_reference); + primitive_reference(id_type id, void* address) noexcept : typeId(id), data(address) {} + primitive_reference(id_type id, const void* address) noexcept : typeId(id) + { ptr_type tmp = reinterpret_cast(address); data = reinterpret_cast(tmp); } + template L_NODISCARD T* cast() { @@ -51,6 +68,7 @@ namespace legion::core return nullptr; } }; + struct member_reference { bool is_object; @@ -61,8 +79,8 @@ namespace legion::core primitive_reference primitive; }; - member_reference() : is_object(false), name(""), primitive() {} - member_reference(std::string_view _name, primitive_reference _primitive) : is_object(false), name(_name), primitive(_primitive) {} + member_reference() noexcept : is_object(false), name(""), primitive() {} + member_reference(std::string_view _name, primitive_reference _primitive) noexcept : is_object(false), name(_name), primitive(_primitive) {} member_reference(std::string_view _name, reflector refl) : is_object(true), name(_name), object(refl) {} member_reference(const member_reference& other) { @@ -100,8 +118,9 @@ namespace legion::core }; template - L_NODISCARD reflector make_reflector(T& obj) + L_NODISCARD auto make_reflector(T& obj) -> std::conditional_t, const reflector, reflector> { - return reflector{ localTypeHash(), localNameOfType(),std::vector() }; + ptr_type adress = reinterpret_cast(std::addressof(obj)); + return reflector{ typeHash(), nameOfType(), std::vector(), reinterpret_cast(adress) }; } } diff --git a/legion/engine/physics/components/rigidbody.hpp b/legion/engine/physics/components/rigidbody.hpp index 62e8ef162..6eefece98 100644 --- a/legion/engine/physics/components/rigidbody.hpp +++ b/legion/engine/physics/components/rigidbody.hpp @@ -33,18 +33,6 @@ namespace legion::physics bool isAsleep; - template - void serialize(Archive& archive) - { - //We won't need to manually name all the components in the future - archive(cereal::make_nvp("Name", std::string("Rigidbody")), cereal::make_nvp("Inverse Mass",inverseMass), - cereal::make_nvp("Velocity",velocity),cereal::make_nvp("Acceleration",acc), cereal::make_nvp("Linear Drag",linearDrag), - cereal::make_nvp("Inverse Intertia Tensor",localInverseInertiaTensor),cereal::make_nvp("Angular Acceleration",angularAcc), - cereal::make_nvp("Angular Velocity",angularVelocity),cereal::make_nvp("Angular Drag",angularDrag),cereal::make_nvp("Global Centre of Mass",globalCentreOfMass), - cereal::make_nvp("Force Accumulator",forceAccumulator),cereal::make_nvp("Torque Accumulator",torqueAccumulator),cereal::make_nvp("Restitution",restitution), - cereal::make_nvp("Friction",friction),cereal::make_nvp("Is Asleep?",isAsleep)); - } - static float calculateRestitution(float restitutionA, float restitutionB) { return (restitutionA + restitutionB) / 2.0f; diff --git a/legion/engine/physics/physics_statics.hpp b/legion/engine/physics/physics_statics.hpp index b641fee7e..eaf739876 100644 --- a/legion/engine/physics/physics_statics.hpp +++ b/legion/engine/physics/physics_statics.hpp @@ -486,7 +486,7 @@ namespace legion::physics { con.draw_cells_json("assets/voronoi/output/cells.json"); std::ifstream f("assets/voronoi/output/cells.json"); - return serialization::SerializationUtil::JSONDeserialize< std::vector>>(f); + return serialization::json_serializer>>::deserialize(f); } /**@brief Checks collision between two AABB colliders and returns whether there is collision diff --git a/legion/engine/rendering/components/renderable.hpp b/legion/engine/rendering/components/renderable.hpp index 2b5416ccd..0dbae4dba 100644 --- a/legion/engine/rendering/components/renderable.hpp +++ b/legion/engine/rendering/components/renderable.hpp @@ -22,17 +22,6 @@ namespace legion::rendering } material_handle material = invalid_material_handle; - - template - void save(Archive& oa) - { - oa(CEREAL_NVP(material)); - } - template - void load(Archive& ia) - { - ia(CEREAL_NVP(material)); - } }; struct mesh_renderable : public ecs::archetype diff --git a/legion/engine/rendering/data/material.hpp b/legion/engine/rendering/data/material.hpp index 2d97b67ae..6034e6093 100644 --- a/legion/engine/rendering/data/material.hpp +++ b/legion/engine/rendering/data/material.hpp @@ -83,8 +83,6 @@ namespace legion::rendering friend struct material_handle; private: shader_handle m_shader; - bool m_canLoadOrSave = true; - void init(const shader_handle& shader) { @@ -247,16 +245,6 @@ namespace legion::rendering attribute get_attribute(const std::string& name); bool operator==(const material_handle& other) const { return id == other.id; } - - template - void save(Archive& oa) const; - - template - void load(Archive& oa); - - bool getLoadOrSaveBit() const; - void setLoadOrSaveBit(bool canBeSavedOrLoaded); - }; @@ -528,144 +516,6 @@ namespace legion::rendering return submaterial.parameters.count(id) && submaterial.parameters[id]->type() == typeHash(); } #pragma endregion - - template - void material_handle::save(Archive& oa) const - { - - async::readonly_guard guard(MaterialCache::m_materialLock); - material& m = MaterialCache::m_materials[id]; - - - //Bob the ini builder - detail::IniBuilder bob; - - //Generate some Metadata - bob.comment("File is autogenerated by Bob the IniBuilder, please do not edit"); - bob.comment("(c) Legion-Engine 2021 MIT-License"); - bob.comment(""); - bob.comment("Base parameters contains static information about the material"); - - // Generate base section - // Currently includes only the shader path of the material - bob.section("base").glyph("shader").eq().value(m.m_shader.get_path()).finish_entry(); - bob.comment("Custom Parameters contains dynamic information about the material"); - bob.comment("if you _really_ need to edit this file, it is probably something here!"); - bob.section("custom"); - - - // Iterate over all parameters in the material - for (auto& [key, value] : m.get_params()) - { - // get the string key to the value - std::string kv = value->get_name(); - - // check if the material prop is internal and should not be safed - if (common::starts_with(kv, "lgn_")) - continue; - - // check if the key ends with a trailing NUL for whatever reason, - // and just remove it - if (common::ends_with(kv, "\0")) - kv.resize(kv.size() - 1); - - // add the key + the equals sign - // for instance - // "material_input.emissive=" - bob.push_state(); - bob.glyph(kv).eq(); - - // determine what type of variable we are dealing with - if (value->type() == typeHash()) - { - // add the value and finish the entry - bob.value(static_cast*>(value.get())->get_value()).finish_entry(); - continue; - } - if (value->type() == typeHash()) - { - bob.value(static_cast*>(value.get())->get_value()).finish_entry(); - continue; - } - if (value->type() == typeHash()) - { - bob.value(static_cast*>(value.get())->get_value()).finish_entry(); - continue; - } - if (value->type() == typeHash()) - { - bob.value(static_cast*>(value.get())->get_value()).finish_entry(); - continue; - } - if (value->type() == typeHash()) - { - bob.value(static_cast*>(value.get())->get_value()).finish_entry(); - continue; - } - if (value->type() == typeHash()) - { - bob.value(static_cast*>(value.get())->get_value()).finish_entry(); - continue; - } - if (value->type() == typeHash()) - { - bob.value(static_cast*>(value.get())->get_value()).finish_entry(); - continue; - } - if (value->type() == typeHash()) - { - //for the texture handle we need to extract the texture first and ask it for its path - texture_handle th = static_cast*>(value.get())->get_value(); - std::string path = th.get_texture().path; - if(path.empty()) - { - bob.pop_state(); - continue; - } - bob.value(path).finish_entry(); - continue; - } - } - - //TODO(algo-ryth-mix): there needs to be a san step here to avoid impossible filenames! - fs::view file("assets://materials/" + m.get_name() + ".material"); - file.set(fs::basic_resource(bob.get())); - oa(cereal::make_nvp("MaterialFile", file.get_virtual_path())); - } - template - void material_handle::load(Archive& ia) - { - if (!getLoadOrSaveBit()) - { - return; - } - - std::string filepath; - ia(cereal::make_nvp("MaterialFile", filepath)); - const fs::view file(filepath); - if (!file.file_info().exists) return; - - const auto shader_location = extract_string("base", "shader", file); - - async::readwrite_guard guard(MaterialCache::m_materialLock); - auto materialname = file.get_filename().value(); - materialname = materialname.substr(0, materialname.find_last_of('.')); - id = MaterialCache::create_material(materialname, fs::view(shader_location)).id; - apply_material_conf(*this, "custom", file); - } - - - inline bool material_handle::getLoadOrSaveBit() const - { - async::readonly_guard guard(MaterialCache::m_materialLock); - return MaterialCache::m_materials[id].m_canLoadOrSave; - } - - inline void material_handle::setLoadOrSaveBit(bool canBeSavedOrLoaded) - { - async::readwrite_guard guard(MaterialCache::m_materialLock); - MaterialCache::m_materials[id].m_canLoadOrSave = canBeSavedOrLoaded; - } } diff --git a/legion/engine/rendering/data/shader.cpp b/legion/engine/rendering/data/shader.cpp index 028e83627..41d36ca75 100644 --- a/legion/engine/rendering/data/shader.cpp +++ b/legion/engine/rendering/data/shader.cpp @@ -903,7 +903,7 @@ namespace legion::rendering shader_handle ShaderCache::create_shader(const fs::view& file, shader_import_settings settings) { - return create_shader(file.get_filename(), file, settings); + return create_shader(*file.get_filename(), file, settings); } shader_handle ShaderCache::get_handle(const std::string& name) diff --git a/legion/engine/rendering/data/texture.cpp b/legion/engine/rendering/data/texture.cpp index 7f4965913..1af253d00 100644 --- a/legion/engine/rendering/data/texture.cpp +++ b/legion/engine/rendering/data/texture.cpp @@ -149,7 +149,7 @@ namespace legion::rendering texture_handle TextureCache::create_texture(const fs::view& file, texture_import_settings settings) { OPTICK_EVENT(); - return create_texture(file.get_filename(), file, settings); + return create_texture(*file.get_filename(), file, settings); } texture_handle TextureCache::create_texture(const std::string& name, math::ivec2 size, texture_import_settings settings)