From 3b2ca2756202aa6d3e9519a67b91ef46ac628b91 Mon Sep 17 00:00:00 2001 From: Klas Eskilson Date: Fri, 2 Jun 2017 09:46:11 -0400 Subject: [PATCH 01/12] [Cmake] Rename use renamed ghl_copy_files macro --- apps/OpenSpace/CMakeLists.txt | 2 +- support/cmake/support_macros.cmake | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/OpenSpace/CMakeLists.txt b/apps/OpenSpace/CMakeLists.txt index c5e93b08bb..b4ffa29792 100644 --- a/apps/OpenSpace/CMakeLists.txt +++ b/apps/OpenSpace/CMakeLists.txt @@ -96,7 +96,7 @@ add_executable(${APPLICATION_NAME} ${RESOURCE_FILE} ) if (OPENSPACE_SPOUT_SUPPORT) - copy_files( + ghl_copy_files( ${APPLICATION_NAME} ${OPENSPACE_APPS_DIR}/OpenSpace/ext/spout/SpoutLibrary.dll ) diff --git a/support/cmake/support_macros.cmake b/support/cmake/support_macros.cmake index 82e00c7651..237e677b61 100644 --- a/support/cmake/support_macros.cmake +++ b/support/cmake/support_macros.cmake @@ -247,7 +247,7 @@ function (handle_applications) if (WIN32) - copy_files( + ghl_copy_files( ${APPLICATION_NAME} "${CURL_ROOT_DIR}/lib/libcurl.dll" "${CURL_ROOT_DIR}/lib/libeay32.dll" @@ -293,7 +293,7 @@ function (handle_option_vld) target_include_directories(libOpenSpace PUBLIC ${OPENSPACE_EXT_DIR}/vld) foreach (app ${OPENSPACE_APPLCATIONS}) - copy_files(${app} "${OPENSPACE_EXT_DIR}/vld/bin/vld_x64.dll") + ghl_copy_files(${app} "${OPENSPACE_EXT_DIR}/vld/bin/vld_x64.dll") endforeach () endif () endfunction () @@ -503,7 +503,7 @@ function (handle_internal_modules) if (WIN32) foreach (application ${OPENSPACE_APPLICATIONS}) foreach (dll ${dll_list}) - copy_files(${application} ${dll}) + ghl_copy_files(${application} ${dll}) endforeach () endforeach () endif () @@ -511,7 +511,7 @@ endfunction () function (copy_dynamic_libraries) if (WIN32) - copy_files(OpenSpace "${CURL_ROOT_DIR}/lib/libcurl.dll") + ghl_copy_files(OpenSpace "${CURL_ROOT_DIR}/lib/libcurl.dll") # Copy DLLs needed by Ghoul into the executable directory ghl_copy_shared_libraries(OpenSpace ${OPENSPACE_EXT_DIR}/ghoul) From ea8442d996b7181164c4c93ea2483921e18372f9 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sat, 3 Jun 2017 13:38:02 -0400 Subject: [PATCH 02/12] Enable networked specifications for ScreenSpaceImages --- modules/onscreengui/src/gui.cpp | 9 +++------ src/scripting/scriptengine_lua.inl | 1 + 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/onscreengui/src/gui.cpp b/modules/onscreengui/src/gui.cpp index 7a44eb4583..33cfa20ae1 100644 --- a/modules/onscreengui/src/gui.cpp +++ b/modules/onscreengui/src/gui.cpp @@ -210,12 +210,9 @@ void addScreenSpaceRenderable(std::string texturePath) { return; } - texturePath = absPath(texturePath); - texturePath = FileSys.convertPathSeparator(texturePath, '/'); - - std::string luaTable = - "{Type = 'ScreenSpaceImage', TexturePath = '" + texturePath + "' }"; - std::string script = "openspace.registerScreenSpaceRenderable(" + luaTable + ");"; + const std::string luaTable = + "{Type = 'ScreenSpaceImage', TexturePath = openspace.absPath('" + texturePath + "') }"; + const std::string script = "openspace.registerScreenSpaceRenderable(" + luaTable + ");"; OsEng.scriptEngine().queueScript(script, openspace::scripting::ScriptEngine::RemoteScripting::Yes); } } // namespace diff --git a/src/scripting/scriptengine_lua.inl b/src/scripting/scriptengine_lua.inl index a65f70f3d4..0eda39fd16 100644 --- a/src/scripting/scriptengine_lua.inl +++ b/src/scripting/scriptengine_lua.inl @@ -200,6 +200,7 @@ int absolutePath(lua_State* L) { std::string path = luaL_checkstring(L, -1); path = absPath(path); + path = FileSys.convertPathSeparator(path, '/'); lua_pushstring(L, path.c_str()); return 1; } From 013e448c36680df7e3b30b09e3c2bf9df2f0a2c2 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sat, 3 Jun 2017 14:29:33 -0400 Subject: [PATCH 03/12] Adding a Gui window to show the registered file paths (closes #329) --- modules/onscreengui/CMakeLists.txt | 2 + modules/onscreengui/include/gui.h | 2 + .../include/guifilepathcomponent.h | 43 +++++++++++++ modules/onscreengui/src/gui.cpp | 10 +++ .../onscreengui/src/guifilepathcomponent.cpp | 62 +++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 modules/onscreengui/include/guifilepathcomponent.h create mode 100644 modules/onscreengui/src/guifilepathcomponent.cpp diff --git a/modules/onscreengui/CMakeLists.txt b/modules/onscreengui/CMakeLists.txt index eead578fc5..3a0720a818 100644 --- a/modules/onscreengui/CMakeLists.txt +++ b/modules/onscreengui/CMakeLists.txt @@ -27,6 +27,7 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/gui.h ${CMAKE_CURRENT_SOURCE_DIR}/include/guicomponent.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/guifilepathcomponent.h ${CMAKE_CURRENT_SOURCE_DIR}/include/guihelpcomponent.h ${CMAKE_CURRENT_SOURCE_DIR}/include/guiorigincomponent.h ${CMAKE_CURRENT_SOURCE_DIR}/include/guiperformancecomponent.h @@ -42,6 +43,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/gui.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/gui_lua.inl ${CMAKE_CURRENT_SOURCE_DIR}/src/guicomponent.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/guifilepathcomponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guihelpcomponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guiorigincomponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guiperformancecomponent.cpp diff --git a/modules/onscreengui/include/gui.h b/modules/onscreengui/include/gui.h index 04d3056b16..d8a2c91dee 100644 --- a/modules/onscreengui/include/gui.h +++ b/modules/onscreengui/include/gui.h @@ -26,6 +26,7 @@ #define __OPENSPACE_MODULE_ONSCREENGUI___GUI___H__ #include +#include #include #include #include @@ -65,6 +66,7 @@ public: //protected: GuiHelpComponent _help; + GuiFilePathComponent _filePath; GuiOriginComponent _origin; GuiPerformanceComponent _performance; GuiPropertyComponent _globalProperty; diff --git a/modules/onscreengui/include/guifilepathcomponent.h b/modules/onscreengui/include/guifilepathcomponent.h new file mode 100644 index 0000000000..a859bc7bf1 --- /dev/null +++ b/modules/onscreengui/include/guifilepathcomponent.h @@ -0,0 +1,43 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * 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. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_ONSCREENGUI___GUIFILEPATHCOMPONENT___H__ +#define __OPENSPACE_MODULE_ONSCREENGUI___GUIFILEPATHCOMPONENT___H__ + +#include + +namespace openspace { +namespace gui { + +class GuiFilePathComponent : public GuiComponent { +public: + GuiFilePathComponent(); + + void render() override; +}; + +} // namespace gui +} // namespace openspace + +#endif // __OPENSPACE_MODULE_ONSCREENGUI___GUIFILEPATHCOMPONENT___H__ diff --git a/modules/onscreengui/src/gui.cpp b/modules/onscreengui/src/gui.cpp index 33cfa20ae1..c3e520fa33 100644 --- a/modules/onscreengui/src/gui.cpp +++ b/modules/onscreengui/src/gui.cpp @@ -235,6 +235,7 @@ GUI::GUI() addPropertySubOwner(_property); addPropertySubOwner(_screenSpaceProperty); addPropertySubOwner(_virtualProperty); + addPropertySubOwner(_filePath); addPropertySubOwner(_time); addPropertySubOwner(_iswa); } @@ -318,6 +319,7 @@ void GUI::initialize() { _globalProperty.initialize(); _globalProperty.setHasRegularProperties(true); _virtualProperty.initialize(); + _filePath.initialize(); _performance.initialize(); _help.initialize(); _parallel.initialize(); @@ -334,6 +336,7 @@ void GUI::deinitialize() { _globalProperty.deinitialize(); _screenSpaceProperty.deinitialize(); _virtualProperty.deinitialize(); + _filePath.deinitialize(); _property.deinitialize(); delete iniFileBuffer; @@ -485,6 +488,9 @@ void GUI::endFrame() { if (_iswa.isEnabled()) { _iswa.render(); } + if (_filePath.isEnabled()) { + _filePath.render(); + } } ImGui::Render(); @@ -580,6 +586,10 @@ void GUI::render() { ImGui::Checkbox("Virtual Properties", &virtualProperty); _virtualProperty.setEnabled(virtualProperty); + bool filePath = _filePath.isEnabled(); + ImGui::Checkbox("File Paths", &filePath); + _filePath.setEnabled(filePath); + #ifdef OPENSPACE_MODULE_ISWA_ENABLED bool iswa = _iswa.isEnabled(); ImGui::Checkbox("iSWA", &iswa); diff --git a/modules/onscreengui/src/guifilepathcomponent.cpp b/modules/onscreengui/src/guifilepathcomponent.cpp new file mode 100644 index 0000000000..4327fc071f --- /dev/null +++ b/modules/onscreengui/src/guifilepathcomponent.cpp @@ -0,0 +1,62 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * 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. * + ****************************************************************************************/ + +#include + +#include + +#include "imgui.h" + +namespace openspace { +namespace gui { + +GuiFilePathComponent::GuiFilePathComponent() + : GuiComponent("File Path") +{} + +void GuiFilePathComponent::render() { + bool v = _isEnabled; + ImGui::Begin("File Path", &v); + + ImGui::Text( + "%s", + "These are file paths registered in the current OpenSpace instance." + ); + ImGui::Separator(); + + ImGui::Columns(2); + ImGui::Separator(); + std::vector tokens = FileSys.tokens(); + for (const std::string& t : tokens) { + ImGui::Text("%s", t.c_str()); + ImGui::NextColumn(); + ImGui::Text("%s", absPath(t).c_str()); + ImGui::NextColumn(); + ImGui::Separator(); + } + ImGui::End(); +} + +} // gui +} // openspace From 684327acedbb5d6a4e507c6366cca45e72911cf2 Mon Sep 17 00:00:00 2001 From: Klas Eskilson Date: Mon, 5 Jun 2017 16:05:59 -0400 Subject: [PATCH 04/12] Update Ghoul version --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 56bd0eb34a..b76cbabe61 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 56bd0eb34a300e9420e6f894803b4f3a7d3fe383 +Subproject commit b76cbabe61baf05b1105e9dccdae0e7e5f8c4405 From c77fdf23ae1f53dc4abba90400ab640e1188424c Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 6 Jun 2017 09:25:06 -0400 Subject: [PATCH 05/12] Add predefined SGCT config for Spout sharing --- openspace.cfg | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openspace.cfg b/openspace.cfg index 27e2e2a4de..4736a0e50e 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -9,8 +9,6 @@ return { -- A regular 1280x720 window SGCTConfig = sgct.config.single{}, - -- SGCTConfig = sgct.config.single{res={1920, 1080}, shared=true}, - -- A regular 1920x1080 window -- SGCTConfig = sgct.config.single{1920, 1080}, @@ -20,6 +18,10 @@ return { -- A 4k fisheye rendering in a 1024x1024 window -- SGCTConfig = sgct.config.fisheye{1024, 1024, res={4096, 4096}, quality="2k", tilt=27}, + -- Streaming OpenSpace via Spout to OBS + -- SGCTConfig = sgct.config.single{2560, 1440, shared=true, name="WV_OBS_SPOUT1"}, + + --SGCTConfig = "${SGCT}/openvr_oculusRiftCv1.xml", --SGCTConfig = "${SGCT}/openvr_htcVive.xml", From 5096e3ffadd1a4a2a956281024a8fb8346cbaa0b Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 6 Jun 2017 12:08:27 -0400 Subject: [PATCH 06/12] Update SGCT --- ext/sgct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/sgct b/ext/sgct index 40ea897067..b94aa799b5 160000 --- a/ext/sgct +++ b/ext/sgct @@ -1 +1 @@ -Subproject commit 40ea8970673c58a172dabab6ddccc45f0a0e92ac +Subproject commit b94aa799b5b7a5bfff079fc105fcc0be952b3901 From be1b211dfb921bbf9a8c43af7cf6e0c516f46221 Mon Sep 17 00:00:00 2001 From: Gene Payne Date: Tue, 6 Jun 2017 11:42:38 -0600 Subject: [PATCH 07/12] Feature/satellites (#325) * Initial commit of satellites test branch * Modified code to work with batch TLE files from online links specified in .mod file. Does not yet auto-download the files. * Added debug function to mod file for testing static points in orbit * Fixed time offset bug that was corrupting satellite positions * Minor changes for debug output and camera position. * Changed to circle billboard for rendering satellite position * Added satellite group name to each renderable title, and keyboard shortcuts for toggling visibility * Added support for using ghoul luasocket lib to download latest satellite TLE files from celestrak.com * Adding reference to updated Ghoul submodule containing luasocket changes * Updating reference to latest Ghoul submodule in feature/satellites * Updated reference to new ghoul version * Updated reference to new ghoul submodule version for satellites * Updated reference to new ghoul submodule version for satellits * Updated versions of TLE files * Added new Lua-accessible downloader available for scene loading * Improved error handling for TLE files * Updated submodule reference for ext/ghoul prior to luasocket addition * Update SGCT reference --- data/scene/satellites.scene | 71 + data/scene/satellites/generate_raw.lua | 66 + data/scene/satellites/satB.png | Bin 0 -> 4281 bytes data/scene/satellites/satellites.mod | 194 +++ data/scene/satellites/tle/geo.txt | 1326 +++++++++++++++++ data/scene/satellites/tle/gps-ops.txt | 93 ++ data/scene/satellites/tle/stations.txt | 180 +++ .../verify_satellites_lua_output.lua | 48 + include/openspace/engine/downloadmanager.h | 14 +- modules/space/translation/tletranslation.cpp | 184 ++- modules/space/translation/tletranslation.h | 8 +- scripts/bind_keys_satellites.lua | 23 + src/engine/downloadmanager.cpp | 17 +- src/engine/openspaceengine.cpp | 6 + src/engine/openspaceengine_lua.inl | 25 + 15 files changed, 2157 insertions(+), 98 deletions(-) create mode 100644 data/scene/satellites.scene create mode 100644 data/scene/satellites/generate_raw.lua create mode 100644 data/scene/satellites/satB.png create mode 100644 data/scene/satellites/satellites.mod create mode 100644 data/scene/satellites/tle/geo.txt create mode 100644 data/scene/satellites/tle/gps-ops.txt create mode 100644 data/scene/satellites/tle/stations.txt create mode 100644 data/scene/satellites/verify_satellites_lua_output.lua create mode 100644 scripts/bind_keys_satellites.lua diff --git a/data/scene/satellites.scene b/data/scene/satellites.scene new file mode 100644 index 0000000000..20eed4c4d4 --- /dev/null +++ b/data/scene/satellites.scene @@ -0,0 +1,71 @@ +function preInitialization() + --[[ + The scripts in this function are executed after the scene is loaded but before the + scene elements have been initialized, thus they should be used to set the time at + which the scene should start and other settings that might determine initialization + critical objects. + ]]-- + + openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/pck00010.tpc") + -- openspace.spice.loadKernel("${OPENSPACE_DATA}/spice/de430_1850-2150.bsp") + + openspace.time.setTime(openspace.time.currentWallTime()) + + --Test for vernal equinox time 2017 + --openspace.time.setTime("2017 MAR 20 10:28:30.500") + + dofile(openspace.absPath('${SCRIPTS}/bind_keys_satellites.lua')) +end + +function postInitialization() + --[[ + The scripts in this function are executed after all objects in the scene have been + created and initialized, but before the first render call. This is the place to set + graphical settings for the renderables. + ]]-- + openspace.printInfo("Setting default values") + openspace.setPropertyValue("SunMarker.renderable.enabled", false) + openspace.setPropertyValue("SunGlare.renderable.enabled", false) + openspace.setPropertyValue("MilkyWay.renderable.enabled", false) + openspace.setPropertyValue("EarthMarker.renderable.enabled", false) + openspace.setPropertyValue("EarthTrail.renderable.enabled", false) + openspace.setPropertyValue("Earth.renderable.performShading", false) + + openspace.resetCameraDirection() + + openspace.printInfo("Done setting default values") + + if openspace.modules.isLoaded("ISWA") then + + openspace.iswa.addCdfFiles("${OPENSPACE_DATA}/cdflist.json"); + + --openspace.iswa.addCygnet(7); + + --openspace.iswa.addCygnet(-4,"Data","Gm"); + --openspace.iswa.addCygnet(-5,"Data","Gm"); + --openspace.iswa.addCygnet(-6,"Data","Gm"); + --openspace.iswa.addCygnet(-7,"Data","Gm"); + --openspace.iswa.addCygnet(-8,"Data","Gm"); + --openspace.iswa.addCygnet(-9,"Data","Gm"); + end +end + +return { + ScenePath = ".", + CommonFolder = "common", + Camera = { + Focus = "Earth", + Position = {-54343425747.129051, -73298476295.934555, 116584089130.590012}, + Rotation = {-0.078983, 0.830093, 0.014241, -0.551819}, + }, + Modules = { + --"satellites/earth", + "sun", + "earth", + -- "stars", + -- "milkyway", + "satellites" + } +} + diff --git a/data/scene/satellites/generate_raw.lua b/data/scene/satellites/generate_raw.lua new file mode 100644 index 0000000000..5b10dc796c --- /dev/null +++ b/data/scene/satellites/generate_raw.lua @@ -0,0 +1,66 @@ +#!/bin/lua + +--For debug purposes, but also for generating raw output in case the parsing +-- isn't working as intended. +function tableLength(T) + local count = 0 + for _ in pairs(T) do count = count + 1 end + return count +end + +output = dofile("satellites.mod") +outputLen = tableLength(output) + +print("return {") +for i=1,outputLen do + type=output[i].Renderable.Type + print(" {") + if( type == "RenderablePlane" ) then + print(" Name = \"" .. output[i].Name .. "\",") + print(" Parent = \"" .. output[i].Parent .. "\",") + print(" Renderable = {") + print(" Type = \"" .. output[i].Renderable.Type .. "\",") + print(" Size = {".. output[i].Renderable.Size[1] .. "," .. output[i].Renderable.Size[2] .. "},") + print(" Origin = \"".. output[i].Renderable.Origin .. "\",") + print(" Body = \"" .. output[i].Renderable.Body .. "\",") + if (output[i].Renderable.Billboard) then + print(" Billboard = true,") + else + print(" Billboard = false,") + end + print(" Texture = \"" .. output[i].Renderable.Texture .. "\",") + print(" },") + print(" Transform = {") + print(" Translation = {") + print(" Type = \"" .. output[i].Transform.Translation.Type .. "\",") + print(" Body = \"" .. output[i].Transform.Translation.Body .. "\",") + print(" Observer = \"" .. output[i].Transform.Translation.Observer .. "\",") + print(" File = \"" .. output[i].Transform.Translation.File .. "\",") + print(" LineNum = " .. output[i].Transform.Translation.LineNum .. ",") + print(" },") + print(" Scale = {") + print(" Type = \"" .. output[i].Transform.Scale.Type .. "\",") + print(" Scale = " .. output[i].Transform.Scale.Scale .. ",") + print(" },") + print(" },") + elseif( type == "RenderableTrailOrbit" ) then + print(" Name = \"" .. output[i].Name .. "\",") + print(" Parent = \"" .. output[i].Parent .. "\",") + print(" Renderable = {") + print(" Type = \"" .. output[i].Renderable.Type .. "\",") + print(" Translation = {") + print(" Type = \"" .. output[i].Renderable.Translation.Type .. "\",") + print(" Body = \"" .. output[i].Renderable.Translation.Body .. "\",") + print(" Observer = \"" .. output[i].Renderable.Translation.Observer .. "\",") + print(" File = \"" .. output[i].Renderable.Translation.File .. "\",") + print(" LineNum = " .. output[i].Renderable.Translation.LineNum .. ",") + print(" },") + print(" Color = {" .. output[i].Renderable.Color[1] .. "," .. output[i].Renderable.Color[2] .. "," .. output[i].Renderable.Color[3] .. "},") + print(" Period = " .. output[i].Renderable.Period .. ",") + print(" Resolution = " .. output[i].Renderable.Resolution .. ",") + print(" },") + print(" GuiName = \"" .. output[i].GuiName .. "\",") + end + print(" },") +end +print("}") diff --git a/data/scene/satellites/satB.png b/data/scene/satellites/satB.png new file mode 100644 index 0000000000000000000000000000000000000000..5e3c14524cefe64f69f0554dcc0349c1a3213c03 GIT binary patch literal 4281 zcmaJ_XH*m07Cw^@q6tM*AX0=I1P#(VNRuKRBm_ihQ3MNBilDS0qT$k{UAcf#14KFq zQYBsy1g{N2I!0PVE)v3}NAtpux8A=uYt7nc_SyT}-|RCp>wJ@R*4~02C58e3@LO4$ z;Q@fSLkR5SpN?)$wy<}ry#qLfG*_k81 z!bC+7$9)ge6uBiUs0{?%_73$(llw%0u-@A2DdZ9NBXJ6rcQD*Stz8w%NZ~Q-OAQ)moSGHJW|B zuX_*e+?mkGlgm@|x*kwcnbqjlaRvsV5sz>~xXoA{?Z}>6x{SYX-SYg^eYZ%ZK$p>8 zxRkdP>-j_c*su%cPKXT-5iAgVwEl1_aLtIT`MX;gc_!Y6woipmf#)9UjV{DW z%%j660TX~BSu4o+&G=FplIA6Y)kTSbb;FOMbH|?ZwDPqc90k=!m~P_m4NwP*ijN?@ z6uL3!*aRw@E=%z$y|aqtuSd8N8q-xFeg4ku4Ge^?9LMt;XJ z9i9$T2HnZzmub%tMQQuHd0dhHi0960!T-P>^LQqcXOBvXkeG^ef8JP^6hM29g< zz)U7bjs&}cfdVGvj+*3)7SFvx7!N_UA|qj23FpKWfR7d1S$DDf%3wq@W|CiDNNAV; zKBDNVRrkJDfvvRV7_ajEr{cZN^xXYg5BStp&%q;Rk~&Y1A@ngqyL^d=A}=c=9(R8I zZw|XA;fM%W_wQt@mlvUL<}-ru36j*2RFe+=$jSUP1u$jJrqGse#n!P#_p?>7X<{g} z@$sbYlwQrJdeXOCu+UkXW*ubMaU7?+qig&-66e zLjxIGjPmSQe^yoUV=LTG9ZFcOq;W%596wX8wx@Jj2T`3$Ry{?Uk>!k#p4r8&>v&DS z>&rtFNhcW@eHmJ7?W@?CTa8}(5M2Qh?0z}Yg*)>d5>$Ep71nr5;4l>*OicoYG zIr1gWn3EZo)n5m@WgwL$LNYwY(T<-w8Y-VVwLSV2{Ci?mhVrk6d%fwa^$U>wF+2IH`-0obYT3aZ z#nd-<4~dXAvf@;k;+?&9A>!~~zhMoZf~ODJbx@T-ECJdjg_|qD)=;_ZWR^p0mX~vb z*p{7Piy}}z#({MxnGrXr@AF|n}XZ5-t?hwL9 zU`DuswGj>r6LfYu`e1gG~rnf??Cd(+& z`!$;@eEtUUn6s>O*nNqJ#gzF3*Yj7WL1vs`s^8B{!;Jyy&lrgwXA*}d9#hs-)8FPe zg){cF9~+LMECwW#3!Q7hoZYGEo6(f>F~wf_>1KtQ9Cy0u5gkviNl$4yYq6aW$~%(0|Hm+f=X{4=M01>a47=QAN8az*}oW;*!eLDy@Y{`5%X+ zDH<^LSVQLR1vXj7Wk`VjMM8>N(Vpk+vBVAai|1Z`n?8DKBEPyyQ6=(u|M^C(=^tBf|cXX9fu7f)rJ)ybE`t+$vU^{osku z0KZvzKCD{Z6Hlr3V@S|kW@ViRKHn?{{gGC~2ZdDqkPq-;ngsm1ZO(*~9aO7Az{`4k zw1!467nE6#Yb@z3VQOP#ohJ*}3_ z!TkgTU2PUS{FjfDFi?i9*MsK?2x7vGjO$-*Ymo(G(6?;v*xS>r?2{x-x7YMZPH0{Q zU>p&oy1esK0ye4l2`6px(KN)~6gm%0L(Tp+Jb*%zE<=DwS$%NbhayS3j0CihJwIy! zMlYq|yHd17Nj`fSK5r4ko=D4PwLy1qZx8Dw*HOHeb}FDUIhkx@*tB`sGqN{E3y$HMv=q{J^b{NgXN&UTW3 zH0Q|yspEzjvme<;ILbx3srNDG z&og99VI%x?+>J?$RZdu^?si2U4Cr6yJ{>!RKnG{wsbY_pjgfyg`;U<&E_FujD_&SJ zo%~W=gyhbX*^v1}7F&{o12mKU7*;uq8f{*zRi8v6b|A9+3Bj;)=Qy6tKE-8NI>opujRZyC%*VoKIy3e;x&gE zIC~;za7ta4Q!Q!y1Lgv)9I>H>DW#Bqs>i&ju8E0-f>4ahPH?X*pEYN( z10p~hI(S!wnk!P+wdU~bJybAl__ugM*`=|uKvu*MG^a$w1^49IBsM5u(^_`Z^=|*I z9ap-W(ni>~8J@|O+{<_6W%rNTz&FRp-zsHRB8$`6{41IpgT_-6*I4hVT&^T>vSos% z+EgCLU>Ssn21|^7#aO}{yp{Tm7y{A}5Snx-Es^_SmYJDz_awecj#Ex$K==#I2! zJ)4TYf};r0-=}2^sWU9hMwGfD!utx@y)8Ot@DBcqzO0BY_|@+`p1fLmp7@c@gF>9q zWzl74C|LV9YKM})PicC*J(O1t+l^mN`*TQmA}WJzu*BtlfEEWAmoTDwN0F-9!^i4^ z5YnRY!ZfJw?Dx?Dvd(CgXyM44h{s>HQqziuGQ^|)WE&`hwtf0&{TWy5fLq5H_Cae+ zQiaDTVM?hvcNx01gVpvQUB7NBcl|mOWA&PS`m<2j>de_mQiq$eZVtu+u>6)W(yxx4NR0&U>9hxVyNoH_I?UvjUea8?=7$ zKCKxVXSjjPk25Em#fC7A;@$L>2=H|1*~a(%-Gjp1H|`#Z1FK!%I-A(FFIpBWm(27n zvCQc2;QJ}&x^klgwWG+K5A^@$*bjSK%5p)=zlL9TtTq>~)lK&k;%^ti&*CaOg zrOFef>XopD3ghA@=Vse<&n|@wXAk_!>VDAgH46Jc;Q7p0BoRLAa&}7O;)>D6O0Yw; zht~>pa|Y(j#g4P(erL;}yGXgH* zTwy+0fShjH70V>Zu7|q?_ z&*Ee1Yra%%UH}(P!u&|uH;~x%UYuC|O@iB{P3&~FA1L`@VLY9ES)Ez1efFd_=t!>Dz3)VN zVZR@5rZ1?_6N6eJBI{MKkL#jX6OiqckOK4r{7@Im2~lSLBwrP&H z{-cNqKU+PtzwY}l%+&oVS}E)KI|55aAlcD%!nk~*dY0ZJl&Tb z6J6QUI^DXj^>J?(!v0Ws z(25j@6%twz6F?g~C%-sIl&lwakp5A!YW&%6nsNoI^gE3~)B>%Ku1UUD=0@Ld&>iUr zdW4Uc(-&Bgr|{j2^h2%UwK)|`%dp)CzYW(Slqu05@?d1GIxvMNIyt#beGUN zOppExlln^C3$X!P0rzEQ%1V8qvnyy*zyJ)$CLT=^-X0lX@3P$W|A1s@Dye;i_y4cV gHaMkhCA-d%G%?d06y*Jf`$qv-ncJJynh@{&2mD>OM*si- literal 0 HcmV?d00001 diff --git a/data/scene/satellites/satellites.mod b/data/scene/satellites/satellites.mod new file mode 100644 index 0000000000..812c213a5c --- /dev/null +++ b/data/scene/satellites/satellites.mod @@ -0,0 +1,194 @@ +DOWNLOAD = true + +function dirListing(dirname) + f = io.popen('ls ' .. dirname) + files = {} + for name in f:lines() do + table.insert(files, name) + end + return files +end + +function values(t) + local i = 0 + return function () i = i + 1; return t[i] end +end + +function trimString(s) + s = s:gsub("^%s*(.-)%s*$", "%1") + s = s:gsub("%s+", "_") + s = s:gsub("[%-()]", "") + return s +end + +function getPeriodFromFile(line2) + return tonumber(string.sub(line2, 53, 63)) +end + +function getNumLinesInFile(filename) + local ctr = 0 + for _ in io.lines(filename) do + ctr = ctr + 1 + end + return ctr +end + +function isEmpty(s) + return s == nil or s == '' +end + +--Check format of a set of 3 TLE file lines and return nonzero if there is a format error +function checkTleFileFormat(lineArr) + if isEmpty(lineArr[1]) or isEmpty(lineArr[2]) or isEmpty(lineArr[3]) then + return -1 + end + if string.sub(lineArr[2], 1, 2) ~= "1 " then + return -1 + end + if string.sub(lineArr[3], 1, 2) ~= "2 " then + return -1 + end + return 0 +end + + +function getSat(title, file, lineNum) + return { + Name = title, + Parent = "EarthInertial", + Renderable = { + Type = "RenderablePlane", + Size = {3.0, 4.0}, + Origin = "Center", + Body = "TLE", + Billboard = true, + Texture = "satB.png" + }, + Transform = { + Translation = { + Type = "TLETranslation", + Body = title, + Observer = "EarthInertial", + File = file, + LineNum = lineNum + }, + Scale = { + Type = "StaticScale", + Scale = 1, + } + } + } +end + +function getSatTrail(title, file, lineNum, per, color) + trailName = title .. "_trail" + + return { + Name = trailName, + Parent = "EarthInertial", + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "TLETranslation", + Body = title, + Observer = "EarthInertial", + File = file, + LineNum = lineNum + }, + Color = color, + Period = per, + Resolution = 160 + }, + GuiName = "/Satellites/" .. trailName + } +end + +function getTestPoint(parent, name, x, y, z) + return { + Name = name, + Parent = parent, + Renderable = { + Type = "RenderablePlane", + Size = {3.0, 4.0}, + Origin = "Center", + Body = "TLE", + Billboard = true, + Texture = "satB.png" + }, + Transform = { + Translation = { + Type = "StaticTranslation", + Position = {x, y, z}, + }, + Scale = { + Type = "StaticScale", + Scale = 1, + } + } + } +end + +------------------------------------------------------------- +--Name, URL, and color scheme for each satellite group +satelliteGroups = { + { title = "GPS", + url = "http://celestrak.com/NORAD/elements/gps-ops.txt", + trailColor = {0.9, 0.5, 0.0} + }, + { title = "SpaceStations", + url = "http://celestrak.com/NORAD/elements/stations.txt", + trailColor = {0.9, 0.0, 0.0} + }, + { title = "Geostationary", + url = "http://celestrak.com/NORAD/elements/geo.txt", + trailColor = {0.9, 0.9, 0.0} + }, +} + +modElements = {} +fileErr = "" +for sOrbit in values(satelliteGroups) do + filename = sOrbit.url:match("([^/]+)$") + filenameSansExt = filename:gsub(filename:match "(%.%w+)$", "") + sOrbit.path = "satellites/tle/" .. filename + + if DOWNLOAD then + openspace.downloadFile(sOrbit.url, sOrbit.path) + end + sOrbit.path = "../" .. sOrbit.path + pathFromScenegraphParent = "./" .. sOrbit.path + + line = {} + myfile = io.open(sOrbit.path, "r") + lines = getNumLinesInFile(sOrbit.path) + --now loop through the tle file and get each set of 3 lines + if myfile then + for n=1,lines,3 do + line[1] = myfile:read('*l') --title line + line[2] = myfile:read('*l') + line[3] = myfile:read('*l') + if( checkTleFileFormat(line) == 0 ) then + title = trimString(line[1]) + per = getPeriodFromFile(line[3]) + per = 1.0 / per * 2 --trail for 2x a single revolution + table.insert(modElements, getSat(filenameSansExt .. "_" .. title, pathFromScenegraphParent, n)) + table.insert(modElements, getSatTrail(filenameSansExt .. "_" .. title, + pathFromScenegraphParent, n, per, sOrbit.trailColor)) + else + fileErr = " TLE file syntax error on line " .. n .. ": " .. sOrbit.path + break + end + end + else + fileErr = " File not found: " .. sOrbit.path + break + end +end +assert(fileErr == "", fileErr) + + +if (fileErr == "") then + return modElements +else + return "Invalid file: " .. fileErr +end diff --git a/data/scene/satellites/tle/geo.txt b/data/scene/satellites/tle/geo.txt new file mode 100644 index 0000000000..f454cdd1d4 --- /dev/null +++ b/data/scene/satellites/tle/geo.txt @@ -0,0 +1,1326 @@ +TDRS 3 +1 19548U 88091B 17109.46103508 -.00000300 00000-0 00000-0 0 9992 +2 19548 14.4366 8.5664 0038366 314.4943 348.2278 1.00278758 91817 +SKYNET 4C +1 20776U 90079A 17109.37676898 .00000127 00000-0 00000-0 0 9999 +2 20776 13.8022 16.7071 0004129 33.0118 326.9789 1.00271853 97371 +TDRS 5 +1 21639U 91054B 17109.79822090 .00000088 00000-0 00000-0 0 9991 +2 21639 14.3398 22.0348 0025712 348.0351 317.8695 1.00281320 94167 +TDRS 6 +1 22314U 93003B 17109.45807795 -.00000291 00000-0 00000-0 0 9993 +2 22314 13.8633 24.9549 0006813 311.7448 350.0794 1.00268039 88820 +INTELSAT 701 (IS-701) +1 22871U 93066A 17109.44518047 -.00000221 00000-0 00000-0 0 9991 +2 22871 4.0859 67.3063 0004065 323.4869 307.7041 1.00271708 85868 +ASTRA 1D +1 23331U 94070A 17109.38111359 -.00000289 00000-0 00000-0 0 9991 +2 23331 7.4754 49.7042 0004041 326.3094 281.5525 1.00273534 82736 +BRASILSAT B2 +1 23536U 95016A 17109.17233304 -.00000281 00000-0 00000-0 0 9993 +2 23536 7.0987 51.5887 0002352 353.2158 156.6954 1.00270982 80761 +AMSC 1 +1 23553U 95019A 17108.82368405 -.00000116 00000-0 00000-0 0 9994 +2 23553 10.0105 40.4012 0004866 349.8728 10.0670 1.00272600 80621 +TDRS 7 +1 23613U 95035B 17109.74146499 -.00000199 00000-0 00000-0 0 9999 +2 23613 14.9526 15.7382 0031518 358.3734 185.4077 1.00278526 79707 +ECHOSTAR 1 +1 23754U 95073A 17109.43968494 -.00000248 00000-0 00000-0 0 9995 +2 23754 0.6886 90.3287 0002713 305.3278 253.1178 1.00272339 18868 +INMARSAT 3-F1 +1 23839U 96020A 17109.85049412 .00000003 00000-0 00000-0 0 9996 +2 23839 3.8757 67.7545 0006005 321.1232 189.8994 1.00271328 77079 +ASTRA 1F +1 23842U 96021A 17109.86091057 .00000130 00000-0 00000-0 0 9995 +2 23842 0.0454 335.3223 0003840 58.0482 169.0272 1.00274247 18808 +MSAT M1 +1 23846U 96022A 17109.85707654 -.00000085 00000-0 00000-0 0 9996 +2 23846 7.6659 49.2344 0005400 338.8807 21.0525 1.00272402 76893 +INMARSAT 3-F2 +1 24307U 96053A 17109.09942503 -.00000130 00000-0 00000-0 0 9994 +2 24307 2.5085 77.9756 0006616 293.5261 216.1694 1.00271468 75477 +AMC-1 (GE-1) +1 24315U 96054A 17109.02073214 .00000052 00000-0 00000-0 0 9993 +2 24315 1.4453 85.2854 0002702 307.9108 52.4265 1.00272622 12778 +AFRICASAT-2 (MEASAT-2) +1 24653U 96063B 17109.62867817 -.00000229 00000-0 00000-0 0 9991 +2 24653 7.3977 50.1225 0006753 195.7505 336.3446 1.00271035 74912 +EUTELSAT 48A +1 24665U 96067A 17109.79528758 .00000112 00000-0 00000-0 0 9994 +2 24665 6.2644 55.4863 0005290 327.9777 159.1470 1.00272514 75142 +INMARSAT 3-F3 +1 24674U 96070A 17109.55934831 .00000032 00000-0 00000-0 0 9996 +2 24674 3.3190 72.0293 0006158 317.0141 198.2475 1.00273297 74425 +AMC-2 (GE-2) +1 24713U 97002A 17109.43487562 -.00000215 00000-0 00000-0 0 9991 +2 24713 4.2292 66.2290 0005283 329.3197 243.8948 1.00271284 24778 +INTELSAT 26 (IS-26) +1 24732U 97007A 17109.85049412 .00000001 00000-0 00000-0 0 9993 +2 24732 7.3728 50.4423 0005446 0.6341 167.4543 1.00272490 39195 +GALAXY 25 (G-25) +1 24812U 97026A 17108.68375292 -.00000170 00000-0 00000-0 0 9999 +2 24812 0.0254 99.0059 0003618 294.8659 326.1560 1.00272434 72817 +ABS-3 +1 24901U 97042A 17109.82795720 -.00000197 00000-0 00000-0 0 9994 +2 24901 4.7842 63.5836 0008401 318.8832 209.1740 1.00274176 71986 +INTELSAT 5 (IS-5) +1 24916U 97046A 17109.18587367 -.00000146 00000-0 00000-0 0 9993 +2 24916 3.4334 71.3666 0003507 310.4218 49.5972 1.00272302 72073 +AMC-3 (GE-3) +1 24936U 97050A 17109.43866123 -.00000267 00000-0 00000-0 0 9992 +2 24936 0.2562 91.5364 0002773 304.6917 257.4246 1.00272299 18885 +NSS-5 +1 24957U 97053A 17109.86091057 .00000103 00000-0 00000-0 0 9999 +2 24957 3.7272 69.5661 0003844 325.1385 173.8467 1.00273806 71639 +ECHOSTAR 3 +1 25004U 97059A 17108.82026798 -.00000289 00000-0 00000-0 0 9990 +2 25004 2.0352 80.4323 0001581 345.7060 14.4861 1.00271741 71505 +JCSAT-1B +1 25067U 97075A 17109.70661117 -.00000210 00000-0 00000-0 0 9999 +2 25067 5.4605 59.2656 0004387 299.9248 253.1557 1.00273307 73810 +ASTRA 1G +1 25071U 97076A 17109.86091057 .00000101 00000-0 00000-0 0 9990 +2 25071 2.2044 78.5675 0003482 314.1769 176.4222 1.00270827 71015 +BRASILSAT B3 +1 25152U 98006A 17108.79091933 -.00000288 00000-0 00000-0 0 9995 +2 25152 3.9230 68.6320 0003061 319.4917 40.5071 1.00271783 9963 +INMARSAT 3-F5 +1 25153U 98006B 17109.35905175 -.00000293 00000-0 00000-0 0 9997 +2 25153 2.4594 74.2634 0005018 316.2192 252.4390 1.00270718 70330 +NSS-806 +1 25239U 98014A 17109.38817681 -.00000287 00000-0 00000-0 0 9991 +2 25239 0.0676 44.7475 0004496 346.2217 268.9453 1.00271303 70103 +CHINASAT 5A (ZX 5A) +1 25354U 98033A 17109.93330977 -.00000360 00000-0 00000-0 0 9991 +2 25354 1.1195 87.4116 0002824 249.3502 333.0094 1.00271724 73697 +THOR III +1 25358U 98035A 17109.59943801 -.00000046 00000-0 00000-0 0 9996 +2 25358 5.3275 59.4220 0002333 322.0900 37.8721 1.00273475 69301 +INTELSAT 805 (IS-805) +1 25371U 98037A 17109.56476479 -.00000039 00000-0 00000-0 0 9994 +2 25371 0.0552 81.1481 0003018 313.2477 185.7800 1.00272687 69001 +ASTRA 2A +1 25462U 98050A 17109.79707899 -.00000367 00000-0 00000-0 0 9992 +2 25462 0.0506 243.7651 0002414 147.3278 217.4480 1.00272536 12806 +AFRISTAR +1 25515U 98063A 17109.79457863 .00000119 00000-0 00000-0 0 9992 +2 25515 3.1895 69.8428 0004202 324.1197 121.1622 1.00273351 67402 +JCSAT-4A +1 25630U 99006A 17109.84563219 -.00000163 00000-0 00000-0 0 9997 +2 25630 2.1756 80.2784 0001874 315.9107 198.3180 1.00271902 17060 +SKYNET 4E +1 25639U 99009B 17108.01294515 .00000020 00000-0 00000-0 0 9998 +2 25639 10.0819 29.0659 0002679 356.8935 190.9802 1.00270583 17834 +ASIASAT 3S +1 25657U 99013A 17107.40683097 -.00000243 00000-0 00000-0 0 9990 +2 25657 2.3860 78.4929 0003383 306.5182 113.2092 1.00270446 66258 +NIMIQ 1 +1 25740U 99027A 17109.52928144 -.00000207 00000-0 00000-0 0 9998 +2 25740 0.0148 262.6109 0006118 126.2716 282.9891 1.00271762 65567 +ASTRA 1H +1 25785U 99033A 17109.79515799 .00000133 00000-0 00000-0 0 9998 +2 25785 3.7123 69.7226 0002879 318.8391 149.2716 1.00273831 17874 +TELKOM 1 +1 25880U 99042A 17109.82170495 -.00000353 00000-0 00000-0 0 9993 +2 25880 0.0400 110.4166 0001622 302.9461 198.6108 1.00272147 64810 +ABS-7 +1 25894U 99046A 17109.76854753 -.00000370 00000-0 00000-0 0 9990 +2 25894 0.0100 221.8421 0002488 186.6286 192.3438 1.00269076 63594 +ABS-6 +1 25924U 99053A 17108.98254232 -.00000127 00000-0 00000-0 0 9991 +2 25924 0.0384 81.9569 0002927 332.9838 305.0916 1.00273279 64323 +TELSTAR 12 (ORION 2) +1 25949U 99059A 17109.52494125 -.00000070 00000-0 00000-0 0 9999 +2 25949 0.8111 88.8760 0003061 306.1548 252.5735 1.00272242 63981 +AMC-4 (GE-4) +1 25954U 99060A 17108.61145333 -.00000281 00000-0 00000-0 0 9994 +2 25954 0.0649 79.9907 0002280 346.6647 293.3731 1.00272094 10188 +GALAXY 11 (G-11) +1 26038U 99071A 17109.63923093 .00000129 00000-0 00000-0 0 9990 +2 26038 0.0026 2.5462 0001355 340.9142 139.5067 1.00270945 63542 +HISPASAT 1C +1 26071U 00007A 17109.29726701 -.00000220 00000-0 00000-0 0 9990 +2 26071 0.4421 88.4506 0009320 303.0136 199.4140 1.00272624 14096 +SUPERBIRD-B2 +1 26095U 00012A 17109.80052440 -.00000101 00000-0 00000-0 0 9999 +2 26095 0.2773 94.9481 0003255 289.2871 273.9855 1.00272081 62884 +ASIASTAR +1 26107U 00016A 17109.78729904 -.00000340 00000-0 00000-0 0 9995 +2 26107 1.5529 81.9903 0004435 312.3735 202.1717 1.00272644 62385 +EUTELSAT 16C +1 26243U 00019A 17109.10015684 .00000086 00000-0 00000-0 0 9994 +2 26243 4.1563 66.6099 0002776 317.1438 234.1657 1.00271651 62237 +EUTELSAT 80A +1 26369U 00028A 17109.84563219 -.00000149 00000-0 00000-0 0 9997 +2 26369 0.8925 84.9449 0005357 343.0840 165.0478 1.00272070 61896 +TDRS 8 +1 26388U 00034A 17109.33220883 -.00000229 00000-0 00000-0 0 9995 +2 26388 7.3965 56.3283 0005354 255.1959 104.7099 1.00265879 61633 +ECHOSTAR 6 +1 26402U 00038A 17109.54389034 -.00000152 00000-0 00000-0 0 9998 +2 26402 4.0749 67.3876 0003545 322.0443 277.9953 1.00271890 61368 +INTELSAT 9 (IS-9) +1 26451U 00043A 17109.47822243 -.00000276 00000-0 00000-0 0 9991 +2 26451 3.4188 71.5854 0002852 320.7192 304.5359 1.00271946 61292 +BRASILSAT B4 +1 26469U 00046A 17108.91790864 -.00000176 00000-0 00000-0 0 9993 +2 26469 1.5387 85.3831 0003519 316.1537 44.1544 1.00272282 61413 +NILESAT 102 +1 26470U 00046B 17109.84911682 -.00000065 00000-0 00000-0 0 9998 +2 26470 1.5586 83.8345 0004571 303.0626 119.9165 1.00272465 61099 +ASTRA 2B +1 26494U 00054A 17109.79454052 .00000113 00000-0 00000-0 0 9993 +2 26494 2.0920 79.2060 0005340 324.6127 109.6767 1.00272153 13349 +AMC-7 (GE-7) +1 26495U 00054B 17108.79975778 .00000080 00000-0 00000-0 0 9999 +2 26495 0.0616 80.5828 0001259 259.2782 20.1388 1.00270838 60696 +NSS-11 (AAP-1) +1 26554U 00059A 17108.72090013 -.00000353 00000-0 00000-0 0 9997 +2 26554 0.0451 64.5425 0002377 356.1153 154.0906 1.00271371 7759 +N-SAT-110 (JCSAT-110) +1 26559U 00060A 17109.92620640 -.00000360 00000-0 00000-0 0 9990 +2 26559 0.0423 72.2814 0001389 21.9396 197.4928 1.00271713 7732 +AMC-6 (GE-6) +1 26580U 00067A 17109.32571233 -.00000281 00000-0 00000-0 0 9990 +2 26580 0.0453 59.9871 0001458 300.0146 257.8642 1.00272675 60422 +INTELSAT 12 (IS-12) +1 26590U 00068A 17109.86091057 .00000129 00000-0 00000-0 0 9992 +2 26590 0.3603 93.4381 0001859 282.3212 187.2842 1.00271321 18173 +INTELSAT 1R (IS-1R) +1 26608U 00072A 17109.64888602 .00000123 00000-0 00000-0 0 9997 +2 26608 0.1985 89.5020 0002519 220.3285 342.2731 1.00001276 7770 +ANIK F1 +1 26624U 00076A 17108.72312129 -.00000082 00000-0 00000-0 0 9998 +2 26624 0.0329 121.4486 0001707 320.4030 278.1724 1.00272679 9586 +ASTRA 2D +1 26638U 00081A 17109.45244360 .00000043 00000-0 00000-0 0 9997 +2 26638 3.5382 70.2996 0001895 310.9025 49.1246 1.00269565 19363 +AMC-8 (GE-8) +1 26639U 00081B 17109.66575950 .00000096 00000-0 00000-0 0 9991 +2 26639 0.0560 75.8639 0002916 324.0708 268.6731 1.00272105 59802 +SKYNET 4F +1 26695U 01005B 17109.15862542 -.00000250 00000-0 00000-0 0 9993 +2 26695 8.8321 37.0552 0004216 348.6438 204.8395 1.00269486 59329 +EUTELSAT 33C +1 26719U 01011A 17109.87063199 .00000147 00000-0 00000-0 0 9991 +2 26719 0.0686 12.8898 0005091 16.5455 165.2656 1.00275966 59005 +INTELSAT 10 (IS-10) +1 26766U 01019A 17109.86091057 .00000119 00000-0 00000-0 0 9993 +2 26766 1.3948 85.4036 0002391 289.9535 190.2135 1.00270276 12094 +INTELSAT 901 (IS-901) +1 26824U 01024A 17109.84336321 -.00000149 00000-0 00000-0 0 9992 +2 26824 0.0261 280.0596 0002831 114.8867 98.7920 1.00272393 58153 +ASTRA 2C +1 26853U 01025A 17109.89842194 .00000038 00000-0 00000-0 0 9996 +2 26853 0.2757 90.5540 0003028 300.1366 201.2142 1.00271942 11518 +ARTEMIS +1 26863U 01029A 17108.74833679 -.00000369 00000-0 00000-0 0 9990 +2 26863 12.6705 33.6757 0002710 24.5441 181.1801 1.00267824 58844 +INTELSAT 902 (IS-902) +1 26900U 01039A 17109.85049412 .00000024 00000-0 00000-0 0 9997 +2 26900 0.0207 123.4981 0002941 258.6277 194.1630 1.00271979 57225 +EUTELSAT 12 WEST B +1 26927U 01042A 17109.09950126 -.00000108 00000-0 00000-0 0 9993 +2 26927 0.0540 18.6027 0006151 4.9416 207.1825 1.00272329 56965 +DIRECTV 4S +1 26985U 01052A 17109.59659368 -.00000121 00000-0 00000-0 0 9992 +2 26985 0.0173 196.8244 0002186 206.8425 277.8074 1.00271771 56441 +INSAT-3C +1 27298U 02002A 17109.87176521 -.00000267 00000-0 00000-0 0 9993 +2 27298 0.5003 91.6589 0004933 233.5397 290.2973 1.00273754 55862 +ECHOSTAR 7 +1 27378U 02006A 17109.71466358 -.00000008 00000-0 00000-0 0 9992 +2 27378 0.0548 74.8635 0001555 283.1864 348.4514 1.00270570 55514 +INTELSAT 904 (IS-904) +1 27380U 02007A 17109.63923093 .00000127 00000-0 00000-0 0 9992 +2 27380 0.0404 99.7366 0003360 4.1943 19.2228 1.00279069 18224 +TDRS 9 +1 27389U 02011A 17109.32162528 -.00000104 00000-0 00000-0 0 9996 +2 27389 5.1301 79.8004 0020998 249.8573 341.4901 1.00273213 56894 +JCSAT 2A +1 27399U 02015A 17109.87141731 -.00000315 00000-0 00000-0 0 9998 +2 27399 0.3548 92.8407 0000493 181.3625 23.6921 1.00270828 55072 +ASTRA 3A +1 27400U 02015B 17108.74733222 -.00000286 00000-0 00000-0 0 9995 +2 27400 3.7011 69.0425 0002665 329.0947 30.9172 1.00268942 55178 +INTELSAT 903 (IS-903) +1 27403U 02016A 17109.43050628 -.00000246 00000-0 00000-0 0 9994 +2 27403 0.0138 258.2337 0003167 139.5278 290.4450 1.00271614 55097 +NSS-7 +1 27414U 02019A 17109.70994167 -.00000162 00000-0 00000-0 0 9991 +2 27414 1.7744 83.3135 0002842 313.9766 46.2757 1.00271193 55024 +DIRECTV 5 (TEMPO 1) +1 27426U 02023A 17108.73086731 -.00000064 00000-0 00000-0 0 9991 +2 27426 0.0174 266.3382 0003496 130.1742 323.5161 1.00271176 54752 +INTELSAT 905 (IS-905) +1 27438U 02027A 17109.84304013 -.00000192 00000-0 00000-0 0 9999 +2 27438 0.0135 247.4194 0002498 133.9617 105.7411 1.00271435 17830 +EXPRESS-A4 +1 27441U 02029A 17109.27555153 -.00000250 00000-0 00000-0 0 9990 +2 27441 5.9632 56.8825 0002023 16.9727 18.2654 1.00267462 54427 +GALAXY 3C (G-3C) +1 27445U 02030A 17108.68898528 -.00000159 00000-0 00000-0 0 9994 +2 27445 0.0191 284.8932 0001504 58.2763 16.8302 1.00271627 54401 +EUTELSAT 5 WEST A +1 27460U 02035A 17109.43703532 -.00000051 00000-0 00000-0 0 9991 +2 27460 0.0485 30.4144 0005369 358.3253 331.2953 1.00271966 54081 +N-STAR C +1 27461U 02035B 17109.75327161 -.00000314 00000-0 00000-0 0 9999 +2 27461 4.5246 65.1141 0003778 315.1078 234.9984 1.00271536 54116 +ECHOSTAR 8 +1 27501U 02039A 17109.28818986 -.00000250 00000-0 00000-0 0 9995 +2 27501 0.9663 88.6476 0003003 274.4750 231.3324 1.00272783 53720 +EUTELSAT 36 WEST A +1 27508U 02040A 17107.52824913 -.00000253 00000-0 00000-0 0 9999 +2 27508 0.0788 36.9108 0006573 344.5112 338.6092 1.00271702 53633 +METEOSAT-8 (MSG-1) +1 27509U 02040B 17109.89696630 .00000136 00000-0 00000-0 0 9994 +2 27509 4.7412 58.5517 0000716 163.2488 350.7710 1.00280418 53713 +INTELSAT 906 (IS-906) +1 27513U 02041A 17109.85049412 .00000006 00000-0 00000-0 0 9992 +2 27513 0.0246 261.5437 0002848 130.4092 186.4908 1.00271356 53426 +KODAMA (DRTS) +1 27516U 02042B 17108.79642807 -.00000244 00000-0 00000-0 0 9990 +2 27516 4.9371 62.3918 0003298 332.2488 189.8891 1.00269658 53490 +KALPANA-1 (METSAT 1) +1 27525U 02043A 17109.37368610 -.00000081 00000-0 00000-0 0 9992 +2 27525 6.2545 55.6080 0013939 237.1150 122.7165 1.00273039 53516 +HISPASAT 1D +1 27528U 02044A 17109.39356382 -.00000224 00000-0 00000-0 0 9990 +2 27528 0.0371 320.0927 0005078 59.4549 299.8001 1.00270661 53398 +TDRS 10 +1 27566U 02055A 17109.07101571 .00000075 00000-0 00000-0 0 9990 +2 27566 4.9345 58.6619 0010010 245.5996 114.2712 1.00268874 52685 +NSS-6 +1 27603U 02057A 17109.87176521 -.00000279 00000-0 00000-0 0 9996 +2 27603 0.0413 67.8725 0001723 296.7346 252.3915 1.00273439 52556 +NIMIQ 2 +1 27632U 02062A 17109.64448081 -.00000115 00000-0 00000-0 0 9991 +2 27632 1.8732 82.2184 0003990 251.5302 108.6754 0.99546813 52336 +INTELSAT 907 (IS-907) +1 27683U 03007A 17109.49926753 -.00000210 00000-0 00000-0 0 9993 +2 27683 0.0063 240.7075 0003065 158.7584 320.5619 1.00271958 51896 +GALAXY 12 (G-12) +1 27715U 03013B 17109.66402826 .00000050 00000-0 00000-0 0 9996 +2 27715 0.0478 86.1011 0001993 315.8430 276.0639 1.00273936 51455 +ASIASAT 4 +1 27718U 03014A 17109.27571116 -.00000368 00000-0 00000-0 0 9999 +2 27718 0.0556 98.2673 0000790 212.2328 118.4097 1.00269480 51370 +HELLAS-SAT 2 +1 27811U 03020A 17109.79503602 .00000144 00000-0 00000-0 0 9993 +2 27811 0.0125 212.9725 0003974 178.8493 141.4613 1.00273626 9310 +AMC-9 (GE-12) +1 27820U 03024A 17109.46737024 -.00000224 00000-0 00000-0 0 9998 +2 27820 0.0218 293.7748 0002764 83.8388 275.3891 1.00271813 50833 +THURAYA-2 +1 27825U 03026A 17109.79517323 .00000126 00000-0 00000-0 0 9999 +2 27825 4.8685 28.9069 0005038 348.5579 160.8904 1.00275241 50801 +OPTUS C1 +1 27831U 03028B 17109.78035437 -.00000155 00000-0 00000-0 0 9991 +2 27831 0.0507 133.4426 0002595 268.8651 242.7021 1.00272565 19517 +ECHOSTAR 12 (RAINBOW 1) +1 27852U 03033A 17109.46075083 -.00000290 00000-0 00000-0 0 9996 +2 27852 0.0382 63.8611 0001223 318.1922 290.3816 1.00270465 50423 +GALAXY 23 (G-23) +1 27854U 03034A 17109.64054391 .00000005 00000-0 00000-0 0 9991 +2 27854 0.0150 251.0578 0002912 134.7122 291.7534 1.00272107 50192 +EUTELSAT 33A +1 27948U 03043A 17109.79483020 .00000146 00000-0 00000-0 0 9992 +2 27948 2.2541 78.4922 0001717 242.0173 204.6018 1.00275799 11938 +GALAXY 13 (HORIZONS-1) +1 27954U 03044A 17109.48439302 .00000040 00000-0 00000-0 0 9993 +2 27954 0.0453 97.4231 0001056 288.3798 229.3282 1.00271259 49619 +ZHONGXING-20 +1 28082U 03052A 17109.86986843 -.00000331 00000-0 00000-0 0 9998 +2 28082 3.3906 71.5956 0004111 304.0462 248.9623 1.00274401 49211 +YAMAL 202 +1 28089U 03053A 17109.86091057 .00000112 00000-0 00000-0 0 9996 +2 28089 0.0554 83.4076 0003529 305.2504 178.3485 1.00271369 49131 +EXPRESS-AM22 (SESAT 2) +1 28134U 03060A 17109.83425608 -.00000145 00000-0 00000-0 0 9992 +2 28134 0.3278 90.4268 0000687 5.5471 132.5702 1.00271889 48730 +AMC-10 (GE-10) +1 28154U 04003A 17109.46557576 .00000080 00000-0 00000-0 0 9998 +2 28154 0.0231 283.7817 0002941 134.7830 181.7953 1.00273228 48388 +ABS-4 (MOBISAT-1) +1 28184U 04007A 17108.79562766 .00000033 00000-0 00000-0 0 9995 +2 28184 0.0252 265.3286 0001924 120.7856 168.3679 1.00270738 18783 +EUTELSAT 7A +1 28187U 04008A 17109.83313484 .00000040 00000-0 00000-0 0 9994 +2 28187 0.0698 23.2349 0003112 28.0538 103.7450 1.00272687 47843 +DIRECTV 7S +1 28238U 04016A 17109.70783875 -.00000007 00000-0 00000-0 0 9995 +2 28238 0.0349 29.0632 0003005 9.5876 305.0945 1.00272397 47521 +AMC-11 (GE-11) +1 28252U 04017A 17109.46930970 .00000061 00000-0 00000-0 0 9994 +2 28252 0.0398 48.4822 0002797 354.9918 202.2254 1.00272474 47154 +INTELSAT 10-02 +1 28358U 04022A 17109.84357525 -.00000019 00000-0 00000-0 0 9992 +2 28358 0.0110 181.1909 0000091 89.7002 239.9407 1.00271548 47086 +APSTAR 5 (TELSTAR 18) +1 28364U 04024A 17108.67767421 -.00000303 00000-0 00000-0 0 9997 +2 28364 0.0571 92.2449 0002968 301.6073 195.0706 1.00270267 47063 +ANIK F2 +1 28378U 04027A 17109.75490392 -.00000058 00000-0 00000-0 0 9992 +2 28378 0.0327 10.2643 0000174 94.3803 264.0852 1.00272731 46816 +AMAZONAS 1 +1 28393U 04031A 17109.09889142 -.00000253 00000-0 00000-0 0 9993 +2 28393 1.6288 83.9426 0004611 316.5274 166.3344 1.00270901 46528 +AMC-15 +1 28446U 04041A 17109.53001451 -.00000096 00000-0 00000-0 0 9996 +2 28446 0.0163 82.5996 0002548 331.7430 239.2279 1.00270612 45849 +AMC-16 +1 28472U 04048A 17109.28730701 -.00000214 00000-0 00000-0 0 9993 +2 28472 0.0471 59.9322 0002824 346.8967 179.1812 1.00272778 45211 +NSS-10 (AMC-12) +1 28526U 05003A 17108.32271427 -.00000258 00000-0 00000-0 0 9992 +2 28526 0.0290 15.7760 0003009 25.7409 243.8406 1.00272548 44757 +XTAR-EUR +1 28542U 05005A 17108.34551944 .00000143 00000-0 00000-0 0 9991 +2 28542 0.0391 71.8345 0003282 317.8171 330.3713 1.00276151 44626 +XM-3 (RHYTHM) +1 28626U 05008A 17109.28605345 -.00000213 00000-0 00000-0 0 9995 +2 28626 0.0166 47.5910 0000189 341.0688 196.7839 1.00268725 9095 +INMARSAT 4-F1 +1 28628U 05009A 17109.05582249 -.00000267 00000-0 00000-0 0 9999 +2 28628 2.8685 11.1659 0003296 29.9529 329.8263 1.00272220 44126 +APSTAR 6 +1 28638U 05012A 17109.93487365 -.00000327 00000-0 00000-0 0 9991 +2 28638 0.0499 68.4318 0002249 335.2848 275.0303 1.00269643 68860 +SPACEWAY 1 +1 28644U 05015A 17109.62982047 -.00000110 00000-0 00000-0 0 9994 +2 28644 0.0049 159.3887 0000185 275.0996 257.2391 1.00272361 43965 +DIRECTV 8 +1 28659U 05019A 17108.70523236 -.00000123 00000-0 00000-0 0 9997 +2 28659 0.0129 280.9460 0003657 119.7236 319.3625 1.00272462 43597 +GALAXY 28 (G-28) +1 28702U 05022A 17109.42243941 -.00000193 00000-0 00000-0 0 9999 +2 28702 0.0122 204.0909 0002026 199.7705 226.9152 1.00268822 18564 +EXPRESS-AM3 +1 28707U 05023A 17109.62966170 -.00000330 00000-0 00000-0 0 9996 +2 28707 0.0092 329.2575 0001659 83.3644 124.9591 1.00270309 43302 +THAICOM 4 +1 28786U 05028A 17109.59563442 -.00000371 00000-0 00000-0 0 9994 +2 28786 0.0118 230.3243 0002092 165.6598 145.8354 1.00268640 18739 +GALAXY 14 (G-14) +1 28790U 05030A 17109.48875712 .00000028 00000-0 00000-0 0 9994 +2 28790 0.0384 74.1639 0002401 315.5495 229.0270 1.00273948 42756 +ANIK F1R +1 28868U 05036A 17109.52684413 -.00000082 00000-0 00000-0 0 9998 +2 28868 0.0386 63.6774 0003129 327.7708 258.7292 1.00272492 42607 +GALAXY 15 (G-15) +1 28884U 05041A 17109.46769616 .00000071 00000-0 00000-0 0 9991 +2 28884 0.0384 87.3342 0001713 311.3453 204.4300 1.00273785 42200 +SYRACUSE 3A +1 28885U 05041B 17109.86091057 .00000120 00000-0 00000-0 0 9998 +2 28885 0.0222 285.3830 0002879 108.2610 171.4361 1.00275192 42211 +INMARSAT 4-F2 +1 28899U 05044A 17109.27600366 .00000004 00000-0 00000-0 0 9991 +2 28899 2.5627 11.0679 0002772 32.6957 327.0524 1.00270578 41978 +TELKOM 2 +1 28902U 05046A 17109.76854753 -.00000371 00000-0 00000-0 0 9991 +2 28902 0.0276 142.9573 0000776 277.6646 182.0405 1.00269663 41690 +SPACEWAY 2 +1 28903U 05046B 17109.53975024 -.00000134 00000-0 00000-0 0 9999 +2 28903 0.0333 75.6302 0000437 32.3955 195.0431 1.00271564 41944 +INSAT-4A +1 28911U 05049A 17109.19304538 -.00000173 00000-0 00000-0 0 9992 +2 28911 0.0896 93.9505 0003716 237.1802 28.8541 1.00271991 12176 +METEOSAT-9 (MSG-2) +1 28912U 05049B 17109.19149598 .00000055 00000-0 00000-0 0 9994 +2 28912 2.0885 70.7642 0000522 79.5257 135.4674 1.00268082 41526 +EUTELSAT 172A (GE-23) +1 28924U 05052A 17109.64414611 -.00000014 00000-0 00000-0 0 9998 +2 28924 0.0706 355.4632 0005866 37.6286 218.7303 1.00273847 18808 +ECHOSTAR 10 +1 28935U 06003A 17109.52284194 -.00000064 00000-0 00000-0 0 9990 +2 28935 0.0546 73.5972 0001864 341.9720 230.2926 1.00273462 40937 +HIMAWARI-7 (MTSAT-2) +1 28937U 06004A 17109.87357476 -.00000251 00000-0 00000-0 0 9993 +2 28937 0.0536 94.0981 0003570 289.3209 284.2189 1.00269818 40939 +SPAINSAT +1 28945U 06007A 17108.50890032 -.00000224 00000-0 00000-0 0 9994 +2 28945 0.0281 235.8195 0002521 155.2004 328.9996 1.00271702 40674 +EUTELSAT HOT BIRD 13E +1 28946U 06007B 17109.38717225 .00000079 00000-0 00000-0 0 9991 +2 28946 0.0589 259.6256 0003248 180.9284 279.4880 1.00272688 40755 +JCSAT-5A +1 29045U 06010A 17109.79755922 -.00000336 00000-0 00000-0 0 9994 +2 29045 0.0132 265.3814 0002096 155.2969 206.5745 1.00271513 40239 +ASTRA 1KR +1 29055U 06012A 17109.87549389 .00000112 00000-0 00000-0 0 9995 +2 29055 0.0648 276.0152 0000832 45.1147 221.4152 1.00274823 12185 +GOES 13 +1 29155U 06018A 17108.63348614 -.00000258 00000-0 00000-0 0 9995 +2 29155 0.3062 272.8347 0005138 151.4577 295.7654 1.00279229 9835 +EUTELSAT 113 WEST A +1 29162U 06020A 17108.73887038 -.00000045 00000-0 00000-0 0 9999 +2 29162 0.0192 277.4806 0002853 112.3865 330.1540 1.00272071 39910 +THAICOM 5 +1 29163U 06020B 17109.91575226 -.00000130 00000-0 00000-0 0 9999 +2 29163 0.0113 266.6952 0003840 104.2002 245.4828 1.00272591 39954 +GALAXY 16 (G-16) +1 29236U 06023A 17109.53974882 -.00000135 00000-0 00000-0 0 9997 +2 29236 0.0088 209.0266 0002818 192.6949 261.4131 1.00272563 39718 +EUTELSAT HOT BIRD 13B +1 29270U 06032A 17109.87549389 .00000078 00000-0 00000-0 0 9997 +2 29270 0.0863 324.0839 0005219 54.6606 157.5753 1.00272770 13780 +JCSAT-3A +1 29272U 06033A 17109.79746014 -.00000354 00000-0 00000-0 0 9993 +2 29272 0.0178 233.9351 0001863 185.1999 204.0397 1.00268201 14196 +SYRACUSE 3B +1 29273U 06033B 17109.85243352 -.00000052 00000-0 00000-0 0 9993 +2 29273 0.0016 117.1534 0004854 262.8406 129.8176 1.00272026 39177 +KOREASAT 5 (MUGUNGWHA 5) +1 29349U 06034A 17109.79706375 -.00000367 00000-0 00000-0 0 9999 +2 29349 0.0171 262.2876 0001197 206.2811 139.5217 1.00270677 7778 +ZHONGXING-22A +1 29398U 06038A 17109.94158009 -.00000324 00000-0 00000-0 0 9992 +2 29398 5.6881 58.1086 0002029 261.7195 329.1449 1.00272905 38866 +DIRECTV 9S +1 29494U 06043A 17109.59659368 -.00000122 00000-0 00000-0 0 9996 +2 29494 0.0235 133.4313 0003478 263.5751 284.5543 1.00272093 38555 +OPTUS D1 +1 29495U 06043B 17109.78035437 -.00000119 00000-0 00000-0 0 9999 +2 29495 0.0389 65.8650 0003495 327.4598 255.6741 1.00272455 38579 +XM-4 (BLUES) +1 29520U 06049A 17109.73126757 -.00000031 00000-0 00000-0 0 9998 +2 29520 0.0175 50.0377 0000165 41.1512 264.8500 1.00272409 17931 +BADR-4 +1 29526U 06051A 17109.10043128 .00000136 00000-0 00000-0 0 9993 +2 29526 0.0617 320.4353 0005022 40.9358 268.1979 1.00276660 38335 +FENGYUN 2D +1 29640U 06053A 17109.93315478 -.00000365 00000-0 10000-3 0 9992 +2 29640 4.3387 64.6675 0004916 340.2554 262.8725 1.00281669 38012 +WILDBLUE-1 +1 29643U 06054A 17109.74856689 -.00000057 00000-0 00000-0 0 9993 +2 29643 0.0444 100.1325 0001842 303.9370 322.2794 1.00272752 38006 +AMC-18 +1 29644U 06054B 17109.53001424 -.00000097 00000-0 00000-0 0 9994 +2 29644 0.0146 49.5256 0002597 345.3404 258.8092 1.00271942 38006 +MEASAT-3 +1 29648U 06056A 17109.82485502 -.00000250 00000-0 00000-0 0 9996 +2 29648 0.0479 125.6704 0002875 328.1086 142.7705 1.00269997 16912 +INSAT-4B +1 30793U 07007A 17109.87176521 -.00000266 00000-0 00000-0 0 9996 +2 30793 0.1032 95.6431 0006761 328.5772 191.2662 1.00270562 8662 +SKYNET 5A +1 30794U 07007B 17109.87176521 -.00000279 00000-0 00000-0 0 9991 +2 30794 0.0701 1.1274 0003350 33.5560 222.4814 1.00269254 37159 +ANIK F3 +1 31102U 07009A 17109.92227799 -.00000009 00000-0 00000-0 0 9998 +2 31102 0.0160 222.4812 0002235 174.9197 24.1145 1.00269555 13012 +ASTRA 1L +1 31306U 07016A 17109.87549389 .00000112 00000-0 00000-0 0 9992 +2 31306 0.0802 300.7492 0003627 55.5715 186.2058 1.00274256 11533 +GALAXY 17 (G-17) +1 31307U 07016B 17109.53587587 -.00000182 00000-0 00000-0 0 9996 +2 31307 0.0392 33.9344 0003513 8.9980 266.8033 1.00270261 36525 +ZHONGXING-6B +1 31800U 07031A 17109.79713234 -.00000370 00000-0 00000-0 0 9998 +2 31800 0.0131 249.1006 0002398 139.7626 221.7240 1.00270095 35894 +DIRECTV 10 +1 31862U 07032A 17108.71065751 -.00000111 00000-0 00000-0 0 9995 +2 31862 0.0365 34.4633 0000151 39.8688 285.6743 1.00271941 12089 +SPACEWAY 3 +1 32018U 07036A 17109.40753358 -.00000160 00000-0 00000-0 0 9991 +2 32018 0.0098 99.7378 0000110 334.5356 185.1857 1.00272613 35574 +BSAT-3A +1 32019U 07036B 17109.11866778 -.00000359 00000-0 00000-0 0 9991 +2 32019 0.0456 154.5305 0000478 83.1873 122.2826 1.00272208 16950 +INSAT-4CR +1 32050U 07037A 17109.86091057 .00000117 00000-0 00000-0 0 9990 +2 32050 0.0660 93.9132 0003220 286.0159 185.9821 1.00270887 17857 +OPTUS D2 +1 32252U 07044A 17109.87340333 -.00000192 00000-0 00000-0 0 9991 +2 32252 0.0147 192.5936 0003662 203.3350 278.6486 1.00270752 34895 +INTELSAT 11 (IS-11) +1 32253U 07044B 17109.47116498 -.00000277 00000-0 00000-0 0 9995 +2 32253 0.0142 198.5042 0001905 211.1170 284.7663 1.00271114 34977 +STAR ONE C1 +1 32293U 07056A 17108.60588995 -.00000285 00000-0 00000-0 0 9990 +2 32293 0.0361 68.8879 0002906 338.6367 312.5045 1.00271618 18230 +SKYNET 5B +1 32294U 07056B 17109.87063199 .00000134 00000-0 00000-0 0 9997 +2 32294 0.0726 346.6530 0003739 49.7473 150.3091 1.00276152 34673 +ASTRA 4A (SIRIUS 4) +1 32299U 07057A 17109.95935472 .00000024 00000-0 00000-0 0 9992 +2 32299 0.0618 74.8891 0002823 318.7908 164.7363 1.00272121 18162 +HORIZONS-2 +1 32388U 07063B 17109.84563219 -.00000191 00000-0 00000-0 0 9998 +2 32388 0.0139 286.0592 0003273 110.1844 201.1581 1.00270534 34316 +THURAYA-3 +1 32404U 08001A 17109.80549667 -.00000311 00000-0 00000-0 0 9991 +2 32404 4.0825 353.1399 0004631 32.5027 210.9089 1.00270104 33976 +EXPRESS-AM33 +1 32478U 08003A 17109.84077001 -.00000289 00000-0 00000-0 0 9990 +2 32478 0.0152 301.6644 0001053 137.1186 168.4942 1.00270167 34076 +THOR 5 +1 32487U 08006A 17109.84357525 -.00000017 00000-0 00000-0 0 9994 +2 32487 0.0100 224.3860 0002686 173.0011 113.6769 1.00272716 33631 +KIZUNA (WINDS) +1 32500U 08007A 17109.80034125 -.00000267 00000-0 00000-0 0 9992 +2 32500 0.7105 90.5243 0002802 311.4971 237.1260 1.00273000 33354 +AMC-14 +1 32708U 08011A 17109.00940753 .00000101 00000-0 00000-0 0 9998 +2 32708 19.0110 63.7353 0041194 353.4410 171.4592 1.00272819 34602 +DIRECTV 11 +1 32729U 08013A 17109.59358875 -.00000134 00000-0 00000-0 0 9992 +2 32729 0.0382 56.0864 0000304 59.8688 206.4364 1.00272124 12061 +ICO G1 +1 32763U 08016A 17109.46311039 -.00000181 00000-0 00000-0 0 9992 +2 32763 3.8629 354.2733 0003193 34.8018 252.5437 1.00272162 33036 +VINASAT-1 +1 32767U 08018A 17108.06029192 -.00000337 00000-0 00000-0 0 9992 +2 32767 0.0428 64.1353 0001962 353.4287 302.4590 1.00271670 33040 +STAR ONE C2 +1 32768U 08018B 17108.61978712 -.00000273 00000-0 00000-0 0 9994 +2 32768 0.0454 131.1825 0003418 308.8962 279.9645 1.00271304 32997 +TIANLIAN 1-01 +1 32779U 08019A 17109.94017743 -.00000145 00000-0 10000-3 0 9994 +2 32779 2.6814 76.3679 0035007 234.3891 316.0256 1.00272939 32926 +AMOS-3 +1 32794U 08022A 17109.09970708 -.00000043 00000-0 00000-0 0 9993 +2 32794 0.0595 104.8299 0001689 273.7177 220.6565 1.00274012 32892 +GALAXY 18 (G-18) +1 32951U 08024A 17108.76661383 .00000017 00000-0 00000-0 0 9999 +2 32951 0.0196 250.6568 0003081 141.7617 327.6053 1.00272266 12352 +CHINASAT 9 (ZX 9) +1 33051U 08028A 17109.93891748 -.00000256 00000-0 00000-0 0 9991 +2 33051 0.0035 93.5519 0004154 291.3009 253.5683 1.00270607 32462 +SKYNET 5C +1 33055U 08030A 17109.84336321 -.00000147 00000-0 00000-0 0 9998 +2 33055 0.0642 16.5151 0003689 30.9862 86.4341 1.00272518 32426 +TURKSAT 3A +1 33056U 08030B 17109.79511987 .00000138 00000-0 00000-0 0 9995 +2 33056 0.0739 86.4901 0004970 315.6520 134.1612 1.00271757 18814 +INTELSAT 25 (IS-25) +1 33153U 08034A 17109.51030431 -.00000232 00000-0 00000-0 0 9993 +2 33153 0.0221 260.1104 0002454 125.8941 334.0133 1.00272750 32096 +BADR-6 +1 33154U 08034B 17109.87063199 .00000136 00000-0 00000-0 0 9992 +2 33154 0.0621 44.7690 0005842 358.1876 144.6091 1.00271980 32215 +ECHOSTAR 11 +1 33207U 08035A 17108.73053534 -.00000065 00000-0 00000-0 0 9990 +2 33207 0.0397 67.8246 0003497 338.4058 313.8032 1.00272857 32101 +SUPERBIRD-C2 +1 33274U 08038A 17109.87357476 -.00000259 00000-0 00000-0 0 9990 +2 33274 0.0175 254.8108 0001102 148.1655 263.6446 1.00272781 31830 +AMC-21 +1 33275U 08038B 17109.48875500 .00000028 00000-0 00000-0 0 9994 +2 33275 0.0597 72.0698 0002853 336.6617 210.0961 1.00272871 31949 +INMARSAT 4-F3 +1 33278U 08039A 17109.54169668 -.00000145 00000-0 00000-0 0 9997 +2 33278 3.0225 0.8885 0002543 31.1201 272.8375 1.00270930 13031 +NIMIQ 4 +1 33373U 08044A 17109.46418286 -.00000228 00000-0 00000-0 0 9995 +2 33373 0.0127 253.3092 0002498 126.3359 273.2011 1.00272436 31282 +GALAXY 19 (G-19) +1 33376U 08045A 17108.69456288 -.00000147 00000-0 00000-0 0 9997 +2 33376 0.0180 201.4039 0003192 201.2704 317.3551 1.00271627 31402 +VENESAT-1 +1 33414U 08055A 17109.29742709 -.00000246 00000-0 00000-0 0 9994 +2 33414 0.0564 65.0437 0001550 335.6881 195.9200 1.00271731 31138 +ASTRA 1M +1 33436U 08057A 17109.79453292 .00000111 00000-0 00000-0 0 9991 +2 33436 0.0161 246.8605 0003173 199.6942 66.7212 1.00271822 12206 +CIEL-2 +1 33453U 08063A 17109.66402826 .00000050 00000-0 00000-0 0 9992 +2 33453 0.0116 44.2125 0002959 349.6556 284.2771 1.00272823 30615 +EUTELSAT HOT BIRD 13C +1 33459U 08065A 17109.38720225 .00000079 00000-0 00000-0 0 9996 +2 33459 0.0561 323.4386 0005095 90.1267 306.4869 1.00272815 13838 +EUTELSAT 48D +1 33460U 08065B 17109.86091057 .00000116 00000-0 00000-0 0 9997 +2 33460 0.0572 41.5451 0001890 7.3274 157.2778 1.00272378 30485 +FENGYUN 2E +1 33463U 08066A 17109.82749177 -.00000213 00000-0 00000-0 0 9999 +2 33463 2.0739 66.6329 0003551 221.5686 305.0095 1.00271621 30542 +EXPRESS-AM44 +1 33595U 09007A 17109.33478159 -.00000097 00000-0 00000-0 0 9996 +2 33595 0.0134 304.5978 0001027 164.3620 208.1833 1.00272382 30006 +NSS-9 +1 33749U 09008A 17109.73882491 .00000064 00000-0 00000-0 0 9993 +2 33749 0.0358 28.5591 0002035 359.3335 269.1842 1.00273094 30017 +EUTELSAT 33E +1 33750U 09008B 17109.01307773 .00000147 00000-0 00000-0 0 9993 +2 33750 0.0135 26.4820 0001679 21.3926 197.2626 1.00274623 30042 +TELSTAR 11N +1 34111U 09009A 17109.45534944 -.00000259 00000-0 00000-0 0 9991 +2 34111 0.0131 205.2854 0002403 177.1310 311.6896 1.00268981 29866 +EUTELSAT 10A +1 34710U 09016A 17109.70154076 .00000061 00000-0 00000-0 0 9996 +2 34710 0.0698 355.3875 0004856 30.8383 84.3356 1.00275764 7710 +SES-7 (PROTOSTAR 2) +1 34941U 09027A 17109.79693414 -.00000353 00000-0 00000-0 0 9992 +2 34941 0.0705 80.2056 0001202 221.3619 301.6514 1.00270190 29095 +MEASAT-3A +1 35362U 09032A 17109.16953314 -.00000250 00000-0 00000-0 0 9991 +2 35362 0.0280 197.3379 0000312 225.1106 297.5598 1.00272517 28698 +GOES 14 +1 35491U 09033A 17108.71406314 -.00000103 00000-0 00000-0 0 9995 +2 35491 0.1495 104.6482 0004650 130.2456 125.0674 1.00271916 28613 +SIRIUS FM-5 +1 35493U 09034A 17109.52928144 -.00000208 00000-0 00000-0 0 9994 +2 35493 0.0135 239.3975 0000848 142.8224 289.9841 1.00268061 13195 +TERRESTAR-1 +1 35496U 09035A 17109.68338181 -.00000066 00000-0 00000-0 0 9993 +2 35496 2.9409 343.2569 0002896 46.8937 312.8199 1.00272222 28637 +ASIASAT 5 +1 35696U 09042A 17109.93537084 -.00000316 00000-0 00000-0 0 9992 +2 35696 0.0579 95.4909 0001526 265.5110 284.4445 1.00270557 28123 +JCSAT-RA (JCSAT-12) +1 35755U 09044A 17109.06865655 -.00000354 00000-0 00000-0 0 9994 +2 35755 0.0679 62.3793 0001075 1.8255 295.8113 1.00271686 28070 +OPTUS D3 +1 35756U 09044B 17109.68775817 -.00000156 00000-0 00000-0 0 9993 +2 35756 0.0198 30.5105 0004173 356.3031 224.7639 1.00269234 28084 +PALAPA D +1 35812U 09046A 17109.11021490 -.00000366 00000-0 00000-0 0 9990 +2 35812 0.0127 110.2739 0002700 328.6549 281.1065 1.00270819 28135 +NIMIQ 5 +1 35873U 09050A 17109.46471139 -.00000265 00000-0 00000-0 0 9997 +2 35873 0.0186 127.8859 0002202 272.6371 261.8144 1.00271105 27818 +AMAZONAS 2 +1 35942U 09054A 17109.46075057 -.00000290 00000-0 00000-0 0 9995 +2 35942 0.0406 125.2718 0003417 314.6649 232.6780 1.00270146 27647 +COMSATBW-1 +1 35943U 09054B 17109.85049412 .00000015 00000-0 00000-0 0 9999 +2 35943 0.0725 88.4800 0002890 319.0195 169.8273 1.00274343 27712 +NSS-12 +1 36032U 09058A 17109.26519408 .00000063 00000-0 00000-0 0 9998 +2 36032 0.0153 85.3786 0002693 310.2156 324.4289 1.00272724 27398 +THOR 6 +1 36033U 09058B 17109.84357525 -.00000018 00000-0 00000-0 0 9994 +2 36033 0.0338 116.9640 0002031 297.2204 96.7807 1.00272077 27428 +INTELSAT 14 (IS-14) +1 36097U 09064A 17108.55049208 -.00000282 00000-0 00000-0 0 9997 +2 36097 0.0142 228.2092 0002443 161.3500 330.4546 1.00271068 27153 +EUTELSAT 36B +1 36101U 09065A 17109.79495979 .00000147 00000-0 00000-0 0 9990 +2 36101 0.0706 354.6828 0004733 45.6029 129.9147 1.00275688 27183 +INTELSAT 15 (IS-15) +1 36106U 09067A 17109.84563219 -.00000193 00000-0 00000-0 0 9998 +2 36106 0.0229 65.0036 0002009 328.0303 204.6632 1.00267015 27050 +DIRECTV 12 +1 36131U 09075A 17109.53266096 -.00000111 00000-0 00000-0 0 9994 +2 36131 0.0098 215.7537 0000482 195.2069 245.8201 1.00272300 13055 +BEIDOU G1 +1 36287U 10001A 17109.80396529 -.00000294 00000-0 00000-0 0 9994 +2 36287 1.5014 356.3553 0001843 133.5478 147.5544 1.00266935 26624 +RADUGA-1M 2 +1 36358U 10002A 17109.74146499 -.00000192 00000-0 00000-0 0 9993 +2 36358 0.0258 255.8745 0002954 181.3783 122.7018 1.00271726 26464 +SDO +1 36395U 10005A 17109.59659368 -.00000050 00000-0 00000-0 0 9997 +2 36395 28.6969 141.4739 0000909 180.0516 359.3382 1.00274604 26517 +INTELSAT 16 (IS-16) +1 36397U 10006A 17109.34395734 -.00000293 00000-0 00000-0 0 9996 +2 36397 0.0499 77.8533 0001720 325.7835 229.7205 1.00271029 26320 +GOES 15 +1 36411U 10008A 17108.80111742 .00000082 00000-0 00000-0 0 9995 +2 36411 0.0845 107.5451 0002196 40.7905 211.6823 1.00271261 26135 +ECHOSTAR 14 +1 36499U 10010A 17109.71162832 -.00000008 00000-0 00000-0 0 9990 +2 36499 0.0132 237.5525 0002726 149.0214 318.7152 1.00272472 13035 +SES-1 +1 36516U 10016A 17109.59659368 -.00000123 00000-0 00000-0 0 9995 +2 36516 0.0562 71.6275 0002616 328.5076 281.5327 1.00272043 25587 +ASTRA 3B +1 36581U 10021A 17109.87063199 .00000128 00000-0 00000-0 0 9999 +2 36581 0.0480 20.8086 0003000 0.4031 163.8492 1.00271018 25338 +COMSATBW-2 +1 36582U 10021B 17109.87549389 .00000080 00000-0 00000-0 0 9997 +2 36582 0.0248 272.1949 0002509 141.3746 122.9332 1.00273454 25438 +BEIDOU G3 +1 36590U 10024A 17109.81804083 -.00000362 00000-0 00000-0 0 9992 +2 36590 1.5460 35.8006 0005170 317.5997 259.7029 1.00268954 25238 +BADR-5 +1 36592U 10025A 17109.87063199 .00000136 00000-0 00000-0 0 9994 +2 36592 0.0084 199.0521 0001284 219.6189 128.8932 1.00271675 19672 +COMS 1 +1 36744U 10032A 17109.79746014 -.00000352 00000-0 00000-0 0 9997 +2 36744 0.0128 296.6078 0001143 114.8177 211.9829 1.00272096 17549 +ARABSAT-5A +1 36745U 10032B 17109.01507715 .00000145 00000-0 00000-0 0 9995 +2 36745 0.0588 27.1817 0003181 358.4253 217.6208 1.00274332 25079 +ECHOSTAR 15 +1 36792U 10034A 17109.46845527 -.00000290 00000-0 00000-0 0 9996 +2 36792 0.0567 72.1387 0002685 341.0816 261.5451 1.00271876 24843 +NILESAT 201 +1 36830U 10037A 17109.84516125 -.00000066 00000-0 00000-0 0 9994 +2 36830 0.0464 168.5990 0005942 238.0145 98.7804 1.00273128 24744 +RASCOM-QAF 1R +1 36831U 10037B 17108.41786415 .00000010 00000-0 00000-0 0 9996 +2 36831 0.0201 102.7993 0004916 279.9705 337.2565 1.00272628 24753 +CHINASAT 6A (ZX 6A) +1 37150U 10042A 17109.93330977 -.00000362 00000-0 00000-0 0 9994 +2 37150 0.0339 148.1711 0000865 5.2443 155.8482 1.00269088 24354 +QZS-1 (MICHIBIKI) +1 37158U 10045A 17106.42285458 -.00000167 00000-0 00000-0 0 9992 +2 37158 40.8146 160.2213 0750190 269.8852 60.8395 1.00298496 24136 +XM-5 +1 37185U 10053A 17109.28730701 -.00000213 00000-0 00000-0 0 9996 +2 37185 0.0141 218.6640 0000712 157.1236 210.0100 1.00268489 23944 +BSAT-3B +1 37207U 10056B 17109.82409681 -.00000359 00000-0 00000-0 0 9995 +2 37207 0.0457 359.1733 0003651 352.5047 262.9732 1.00270791 18714 +BEIDOU G4 +1 37210U 10057A 17109.73863873 -.00000119 00000-0 00000-0 0 9991 +2 37210 0.9518 53.7889 0003556 171.8932 48.2646 1.00272575 23743 +SKYTERRA 1 +1 37218U 10061A 17108.62239055 -.00000128 00000-0 00000-0 0 9990 +2 37218 3.2972 329.9464 0002278 140.2680 219.4488 1.00272470 23658 +ZHONGXING-20A +1 37234U 10064A 17109.87157751 -.00000346 00000-0 00000-0 0 9993 +2 37234 0.0460 106.1696 0005375 277.6857 268.0576 1.00267735 23484 +HYLAS 1 +1 37237U 10065A 17109.43476604 -.00000242 00000-0 00000-0 0 9995 +2 37237 0.0731 68.6326 0001460 328.0586 294.0799 1.00270893 23431 +INTELSAT 17 (IS-17) +1 37238U 10065B 17108.93860541 -.00000011 00000-0 00000-0 0 9991 +2 37238 0.0223 237.4196 0002329 147.5520 226.1557 1.00274737 23367 +EUTELSAT KA-SAT 9A +1 37258U 10069A 17108.40071294 .00000054 00000-0 00000-0 0 9994 +2 37258 0.0359 282.2401 0001368 168.1724 269.6075 1.00270842 10493 +HISPASAT 1E +1 37264U 10070A 17109.39356382 -.00000224 00000-0 00000-0 0 9996 +2 37264 0.0575 100.2730 0003575 319.1902 259.9345 1.00272529 19633 +KOREASAT 6 +1 37265U 10070B 17109.76854753 -.00000370 00000-0 00000-0 0 9995 +2 37265 0.0087 207.2756 0001837 184.0850 209.3751 1.00271901 23232 +ELEKTRO-L 1 (GOMS 2) +1 37344U 11001A 17108.74003432 -.00000253 00000-0 00000-0 0 9995 +2 37344 2.3178 78.1764 0004346 284.5008 75.5986 1.00223056 22936 +BEIDOU IGSO 3 +1 37384U 11013A 17109.80124025 -.00000143 00000-0 10000-3 0 9994 +2 37384 57.7566 73.5430 0027952 212.7482 331.4004 1.00278676 22136 +INTELSAT NEW DAWN +1 37392U 11016A 17109.87063199 .00000147 00000-0 00000-0 0 9996 +2 37392 0.0130 188.6692 0000865 231.1277 134.6051 1.00274587 19758 +YAHSAT 1A +1 37393U 11016B 17109.90061142 .00000092 00000-0 00000-0 0 9996 +2 37393 0.0181 240.8846 0001741 153.6982 190.3197 1.00272051 8866 +TELSTAR 14R +1 37602U 11021A 17109.24567582 -.00000288 00000-0 00000-0 0 9999 +2 37602 0.0366 27.4091 0001608 347.0447 218.5197 1.00272198 22234 +GSAT-8 +1 37605U 11022A 17109.86091057 .00000076 00000-0 00000-0 0 9994 +2 37605 0.1020 87.9553 0004486 216.8651 268.3149 1.00272462 19674 +ST-2 +1 37606U 11022B 17109.83913135 -.00000220 00000-0 00000-0 0 9994 +2 37606 0.0170 196.3808 0001828 221.1240 180.7207 1.00273015 21702 +CHINASAT 10 (ZX 10) +1 37677U 11026A 17109.51775259 -.00000359 00000-0 00000-0 0 9997 +2 37677 0.0474 84.0307 0002648 126.3531 294.2764 1.00248803 21429 +TIANLIAN 1-02 +1 37737U 11032A 17109.22132347 .00000022 00000-0 00000-0 0 9990 +2 37737 2.4701 77.6299 0006823 222.1705 164.0957 1.00273480 21179 +GSAT-12 +1 37746U 11034A 17109.87308744 -.00000174 00000-0 00000-0 0 9998 +2 37746 0.0499 103.0529 0006623 359.3848 143.0422 1.00271661 9951 +SES-3 +1 37748U 11035A 17109.62982073 -.00000110 00000-0 00000-0 0 9997 +2 37748 0.0131 315.2486 0002598 50.3515 326.0524 1.00271835 21066 +KAZSAT-2 +1 37749U 11035B 17108.82036674 -.00000207 00000-0 00000-0 0 9993 +2 37749 0.0276 298.8314 0001947 146.6449 143.5009 1.00271885 21015 +ASTRA 1N +1 37775U 11041A 17109.79454052 .00000111 00000-0 00000-0 0 9993 +2 37775 0.0548 354.8739 0005564 50.1394 108.2864 1.00272289 10998 +BSAT-3C (JCSAT-110R) +1 37776U 11041B 17109.92647481 -.00000359 00000-0 00000-0 0 9994 +2 37776 0.0628 86.8751 0000719 41.7491 163.0887 1.00271027 16950 +PAKSAT-1R +1 37779U 11042A 17109.63964149 .00000145 00000-0 00000-0 0 9991 +2 37779 0.0496 59.7647 0004277 323.8999 92.5225 1.00271125 20933 +CHINASAT 1A (ZX 1A) +1 37804U 11047A 17109.64563262 -.00000346 00000-0 00000-0 0 9991 +2 37804 0.0647 87.7233 0001187 300.6810 181.7995 1.00269866 20534 +COSMOS 2473 +1 37806U 11048A 17109.33167506 -.00000116 00000-0 00000-0 0 9996 +2 37806 0.0611 102.8656 0003218 326.5672 244.0896 1.00272171 20519 +SES-2 +1 37809U 11049A 17109.52928144 -.00000204 00000-0 00000-0 0 9992 +2 37809 0.0320 80.9550 0002347 303.1926 287.2002 1.00271215 20474 +ARABSAT-5C +1 37810U 11049B 17109.87549389 .00000115 00000-0 00000-0 0 9992 +2 37810 0.0654 18.1795 0002915 5.7152 159.4168 1.00272348 20513 +EUTELSAT 7 WEST A +1 37816U 11051A 17109.44320334 -.00000068 00000-0 00000-0 0 9999 +2 37816 0.0856 50.0242 0001131 67.8455 242.1471 1.00273777 20366 +QUETZSAT 1 +1 37826U 11054A 17109.43968457 -.00000250 00000-0 00000-0 0 9999 +2 37826 0.0316 302.4492 0002329 110.2871 236.2771 1.00270439 20543 +INTELSAT 18 (IS-18) +1 37834U 11056A 17109.61446186 .00000044 00000-0 00000-0 0 9990 +2 37834 0.0165 251.9388 0002374 157.1755 199.9933 1.00271778 20303 +EUTELSAT 16A +1 37836U 11057A 17109.87549389 .00000095 00000-0 00000-0 0 9996 +2 37836 0.0688 11.3974 0004387 22.8398 145.0663 1.00272259 12455 +VIASAT-1 +1 37843U 11059A 17109.73399147 -.00000031 00000-0 00000-0 0 9997 +2 37843 0.0197 236.4052 0002479 157.4525 323.2884 1.00269890 13781 +ASIASAT 7 +1 37933U 11069A 17109.78712543 -.00000343 00000-0 00000-0 0 9998 +2 37933 0.0096 259.7854 0001554 107.5606 229.5962 1.00273137 11317 +LUCH 5A +1 37951U 11074B 17109.73848825 -.00000053 00000-0 00000-0 0 9990 +2 37951 1.5543 186.3003 0004116 188.6346 265.8699 1.00272821 19642 +NIGCOMSAT 1R +1 38014U 11077A 17109.12702867 .00000136 00000-0 00000-0 0 9993 +2 38014 0.0440 63.2942 0000489 301.7407 290.5990 1.00271728 19478 +FENGYUN 2F +1 38049U 12002A 17109.76854753 -.00000364 00000-0 00000-0 0 9996 +2 38049 1.5975 78.0440 0002882 173.6427 344.9934 1.00280529 19346 +SES-4 +1 38087U 12007A 17108.13199622 -.00000177 00000-0 00000-0 0 9992 +2 38087 0.0123 290.4055 0002279 98.2536 203.2582 1.00268262 18921 +BEIDOU G5 +1 38091U 12008A 17109.53852497 .00000048 00000-0 00000-0 0 9995 +2 38091 2.1174 55.1503 0002755 242.4129 162.9155 1.00276830 18937 +INTELSAT 22 (IS-22) +1 38098U 12011A 17109.22329971 -.00000067 00000-0 00000-0 0 9990 +2 38098 0.0125 300.4427 0001919 88.3020 331.2659 1.00270814 18291 +APSTAR 7 +1 38107U 12013A 17109.75336005 -.00000110 00000-0 00000-0 0 9996 +2 38107 0.0342 120.7564 0002548 256.6070 178.3835 1.00272029 18625 +YAHSAT 1B +1 38245U 12016A 17109.29122739 .00000118 00000-0 00000-0 0 9995 +2 38245 0.0189 237.5950 0001815 158.4243 323.9982 1.00271381 12085 +JCSAT-13 +1 38331U 12023A 17109.07957790 -.00000365 00000-0 00000-0 0 9993 +2 38331 0.0122 223.7308 0001641 175.4996 320.7814 1.00269320 17986 +VINASAT-2 +1 38332U 12023B 17109.79755161 -.00000337 00000-0 00000-0 0 9990 +2 38332 0.0089 224.0944 0002431 193.4078 209.5413 1.00270741 13117 +NIMIQ 6 +1 38342U 12026A 17108.67826164 -.00000182 00000-0 00000-0 0 9990 +2 38342 0.0093 223.5817 0002838 174.8111 321.6274 1.00271706 16888 +CHINASAT 2A (ZX 2A) +1 38352U 12028A 17109.80505128 -.00000302 00000-0 00000-0 0 9997 +2 38352 0.0679 91.1551 0004179 266.0557 238.9693 1.00272187 17836 +INTELSAT 19 (IS-19) +1 38356U 12030A 17108.96319055 -.00000065 00000-0 00000-0 0 9998 +2 38356 0.0029 7.1052 0003031 24.6900 328.2230 1.00269853 17968 +ECHOSTAR 17 +1 38551U 12035A 17108.72245865 -.00000083 00000-0 00000-0 0 9991 +2 38551 0.0201 228.1002 0001906 154.8912 337.0172 1.00270869 17518 +METEOSAT-10 (MSG-3) +1 38552U 12035B 17109.42366536 -.00000013 00000-0 00000-0 0 9992 +2 38552 0.7872 51.1906 0000394 69.3907 239.4278 1.00276842 17341 +SES-5 +1 38652U 12036A 17109.09993578 .00000026 00000-0 00000-0 0 9992 +2 38652 0.0310 261.9356 0001988 148.0310 198.3715 1.00273741 17518 +TIANLIAN 1-03 +1 38730U 12040A 17109.39372586 .00000064 00000-0 00000-0 0 9999 +2 38730 0.0348 243.4357 0002785 183.6680 292.9310 1.00274200 15176 +INTELSAT 20 (IS-20) +1 38740U 12043A 17108.23601258 -.00000033 00000-0 00000-0 0 9993 +2 38740 0.0252 136.2162 0000701 66.0360 157.7489 1.00272441 17216 +HYLAS 2 +1 38741U 12043B 17109.33713261 .00000146 00000-0 00000-0 0 9998 +2 38741 0.0394 66.1517 0001949 338.2700 315.5991 1.00273334 17221 +INTELSAT 21 (IS-21) +1 38749U 12045A 17108.58645190 -.00000293 00000-0 00000-0 0 9993 +2 38749 0.0152 259.1644 0002045 139.5306 321.3243 1.00271023 17080 +ASTRA 2F +1 38778U 12051A 17109.34491338 .00000141 00000-0 00000-0 0 9991 +2 38778 0.0526 229.5647 0000623 50.2926 80.1410 1.00271021 7621 +GSAT-10 +1 38779U 12051B 17109.19322503 -.00000173 00000-0 00000-0 0 9998 +2 38779 0.0675 96.6564 0002579 325.5687 297.8061 1.00270698 16574 +INTELSAT 23 (IS-23) +1 38867U 12057A 17108.57264125 -.00000293 00000-0 00000-0 0 9991 +2 38867 0.0253 259.2573 0002088 147.0398 313.7248 1.00268747 16445 +BEIDOU G6 +1 38953U 12059A 17109.94022429 -.00000183 00000-0 10000-3 0 9992 +2 38953 1.5354 80.0034 0003410 183.5982 7.1134 1.00274696 16500 +LUCH 5B +1 38977U 12061A 17109.32845620 -.00000137 00000-0 00000-0 0 9994 +2 38977 3.4264 74.9099 0004071 303.8364 290.7467 1.00270606 16624 +YAMAL 300K +1 38978U 12061B 17109.73882491 .00000062 00000-0 00000-0 0 9993 +2 38978 0.0334 64.1347 0000116 302.6522 290.1709 1.00269827 16325 +STAR ONE C3 +1 38991U 12062A 17109.27983056 -.00000257 00000-0 00000-0 0 9994 +2 38991 0.0491 79.1354 0002001 304.0560 210.1285 1.00271852 16222 +EUTELSAT 21B +1 38992U 12062B 17109.36332927 .00000121 00000-0 00000-0 0 9999 +2 38992 0.0687 11.5802 0002286 27.7946 320.6471 1.00271786 16310 +ECHOSTAR 16 +1 39008U 12065A 17108.59617560 -.00000290 00000-0 00000-0 0 9992 +2 39008 0.0209 223.8197 0001669 166.1593 330.0305 1.00270268 16252 +CHINASAT 12 (ZX 12) +1 39017U 12067A 17109.84077001 -.00000216 00000-0 00000-0 0 9991 +2 39017 0.0125 52.1679 0002902 344.5220 201.6274 1.00272419 16165 +EUTELSAT 70B +1 39020U 12069A 17109.22781213 -.00000052 00000-0 00000-0 0 9994 +2 39020 0.0761 40.3174 0001704 359.9847 319.7156 1.00273572 16068 +YAMAL 402 +1 39022U 12070A 17108.99755815 .00000077 00000-0 10000-3 0 9990 +2 39022 0.0104 185.9569 0002622 214.6557 220.6940 1.00272685 16043 +SKYNET 5D +1 39034U 12075A 17109.90061177 .00000091 00000-0 00000-0 0 9993 +2 39034 0.0721 4.8617 0003646 27.9290 192.3561 1.00271793 15974 +MEXSAT 3 +1 39035U 12075B 17109.74108741 -.00000034 00000-0 00000-0 0 9993 +2 39035 0.0327 143.1688 0001629 254.3807 322.4675 1.00272109 15627 +TDRS 11 +1 39070U 13004A 17108.81217845 .00000081 00000-0 00000-0 0 9999 +2 39070 5.4717 328.7221 0010135 305.8529 53.8845 1.00265360 13147 +AMAZONAS 3 +1 39078U 13006A 17108.59469008 -.00000291 00000-0 00000-0 0 9998 +2 39078 0.0226 192.8297 0001208 189.3655 337.8146 1.00272840 11339 +AZERSPACE 1 +1 39079U 13006B 17109.29572733 .00000125 00000-0 00000-0 0 9992 +2 39079 0.0380 59.2069 0002155 358.2504 302.5687 1.00272231 15388 +EUTELSAT 117 WEST A +1 39122U 13012A 17108.74938232 -.00000021 00000-0 00000-0 0 9993 +2 39122 0.0621 84.5471 0002723 307.7139 327.7605 1.00272703 14907 +ANIK G1 +1 39127U 13014A 17108.72301666 -.00000082 00000-0 00000-0 0 9990 +2 39127 0.0141 251.0073 0001596 105.7194 3.2770 1.00272421 14706 +CHINASAT 11 (ZX 11) +1 39157U 13020A 17109.82005012 -.00000299 00000-0 00000-0 0 9998 +2 39157 0.0110 209.0480 0002464 106.9430 285.3027 1.00269299 14607 +EUTELSAT 7B +1 39163U 13022A 17108.40640327 .00000040 00000-0 00000-0 0 9997 +2 39163 0.0489 41.3036 0005001 330.3367 348.3758 1.00272149 14440 +SES-6 +1 39172U 13026A 17109.40461581 -.00000269 00000-0 00000-0 0 9999 +2 39172 0.0169 71.6556 0001814 346.6849 254.5218 1.00269637 14189 +IRNSS-1A +1 39199U 13034A 17107.59747611 .00000118 00000-0 00000-0 0 9998 +2 39199 28.7210 116.0761 0021173 188.9070 171.0962 1.00271071 13809 +ALPHASAT +1 39215U 13038A 17109.43561126 .00000131 00000-0 00000-0 0 9996 +2 39215 1.6489 29.6730 0001563 5.9468 353.7801 1.00273935 10507 +INSAT-3D +1 39216U 13038B 17108.19845532 -.00000164 00000-0 00000-0 0 9992 +2 39216 0.1114 95.6066 0001281 289.2214 335.1824 1.00270427 13566 +EUTELSAT 25B +1 39233U 13044A 17109.35241066 .00000135 00000-0 00000-0 0 9996 +2 39233 0.0548 38.0621 0001893 351.2735 330.6803 1.00269362 13091 +GSAT-7 +1 39234U 13044B 17109.21797557 -.00000086 00000-0 00000-0 0 9999 +2 39234 0.0905 98.9459 0002312 216.3847 44.6560 1.00272984 11819 +AMOS-4 +1 39237U 13045A 17109.24289309 -.00000002 00000-0 00000-0 0 9995 +2 39237 0.0307 129.6945 0001970 232.1057 358.2058 1.00274519 13418 +ASTRA 2E +1 39285U 13056A 17109.34401615 .00000142 00000-0 00000-0 0 9991 +2 39285 0.0672 39.3149 0002281 347.3279 333.3742 1.00273719 12920 +SIRIUS FM-6 +1 39360U 13058A 17109.74482623 -.00000025 00000-0 00000-0 0 9990 +2 39360 0.0056 268.1075 0000804 306.6532 145.2396 1.00270730 12801 +RADUGA-1M 3 +1 39375U 13062A 17109.89285655 -.00000048 00000-0 00000-0 0 9998 +2 39375 0.0057 227.8524 0002812 191.6803 180.0873 1.00273461 12589 +SES-8 +1 39460U 13071A 17109.15996438 -.00000277 00000-0 00000-0 0 9994 +2 39460 0.0215 233.8425 0002700 181.3674 304.8155 1.00268173 12320 +INMARSAT 5-F1 +1 39476U 13073A 17109.85049412 .00000019 00000-0 00000-0 0 9994 +2 39476 0.0141 212.3345 0000584 298.4402 66.1473 1.00270688 12386 +TKSAT-1 (TUPAC KATARI) +1 39481U 13075A 17109.52928144 -.00000203 00000-0 00000-0 0 9990 +2 39481 0.0117 242.6857 0002588 127.5037 300.9650 1.00271252 12048 +EXPRESS-AM5 +1 39487U 13077A 17107.84678245 -.00000288 00000-0 00000-0 0 9998 +2 39487 0.0238 312.2169 0000702 25.0086 313.8487 1.00273362 12809 +GSAT-14 +1 39498U 14001A 17109.21821508 -.00000086 00000-0 00000-0 0 9999 +2 39498 0.0256 161.8848 0004623 253.8490 304.3152 1.00272765 11909 +THAICOM 6 +1 39500U 14002A 17109.91575337 -.00000130 00000-0 00000-0 0 9997 +2 39500 0.0622 121.4131 0002324 315.5938 179.3442 1.00273862 11907 +TDRS 12 +1 39504U 14004A 17108.47280783 -.00000282 00000-0 00000-0 0 9999 +2 39504 6.0422 336.1678 0002694 28.4941 331.3755 1.00276390 10725 +ABS-2 +1 39508U 14006A 17109.21554072 -.00000095 00000-0 00000-0 0 9995 +2 39508 0.0656 73.3977 0003400 312.5250 334.0996 1.00272187 11773 +ATHENA-FIDUS +1 39509U 14006B 17109.31836167 .00000146 00000-0 00000-0 0 9991 +2 39509 0.0172 258.0824 0001436 153.6976 308.2329 1.00271121 11530 +TURKSAT 4A +1 39522U 14007A 17108.30939973 .00000137 00000-0 00000-0 0 9994 +2 39522 0.0482 271.6731 0002588 66.3946 21.9257 1.00273681 11445 +EXPRESS-AT1 +1 39612U 14010A 17109.86056334 .00000069 00000-0 00000-0 0 9995 +2 39612 0.0239 342.1001 0001390 119.8162 112.0397 1.00273860 11506 +EXPRESS-AT2 +1 39613U 14010B 17109.80396529 -.00000290 00000-0 00000-0 0 9990 +2 39613 0.0192 309.9020 0000507 163.1051 164.3590 1.00272134 11334 +AMAZONAS 4A +1 39616U 14011A 17109.59198177 -.00000291 00000-0 00000-0 0 9990 +2 39616 0.0700 69.3908 0005338 327.2211 323.4301 1.00269976 11150 +ASTRA 5B +1 39617U 14011B 17109.87063199 .00000146 00000-0 00000-0 0 9995 +2 39617 0.0620 306.2519 0003203 96.4430 150.3628 1.00272796 11131 +IRNSS-1B +1 39635U 14017A 17106.10098970 .00000066 00000-0 00000-0 0 9990 +2 39635 29.2031 295.8732 0018997 177.1399 182.8116 1.00276752 11225 +LUCH 5V +1 39727U 14023A 17109.93906795 -.00000281 00000-0 00000-0 0 9996 +2 39727 2.8199 299.0931 0002966 94.5519 247.3971 1.00271915528978 +KAZSAT 3 +1 39728U 14023B 17109.26104713 .00000052 00000-0 00000-0 0 9998 +2 39728 0.0143 251.6382 0001230 229.4791 238.8947 1.00270882 8902 +EUTELSAT 3B +1 39773U 14030A 17109.95680470 .00000011 00000-0 00000-0 0 9996 +2 39773 0.0841 322.3770 0001701 75.8441 157.5548 1.00272325 10532 +ASIASAT 8 +1 40107U 14046A 17108.43659856 -.00000042 00000-0 00000-0 0 9997 +2 40107 0.0119 246.9864 0000325 121.2645 351.7496 1.00270279 68608 +ASIASAT 6 +1 40141U 14052A 17109.94058306 -.00000371 00000-0 00000-0 0 9997 +2 40141 0.0162 237.3406 0000978 188.5950 240.8089 1.00271351 9512 +OPTUS 10 +1 40146U 14054A 17108.96873335 -.00000082 00000-0 00000-0 0 9991 +2 40146 0.0733 334.7330 0001585 59.1047 326.1773 1.00274086 9486 +MEASAT-3B +1 40147U 14054B 17109.16977926 -.00000249 00000-0 00000-0 0 9991 +2 40147 0.0139 31.0682 0002670 358.9432 330.0039 1.00270102 9369 +LUCH (OLYMP) +1 40258U 14058A 17109.92803998 .00000060 00000-0 00000-0 0 9999 +2 40258 0.0075 179.7868 0000515 208.9661 163.4552 1.00272906 9396 +HIMAWARI-8 +1 40267U 14060A 17109.03337671 -.00000284 00000-0 00000-0 0 9993 +2 40267 0.0169 99.4949 0000850 348.4065 272.1083 1.00269924 9313 +IRNSS-1C +1 40269U 14061A 17108.89275674 -.00000173 00000-0 00000-0 0 9990 +2 40269 3.1333 251.6716 0019082 9.6181 350.2659 1.00269076 9267 +INTELSAT 30 (IS-30) +1 40271U 14062A 17109.40753358 -.00000158 00000-0 00000-0 0 9995 +2 40271 0.0126 211.5975 0001766 255.2120 152.5341 1.00268435 9214 +ARSAT 1 +1 40272U 14062B 17109.43866049 -.00000268 00000-0 00000-0 0 9993 +2 40272 0.0110 235.2023 0001094 173.8657 244.7704 1.00270905 9064 +EXPRESS-AM6 +1 40277U 14064A 17109.63283528 .00000089 00000-0 00000-0 0 9997 +2 40277 0.0221 327.4450 0000810 134.3775 26.9122 1.00271395 8043 +GSAT-16 +1 40332U 14078A 17109.27071338 .00000076 00000-0 00000-0 0 9994 +2 40332 0.0788 86.2534 0006291 346.8056 287.0151 1.00272192 8584 +DIRECTV 14 +1 40333U 14078B 17109.59358875 -.00000133 00000-0 00000-0 0 9999 +2 40333 0.0146 249.3051 0000286 129.3243 303.7125 1.00270870 8611 +YAMAL 401 +1 40345U 14082A 17109.34233956 -.00000236 00000-0 00000-0 0 9996 +2 40345 0.0666 80.5801 0001445 8.0577 332.1630 1.00269966 8868 +ASTRA 2G +1 40364U 14089A 17109.34497921 .00000141 00000-0 00000-0 0 9992 +2 40364 0.0153 357.1621 0004863 56.7436 306.1394 1.00272491 8421 +FENGYUN 2G +1 40367U 14090A 17109.43598381 -.00000335 00000-0 00000-0 0 9995 +2 40367 0.5568 261.4214 0002558 301.0266 266.4441 1.00260509 8495 +INMARSAT 5-F2 +1 40384U 15005A 17109.35414264 -.00000293 00000-0 00000-0 0 9992 +2 40384 0.0206 237.1065 0000486 193.7680 209.2452 1.00270089 8127 +ABS-3A +1 40424U 15010A 17108.43380787 -.00000034 00000-0 00000-0 0 9996 +2 40424 0.0115 243.8763 0001944 64.0974 52.0132 1.00273027 7859 +EUTELSAT 115 WEST B +1 40425U 15010B 17108.74397819 -.00000033 00000-0 00000-0 0 9994 +2 40425 0.0023 66.7907 0000609 235.4939 57.7095 1.00270139 7853 +EXPRESS-AM7 +1 40505U 15012A 17109.81855196 .00000142 00000-0 00000-0 0 9991 +2 40505 0.0007 199.1072 0002517 175.9892 167.6787 1.00272783 7816 +IRNSS-1D +1 40547U 15018A 17108.93580479 -.00000310 00000-0 00000-0 0 9992 +2 40547 29.1864 295.9627 0019702 179.0393 180.9184 1.00273644 7446 +BEIDOU I1-S +1 40549U 15019A 17109.50198778 -.00000141 00000-0 00000-0 0 9998 +2 40549 54.4510 334.4397 0039145 181.6881 324.0406 1.00253900 7535 +THOR 7 +1 40613U 15022A 17108.42761913 -.00000016 00000-0 00000-0 0 9992 +2 40613 0.0384 109.0718 0002651 284.7857 326.1639 1.00273293 7264 +TURKMENALEM52E/MONACOSAT +1 40617U 15023A 17109.27900221 .00000095 00000-0 00000-0 0 9994 +2 40617 0.0069 271.1428 0003030 130.2756 318.6046 1.00269720 7293 +DIRECTV 15 +1 40663U 15026A 17108.71042695 -.00000111 00000-0 00000-0 0 9998 +2 40663 0.0196 120.0555 0000297 13.2497 226.7019 1.00270236 6979 +SKY MEXICO-1 +1 40664U 15026B 17108.64406019 -.00000243 00000-0 00000-0 0 9991 +2 40664 0.0167 136.0530 0002150 262.9701 320.9971 1.00273348 6981 +METEOSAT-11 (MSG-4) +1 40732U 15034A 17108.11510896 -.00000039 00000-0 00000-0 0 9990 +2 40732 1.9279 244.3808 0000871 108.3788 251.4878 1.00271839 6480 +STAR ONE C4 +1 40733U 15034B 17108.61973130 -.00000273 00000-0 00000-0 0 9990 +2 40733 0.0518 50.5684 0003073 346.9583 322.4994 1.00270157 6486 +INTELSAT 34 (IS-34) +1 40874U 15039A 17108.57945464 -.00000293 00000-0 00000-0 0 9997 +2 40874 0.0153 252.0193 0000803 313.8730 154.1083 1.00271237 6126 +EUTELSAT 8 WEST B +1 40875U 15039B 17109.44529436 -.00000074 00000-0 00000-0 0 9999 +2 40875 0.0704 355.3737 0003352 21.2704 343.3722 1.00272004 6140 +GSAT-6 +1 40880U 15041A 17109.19302429 -.00000172 00000-0 00000-0 0 9990 +2 40880 0.0261 183.0365 0007277 107.3728 69.5125 1.00268789 6081 +INMARSAT 5-F3 +1 40882U 15042A 17108.92546331 .00000041 00000-0 00000-0 0 9999 +2 40882 0.0208 236.9687 0000953 249.1479 233.8922 1.00267404 6007 +TJS-1 +1 40892U 15046A 17109.73035331 -.00000165 00000-0 00000-0 0 9995 +2 40892 0.0820 276.5696 0007514 110.2171 239.0989 1.00272336 6006 +EXPRESS-AM8 +1 40895U 15048A 17109.79632778 -.00000120 00000-0 00000-0 0 9995 +2 40895 0.0171 315.4830 0000930 145.1881 20.0907 1.00272184 5830 +BEIDOU I2-S +1 40938U 15053A 17109.33759767 -.00000114 00000-0 00000-0 0 9990 +2 40938 54.2856 297.3332 0047489 171.5106 315.4929 1.00264459 5816 +SKY MUSTER (NBN1A) +1 40940U 15054A 17109.03457499 -.00000287 00000-0 00000-0 0 9999 +2 40940 0.0177 248.5059 0001797 145.1389 326.3717 1.00270402 5743 +ARSAT 2 +1 40941U 15054B 17108.65020886 -.00000233 00000-0 00000-0 0 9994 +2 40941 0.0146 240.4549 0001383 175.1351 304.4277 1.00270663 5778 +MORELOS 3 +1 40946U 15056A 17108.65511739 -.00000058 00000-0 00000-0 0 9998 +2 40946 6.4994 329.8239 0001904 350.7732 9.0858 1.00271301 5734 +APSTAR 9 +1 40982U 15059A 17109.02956332 -.00000274 00000-0 00000-0 0 9995 +2 40982 0.0146 174.3096 0000543 157.3652 28.3273 1.00272514 5616 +TURKSAT 4B +1 40984U 15060A 17109.28455546 .00000106 00000-0 00000-0 0 9991 +2 40984 0.0141 240.2982 0001880 146.2651 333.4463 1.00272723 5579 +CHINASAT 2C (ZX 2C) +1 41021U 15063A 17109.81452186 -.00000332 00000-0 00000-0 0 9995 +2 41021 0.0096 299.9183 0003598 93.2700 211.5288 1.00269171 5461 +GSAT-15 +1 41028U 15065A 17109.16405506 -.00000266 00000-0 00000-0 0 9992 +2 41028 0.0775 95.0431 0002136 304.3112 320.6664 1.00271474 5316 +BADR-7 (ARABSAT-6B) +1 41029U 15065B 17108.35361110 .00000137 00000-0 00000-0 0 9991 +2 41029 0.0576 258.0240 0002310 352.7034 109.2520 1.00275353 5197 +LAOSAT 1 +1 41034U 15067A 17109.06709502 -.00000352 00000-0 00000-0 0 9999 +2 41034 0.0073 135.8570 0000526 91.2878 132.8508 1.00267321 5320 +TELSTAR 12V +1 41036U 15068A 17108.46733881 -.00000127 00000-0 00000-0 0 9992 +2 41036 0.0205 234.5402 0002195 157.1075 328.3700 1.00272542 5074 +CHINASAT 1C (ZX 1C) +1 41103U 15073A 17109.84563218 -.00000160 00000-0 00000-0 0 9998 +2 41103 0.0198 295.5873 0003254 27.4648 271.0110 1.00274317 5128 +ELEKTRO-L 2 +1 41105U 15074A 17109.74146499 -.00000106 00000-0 00000-0 0 9998 +2 41105 0.0675 43.5062 0002143 13.6273 133.8389 1.00271793 4978 +COSMOS 2513 +1 41121U 15075A 17104.80737361 -.00000150 00000-0 00000-0 0 9992 +2 41121 0.0614 89.3769 0003377 318.8997 165.7933 1.00272829 5009 +EXPRESS-AMU1 +1 41191U 15082A 17109.79495979 .00000147 00000-0 00000-0 0 9991 +2 41191 0.0061 239.0346 0002242 134.0689 157.2840 1.00275812 4965 +GAOFEN 4 +1 41194U 15083A 17109.95158472 -.00000344 00000-0 00000-0 0 9997 +2 41194 0.0276 270.5707 0002482 288.3881 97.5910 1.00272587 4948 +BELINTERSAT-1 +1 41238U 16001A 17109.86091057 .00000098 00000-0 10000-3 0 9991 +2 41238 0.0476 80.8418 0001400 321.8439 166.8973 1.00270521 4733 +IRNSS-1E +1 41241U 16003A 17109.43385342 -.00000261 00000-0 00000-0 0 9992 +2 41241 28.6899 115.7032 0019738 187.5177 172.4980 1.00269458 4649 +INTELSAT 29E (IS-29E) +1 41308U 16004A 17108.56430669 -.00000290 00000-0 00000-0 0 9995 +2 41308 0.0112 234.0167 0001813 152.7944 333.2029 1.00271523 4603 +EUTELSAT 9B +1 41310U 16005A 17108.40084250 .00000053 00000-0 00000-0 0 9999 +2 41310 0.0659 103.3328 0004200 242.3758 14.2841 1.00271734 4568 +SES-9 +1 41380U 16013A 17109.12304699 -.00000354 00000-0 00000-0 0 9992 +2 41380 0.0289 292.5928 0001503 120.3229 307.1031 1.00273492 3952 +EUTELSAT 65 WEST A +1 41382U 16014A 17108.60646641 -.00000284 00000-0 00000-0 0 9995 +2 41382 0.0535 1.4670 0001810 42.9219 315.6301 1.00269437 4092 +IRNSS-1F +1 41384U 16015A 17108.07655739 .00000144 00000-0 00000-0 0 9991 +2 41384 4.2823 266.5566 0021021 174.5290 185.3144 1.00268992 4132 +BEIDOU IGSO 6 +1 41434U 16021A 17109.93294973 -.00000104 00000-0 10000-3 0 9990 +2 41434 55.4678 73.0379 0027418 186.2336 20.1519 1.00282535 3943 +IRNSS-1G +1 41469U 16027A 17109.80548166 -.00000350 00000-0 00000-0 0 9995 +2 41469 4.3521 267.8276 0001662 81.9772 277.8583 1.00272940 3657 +JCSAT 2B +1 41471U 16028A 17108.99641659 -.00000174 00000-0 00000-0 0 9993 +2 41471 0.0152 212.5195 0001316 207.3801 300.1134 1.00267815 3537 +THAICOM 8 +1 41552U 16031A 17109.20564832 -.00000130 00000-0 00000-0 0 9991 +2 41552 0.0609 49.6106 0005206 346.5402 323.8895 1.00271880 3184 +INTELSAT 31 (IS-31) +1 41581U 16035A 17108.68905406 -.00000159 00000-0 00000-0 0 9995 +2 41581 0.0165 235.0901 0001521 329.6450 155.2623 1.00270775 3153 +BEIDOU G7 +1 41586U 16037A 17108.89666898 -.00000258 00000-0 00000-0 0 9994 +2 41586 1.3357 315.3485 0001413 293.0668 66.1289 1.00271303 3245 +ABS-2A +1 41588U 16038A 17109.21603041 -.00000092 00000-0 00000-0 0 9991 +2 41588 0.0140 203.8626 0001635 106.8769 49.2463 1.00271507 3174 +EUTELSAT 117 WEST B +1 41589U 16038B 17108.74976076 -.00000020 00000-0 00000-0 0 9991 +2 41589 0.0020 62.9880 0000589 245.6426 51.3642 1.00271393 3151 +BRISAT +1 41591U 16039A 17108.00901951 -.00000206 00000-0 00000-0 0 9990 +2 41591 0.0233 244.8899 0002135 138.2883 336.8314 1.00268925 3080 +ECHOSTAR 18 +1 41592U 16039B 17108.59571440 -.00000290 00000-0 00000-0 0 9994 +2 41592 0.0362 83.3856 0002203 301.1179 335.5116 1.00272705 3085 +TIANTONG-1 1 +1 41725U 16048A 17109.98839853 -.00000331 00000-0 00000-0 0 9997 +2 41725 4.6664 325.2502 0005147 47.8490 292.4837 1.00273060 2720 +JCSAT-16 +1 41729U 16050A 17108.97413394 -.00000101 00000-0 00000-0 0 9995 +2 41729 0.0214 233.9840 0001950 164.1830 321.8468 1.00269925 2524 +INTELSAT 36 (IS-36) +1 41747U 16053A 17107.23874362 -.00000034 00000-0 00000-0 0 9997 +2 41747 0.0400 57.8421 0002632 315.5832 346.5849 1.00272866 2403 +INTELSAT 33E (IS-33E) +1 41748U 16053B 17109.25689042 .00000040 00000-0 00000-0 0 9997 +2 41748 0.0077 283.4605 0001942 115.4537 321.1050 1.00272322 2665 +INSAT-3DR +1 41752U 16054A 17109.21783586 -.00000086 00000-0 00000-0 0 9998 +2 41752 0.0502 110.6593 0006977 172.6235 76.6448 1.00273404 2275 +GSAT-18 +1 41793U 16060A 17109.21832816 -.00000086 00000-0 00000-0 0 9991 +2 41793 0.0681 103.5668 0007141 344.5396 271.9804 1.00272774 1997 +SKY MUSTER 2 +1 41794U 16060B 17109.02193438 -.00000253 00000-0 00000-0 0 9997 +2 41794 0.0161 252.1229 0001560 142.4845 325.4077 1.00271260 1983 +HIMAWARI-9 +1 41836U 16064A 17109.03310503 -.00000284 00000-0 00000-0 0 9997 +2 41836 0.0162 231.3963 0000976 186.6913 301.9219 1.00268372 1641 +SHIJIAN-17 (SJ-17) +1 41838U 16065A 17109.80052440 -.00000093 00000-0 00000-0 0 9996 +2 41838 0.0565 66.4860 0008876 31.5156 201.2680 1.00267898 1687 +GOES 16 +1 41866U 16071A 17108.67373753 -.00000190 00000-0 00000-0 0 9999 +2 41866 0.0014 223.2961 0001987 178.7937 317.9255 1.00269109 1555 +TIANLIAN 1-04 +1 41869U 16072A 17107.14392972 -.00000118 00000-0 00000-0 0 9998 +2 41869 2.7838 290.2877 0005754 125.0979 278.8535 1.00271227 1749 +FENGYUN 4A +1 41882U 16077A 17109.58103998 -.00000307 00000-0 00000-0 0 9996 +2 41882 0.1297 268.7524 0002994 226.4283 21.1594 1.00263665 1438 +ECHOSTAR 19 +1 41893U 16079A 17108.69476273 -.00000146 00000-0 00000-0 0 9991 +2 41893 0.0187 226.6808 0001485 182.5815 310.7505 1.00268526 1173 +STAR ONE D1 +1 41904U 16082B 17108.65855044 -.00000219 00000-0 00000-0 0 9992 +2 41904 0.0245 111.6291 0002451 293.1443 315.2510 1.00272670 1227 +TJS-2 +1 41911U 17001A 17109.50654808 -.00000351 00000-0 00000-0 0 9999 +2 41911 0.7999 280.0638 0002553 167.2440 50.2427 1.00265878 1185 +HISPASAT 36W-1 +1 41942U 17006A 17108.49778271 -.00000201 00000-0 00000-0 0 9990 +2 41942 0.0307 126.3547 0002775 260.8299 332.8345 1.00273657 972 +TELKOM 3S +1 41944U 17007A 17109.09603879 -.00000371 00000-0 00000-0 0 9999 +2 41944 0.0531 73.1774 0000708 6.1870 280.6486 1.00271256 669 +INTELSAT 32E (IS-32E) +1 41945U 17007B 17108.54534578 -.00000277 00000-0 00000-0 0 9993 +2 41945 0.0211 232.4659 0000439 284.8357 202.7003 1.00268694 698 diff --git a/data/scene/satellites/tle/gps-ops.txt b/data/scene/satellites/tle/gps-ops.txt new file mode 100644 index 0000000000..5a498425e9 --- /dev/null +++ b/data/scene/satellites/tle/gps-ops.txt @@ -0,0 +1,93 @@ +GPS BIIR-2 (PRN 13) +1 24876U 97035A 17109.73375644 -.00000012 00000-0 00000-0 0 9992 +2 24876 55.5643 229.4105 0036557 106.5416 253.8548 2.00562036144850 +GPS BIIR-3 (PRN 11) +1 25933U 99055A 17109.65740979 .00000008 00000-0 00000-0 0 9993 +2 25933 51.5943 80.2017 0164482 93.5980 140.6974 2.00559092128473 +GPS BIIR-4 (PRN 20) +1 26360U 00025A 17109.81822694 .00000034 00000-0 00000-0 0 9999 +2 26360 53.1062 157.3245 0041561 90.8273 1.8392 2.00564454124177 +GPS BIIR-5 (PRN 28) +1 26407U 00040A 17109.72770267 -.00000058 00000-0 00000-0 0 9993 +2 26407 56.6488 347.4270 0199991 270.0939 38.2665 2.00567294122845 +GPS BIIR-6 (PRN 14) +1 26605U 00071A 17109.91594260 -.00000014 00000-0 00000-0 0 9997 +2 26605 55.1353 227.1576 0091621 248.1584 104.4436 2.00567152120445 +GPS BIIR-7 (PRN 18) +1 26690U 01004A 17109.78566808 .00000030 00000-0 00000-0 0 9997 +2 26690 53.0287 160.2705 0181728 256.2994 113.2448 2.00553627118851 +GPS BIIR-8 (PRN 16) +1 27663U 03005A 17109.59259250 -.00000059 00000-0 00000-0 0 9992 +2 27663 56.7184 347.1682 0092496 23.4683 306.5317 2.00563261104201 +GPS BIIR-9 (PRN 21) +1 27704U 03010A 17109.45896894 .00000044 00000-0 00000-0 0 9993 +2 27704 53.8252 100.6579 0242330 263.6172 289.5204 2.00560332102998 +GPS BIIR-10 (PRN 22) +1 28129U 03058A 17108.92540211 .00000021 00000-0 00000-0 0 9992 +2 28129 52.9154 160.3028 0078030 259.1988 99.9936 2.00579000 97688 +GPS BIIR-11 (PRN 19) +1 28190U 04009A 17109.78405102 -.00000044 00000-0 00000-0 0 9997 +2 28190 55.9742 48.2291 0100656 53.7277 206.5104 2.00565372 95887 +GPS BIIR-12 (PRN 23) +1 28361U 04023A 17109.67197838 -.00000016 00000-0 00000-0 0 9994 +2 28361 54.1189 222.3390 0116919 218.8962 232.5879 2.00552789 93943 +GPS BIIR-13 (PRN 02) +1 28474U 04045A 17109.80139524 .00000047 00000-0 00000-0 0 9999 +2 28474 54.2062 100.0906 0169972 246.2805 298.8317 2.00552002 91333 +GPS BIIRM-1 (PRN 17) +1 28874U 05038A 17109.78616237 -.00000048 00000-0 00000-0 0 9996 +2 28874 56.1319 45.4826 0118701 254.3506 28.1379 2.00570959 84737 +GPS BIIRM-2 (PRN 31) +1 29486U 06042A 17109.84481250 .00000007 00000-0 00000-0 0 9998 +2 29486 55.4369 284.6203 0085225 343.6385 263.4212 2.00562325 77337 +GPS BIIRM-3 (PRN 12) +1 29601U 06052A 17109.44438112 -.00000058 00000-0 00000-0 0 9990 +2 29601 56.6911 346.0938 0064836 46.5746 314.0087 2.00578841 76304 +GPS BIIRM-4 (PRN 15) +1 32260U 07047A 17109.76747141 -.00000018 00000-0 00000-0 0 9996 +2 32260 53.2450 218.7351 0089867 32.0784 328.4730 2.00550702 69758 +GPS BIIRM-5 (PRN 29) +1 32384U 07062A 17109.82767948 -.00000047 00000-0 00000-0 0 9996 +2 32384 56.1949 46.0590 0007162 349.1522 190.7070 2.00567498 68450 +GPS BIIRM-6 (PRN 07) +1 32711U 08012A 17109.17017566 .00000005 00000-0 00000-0 0 9991 +2 32711 55.1649 284.0298 0104617 211.6174 147.7414 2.00555102 66640 +GPS BIIRM-8 (PRN 05) +1 35752U 09043A 17109.80875753 .00000030 00000-0 00000-0 0 9992 +2 35752 54.2447 161.8840 0048052 28.4418 96.4367 2.00557153 56266 +GPS BIIF-1 (PRN 25) +1 36585U 10022A 17109.45861331 -.00000056 00000-0 00000-0 0 9993 +2 36585 56.0008 342.9525 0062857 43.8593 292.2361 2.00572192 50488 +GPS BIIF-2 (PRN 01) +1 37753U 11036A 17109.65756309 .00000053 00000-0 00000-0 0 9993 +2 37753 55.4143 103.1083 0063799 28.9219 177.7211 2.00561953 42171 +GPS BIIF-3 (PRN 24) +1 38833U 12053A 17109.36112639 .00000003 00000-0 00000-0 0 9998 +2 38833 54.1932 280.9976 0055446 25.7503 334.5131 2.00560911 33233 +GPS BIIF-4 (PRN 27) +1 39166U 13023A 17109.71335229 -.00000054 00000-0 00000-0 0 9994 +2 39166 55.8396 42.5193 0046353 15.5591 344.5802 2.00565270 28782 +GPS BIIF-5 (PRN 30) +1 39533U 14008A 17109.71803235 .00000003 00000-0 00000-0 0 9996 +2 39533 54.3474 286.2694 0026612 180.2094 179.7840 2.00561576 22608 +GPS BIIF-6 (PRN 06) +1 39741U 14026A 17109.49522789 .00000051 00000-0 00000-0 0 9997 +2 39741 55.4016 102.6345 0010242 287.2500 72.6522 2.00565694 21432 +GPS BIIF-7 (PRN 09) +1 40105U 14045A 17109.58870938 -.00000015 00000-0 00000-0 0 9997 +2 40105 54.6417 222.2176 0006094 114.5172 245.5503 2.00565991 19002 +GPS BIIF-8 (PRN 03) +1 40294U 14068A 17109.45908091 .00000027 00000-0 00000-0 0 9991 +2 40294 54.9913 162.8335 0006001 343.2122 16.8409 2.00553719 18104 +GPS BIIF-9 (PRN 26) +1 40534U 15013A 17109.59579211 -.00000056 00000-0 00000-0 0 9995 +2 40534 54.9576 342.1019 0018236 356.2473 3.7829 2.00562102 14725 +GPS BIIF-10 (PRN 08) +1 40730U 15033A 17109.25722952 -.00000055 00000-0 00000-0 0 9999 +2 40730 55.3741 42.2354 0027546 314.4917 45.2822 2.00570200 12905 +GPS BIIF-11 (PRN 10) +1 41019U 15062A 17109.31059499 .00000026 00000-0 00000-0 0 9995 +2 41019 55.0013 162.6249 0025268 204.7841 155.1668 2.00563458 10725 +GPS BIIF-12 (PRN 32) +1 41328U 16007A 17109.39652641 -.00000014 00000-0 00000-0 0 9992 +2 41328 54.8999 222.3973 0011692 216.7815 143.1423 2.00558460 8782 diff --git a/data/scene/satellites/tle/stations.txt b/data/scene/satellites/tle/stations.txt new file mode 100644 index 0000000000..0f0506fc87 --- /dev/null +++ b/data/scene/satellites/tle/stations.txt @@ -0,0 +1,180 @@ +ISS (ZARYA) +1 25544U 98067A 17109.92096824 .00002787 00000-0 49344-4 0 9990 +2 25544 51.6434 328.7262 0007243 75.4107 32.5712 15.54131334 52697 +TIANGONG 1 +1 37820U 11053A 17109.70783838 .00019763 00000-0 12539-3 0 9991 +2 37820 42.7590 197.4071 0018147 19.0253 112.4332 15.75889937318739 +AGGIESAT 4 +1 41313U 98067HP 17109.81227259 .00031142 00000-0 24561-3 0 9998 +2 41313 51.6371 301.8896 0003500 267.9298 92.1299 15.71127246 69747 +BEVO 2 +1 41314U 98067HQ 17109.68429905 .00156013 20027-4 50373-3 0 9996 +2 41314 51.6235 283.2567 0005515 275.3685 84.6691 15.90548487 69787 +MINXSS +1 41474U 98067HU 17109.73827802 .00306018 48569-4 71516-3 0 9992 +2 41474 51.6472 293.8859 0006892 279.9569 80.0662 15.96438057 53089 +STMSAT-1 +1 41476U 98067HW 17109.88070258 .02335240 11870-4 10986-2 0 9994 +2 41476 51.6204 288.5305 0012717 288.4489 71.5067 16.20615210 53079 +NODES 2 +1 41477U 98067HX 17109.78732856 .00065132 00000-0 42046-3 0 9993 +2 41477 51.6317 305.4154 0003507 222.8310 137.2416 15.75484120 52843 +NODES 1 +1 41478U 98067HY 17109.81327838 .00066571 00000-0 43583-3 0 9993 +2 41478 51.6337 305.5905 0003334 219.7891 140.2864 15.75153441 52848 +FLOCK 2E'-1 +1 41479U 98067HZ 17109.82905449 .00029193 00000-0 27831-3 0 9992 +2 41479 51.6365 313.2731 0001172 62.9361 297.1754 15.66532776 52708 +FLOCK 2E'-3 +1 41480U 98067JA 17109.78977551 .00023981 00000-0 22881-3 0 9991 +2 41480 51.6367 313.0301 0001516 116.2427 243.8724 15.66630662 52697 +FLOCK 2E'-2 +1 41481U 98067JB 17109.83105879 .00025245 00000-0 23401-3 0 9998 +2 41481 51.6355 311.7758 0001181 45.0304 315.0788 15.67316853 52705 +FLOCK 2E'-4 +1 41482U 98067JC 17109.79676564 .00028405 00000-0 24875-3 0 9995 +2 41482 51.6352 311.5368 0001631 168.7346 191.3688 15.68647594 52701 +FLOCK 2E-1 +1 41483U 98067ID 17109.65478592 .00019453 00000-0 19150-3 0 9995 +2 41483 51.6381 314.4039 0002624 157.9400 202.1709 15.65994639 52522 +FLOCK 2E-2 +1 41484U 98067JE 17109.82139276 .00023265 00000-0 21668-3 0 9991 +2 41484 51.6388 312.5323 0002244 167.0663 193.0391 15.67251790 52561 +FLOCK 2E-3 +1 41486U 98067JG 17109.83030932 .00019642 00000-0 19928-3 0 9993 +2 41486 51.6376 314.8200 0002650 199.1890 160.9006 15.65226077 52551 +FLOCK 2E-4 +1 41487U 98067JH 17109.84556035 .00021562 00000-0 21013-3 0 9994 +2 41487 51.6376 313.3996 0002901 202.4468 157.6401 15.66171142 52573 +FLOCK 2E-6 +1 41563U 98067JM 17109.78874028 .00018524 00000-0 19029-3 0 9995 +2 41563 51.6372 315.2682 0001335 51.8098 308.3017 15.64958450 50616 +FLOCK 2E-5 +1 41564U 98067JN 17109.79523798 .00018624 00000-0 19210-3 0 9995 +2 41564 51.6372 315.3186 0001291 58.7101 301.4020 15.64849440 50604 +FLOCK 2E-7 +1 41565U 98067JP 17109.77087667 .00027808 00000-0 25811-3 0 9992 +2 41565 51.6365 312.8853 0002940 243.9307 116.1387 15.67223362 50539 +FLOCK 2E-8 +1 41566U 98067JQ 17109.80005150 .00089692 00000-0 42658-3 0 9991 +2 41566 51.6335 301.7154 0005913 241.2167 118.8242 15.82123501 50671 +FLOCK 2E'-5 +1 41567U 98067JR 17109.82240982 .00018645 00000-0 19803-3 0 9994 +2 41567 51.6378 316.2578 0003052 269.9747 90.0898 15.64101875 50468 +FLOCK 2E'-6 +1 41568U 98067JS 17109.73365885 .00019933 00000-0 19922-3 0 9998 +2 41568 51.6366 314.8878 0002651 264.8215 95.2478 15.65593919 50502 +FLOCK 2E'-8 +1 41569U 98067JT 17109.81323064 .00028772 00000-0 26479-3 0 9997 +2 41569 51.6363 312.4223 0001607 185.1389 174.9591 15.67417153 50424 +FLOCK 2E'-7 +1 41570U 98067JU 17109.84953955 .00031567 00000-0 26673-3 0 9992 +2 41570 51.6369 310.4309 0002960 184.1959 175.9014 15.69458790 50470 +FLOCK 2E-9 +1 41571U 98067JV 17109.82645424 .00028760 00000-0 26059-3 0 9999 +2 41571 51.6370 311.7739 0002674 242.4455 117.6270 15.67801154 50410 +FLOCK 2E-10 +1 41572U 98067JW 17109.81540411 .00024857 00000-0 23657-3 0 9993 +2 41572 51.6371 313.2010 0003003 248.3230 111.7447 15.66668690 50397 +FLOCK 2E-12 +1 41573U 98067JX 17109.77960367 .00027556 00000-0 25527-3 0 9992 +2 41573 51.6367 312.9551 0002571 267.1560 92.9142 15.67278525 50390 +FLOCK 2E-11 +1 41574U 98067JY 17109.78226357 .00026708 00000-0 24509-3 0 9995 +2 41574 51.6353 312.1863 0003298 269.1599 90.9019 15.67528751 50407 +FLOCK 2E'-9 +1 41575U 98067JZ 17109.81056748 .00029764 00000-0 26509-3 0 9992 +2 41575 51.6348 311.6084 0002751 288.6496 71.4202 15.68204720 50402 +FLOCK 2E'-10 +1 41576U 98067KA 17109.77269490 .00030074 00000-0 27691-3 0 9997 +2 41576 51.6376 312.9270 0002762 288.6796 71.3901 15.67378357 50288 +FLOCK 2E'-11 +1 41577U 98067KB 17109.79101284 .00023668 00000-0 22296-3 0 9993 +2 41577 51.6378 313.0548 0003312 262.9815 97.0805 15.66954445 50106 +FLOCK 2E'-12 +1 41578U 98067KC 17109.83071225 .00028915 00000-0 26144-3 0 9996 +2 41578 51.6355 312.5190 0003879 246.8376 113.2211 15.67846378 50119 +FLOCK 2E'-13 +1 41761U 98067KH 17109.80002983 .00014655 00000-0 18690-3 0 9995 +2 41761 51.6392 324.4021 0007265 49.8199 310.3429 15.59526131 33795 +FLOCK 2E'-14 +1 41762U 98067KJ 17109.85521685 .00012951 00000-0 16504-3 0 9995 +2 41762 51.6404 324.0354 0007100 50.3983 309.7636 15.59672213 33808 +FLOCK 2E'-16 +1 41763U 98067KK 17109.84145497 .00015760 00000-0 19696-3 0 9994 +2 41763 51.6404 323.9389 0006632 60.9401 299.2256 15.59999189 33766 +FLOCK 2E'-15 +1 41764U 98067KL 17109.87177553 .00013668 00000-0 17536-3 0 9992 +2 41764 51.6402 324.1424 0006951 56.4927 303.6730 15.59436947 33760 +TIANGONG-2 +1 41765U 16057A 17109.88457597 .00006208 00000-0 76612-4 0 9995 +2 41765 42.7849 342.3366 0007020 274.6731 154.6477 15.60877974 33874 +FLOCK 2E'-18 +1 41769U 98067KM 17109.85904600 .00012974 00000-0 16652-3 0 9993 +2 41769 51.6402 324.0512 0006179 77.3335 282.8349 15.59486030 33761 +FLOCK 2E'-17 +1 41776U 98067KN 17109.85282571 .00010304 00000-0 13324-3 0 9995 +2 41776 51.6411 324.0213 0006338 78.3972 281.7732 15.59560942 33750 +FLOCK 2E'-19 +1 41777U 98067KP 17109.85740966 .00015381 00000-0 18245-3 0 9990 +2 41777 51.6392 322.5300 0005414 79.0163 281.1440 15.61402073 33734 +FLOCK 2E'-20 +1 41782U 98067KQ 17109.83324911 .00018487 00000-0 22266-3 0 9990 +2 41782 51.6405 323.1334 0005543 75.7821 284.3788 15.60844608 33593 +SOYUZ-MS 02 +1 41820U 16063A 17099.31803792 .00003510 00000-0 60428-4 0 9993 +2 41820 51.6436 21.5790 0006756 40.2971 107.7536 15.54046698 51040 +BANXING-2 +1 41834U 16057H 17109.90404225 .00010491 00000-0 10102-3 0 9995 +2 41834 42.7856 340.6951 0007273 205.2685 229.1726 15.66598364 27965 +SOYUZ-MS 03 +1 41864U 16070A 17108.56623476 .00002987 00000-0 52374-4 0 9994 +2 41864 51.6439 335.4785 0007166 70.0921 13.3272 15.54123193 23600 +STARS-C +1 41895U 98067KR 17109.79899468 .00030018 00000-0 38671-3 0 9995 +2 41895 51.6404 327.3984 0005536 106.1447 254.0155 15.58751599 18878 +TANCREDO-1 +1 41931U 98067KT 17109.86190081 .00052089 00000-0 58691-3 0 9995 +2 41931 51.6395 326.3112 0006129 69.5695 290.5957 15.61995558 14461 +ITF-2 +1 41932U 98067KU 17109.85588580 .00016634 00000-0 22758-3 0 9991 +2 41932 51.6413 327.7805 0006108 60.3108 299.8492 15.57538630 14445 +WASEDA-SAT3 +1 41933U 98067KV 17109.84844175 .00021108 00000-0 28355-3 0 9997 +2 41933 51.6407 327.7291 0005970 62.7540 297.4060 15.57848382 14443 +EGG +1 41934U 98067KW 17109.82873718 .00359689 00000-0 22549-2 0 9997 +2 41934 51.6334 324.5691 0004769 232.7194 127.3371 15.75166791 14578 +AOBA-VELOX 3 +1 41935U 98067KX 17109.85496819 .00018693 00000-0 25356-3 0 9991 +2 41935 51.6411 327.7732 0005547 65.6383 294.5187 15.57678773 14541 +TUPOD +1 41936U 98067KY 17109.76502401 .00076370 00000-0 79702-3 0 9997 +2 41936 51.6390 326.4192 0004334 84.8776 275.2714 15.63809782 13933 +OSNSAT +1 41939U 98067KZ 17109.84725302 .00038473 00000-0 46963-3 0 9991 +2 41939 51.6399 326.9674 0006966 65.0500 295.1216 15.60039674 13811 +PROGRESS-MS 05 +1 42056U 17010A 17108.56623476 .00002987 00000-0 52374-4 0 9993 +2 42056 51.6439 335.4785 0007166 70.0921 13.3272 15.54123193 8629 +LEMUR-2-REDFERN-GOES +1 42059U 98067LA 17109.86490573 .00020711 00000-0 29467-3 0 9992 +2 42059 51.6413 328.5872 0009106 82.8311 277.3716 15.56286742 6922 +TECHEDSAT 5 +1 42066U 98067LB 17109.86435488 .00105210 00000-0 11946-2 0 9994 +2 42066 51.6390 327.8308 0003545 127.5897 232.5420 15.61508635 6667 +LEMUR-2-TRUTNA +1 42067U 98067LC 17109.85891074 .00025317 00000-0 35271-3 0 9998 +2 42067 51.6412 328.5475 0008572 83.5926 276.6041 15.56728774 6755 +LEMUR-2-AUSTINTACIOUS +1 42068U 98067LD 17109.86578689 .00018494 00000-0 26447-3 0 9997 +2 42068 51.6410 328.5924 0008622 83.6075 276.5898 15.56237023 6857 +LEMUR-2-TRUTNAHD +1 42069U 98067LE 17109.86629258 .00021052 00000-0 29958-3 0 9991 +2 42069 51.6412 328.5961 0008488 82.8885 277.3071 15.56276065 6908 +ISS DEB +1 42434U 98067LF 17109.82210271 .00056714 00000-0 79599-3 0 9993 +2 42434 51.6406 329.0485 0005861 67.1845 292.9765 15.56154397 3068 +CYGNUS OA-7 +1 42681U 17019A 17109.46972691 -.00000487 00000-0 00000-0 0 9991 +2 42681 51.6511 331.0240 0010106 169.9930 268.8149 15.53958196 134 diff --git a/data/scene/satellites/verify_satellites_lua_output.lua b/data/scene/satellites/verify_satellites_lua_output.lua new file mode 100644 index 0000000000..224ce53cc0 --- /dev/null +++ b/data/scene/satellites/verify_satellites_lua_output.lua @@ -0,0 +1,48 @@ +#!/bin/lua + +function tableLength(T) + local count = 0 + for _ in pairs(T) do count = count + 1 end + return count +end + +output = dofile("satellites.mod") +outputLen = tableLength(output) + +for i=1,outputLen do + type=output[i].Renderable.Type + print("------------", i) + if( type == "RenderablePlane" ) then + print(output[i].Name) + print(output[i].Parent) + print(output[i].Renderable.Type) + print(output[i].Renderable.Size[1]) + print(output[i].Renderable.Size[2]) + print(output[i].Renderable.Origin) + print(output[i].Renderable.Body) + print(output[i].Renderable.Billboard) + print(output[i].Renderable.Texture) + print(output[i].Transform.Translation.Type) + print(output[i].Transform.Translation.Body) + print(output[i].Transform.Translation.Observer) + print(output[i].Transform.Translation.File) + print(output[i].Transform.Translation.LineNum) + print(output[i].Transform.Scale.Type) + print(output[i].Transform.Scale.Scale) + elseif( type == "RenderableTrailOrbit" ) then + print(output[i].Name) + print(output[i].Parent) + print(output[i].Renderable.Type) + print(output[i].Renderable.Translation.Type) + print(output[i].Renderable.Translation.Body) + print(output[i].Renderable.Translation.Observer) + print(output[i].Renderable.Translation.File) + print(output[i].Renderable.Translation.LineNum) + print(output[i].Renderable.Color[1]) + print(output[i].Renderable.Color[2]) + print(output[i].Renderable.Color[3]) + print(output[i].Renderable.Period) + print(output[i].Renderable.Resolution) + print(output[i].GuiName) + end +end diff --git a/include/openspace/engine/downloadmanager.h b/include/openspace/engine/downloadmanager.h index 366ff8ea58..db7cff07ea 100644 --- a/include/openspace/engine/downloadmanager.h +++ b/include/openspace/engine/downloadmanager.h @@ -85,9 +85,19 @@ public: DownloadManager(std::string requestURL, int applicationVersion, bool useMultithreadedDownload = true); - // callbacks happen on a different thread - std::shared_ptr downloadFile(const std::string& url, const ghoul::filesystem::File& file, + //downloadFile + // url - specifies the target of the download + // file - specifies path to local saved file + // overrideFile - if true, overrides existing file of same name + // failOnError - if true, http codes >= 400 (client/server errors) result in fail + // timeout_secs - timeout in seconds before giving up on download (0 = no timeout) + // finishedCallback - callback when download finished (happens on different thread) + // progressCallback - callback for status during (happens on different thread) + std::shared_ptr downloadFile(const std::string& url, + const ghoul::filesystem::File& file, bool overrideFile = true, + bool failOnError = false, + unsigned int timeout_secs = 0, DownloadFinishedCallback finishedCallback = DownloadFinishedCallback(), DownloadProgressCallback progressCallback = DownloadProgressCallback() ); diff --git a/modules/space/translation/tletranslation.cpp b/modules/space/translation/tletranslation.cpp index 14e65d5b9e..b0fe0f2c3c 100644 --- a/modules/space/translation/tletranslation.cpp +++ b/modules/space/translation/tletranslation.cpp @@ -31,9 +31,11 @@ #include #include #include +#include namespace { const char* KeyFile = "File"; + const char* KeyLineNum = "LineNum"; // The list of leap years only goes until 2056 as we need to touch this file then // again anyway ;) @@ -183,7 +185,8 @@ namespace { // 3 using namespace std::chrono; int SecondsPerDay = static_cast(seconds(hours(24)).count()); - double nSecondsSince2000 = (daysSince2000 + daysInYear) * SecondsPerDay; + //Need to subtract 1 from daysInYear since it is not a zero-based count + double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay; // 4 // We need to remove additionbal leap seconds past 2000 and add them prior to @@ -244,6 +247,12 @@ documentation::Documentation TLETranslation::Documentation() { new StringVerifier, "Specifies the filename of the Two-Line-Element file", Optional::No + }, + { + KeyLineNum, + new DoubleGreaterVerifier(0), + "Specifies the line number within the file where the group of 3 TLE lines begins (1-based)", + Optional::No } }, Exhaustive::No @@ -261,10 +270,11 @@ TLETranslation::TLETranslation(const ghoul::Dictionary& dictionary) ); std::string file = dictionary.value(KeyFile); - readTLEFile(file); + int lineNum = dictionary.value(KeyLineNum); + readTLEFile(file, lineNum); } -void TLETranslation::readTLEFile(const std::string& filename) { +void TLETranslation::readTLEFile(const std::string& filename, int lineNum) { ghoul_assert(FileSys.fileExists(filename), "The filename must exist"); std::ifstream file; @@ -283,101 +293,87 @@ void TLETranslation::readTLEFile(const std::string& filename) { double epoch = 0.0; } keplerElements; - enum class State { - Initial = 0, - ReadFirstLine, - ReadSecondLine, - Finished = ReadSecondLine - }; - - State state = State::Initial; - std::string line; - while (std::getline(file, line)) { - if (line[0] == '1') { - // First line - // Field Columns Content - // 1 01-01 Line number - // 2 03-07 Satellite number - // 3 08-08 Classification (U = Unclassified) - // 4 10-11 International Designator (Last two digits of launch year) - // 5 12-14 International Designator (Launch number of the year) - // 6 15-17 International Designator(piece of the launch) A - // 7 19-20 Epoch Year(last two digits of year) - // 8 21-32 Epoch(day of the year and fractional portion of the day) - // 9 34-43 First Time Derivative of the Mean Motion divided by two - // 10 45-52 Second Time Derivative of Mean Motion divided by six - // 11 54-61 BSTAR drag term(decimal point assumed)[10] - 11606 - 4 - // 12 63-63 The "Ephemeris type" - // 13 65-68 Element set number.Incremented when a new TLE is generated - // 14 69-69 Checksum (modulo 10) - - keplerElements.epoch = epochFromSubstring(line.substr(18, 14)); - state = State::ReadFirstLine; - } - else if (line[0] == '2') { - if (state != State::ReadFirstLine) { - throw ghoul::RuntimeError( - "Malformed TLE file: '" + filename + "'. Line 2 before line 1", - "TLETranslation" - ); - } - // Second line - //Field Columns Content - // 1 01-01 Line number - // 2 03-07 Satellite number - // 3 09-16 Inclination (degrees) - // 4 18-25 Right ascension of the ascending node (degrees) - // 5 27-33 Eccentricity (decimal point assumed) - // 6 35-42 Argument of perigee (degrees) - // 7 44-51 Mean Anomaly (degrees) - // 8 53-63 Mean Motion (revolutions per day) - // 9 64-68 Revolution number at epoch (revolutions) - // 10 69-69 Checksum (modulo 10) - - std::stringstream stream; - stream.exceptions(std::ios::failbit); - - // Get inclination - stream.str(line.substr(8, 8)); - stream >> keplerElements.inclination; - stream.clear(); - - // Get Right ascension of the ascending node - stream.str(line.substr(17, 8)); - stream >> keplerElements.ascendingNode; - stream.clear(); + //Loop through and throw out lines until getting to the linNum of interest + for (unsigned int i = 1; i < lineNum; ++i) + std::getline(file, line); + std::getline(file, line); //Throw out the TLE title line (1st) - // Get Eccentricity - stream.str("0." + line.substr(26, 7)); - stream >> keplerElements.eccentricity; - stream.clear(); - - // Get argument of periapsis - stream.str(line.substr(34, 8)); - stream >> keplerElements.argumentOfPeriapsis; - stream.clear(); - - // Get mean anomaly - stream.str(line.substr(43, 8)); - stream >> keplerElements.meanAnomaly; - stream.clear(); - - // Get mean motion - stream.str(line.substr(52, 11)); - stream >> keplerElements.meanMotion; - - state = State::ReadSecondLine; - break; - } + std::getline(file, line); //Get line 1 of TLE format + if (line[0] == '1') { + // First line + // Field Columns Content + // 1 01-01 Line number + // 2 03-07 Satellite number + // 3 08-08 Classification (U = Unclassified) + // 4 10-11 International Designator (Last two digits of launch year) + // 5 12-14 International Designator (Launch number of the year) + // 6 15-17 International Designator(piece of the launch) A + // 7 19-20 Epoch Year(last two digits of year) + // 8 21-32 Epoch(day of the year and fractional portion of the day) + // 9 34-43 First Time Derivative of the Mean Motion divided by two + // 10 45-52 Second Time Derivative of Mean Motion divided by six + // 11 54-61 BSTAR drag term(decimal point assumed)[10] - 11606 - 4 + // 12 63-63 The "Ephemeris type" + // 13 65-68 Element set number.Incremented when a new TLE is generated + // 14 69-69 Checksum (modulo 10) + keplerElements.epoch = epochFromSubstring(line.substr(18, 14)); + } else { + throw ghoul::RuntimeError("File " + filename + " @ line " + + std::to_string(lineNum + 1) + " doesn't have '1' header"); } - - if (state != State::Finished) { - throw ghoul::RuntimeError( - "Malformed TLE file: Line 1 or 2 missing", - "TLETranslation" - ); + + std::getline(file, line); //Get line 2 of TLE format + if (line[0] == '2') { + // Second line + //Field Columns Content + // 1 01-01 Line number + // 2 03-07 Satellite number + // 3 09-16 Inclination (degrees) + // 4 18-25 Right ascension of the ascending node (degrees) + // 5 27-33 Eccentricity (decimal point assumed) + // 6 35-42 Argument of perigee (degrees) + // 7 44-51 Mean Anomaly (degrees) + // 8 53-63 Mean Motion (revolutions per day) + // 9 64-68 Revolution number at epoch (revolutions) + // 10 69-69 Checksum (modulo 10) + + std::stringstream stream; + stream.exceptions(std::ios::failbit); + + // Get inclination + stream.str(line.substr(8, 8)); + stream >> keplerElements.inclination; + stream.clear(); + + // Get Right ascension of the ascending node + stream.str(line.substr(17, 8)); + stream >> keplerElements.ascendingNode; + stream.clear(); + + // Get Eccentricity + stream.str("0." + line.substr(26, 7)); + stream >> keplerElements.eccentricity; + stream.clear(); + + // Get argument of periapsis + stream.str(line.substr(34, 8)); + stream >> keplerElements.argumentOfPeriapsis; + stream.clear(); + + // Get mean anomaly + stream.str(line.substr(43, 8)); + stream >> keplerElements.meanAnomaly; + stream.clear(); + + // Get mean motion + stream.str(line.substr(52, 11)); + stream >> keplerElements.meanMotion; + } else { + throw ghoul::RuntimeError("File " + filename + " @ line " + + std::to_string(lineNum + 2) + " doesn't have '2' header"); } + file.close(); // Calculate the semi major axis based on the mean motion using kepler's laws keplerElements.semiMajorAxis = calculateSemiMajorAxis(keplerElements.meanMotion); diff --git a/modules/space/translation/tletranslation.h b/modules/space/translation/tletranslation.h index 730fbbe677..a720b8127a 100644 --- a/modules/space/translation/tletranslation.h +++ b/modules/space/translation/tletranslation.h @@ -38,6 +38,11 @@ namespace openspace { */ class TLETranslation : public KeplerTranslation { public: + struct FileFormatError : public ghoul::RuntimeError { + explicit FileFormatError(std::string offense); + std::string offense; + }; + /** * Constructor for the TLETranslation class. The \p dictionary must contain a key for * the file that contains the TLE information. The ghoul::Dictionary will be tested @@ -61,13 +66,14 @@ private: * disallowed values (see KeplerTranslation::setKeplerElements), a * KeplerTranslation::RangeError is thrown. * \param filename The path to the file that contains the TLE file. + * \param lineNum The line number in the file where the set of 3 TLE lines starts * \throw std::system_error if the TLE file is malformed (does not contain at least * two lines that start with \c 1 and \c 2. * \throw KeplerTranslation::RangeError If the Keplerian elements are outside of * the valid range supported by Kepler::setKeplerElements * \pre The \p filename must exist */ - void readTLEFile(const std::string& filename); + void readTLEFile(const std::string& filename, int lineNum); }; } // namespace openspace diff --git a/scripts/bind_keys_satellites.lua b/scripts/bind_keys_satellites.lua new file mode 100644 index 0000000000..c2d53dbd7c --- /dev/null +++ b/scripts/bind_keys_satellites.lua @@ -0,0 +1,23 @@ +--[[ OpenSpace keybinding script loaded from the satellites.scene file ]]-- + +-- Load the common helper functions +dofile(openspace.absPath('${SCRIPTS}/common.lua')) +dofile(openspace.absPath('${SCRIPTS}/bind_common_keys.lua')) + +-- Set focuses + +openspace.bindKey( + "p" , + "if gpsVis then gpsVis = false; else gpsVis = true; end; openspace.setPropertyValue('gps-ops*.renderable.enabled', not gpsVis)", + "Toggles visibility of gps satellites." +) +openspace.bindKey( + "s" , + "if stVis then stVis = false; else stVis = true; end; openspace.setPropertyValue('station*.renderable.enabled', not stVis)", + "Toggles visibility of stations." +) +openspace.bindKey( + "g" , + "if geoVis then geoVis = false; else geoVis = true; end; openspace.setPropertyValue('geo*.renderable.enabled', not geoVis)", + "Toggles visibility of geostationary." +) \ No newline at end of file diff --git a/src/engine/downloadmanager.cpp b/src/engine/downloadmanager.cpp index af894ff333..51ab4e8580 100644 --- a/src/engine/downloadmanager.cpp +++ b/src/engine/downloadmanager.cpp @@ -158,6 +158,7 @@ DownloadManager::DownloadManager(std::string requestURL, int applicationVersion, std::shared_ptr DownloadManager::downloadFile( const std::string& url, const ghoul::filesystem::File& file, bool overrideFile, + bool failOnError, unsigned int timeout_secs, DownloadFinishedCallback finishedCallback, DownloadProgressCallback progressCallback) { if (!overrideFile && FileSys.fileExists(file)) @@ -182,13 +183,23 @@ std::shared_ptr DownloadManager::downloadFile( //LDEBUG("Start downloading file: '" << url << "' into file '" << file.path() << "'"); - auto downloadFunction = [url, finishedCallback, progressCallback, future, fp]() { + auto downloadFunction = [url, + failOnError, + timeout_secs, + finishedCallback, + progressCallback, + future, + fp]() { CURL* curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData); + if (timeout_secs) + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout_secs); + if (failOnError) + curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); ProgressInformation p = { future, @@ -337,6 +348,8 @@ std::vector> DownloadManager::downl line, destination.path() + "/" + file, overrideFiles, + false, + 0, [](const FileFuture& f) { LDEBUG("Finished: " << f.filePath); } ); if (future) @@ -349,6 +362,8 @@ std::vector> DownloadManager::downl fullRequest, requestFile, true, + false, + 0, callback ); diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 11de8ea7ab..b92582582a 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -1242,6 +1242,12 @@ scripting::LuaLibrary OpenSpaceEngine::luaLibrary() { "", "Writes out documentation files" }, + { + "downloadFile", + &luascriptfunctions::downloadFile, + "", + "Downloads a file from Lua scope" + }, { "addVirtualProperty", &luascriptfunctions::addVirtualProperty, diff --git a/src/engine/openspaceengine_lua.inl b/src/engine/openspaceengine_lua.inl index ad48ed9751..cd2695a65b 100644 --- a/src/engine/openspaceengine_lua.inl +++ b/src/engine/openspaceengine_lua.inl @@ -139,6 +139,31 @@ int removeAllVirtualProperties(lua_State* L) { return 0; } +/** +* \ingroup LuaScripts +* downloadFile(): +* Downloads a file from Lua interpreter +*/ +int downloadFile(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 2) + return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments); + std::string uri = luaL_checkstring(L, -2); + std::string savePath = luaL_checkstring(L, -1); + + const std::string _loggerCat = "OpenSpaceEngine"; + LINFO("Downloading file from " << uri); + DownloadManager dm = openspace::DownloadManager("", 1, false); + std::shared_ptr future = + dm.downloadFile(uri, absPath("${SCENE}/" + savePath), true, true, 5); + if (!future || (future && !future->isFinished)) { + std::string errorMsg = "Download failed"; + if (future) + errorMsg += ": " + future->errorMessage; + return luaL_error(L, errorMsg.c_str()); + } + return 1; +} } // namespace luascriptfunctions } // namespace openspace From bb05ef46a1e5e539ade30893d7c3d57de2118164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Nov=C3=A9n?= Date: Tue, 6 Jun 2017 13:44:27 -0400 Subject: [PATCH 08/12] Update json library to latest version (#322) --- ext/json/json.hpp | 10061 ++++++++++++++++++++++++++++++++------------ 1 file changed, 7414 insertions(+), 2647 deletions(-) diff --git a/ext/json/json.hpp b/ext/json/json.hpp index db73336723..6dfc1831fa 100644 --- a/ext/json/json.hpp +++ b/ext/json/json.hpp @@ -1,70 +1,70 @@ -/*! -@mainpage +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 2.1.1 +|_____|_____|_____|_|___| https://github.com/nlohmann/json -These pages contain the API documentation of JSON for Modern C++, a C++11 -header-only JSON class. +Licensed under the MIT License . +Copyright (c) 2013-2017 Niels Lohmann . -Class @ref nlohmann::basic_json is a good entry point for the documentation. +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: -@copyright The code is licensed under the [MIT - License](http://opensource.org/licenses/MIT): -
- Copyright © 2013-2016 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. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -@author [Niels Lohmann](http://nlohmann.me) -@see https://github.com/nlohmann/json to download the source code - -@version 1.1.0 +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. */ #ifndef NLOHMANN_JSON_HPP #define NLOHMANN_JSON_HPP -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform +#include // array +#include // assert +#include // isdigit +#include // and, not, or +#include // isfinite, labs, ldexp, signbit +#include // nullptr_t, ptrdiff_t, size_t +#include // int64_t, uint64_t +#include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull +#include // strlen +#include // forward_list +#include // function, hash, less +#include // initializer_list +#include // setw +#include // istream, ostream +#include // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator +#include // numeric_limits +#include // locale +#include // map +#include // addressof, allocator, allocator_traits, unique_ptr +#include // accumulate +#include // stringstream +#include // domain_error, invalid_argument, out_of_range +#include // getline, stoi, string, to_string +#include // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type +#include // declval, forward, make_pair, move, pair, swap +#include // vector -// enable ssize_t on MinGW -#ifdef __GNUC__ - #ifdef __MINGW32__ - #include +// exclude unsupported compilers +#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__) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif @@ -74,10 +74,30 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation. #pragma GCC diagnostic ignored "-Wfloat-equal" #endif -// enable ssize_t for MSVC -#ifdef _MSC_VER - #include - using ssize_t = SSIZE_T; +// disable documentation warnings on clang +#if defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow for portable deprecation warnings +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) + #define JSON_DEPRECATED __declspec(deprecated) +#else + #define JSON_DEPRECATED +#endif + +// allow to disable exceptions +#if not defined(JSON_NOEXCEPTION) || defined(__EXCEPTIONS) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) +#else + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) #endif /*! @@ -88,51 +108,869 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation. namespace nlohmann { - /*! @brief unnamed namespace with internal helper functions + +This namespace collects some functions that could not be defined inside the +@ref basic_json class. + +@since version 2.1.0 +*/ +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 @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 */ -namespace +enum class value_t : uint8_t { -/*! -@brief Helper to determine whether there's a key_type for T. -@sa http://stackoverflow.com/a/7728728/266378 -*/ -template -struct has_mapped_type -{ - private: - template static char test(typename C::mapped_type*); - template static char (&test(...))[2]; - public: - static constexpr bool value = sizeof(test(0)) == 1; + 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) + discarded ///< discarded by the 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 +- furthermore, each type is not smaller than itself + +@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 + } + }; + + // discarded values are not comparable + if (lhs == value_t::discarded or rhs == value_t::discarded) + { + return false; + } + + return order[static_cast(lhs)] < + order[static_cast(rhs)]; } + +///////////// +// helpers // +///////////// + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +template +using uncvref_t = typename std::remove_cv::type>::type; + +// taken from http://stackoverflow.com/a/26936864/266378 +template +using is_unscoped_enum = + std::integral_constant::value and + std::is_enum::value>; + +/* +Implementation of two C++17 constructs: conjunction, negation. This is needed +to avoid evaluating all the traits in a condition + +For example: not std::is_same::value and has_value_type::value +will not compile when T = void (on MSVC at least). Whereas +conjunction>, has_value_type>::value will +stop evaluating if negation<...>::value == false + +Please note that those constructs must be used with caution, since symbols can +become very long quickly (which can slow down compilation and cause MSVC +internal compiler errors). Only use it when you have to (see example ahead). +*/ +template struct conjunction : std::true_type {}; +template struct conjunction : B1 {}; +template +struct conjunction : std::conditional, B1>::type {}; + +template struct negation : std::integral_constant < bool, !B::value > {}; + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + + +////////////////// +// constructors // +////////////////// + +template struct external_constructor; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + { + 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_type = value_t::string; + j.m_value = s; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + { + // replace infinity and NAN by null + if (not std::isfinite(val)) + { + j = BasicJsonType{}; + } + else + { + 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_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_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_type = value_t::array; + j.m_value = arr; + j.assert_invariant(); + } + + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + { + using std::begin; + using std::end; + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + { + j.m_type = value_t::object; + j.m_value = obj; + j.assert_invariant(); + } + + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + { + using std::begin; + using std::end; + + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); + j.assert_invariant(); + } +}; + + +//////////////////////// +// has_/is_ functions // +//////////////////////// + +/*! +@brief Helper to determine whether there's a key_type for T. + +This helper is used to tell associative containers apart from other containers +such as sequence containers. For instance, `std::map` passes the test as it +contains a `mapped_type`, whereas `std::vector` fails the test. + +@sa http://stackoverflow.com/a/7728728/266378 +@since version 1.0.0, overworked in version 2.0.6 +*/ +#define NLOHMANN_JSON_HAS_HELPER(type) \ + template struct has_##type { \ + private: \ + template \ + static int detect(U &&); \ + static void detect(...); \ + public: \ + static constexpr bool value = \ + std::is_integral()))>::value; \ + } + +NLOHMANN_JSON_HAS_HELPER(mapped_type); +NLOHMANN_JSON_HAS_HELPER(key_type); +NLOHMANN_JSON_HAS_HELPER(value_type); +NLOHMANN_JSON_HAS_HELPER(iterator); + +#undef NLOHMANN_JSON_HAS_HELPER + + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl +{ + static constexpr auto value = + std::is_constructible::value and + std::is_constructible::value; +}; + +template +struct is_compatible_object_type +{ + static auto constexpr value = is_compatible_object_type_impl < + conjunction>, + has_mapped_type, + has_key_type>::value, + typename BasicJsonType::object_t, CompatibleObjectType >::value; +}; + +template +struct is_basic_json_nested_type +{ + static auto constexpr value = std::is_same::value or + std::is_same::value or + std::is_same::value or + std::is_same::value or + std::is_same::value; +}; + +template +struct is_compatible_array_type +{ + static auto constexpr value = + conjunction>, + negation>, + negation>, + negation>, + has_value_type, + has_iterator>::value; +}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + std::is_constructible::value and + CompatibleLimits::is_integer and + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type +{ + static constexpr auto value = + is_compatible_integer_type_impl < + std::is_integral::value and + not std::is_same::value, + RealIntegerType, CompatibleNumberIntegerType > ::value; +}; + + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json +{ + private: + // also check the return type of from_json + template::from_json( + std::declval(), std::declval()))>::value>> + static int detect(U&&); + static void detect(...); + + public: + static constexpr bool value = std::is_integral>()))>::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 +{ + private: + template < + typename U, + typename = enable_if_t::from_json(std::declval()))>::value >> + static int detect(U&&); + static void detect(...); + + public: + static constexpr bool value = std::is_integral>()))>::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +template +struct has_to_json +{ + private: + template::to_json( + std::declval(), std::declval()))> + static int detect(U&&); + static void detect(...); + + public: + static constexpr bool value = std::is_integral>()))>::value; +}; + + +///////////// +// 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::value, int> = 0> +void to_json(BasicJsonType& j, FloatType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template < + typename BasicJsonType, typename CompatibleNumberUnsignedType, + enable_if_t::value, int> = 0 > +void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template < + typename BasicJsonType, typename CompatibleNumberIntegerType, + enable_if_t::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, UnscopedEnumType e) noexcept +{ + external_constructor::construct(j, e); +} + +template < + typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < + is_compatible_array_type::value or + std::is_same::value, + int > = 0 > +void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +{ + external_constructor::construct(j, arr); +} + +template < + typename BasicJsonType, typename CompatibleObjectType, + enable_if_t::value, + int> = 0 > +void to_json(BasicJsonType& j, const CompatibleObjectType& arr) +{ + external_constructor::construct(j, arr); +} + + +/////////////// +// from_json // +/////////////// + +// overloads for basic_json template parameters +template::value and + not 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; + } + default: + { + JSON_THROW( + std::domain_error("type must be number, but is " + j.type_name())); + } + } +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +{ + if (not j.is_boolean()) + { + JSON_THROW(std::domain_error("type must be boolean, but is " + j.type_name())); + } + b = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +{ + if (not j.is_string()) + { + JSON_THROW(std::domain_error("type must be string, but is " + j.type_name())); + } + 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, UnscopedEnumType& e) +{ + typename std::underlying_type::type val; + get_arithmetic_value(j, val); + e = static_cast(val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) +{ + if (not j.is_array()) + { + JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); + } + arr = *j.template get_ptr(); +} + +// forward_list doesn't have an insert method +template +void from_json(const BasicJsonType& j, std::forward_list& l) +{ + // do not perform the check when user wants to retrieve jsons + // (except when it's null.. ?) + if (j.is_null()) + { + JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); + } + if (not std::is_same::value) + { + if (not j.is_array()) + { + JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); + } + } + for (auto it = j.rbegin(), end = j.rend(); it != end; ++it) + { + l.push_front(it->template get()); + } +} + +template +void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>) +{ + using std::begin; + using std::end; + + std::transform(j.begin(), j.end(), + std::inserter(arr, end(arr)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); +} + +template +auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>) +-> decltype( + arr.reserve(std::declval()), + void()) +{ + using std::begin; + using std::end; + + arr.reserve(j.size()); + std::transform( + j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); +} + +template::value and + not std::is_same::value, int> = 0> +void from_json(const BasicJsonType& j, CompatibleArrayType& arr) +{ + if (j.is_null()) + { + JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); + } + + // when T == BasicJsonType, do not check if value_t is correct + if (not std::is_same::value) + { + if (not j.is_array()) + { + JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); + } + } + from_json_array_impl(j, arr, priority_tag<1> {}); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, CompatibleObjectType& obj) +{ + if (not j.is_object()) + { + JSON_THROW(std::domain_error("type must be object, but is " + j.type_name())); + } + + auto inner_object = j.template get_ptr(); + using std::begin; + using std::end; + // we could avoid the assignment, but this might require a for loop, which + // might be less efficient than the container constructor for some + // containers (would it?) + obj = CompatibleObjectType(begin(*inner_object), end(*inner_object)); +} + +// 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::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + not 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; + } + default: + { + JSON_THROW(std::domain_error("type must be number, but is " + j.type_name())); + } + } +} + +struct to_json_fn +{ + private: + template + auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) + { + return to_json(j, std::forward(val)); + } + + template + void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept + { + static_assert(sizeof(BasicJsonType) == 0, + "could not find to_json() method in T's namespace"); + } + + public: + template + void operator()(BasicJsonType& j, T&& val) const + noexcept(noexcept(std::declval().call(j, std::forward(val), priority_tag<1> {}))) + { + return call(j, std::forward(val), priority_tag<1> {}); + } +}; + +struct from_json_fn +{ + private: + template + auto call(const BasicJsonType& j, T& val, priority_tag<1>) const + noexcept(noexcept(from_json(j, val))) + -> decltype(from_json(j, val), void()) + { + return from_json(j, val); + } + + template + void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept + { + static_assert(sizeof(BasicJsonType) == 0, + "could not find from_json() method in T's namespace"); + } + + public: + template + void operator()(const BasicJsonType& j, T& val) const + noexcept(noexcept(std::declval().call(j, val, priority_tag<1> {}))) + { + return call(j, val, priority_tag<1> {}); + } +}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; +} // namespace detail + + +/// namespace to hold default `to_json` / `from_json` functions +namespace +{ +constexpr const auto& to_json = detail::static_const::value; +constexpr const auto& from_json = detail::static_const::value; +} + + +/*! +@brief default JSONSerializer template argument + +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer +{ + /*! + @brief convert a JSON value to any value type + + This function is usually called by the `get()` function of the + @ref basic_json class (either explicit or via conversion operators). + + @param[in] j JSON value to read from + @param[in,out] val value to write to + */ + template + static void from_json(BasicJsonType&& j, ValueType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) + { + ::nlohmann::from_json(std::forward(j), val); + } + + /*! + @brief convert any value type to a JSON value + + This function is usually called by the constructors of the @ref basic_json + class. + + @param[in,out] j JSON value to write to + @param[in] val value to read from + */ + template + static void to_json(BasicJsonType& j, ValueType&& val) noexcept( + noexcept(::nlohmann::to_json(j, std::forward(val)))) + { + ::nlohmann::to_json(j, std::forward(val)); + } +}; + + /*! @brief a class to store JSON values -@tparam ObjectType type for JSON objects (@c std::map by default; will be used +@tparam ObjectType type for JSON objects (`std::map` by default; will be used in @ref object_t) -@tparam ArrayType type for JSON arrays (@c std::vector by default; will be used +@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used in @ref array_t) -@tparam StringType type for JSON strings and object keys (@c std::string by +@tparam StringType type for JSON strings and object keys (`std::string` by default; will be used in @ref string_t) -@tparam BooleanType type for JSON booleans (@c `bool` by default; will be used +@tparam BooleanType type for JSON booleans (`bool` by default; will be used in @ref boolean_t) -@tparam NumberIntegerType type for JSON integer numbers (@c `int64_t` by +@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by default; will be used in @ref number_integer_t) -@tparam NumberFloatType type for JSON floating-point numbers (@c `double` by +@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c +`uint64_t` by default; will be used in @ref number_unsigned_t) +@tparam NumberFloatType type for JSON floating-point numbers (`double` by default; will be used in @ref number_float_t) -@tparam AllocatorType type of the allocator to use (@c `std::allocator` by +@tparam AllocatorType type of the allocator to use (`std::allocator` by default) +@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` +and `from_json()` (@ref adl_serializer by default) @requirement The class satisfies the following concept requirements: - Basic - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): - JSON values can be default constructed. The result will be a JSON null value. + JSON values can be default constructed. The result will be a JSON null + value. - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): A JSON value can be constructed from an rvalue argument. - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): @@ -147,8 +985,8 @@ default) - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): JSON values have [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): - All non-static data members are private and standard layout types, the class - has no virtual functions or (virtual) base classes. + All non-static data members are private and standard layout types, the + class has no virtual functions or (virtual) base classes. - Library-wide - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): JSON values can be compared with `==`, see @ref @@ -169,11 +1007,19 @@ default) JSON values can be used like STL containers and provide reverse iterator access. +@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(). + @internal @note ObjectType trick from http://stackoverflow.com/a/9860911 @endinternal -@see RFC 7159 +@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange +Format](http://rfc7159.net/rfc7159) @since version 1.0.0 @@ -184,29 +1030,37 @@ template < template class ArrayType = std::vector, class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = int64_t, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, class NumberFloatType = double, - template class AllocatorType = std::allocator + template class AllocatorType = std::allocator, + template class JSONSerializer = adl_serializer > class basic_json { private: + template friend struct detail::external_constructor; /// workaround type for MSVC - using basic_json_t = basic_json; + using basic_json_t = basic_json; public: + using value_t = detail::value_t; + // forward declarations + template class iter_impl; + template class json_reverse_iterator; + class json_pointer; + template + using json_serializer = JSONSerializer; ///////////////////// // 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 @@ -230,13 +1084,10 @@ class basic_json /// the type of an element const pointer using const_pointer = typename std::allocator_traits::const_pointer; - // forward declaration - template class json_reverse_iterator; - /// an iterator for a basic_json container - class iterator; + using iterator = iter_impl; /// a const iterator for a basic_json container - class const_iterator; + 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 @@ -253,12 +1104,92 @@ class basic_json return allocator_type(); } + /*! + @brief returns version information on the library + + This function returns a JSON object with information about the library, + including the version number and information on the platform and compiler. + + @return JSON object holding version information + key | description + ----------- | --------------- + `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). + `copyright` | The copyright line for the library as string. + `name` | The name of the library as string. + `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. + `url` | The URL of the project as string. + `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). + + @liveexample{The following code shows an example output of the `meta()` + function.,meta} + + @complexity Constant. + + @since 2.1.0 + */ + static basic_json meta() + { + basic_json result; + + result["copyright"] = "(C) 2013-2017 Niels Lohmann"; + result["name"] = "JSON for Modern C++"; + result["url"] = "https://github.com/nlohmann/json"; + result["version"] = + { + {"string", "2.1.1"}, + {"major", 2}, + {"minor", 1}, + {"patch", 1} + }; + +#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(__clang__) + result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; +#elif defined(__ICC) || defined(__INTEL_COMPILER) + result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; +#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. /// @{ /*! @@ -274,8 +1205,8 @@ class basic_json @tparam ObjectType the container to store objects (e.g., `std::map` or `std::unordered_map`) - @tparam StringType the type of the keys or names (e.g., `std::string`). The - comparison function `std::less` is used to order elements + @tparam StringType the type of the keys or names (e.g., `std::string`). + The comparison function `std::less` is used to order elements inside the container. @tparam AllocatorType the allocator to use for objects (e.g., `std::allocator`) @@ -283,8 +1214,8 @@ class basic_json #### Default type With the default values for @a ObjectType (`std::map`), @a StringType - (`std::string`), and @a AllocatorType (`std::allocator`), the default value - for @a object_t is: + (`std::string`), and @a AllocatorType (`std::allocator`), the default + value for @a object_t is: @code {.cpp} std::map< @@ -301,16 +1232,16 @@ class basic_json the default type, objects have the following behavior: - When all names are unique, objects will be interoperable in the sense - that all software implementations receiving that object will agree on the - name-value mappings. + that all software implementations receiving that object will agree on + the name-value mappings. - When the names within an object are not unique, later stored name/value pairs overwrite previously stored name/value pairs, leaving the used names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will be treated as equal and both stored as `{"key": 1}`. - Internally, name/value pairs are stored in lexicographical order of the - names. Objects will also be serialized (see @ref dump) in this order. For - instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and - serialized as `{"a": 2, "b": 1}`. + names. Objects will also be serialized (see @ref dump) in this order. + For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored + and serialized as `{"a": 2, "b": 1}`. - When comparing objects, the order of the name/value pairs is irrelevant. This makes objects interoperable in the sense that they will not be affected by these differences. For instance, `{"b": 1, "a": 2}` and @@ -323,23 +1254,24 @@ class basic_json In this class, the object's limit of nesting is not constraint explicitly. However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the @ref - max_size function of a JSON object. + runtime environment. A theoretical limit can be queried by calling the + @ref max_size function of a JSON object. #### Storage Objects are stored as pointers in a @ref basic_json type. That is, for any - access to object values, a pointer of type `object_t*` must be dereferenced. + access to object values, a pointer of type `object_t*` must be + dereferenced. @sa @ref array_t -- type for an array value @since version 1.0.0 - @note The order name/value pairs are added to the object is *not* preserved - by the library. Therefore, iterating an object may return name/value pairs - in a different order than they were originally stored. In fact, keys will - be traversed in alphabetical order as `std::map` with `std::less` is used - by default. Please note this behavior conforms to [RFC + @note The order name/value pairs are added to the object is *not* + preserved by the library. Therefore, iterating an object may return + name/value pairs in a different order than they were originally stored. In + fact, keys will be traversed in alphabetical order as `std::map` with + `std::less` is used by default. Please note this behavior conforms to [RFC 7159](http://rfc7159.net/rfc7159), because any order implements the specified "unordered" nature of JSON objects. */ @@ -360,7 +1292,7 @@ class basic_json @tparam ArrayType container type to store arrays (e.g., `std::vector` or `std::list`) - @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) + @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) #### Default type @@ -381,8 +1313,8 @@ class basic_json In this class, the array's limit of nesting is not constraint explicitly. However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the @ref - max_size function of a JSON array. + runtime environment. A theoretical limit can be queried by calling the + @ref max_size function of a JSON array. #### Storage @@ -402,8 +1334,8 @@ class basic_json > A string is a sequence of zero or more Unicode characters. To store objects in C++, a type is defined by the template parameter - described below. Unicode values are split by the JSON class into byte-sized - characters during deserialization. + described below. Unicode values are split by the JSON class into + byte-sized characters during deserialization. @tparam StringType the container to store strings (e.g., `std::string`). Note this container is used for keys/names in objects, see @ref object_t. @@ -417,6 +1349,12 @@ class basic_json std::string @endcode + #### Encoding + + Strings are stored in UTF-8 encoding. Therefore, functions like + `std::string::size()` or `std::string::length()` return the number of + bytes in the string rather than the number of characters or glyphs. + #### String comparison [RFC 7159](http://rfc7159.net/rfc7159) states: @@ -472,18 +1410,19 @@ class basic_json @brief a type for a number (integer) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most programming - > languages. A number is represented in base 10 using decimal digits. It - > contains an integer component that may be prefixed with an optional minus - > sign, which may be followed by a fraction part and/or an exponent part. - > Leading zeros are not allowed. (...) Numeric values that cannot be - > represented in the grammar below (such as Infinity and NaN) are not - > permitted. + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. - This description includes both integer and floating-point numbers. However, - C++ allows more precise storage if it is known whether the number is an - integer or a floating-point number. Therefore, two different types, @ref - number_integer_t and @ref number_float_t are used. + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. To store integer numbers in C++, a type is defined by the template parameter @a NumberIntegerType which chooses the type to use. @@ -502,8 +1441,8 @@ class basic_json - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as octal number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. During - deserialization, leading zeros yield an error. + instance, the C++ integer literal `010` will be serialized to `8`. + During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits @@ -514,9 +1453,10 @@ class basic_json When the default type is used, the maximal integer number that can be stored is `9223372036854775807` (INT64_MAX) and the minimal integer number that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers - that are out of range will yield over/underflow when used in a constructor. - During deserialization, too large or small integer numbers will be - automatically be stored as @ref number_float_t. + that are out of range will yield over/underflow when used in a + constructor. During deserialization, too large or small integer numbers + will be automatically be stored as @ref number_unsigned_t or @ref + number_float_t. [RFC 7159](http://rfc7159.net/rfc7159) further states: > Note that when such software is used, numbers that are integers and are @@ -532,26 +1472,100 @@ class basic_json @sa @ref number_float_t -- type for number values (floating-point) + @sa @ref number_unsigned_t -- type for number values (unsigned integer) + @since version 1.0.0 */ using number_integer_t = NumberIntegerType; + /*! + @brief a type for a number (unsigned) + + [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. + + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. + + To store unsigned integer numbers in C++, a type is defined by the + template parameter @a NumberUnsignedType which chooses the type to use. + + #### Default type + + With the default values for @a NumberUnsignedType (`uint64_t`), the + default value for @a number_unsigned_t is: + + @code {.cpp} + uint64_t + @endcode + + #### Default behavior + + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in integer literals lead to an interpretation as octal + number. Internally, the value will be stored as decimal number. For + instance, the C++ integer literal `010` will be serialized to `8`. + During deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. + + #### Limits + + [RFC 7159](http://rfc7159.net/rfc7159) specifies: + > An implementation may set limits on the range and precision of numbers. + + When the default type is used, the maximal integer number that can be + stored is `18446744073709551615` (UINT64_MAX) and the minimal integer + number that can be stored is `0`. Integer numbers that are out of range + will yield over/underflow when used in a constructor. During + deserialization, too large or small integer numbers will be automatically + be stored as @ref number_integer_t or @ref number_float_t. + + [RFC 7159](http://rfc7159.net/rfc7159) further states: + > Note that when such software is used, numbers that are integers and are + > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense + > that implementations will agree exactly on their numeric values. + + As this range is a subrange (when considered in conjunction with the + number_integer_t type) of the exactly supported range [0, UINT64_MAX], + this class's integer type is interoperable. + + #### Storage + + Integer number values are stored directly inside a @ref basic_json type. + + @sa @ref number_float_t -- type for number values (floating-point) + @sa @ref number_integer_t -- type for number values (integer) + + @since version 2.0.0 + */ + using number_unsigned_t = NumberUnsignedType; + /*! @brief a type for a number (floating-point) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most programming - > languages. A number is represented in base 10 using decimal digits. It - > contains an integer component that may be prefixed with an optional minus - > sign, which may be followed by a fraction part and/or an exponent part. - > Leading zeros are not allowed. (...) Numeric values that cannot be - > represented in the grammar below (such as Infinity and NaN) are not - > permitted. + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. - This description includes both integer and floating-point numbers. However, - C++ allows more precise storage if it is known whether the number is an - integer or a floating-point number. Therefore, two different types, @ref - number_integer_t and @ref number_float_t are used. + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. To store floating-point numbers in C++, a type is defined by the template parameter @a NumberFloatType which chooses the type to use. @@ -568,8 +1582,8 @@ class basic_json #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in floating-point literals will be ignored. Internally, the - value will be stored as decimal number. For instance, the C++ + leading zeros in floating-point literals will be ignored. Internally, + the value will be stored as decimal number. For instance, the C++ floating-point literal `01.2` will be serialized to `1.2`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. @@ -580,9 +1594,9 @@ class basic_json > This specification allows implementations to set limits on the range and > precision of numbers accepted. Since software that implements IEEE > 754-2008 binary64 (double precision) numbers is generally available and - > widely used, good interoperability can be achieved by implementations that - > expect no more precision or range than these provide, in the sense that - > implementations will approximate JSON numbers within the expected + > widely used, good interoperability can be achieved by implementations + > that expect no more precision or range than these provide, in the sense + > that implementations will approximate JSON numbers within the expected > precision. This implementation does exactly follow this approach, as it uses double @@ -597,41 +1611,16 @@ class basic_json @sa @ref number_integer_t -- type for number values (integer) + @sa @ref number_unsigned_t -- type for number values (unsigned integer) + @since version 1.0.0 */ using number_float_t = NumberFloatType; /// @} - - /////////////////////////// - // 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 is_null(), @ref - is_object(), @ref is_array(), @ref is_string(), @ref is_boolean(), @ref - is_number(), and @ref is_discarded() rely on it. - - @since version 1.0.0 - */ - enum class value_t : 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 (integer) - number_float, ///< number value (floating-point) - discarded ///< discarded by the the parser callback function - }; - - private: + /// helper for exception-safe object creation template static T* create(Args&& ... args) @@ -643,6 +1632,7 @@ class basic_json }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward(args)...); + assert(object != nullptr); return object.release(); } @@ -653,7 +1643,24 @@ class basic_json /*! @brief a JSON value - The actual storage for a JSON value of the @ref basic_json class. + 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 + 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 */ @@ -669,15 +1676,19 @@ class basic_json 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() noexcept = default; + 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 @@ -715,14 +1726,29 @@ class basic_json break; } + case value_t::number_unsigned: + { + number_unsigned = number_unsigned_t(0); + break; + } + case value_t::number_float: { number_float = number_float_t(0.0); break; } + case value_t::null: + { + break; + } + default: { + if (t == value_t::null) + { + JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE + } break; } } @@ -747,6 +1773,21 @@ class basic_json } }; + /*! + @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. + */ + void assert_invariant() const + { + assert(m_type != value_t::object or m_value.object != nullptr); + assert(m_type != value_t::array or m_value.array != nullptr); + assert(m_type != value_t::string or m_value.string != nullptr); + } public: ////////////////////////// @@ -759,6 +1800,8 @@ class basic_json This enumeration lists the parser events that can trigger calling a callback function of type @ref parser_callback_t during parsing. + @image html callback_events.png "Example when certain parse events are triggered" + @since version 1.0.0 */ enum class parse_event_t : uint8_t @@ -781,12 +1824,13 @@ class basic_json @brief per-element parser callback type With a parser callback function, the result of parsing a JSON text can be - influenced. When passed to @ref parse(std::istream&, parser_callback_t) or - @ref parse(const string_t&, parser_callback_t), it is called on certain - events (passed as @ref parse_event_t via parameter @a event) with a set - recursion depth @a depth and context JSON value @a parsed. The return value - of the callback function is a boolean indicating whether the element that - emitted the callback shall be kept or not. + influenced. When passed to @ref parse(std::istream&, const + parser_callback_t) or @ref parse(const CharT, const parser_callback_t), + it is called on certain events (passed as @ref parse_event_t via parameter + @a event) with a set recursion depth @a depth and context JSON value + @a parsed. The return value of the callback function is a boolean + indicating whether the element that emitted the callback shall be kept or + not. We distinguish six scenarios (determined by the event type) in which the callback function can be called. The following table describes the values @@ -801,13 +1845,15 @@ class basic_json parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value + @image html callback_events.png "Example when certain parse events are triggered" + Discarding a value (i.e., returning `false`) has different effects depending on the context in which function was called: - Discarded values in structured types are skipped. That is, the parser will behave as if the discarded value was never read. - - In case a value outside a structured type is skipped, it is replaced with - `null`. This case happens if the top-level element is skipped. + - In case a value outside a structured type is skipped, it is replaced + with `null`. This case happens if the top-level element is skipped. @param[in] depth the depth of the recursion during parsing @@ -822,11 +1868,13 @@ class basic_json skipped completely or replaced by an empty discarded object. @sa @ref parse(std::istream&, parser_callback_t) or - @ref parse(const string_t&, parser_callback_t) for examples + @ref parse(const CharT, const parser_callback_t) for examples @since version 1.0.0 */ - using parser_callback_t = std::function; + using parser_callback_t = std::function; ////////////////// @@ -834,6 +1882,8 @@ class basic_json ////////////////// /// @name constructors and destructors + /// Constructors of class @ref basic_json, copy/move constructor, copy + /// assignment, static functions creating objects, and the destructor. /// @{ /*! @@ -861,460 +1911,105 @@ class basic_json @liveexample{The following code shows the constructor for different @ref value_t values,basic_json__value_t} - @sa @ref basic_json(std::nullptr_t) -- create a `null` value - @sa @ref basic_json(boolean_t value) -- create a boolean value - @sa @ref basic_json(const string_t&) -- create a string value - @sa @ref basic_json(const object_t&) -- create a object value - @sa @ref basic_json(const array_t&) -- create a array value - @sa @ref basic_json(const number_float_t) -- create a number - (floating-point) value - @sa @ref basic_json(const number_integer_t) -- create a number (integer) - value - @since version 1.0.0 */ basic_json(const value_t value_type) : m_type(value_type), m_value(value_type) - {} + { + assert_invariant(); + } /*! - @brief create a null object (implicitly) + @brief create a null object - Create a `null` JSON value. This is the implicit version of the `null` - value constructor as it takes no parameters. + Create a `null` JSON value. It either takes a null pointer as parameter + (explicitly creating `null`) or no parameter (implicitly creating `null`). + The passed null pointer itself is not read -- it is only used to choose + the right constructor. @complexity Constant. - @requirement This function satisfies the Container requirements: - - The complexity is constant. - - As postcondition, it holds: `basic_json().empty() == true`. + @exceptionsafety No-throw guarantee: this constructor never throws + exceptions. - @liveexample{The following code shows the constructor for a `null` JSON - value.,basic_json} - - @sa @ref basic_json(std::nullptr_t) -- create a `null` value + @liveexample{The following code shows the constructor with and without a + null pointer parameter.,basic_json__nullptr_t} @since version 1.0.0 */ - basic_json() noexcept = default; - - /*! - @brief create a null object (explicitly) - - Create a `null` JSON value. This is the explicitly version of the `null` - value constructor as it takes a null pointer as parameter. It allows to - create `null` values by explicitly assigning a @c nullptr to a JSON value. - The passed null pointer itself is not read -- it is only used to choose the - right constructor. - - @complexity Constant. - - @liveexample{The following code shows the constructor with null pointer - parameter.,basic_json__nullptr_t} - - @sa @ref basic_json() -- default constructor (implicitly creating a `null` - value) - - @since version 1.0.0 - */ - basic_json(std::nullptr_t) noexcept + basic_json(std::nullptr_t = nullptr) noexcept : basic_json(value_t::null) - {} + { + assert_invariant(); + } /*! - @brief create an object (explicit) + @brief create a JSON value - Create an object JSON value with a given content. + This is a "catch all" constructor for all compatible JSON types; that is, + types for which a `to_json()` method exsits. The constructor forwards the + parameter @a val to that method (to `json_serializer::to_json` method + with `U = uncvref_t`, to be exact). - @param[in] val a value for the object + Template type @a CompatibleType includes, but is not limited to, the + following types: + - **arrays**: @ref array_t and all kinds of compatible containers such as + `std::vector`, `std::deque`, `std::list`, `std::forward_list`, + `std::array`, `std::set`, `std::unordered_set`, `std::multiset`, and + `unordered_multiset` with a `value_type` from which a @ref basic_json + value can be constructed. + - **objects**: @ref object_t and all kinds of compatible associative + containers such as `std::map`, `std::unordered_map`, `std::multimap`, + and `std::unordered_multimap` with a `key_type` compatible to + @ref string_t and a `value_type` from which a @ref basic_json value can + be constructed. + - **strings**: @ref string_t, string literals, and all compatible string + containers can be used. + - **numbers**: @ref number_integer_t, @ref number_unsigned_t, + @ref number_float_t, and all convertible number types such as `int`, + `size_t`, `int64_t`, `float` or `double` can be used. + - **boolean**: @ref boolean_t / `bool` can be used. - @complexity Linear in the size of the passed @a val. + See the examples below. - @throw std::bad_alloc if allocation for object value fails + @tparam CompatibleType a type such that: + - @a CompatibleType is not derived from `std::istream`, + - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move + constructors), + - @a CompatibleType is not a @ref basic_json nested type (e.g., + @ref json_pointer, @ref iterator, etc ...) + - @ref @ref json_serializer has a + `to_json(basic_json_t&, CompatibleType&&)` method - @liveexample{The following code shows the constructor with an @ref object_t - parameter.,basic_json__object_t} + @tparam U = `uncvref_t` - @sa @ref basic_json(const CompatibleObjectType&) -- create an object value - from a compatible STL container + @param[in] val the value to be forwarded - @since version 1.0.0 - */ - basic_json(const object_t& val) - : m_type(value_t::object), m_value(val) - {} + @complexity Usually linear in the size of the passed @a val, also + depending on the implementation of the called `to_json()` + method. - /*! - @brief create an object (implicit) - - Create an object JSON value with a given content. This constructor allows - any type that can be used to construct values of type @ref object_t. - Examples include the types `std::map` and `std::unordered_map`. - - @tparam CompatibleObjectType an object type whose `key_type` and - `value_type` is compatible to @ref object_t - - @param[in] val a value for the object - - @complexity Linear in the size of the passed @a val. - - @throw std::bad_alloc if allocation for object value fails + @throw what `json_serializer::to_json()` throws @liveexample{The following code shows the constructor with several - compatible object type parameters.,basic_json__CompatibleObjectType} + compatible types.,basic_json__CompatibleType} - @sa @ref basic_json(const object_t&) -- create an object value - - @since version 1.0.0 + @since version 2.1.0 */ - template ::value and - std::is_constructible::value, int>::type - = 0> - basic_json(const CompatibleObjectType& val) - : m_type(value_t::object) + template, + detail::enable_if_t::value and + not std::is_same::value and + not detail::is_basic_json_nested_type< + basic_json_t, U>::value and + detail::has_to_json::value, + int> = 0> + basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer::to_json( + std::declval(), std::forward(val)))) { - using std::begin; - using std::end; - m_value.object = create(begin(val), end(val)); + JSONSerializer::to_json(*this, std::forward(val)); + assert_invariant(); } - /*! - @brief create an array (explicit) - - Create an array JSON value with a given content. - - @param[in] val a value for the array - - @complexity Linear in the size of the passed @a val. - - @throw std::bad_alloc if allocation for array value fails - - @liveexample{The following code shows the constructor with an @ref array_t - parameter.,basic_json__array_t} - - @sa @ref basic_json(const CompatibleArrayType&) -- create an array value - from a compatible STL containers - - @since version 1.0.0 - */ - basic_json(const array_t& val) - : m_type(value_t::array), m_value(val) - {} - - /*! - @brief create an array (implicit) - - Create an array JSON value with a given content. This constructor allows - any type that can be used to construct values of type @ref array_t. - Examples include the types `std::vector`, `std::list`, and `std::set`. - - @tparam CompatibleArrayType an object type whose `value_type` is compatible - to @ref array_t - - @param[in] val a value for the array - - @complexity Linear in the size of the passed @a val. - - @throw std::bad_alloc if allocation for array value fails - - @liveexample{The following code shows the constructor with several - compatible array type parameters.,basic_json__CompatibleArrayType} - - @sa @ref basic_json(const array_t&) -- create an array value - - @since version 1.0.0 - */ - template ::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - std::is_constructible::value, int>::type - = 0> - basic_json(const CompatibleArrayType& val) - : m_type(value_t::array) - { - using std::begin; - using std::end; - m_value.array = create(begin(val), end(val)); - } - - /*! - @brief create a string (explicit) - - Create an string JSON value with a given content. - - @param[in] val a value for the string - - @complexity Linear in the size of the passed @a val. - - @throw std::bad_alloc if allocation for string value fails - - @liveexample{The following code shows the constructor with an @ref string_t - parameter.,basic_json__string_t} - - @sa @ref basic_json(const typename string_t::value_type*) -- create a - string value from a character pointer - @sa @ref basic_json(const CompatibleStringType&) -- create a string value - from a compatible string container - - @since version 1.0.0 - */ - basic_json(const string_t& val) - : m_type(value_t::string), m_value(val) - {} - - /*! - @brief create a string (explicit) - - Create a string JSON value with a given content. - - @param[in] val a literal value for the string - - @complexity Linear in the size of the passed @a val. - - @throw std::bad_alloc if allocation for string value fails - - @liveexample{The following code shows the constructor with string literal - parameter.,basic_json__string_t_value_type} - - @sa @ref basic_json(const string_t&) -- create a string value - @sa @ref basic_json(const CompatibleStringType&) -- create a string value - from a compatible string container - - @since version 1.0.0 - */ - basic_json(const typename string_t::value_type* val) - : basic_json(string_t(val)) - {} - - /*! - @brief create a string (implicit) - - Create a string JSON value with a given content. - - @param[in] val a value for the string - - @tparam CompatibleStringType an string type which is compatible to @ref - string_t - - @complexity Linear in the size of the passed @a val. - - @throw std::bad_alloc if allocation for string value fails - - @liveexample{The following code shows the construction of a string value - from a compatible type.,basic_json__CompatibleStringType} - - @sa @ref basic_json(const string_t&) -- create a string value - @sa @ref basic_json(const typename string_t::value_type*) -- create a - string value from a character pointer - - @since version 1.0.0 - */ - template ::value, int>::type - = 0> - basic_json(const CompatibleStringType& val) - : basic_json(string_t(val)) - {} - - /*! - @brief create a boolean (explicit) - - Creates a JSON boolean type from a given value. - - @param[in] val a boolean value to store - - @complexity Constant. - - @liveexample{The example below demonstrates boolean - values.,basic_json__boolean_t} - - @since version 1.0.0 - */ - basic_json(boolean_t val) - : m_type(value_t::boolean), m_value(val) - {} - - /*! - @brief create an integer number (explicit) - - Create an integer number JSON value with a given content. - - @tparam T helper type to compare number_integer_t and int (not visible in) - the interface. - - @param[in] val an integer to create a JSON number from - - @note This constructor would have the same signature as @ref - basic_json(const int value), so we need to switch this one off in case - number_integer_t is the same as int. This is done via the helper type @a T. - - @complexity Constant. - - @liveexample{The example below shows the construction of a JSON integer - number value.,basic_json__number_integer_t} - - @sa @ref basic_json(const int) -- create a number value (integer) - @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number - value (integer) from a compatible number type - - @since version 1.0.0 - */ - template::value) - and std::is_same::value - , int>::type = 0> - basic_json(const number_integer_t val) - : m_type(value_t::number_integer), m_value(val) - {} - - /*! - @brief create an integer number from an enum type (explicit) - - Create an integer number JSON value with a given content. - - @param[in] val an integer to create a JSON number from - - @note This constructor allows to pass enums directly to a constructor. As - C++ has no way of specifying the type of an anonymous enum explicitly, we - can only rely on the fact that such values implicitly convert to int. As - int may already be the same type of number_integer_t, we may need to switch - off the constructor @ref basic_json(const number_integer_t). - - @complexity Constant. - - @liveexample{The example below shows the construction of a JSON integer - number value from an anonymous enum.,basic_json__const_int} - - @sa @ref basic_json(const number_integer_t) -- create a number value - (integer) - @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number - value (integer) from a compatible number type - - @since version 1.0.0 - */ - basic_json(const int val) - : m_type(value_t::number_integer), - m_value(static_cast(val)) - {} - - /*! - @brief create an integer number (implicit) - - Create an integer number JSON value with a given content. This constructor - allows any type that can be used to construct values of type @ref - number_integer_t. Examples may include the types `int`, `int32_t`, or - `short`. - - @tparam CompatibleNumberIntegerType an integer type which is compatible to - @ref number_integer_t. - - @param[in] val an integer to create a JSON number from - - @complexity Constant. - - @liveexample{The example below shows the construction of several JSON - integer number values from compatible - types.,basic_json__CompatibleIntegerNumberType} - - @sa @ref basic_json(const number_integer_t) -- create a number value - (integer) - @sa @ref basic_json(const int) -- create a number value (integer) - - @since version 1.0.0 - */ - template::value and - std::numeric_limits::is_integer, CompatibleNumberIntegerType>::type - = 0> - basic_json(const CompatibleNumberIntegerType val) noexcept - : m_type(value_t::number_integer), - m_value(static_cast(val)) - {} - - /*! - @brief create a floating-point number (explicit) - - Create a floating-point number JSON value with a given content. - - @param[in] val a floating-point value to create a JSON number from - - @note RFC 7159 , section 6 - disallows NaN values: - > Numeric values that cannot be represented in the grammar below (such - > as Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is - created instead. - - @complexity Constant. - - @liveexample{The following example creates several floating-point - values.,basic_json__number_float_t} - - @sa @ref basic_json(const CompatibleNumberFloatType) -- create a number - value (floating-point) from a compatible number type - - @since version 1.0.0 - */ - basic_json(const number_float_t val) - : m_type(value_t::number_float), m_value(val) - { - // replace infinity and NAN by null - if (not std::isfinite(val)) - { - m_type = value_t::null; - m_value = json_value(); - } - } - - /*! - @brief create an floating-point number (implicit) - - Create an floating-point number JSON value with a given content. This - constructor allows any type that can be used to construct values of type - @ref number_float_t. Examples may include the types `float`. - - @tparam CompatibleNumberFloatType a floating-point type which is compatible - to @ref number_float_t. - - @param[in] val a floating-point to create a JSON number from - - @note RFC 7159 , section 6 - disallows NaN values: - > Numeric values that cannot be represented in the grammar below (such - > as Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is - created instead. - - @complexity Constant. - - @liveexample{The example below shows the construction of several JSON - floating-point number values from compatible - types.,basic_json__CompatibleNumberFloatType} - - @sa @ref basic_json(const number_float_t) -- create a number value - (floating-point) - - @since version 1.0.0 - */ - template::value and - std::is_floating_point::value>::type - > - basic_json(const CompatibleNumberFloatType val) noexcept - : basic_json(number_float_t(val)) - {} - /*! @brief create a container (array or object) from an initializer list @@ -1325,21 +2020,21 @@ class basic_json 1. If the list is empty, an empty JSON object value `{}` is created. 2. If the list consists of pairs whose first element is a string, a JSON - object value is created where the first elements of the pairs are treated - as keys and the second elements are as values. + object value is created where the first elements of the pairs are + treated as keys and the second elements are as values. 3. In all other cases, an array is created. The rules aim to create the best fit between a C++ initializer list and JSON values. The rationale is as follows: 1. The empty initializer list is written as `{}` which is exactly an empty - JSON object. + JSON object. 2. C++ has now way of describing mapped types other than to list a list of - pairs. As JSON requires that keys must be of type string, rule 2 is the - weakest constraint one can pose on initializer lists to interpret them as - an object. + pairs. As JSON requires that keys must be of type string, rule 2 is the + weakest constraint one can pose on initializer lists to interpret them + as an object. 3. In all other cases, the initializer list could not be interpreted as - JSON object type, so interpreting it as JSON array type is safe. + JSON object type, so interpreting it as JSON array type is safe. With the rules described above, the following JSON values cannot be expressed by an initializer list: @@ -1362,20 +2057,20 @@ class basic_json used by the functions @ref array(std::initializer_list) and @ref object(std::initializer_list). - @param[in] manual_type internal parameter; when @a type_deduction is set to - `false`, the created JSON value will use the provided type (only @ref + @param[in] manual_type internal parameter; when @a type_deduction is set + to `false`, the created JSON value will use the provided type (only @ref value_t::array and @ref value_t::object are valid); when @a type_deduction is set to `true`, this parameter has no effect - @throw std::domain_error if @a type_deduction is `false`, @a manual_type is - `value_t::object`, but @a init contains an element which is not a pair + @throw std::domain_error if @a type_deduction is `false`, @a manual_type + is `value_t::object`, but @a init contains an element which is not a pair whose first element is a string; example: `"cannot create object from initializer list"` @complexity Linear in the size of the initializer list @a init. @liveexample{The example below shows how JSON values are created from - initializer lists,basic_json__list_init_t} + initializer lists.,basic_json__list_init_t} @sa @ref array(std::initializer_list) -- create a JSON array value from an initializer list @@ -1388,22 +2083,13 @@ class basic_json bool type_deduction = true, value_t manual_type = value_t::array) { - // the initializer list could describe an object - bool is_an_object = true; - // check if each element is an array with two elements whose first // element is a string - for (const auto& element : init) + bool is_an_object = std::all_of(init.begin(), init.end(), + [](const basic_json & element) { - if (not element.is_array() or element.size() != 2 - or not element[0].is_string()) - { - // we found an element that makes it impossible to use the - // initializer list as object - is_an_object = false; - break; - } - } + return element.is_array() and element.size() == 2 and element[0].is_string(); + }); // adjust type if type deduction is not wanted if (not type_deduction) @@ -1417,7 +2103,7 @@ class basic_json // if object is wanted but impossible, throw an exception if (manual_type == value_t::object and not is_an_object) { - throw std::domain_error("cannot create object from initializer list"); + JSON_THROW(std::domain_error("cannot create object from initializer list")); } } @@ -1427,19 +2113,19 @@ class basic_json m_type = value_t::object; m_value = value_t::object; - assert(m_value.object != nullptr); - - for (auto& element : init) + std::for_each(init.begin(), init.end(), [this](const basic_json & element) { - m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1])); - } + m_value.object->emplace(*(element[0].m_value.string), element[1]); + }); } else { // the initializer list describes an array -> create array m_type = value_t::array; - m_value.array = create(std::move(init)); + m_value.array = create(init); } + + assert_invariant(); } /*! @@ -1449,8 +2135,8 @@ class basic_json list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the initializer list is empty, the empty array `[]` is created. - @note This function is only needed to express two edge cases that cannot be - realized with the initializer list constructor (@ref + @note This function is only needed to express two edge cases that cannot + be realized with the initializer list constructor (@ref basic_json(std::initializer_list, bool, value_t)). These cases are: 1. creating an array whose elements are all pairs whose first element is a @@ -1466,7 +2152,7 @@ class basic_json @complexity Linear in the size of @a init. - @liveexample{The following code shows an example for the @ref array + @liveexample{The following code shows an example for the `array` function.,array} @sa @ref basic_json(std::initializer_list, bool, value_t) -- @@ -1493,8 +2179,8 @@ class basic_json related function @ref array(std::initializer_list), there are no cases which can only be expressed by this function. That is, any initializer list @a init can also be passed to the initializer list - constructor - @ref basic_json(std::initializer_list, bool, value_t). + constructor @ref basic_json(std::initializer_list, bool, + value_t). @param[in] init initializer list to create an object from (optional) @@ -1506,7 +2192,7 @@ class basic_json @complexity Linear in the size of @a init. - @liveexample{The following code shows an example for the @ref object + @liveexample{The following code shows an example for the `object` function.,object} @sa @ref basic_json(std::initializer_list, bool, value_t) -- @@ -1525,8 +2211,8 @@ class basic_json /*! @brief construct an array with count copies of given value - Constructs a JSON array value by creating @a cnt copies of a passed - value. In case @a cnt is `0`, an empty array is created. As postcondition, + Constructs a JSON array value by creating @a cnt copies of a passed value. + In case @a cnt is `0`, an empty array is created. As postcondition, `std::distance(begin(),end()) == cnt` holds. @param[in] cnt the number of JSON copies of @a val to create @@ -1544,6 +2230,7 @@ class basic_json : m_type(value_t::array) { m_value.array = create(cnt, val); + assert_invariant(); } /*! @@ -1554,8 +2241,8 @@ class basic_json - In case of primitive types (number, boolean, or string), @a first must be `begin()` and @a last must be `end()`. In this case, the value is copied. Otherwise, std::out_of_range is thrown. - - In case of structured types (array, object), the constructor behaves - as similar versions for `std::vector`. + - In case of structured types (array, object), the constructor behaves as + similar versions for `std::vector`. - In case of a null type, std::domain_error is thrown. @tparam InputIT an input iterator type (@ref iterator or @ref @@ -1564,14 +2251,17 @@ class basic_json @param[in] first begin of the range to copy from (included) @param[in] last end of the range to copy from (excluded) + @pre Iterators @a first and @a last must be initialized. **This + precondition is enforced with an assertion.** + @throw std::domain_error if iterators are not compatible; that is, do not belong to the same JSON value; example: `"iterators are not compatible"` @throw std::out_of_range if iterators are for a primitive type (number, boolean, or string) where an out of range error can be detected easily; example: `"iterators out of range"` @throw std::bad_alloc if allocation for object, array, or string fails - @throw std::domain_error if called with a null value; example: `"cannot use - construct with iterators from null"` + @throw std::domain_error if called with a null value; example: `"cannot + use construct with iterators from null"` @complexity Linear in distance between @a first and @a last. @@ -1580,31 +2270,35 @@ class basic_json @since version 1.0.0 */ - template ::value or - std::is_same::value - , int>::type - = 0> - basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type) + template::value or + std::is_same::value, int>::type = 0> + basic_json(InputIT first, InputIT last) { + assert(first.m_object != nullptr); + assert(last.m_object != nullptr); + // make sure iterator fits the current value if (first.m_object != last.m_object) { - throw std::domain_error("iterators are not compatible"); + JSON_THROW(std::domain_error("iterators are not compatible")); } + // 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 (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { - throw std::out_of_range("iterators out of range"); + JSON_THROW(std::out_of_range("iterators out of range")); } break; } @@ -1619,50 +2313,90 @@ class basic_json { case value_t::number_integer: { - assert(first.m_object != nullptr); 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: { - assert(first.m_object != nullptr); m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { - assert(first.m_object != nullptr); m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { - assert(first.m_object != nullptr); 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); + 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); + m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); break; } default: { - assert(first.m_object != nullptr); - throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); + JSON_THROW(std::domain_error("cannot use construct with iterators from " + first.m_object->type_name())); } } + + assert_invariant(); + } + + /*! + @brief construct a JSON value given an input stream + + @param[in,out] i stream to read a serialized JSON value from + @param[in] cb a parser callback function of type @ref parser_callback_t + which is used to control the deserialization by filtering unwanted values + (optional) + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. The complexity can be higher if the parser callback function + @a cb has a super-linear complexity. + + @note A UTF-8 byte order mark is silently ignored. + + @deprecated This constructor is deprecated and will be removed in version + 3.0.0 to unify the interface of the library. Deserialization will be + done by stream operators or by calling one of the `parse` functions, + e.g. @ref parse(std::istream&, const parser_callback_t). That is, calls + like `json j(i);` for an input stream @a i need to be replaced by + `json j = json::parse(i);`. See the example below. + + @liveexample{The example below demonstrates constructing a JSON value from + a `std::stringstream` with and without callback + function.,basic_json__istream} + + @since version 2.0.0, deprecated in version 2.0.3, to be removed in + version 3.0.0 + */ + JSON_DEPRECATED + explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr) + { + *this = parser(i, cb).parse(); + assert_invariant(); } /////////////////////////////////////// @@ -1678,7 +2412,9 @@ class basic_json @complexity Linear in the size of @a other. - @requirement This function satisfies the Container requirements: + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is linear. - As postcondition, it holds: `other == basic_json(other)`. @@ -1692,25 +2428,25 @@ class 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: { - assert(other.m_value.object != nullptr); m_value = *other.m_value.object; break; } case value_t::array: { - assert(other.m_value.array != nullptr); m_value = *other.m_value.array; break; } case value_t::string: { - assert(other.m_value.string != nullptr); m_value = *other.m_value.string; break; } @@ -1727,6 +2463,12 @@ class basic_json 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; @@ -1738,6 +2480,8 @@ class basic_json break; } } + + assert_invariant(); } /*! @@ -1762,23 +2506,30 @@ class basic_json : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) { + // check that passed value is valid + other.assert_invariant(); + // invalidate payload other.m_type = value_t::null; other.m_value = {}; + + assert_invariant(); } /*! @brief copy assignment Copy assignment operator. Copies a JSON value via the "copy and swap" - strategy: It is expressed in terms of the copy constructor, destructor, and - the swap() member function. + strategy: It is expressed in terms of the copy constructor, destructor, + and the swap() member function. @param[in] other value to copy from @complexity Linear. - @requirement This function satisfies the Container requirements: + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is linear. @liveexample{The code below shows and example for the copy assignment. It @@ -1795,9 +2546,14 @@ class basic_json 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); + + assert_invariant(); return *this; } @@ -1808,7 +2564,9 @@ class basic_json @complexity Linear. - @requirement This function satisfies the Container requirements: + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is linear. - All stored elements are destroyed and all memory is freed. @@ -1816,6 +2574,8 @@ class basic_json */ ~basic_json() { + assert_invariant(); + switch (m_type) { case value_t::object: @@ -1858,19 +2618,20 @@ class basic_json /////////////////////// /// @name object inspection + /// Functions to inspect the type of a JSON value. /// @{ /*! @brief serialization Serialization function for JSON values. The function tries to mimic - Python's @p json.dumps() function, and currently supports its @p indent + Python's `json.dumps()` function, and currently supports its @a indent parameter. - @param[in] indent if indent is nonnegative, then array elements and object - members will be pretty-printed with that indent level. An indent level of 0 - will only insert newlines. -1 (the default) selects the most compact - representation + @param[in] indent If indent is nonnegative, then array elements and object + members will be pretty-printed with that indent level. An indent level of + `0` will only insert newlines. `-1` (the default) selects the most compact + representation. @return string containing the serialization of the JSON value @@ -1909,12 +2670,15 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies @ref type() for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `type()` for all JSON types.,type} @since version 1.0.0 */ - value_t type() const noexcept + constexpr value_t type() const noexcept { return m_type; } @@ -1930,12 +2694,21 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies @ref is_primitive for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_primitive()` for all JSON types.,is_primitive} + @sa @ref is_structured() -- returns whether JSON value is structured + @sa @ref is_null() -- returns whether JSON value is `null` + @sa @ref is_string() -- returns whether JSON value is a string + @sa @ref is_boolean() -- returns whether JSON value is a boolean + @sa @ref is_number() -- returns whether JSON value is a number + @since version 1.0.0 */ - bool is_primitive() const noexcept + constexpr bool is_primitive() const noexcept { return is_null() or is_string() or is_boolean() or is_number(); } @@ -1950,12 +2723,19 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies @ref is_structured for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_structured()` for all JSON types.,is_structured} + @sa @ref is_primitive() -- returns whether value is primitive + @sa @ref is_array() -- returns whether value is an array + @sa @ref is_object() -- returns whether value is an object + @since version 1.0.0 */ - bool is_structured() const noexcept + constexpr bool is_structured() const noexcept { return is_array() or is_object(); } @@ -1969,12 +2749,15 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies @ref is_null for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_null()` for all JSON types.,is_null} @since version 1.0.0 */ - bool is_null() const noexcept + constexpr bool is_null() const noexcept { return m_type == value_t::null; } @@ -1988,12 +2771,15 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies @ref is_boolean for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_boolean()` for all JSON types.,is_boolean} @since version 1.0.0 */ - bool is_boolean() const noexcept + constexpr bool is_boolean() const noexcept { return m_type == value_t::boolean; } @@ -2004,20 +2790,26 @@ class basic_json This function returns true iff the JSON value is a number. This includes both integer and floating-point values. - @return `true` if type is number (regardless whether integer or - floating-type), `false` otherwise. + @return `true` if type is number (regardless whether integer, unsigned + integer or floating-type), `false` otherwise. @complexity Constant. - @liveexample{The following code exemplifies @ref is_number for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number()` for all JSON types.,is_number} - @sa @ref is_number_integer() -- check if value is an integer number + @sa @ref is_number_integer() -- check if value is an integer or unsigned + integer number + @sa @ref is_number_unsigned() -- check if value is an unsigned integer + number @sa @ref is_number_float() -- check if value is a floating-point number @since version 1.0.0 */ - bool is_number() const noexcept + constexpr bool is_number() const noexcept { return is_number_integer() or is_number_float(); } @@ -2025,45 +2817,84 @@ class basic_json /*! @brief return whether value is an integer number - This function returns true iff the JSON value is an integer number. This - excludes floating-point values. + This function returns true iff the JSON value is an integer or unsigned + integer number. This excludes floating-point values. - @return `true` if type is an integer number, `false` otherwise. + @return `true` if type is an integer or unsigned integer number, `false` + otherwise. @complexity Constant. - @liveexample{The following code exemplifies @ref is_number_integer for all + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_integer()` for all JSON types.,is_number_integer} @sa @ref is_number() -- check if value is a number + @sa @ref is_number_unsigned() -- check if value is an unsigned integer + number @sa @ref is_number_float() -- check if value is a floating-point number @since version 1.0.0 */ - bool is_number_integer() const noexcept + constexpr bool is_number_integer() const noexcept { - return m_type == value_t::number_integer; + return m_type == value_t::number_integer or m_type == value_t::number_unsigned; + } + + /*! + @brief return whether value is an unsigned integer number + + This function returns true iff the JSON value is an unsigned integer + number. This excludes floating-point and (signed) integer values. + + @return `true` if type is an unsigned integer number, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_unsigned()` for all + JSON types.,is_number_unsigned} + + @sa @ref is_number() -- check if value is a number + @sa @ref is_number_integer() -- check if value is an integer or unsigned + integer number + @sa @ref is_number_float() -- check if value is a floating-point number + + @since version 2.0.0 + */ + constexpr bool is_number_unsigned() const noexcept + { + return m_type == value_t::number_unsigned; } /*! @brief return whether value is a floating-point number This function returns true iff the JSON value is a floating-point number. - This excludes integer values. + This excludes integer and unsigned integer values. @return `true` if type is a floating-point number, `false` otherwise. @complexity Constant. - @liveexample{The following code exemplifies @ref is_number_float for all + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_float()` for all JSON types.,is_number_float} @sa @ref is_number() -- check if value is number @sa @ref is_number_integer() -- check if value is an integer number + @sa @ref is_number_unsigned() -- check if value is an unsigned integer + number @since version 1.0.0 */ - bool is_number_float() const noexcept + constexpr bool is_number_float() const noexcept { return m_type == value_t::number_float; } @@ -2077,12 +2908,15 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies @ref is_object for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_object()` for all JSON types.,is_object} @since version 1.0.0 */ - bool is_object() const noexcept + constexpr bool is_object() const noexcept { return m_type == value_t::object; } @@ -2096,12 +2930,15 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies @ref is_array for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_array()` for all JSON types.,is_array} @since version 1.0.0 */ - bool is_array() const noexcept + constexpr bool is_array() const noexcept { return m_type == value_t::array; } @@ -2115,12 +2952,15 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies @ref is_string for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_string()` for all JSON types.,is_string} @since version 1.0.0 */ - bool is_string() const noexcept + constexpr bool is_string() const noexcept { return m_type == value_t::string; } @@ -2139,12 +2979,15 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies @ref is_discarded for all JSON + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_discarded()` for all JSON types.,is_discarded} @since version 1.0.0 */ - bool is_discarded() const noexcept + constexpr bool is_discarded() const noexcept { return m_type == value_t::discarded; } @@ -2159,12 +3002,15 @@ class basic_json @complexity Constant. - @liveexample{The following code exemplifies the value_t operator for all - JSON types.,operator__value_t} + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies the @ref value_t operator for + all JSON types.,operator__value_t} @since version 1.0.0 */ - operator value_t() const noexcept + constexpr operator value_t() const noexcept { return m_type; } @@ -2176,251 +3022,97 @@ class basic_json // value access // ////////////////// - /// get an object (explicit) - template ::value and - std::is_convertible::value - , int>::type = 0> - T get_impl(T*) const - { - if (is_object()) - { - assert(m_value.object != nullptr); - return T(m_value.object->begin(), m_value.object->end()); - } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } - } - - /// get an object (explicit) - object_t get_impl(object_t*) const - { - if (is_object()) - { - assert(m_value.object != nullptr); - return *(m_value.object); - } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } - } - - /// get an array (explicit) - template ::value and - not std::is_same::value and - not std::is_arithmetic::value and - not std::is_convertible::value and - not has_mapped_type::value - , int>::type = 0> - T get_impl(T*) const - { - if (is_array()) - { - T to_vector; - assert(m_value.array != nullptr); - std::transform(m_value.array->begin(), m_value.array->end(), - std::inserter(to_vector, to_vector.end()), [](basic_json i) - { - return i.get(); - }); - return to_vector; - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } - } - - /// get an array (explicit) - template ::value and - not std::is_same::value - , int>::type = 0> - std::vector get_impl(std::vector*) const - { - if (is_array()) - { - std::vector to_vector; - assert(m_value.array != nullptr); - to_vector.reserve(m_value.array->size()); - std::transform(m_value.array->begin(), m_value.array->end(), - std::inserter(to_vector, to_vector.end()), [](basic_json i) - { - return i.get(); - }); - return to_vector; - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } - } - - /// get an array (explicit) - template ::value and - not has_mapped_type::value - , int>::type = 0> - T get_impl(T*) const - { - if (is_array()) - { - assert(m_value.array != nullptr); - return T(m_value.array->begin(), m_value.array->end()); - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } - } - - /// get an array (explicit) - array_t get_impl(array_t*) const - { - if (is_array()) - { - assert(m_value.array != nullptr); - return *(m_value.array); - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } - } - - /// get a string (explicit) - template ::value - , int>::type = 0> - T get_impl(T*) const - { - if (is_string()) - { - assert(m_value.string != nullptr); - return *m_value.string; - } - else - { - throw std::domain_error("type must be string, but is " + type_name()); - } - } - - /// get a number (explicit) - template::value - , int>::type = 0> - T get_impl(T*) const - { - switch (m_type) - { - case value_t::number_integer: - { - return static_cast(m_value.number_integer); - } - - case value_t::number_float: - { - return static_cast(m_value.number_float); - } - - default: - { - throw std::domain_error("type must be number, but is " + type_name()); - } - } - } - /// get a boolean (explicit) - boolean_t get_impl(boolean_t*) const + boolean_t get_impl(boolean_t* /*unused*/) const { if (is_boolean()) { return m_value.boolean; } - else - { - throw std::domain_error("type must be boolean, but is " + type_name()); - } + + JSON_THROW(std::domain_error("type must be boolean, but is " + type_name())); } /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t*) noexcept + object_t* get_impl_ptr(object_t* /*unused*/) noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (object) - const object_t* get_impl_ptr(const object_t*) const noexcept + 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*) noexcept + array_t* get_impl_ptr(array_t* /*unused*/) noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (array) - const array_t* get_impl_ptr(const array_t*) const noexcept + 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*) noexcept + string_t* get_impl_ptr(string_t* /*unused*/) noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (string) - const string_t* get_impl_ptr(const string_t*) const noexcept + 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*) noexcept + boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (boolean) - const boolean_t* get_impl_ptr(const boolean_t*) const noexcept + 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*) noexcept + 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) - const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept + 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*) noexcept + 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) - const number_float_t* get_impl_ptr(const number_float_t*) const noexcept + constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { return is_number_float() ? &m_value.number_float : nullptr; } @@ -2439,41 +3131,79 @@ class basic_json template static ReferenceType get_ref_impl(ThisType& obj) { - // delegate the call to get_ptr<>() + // helper type using PointerType = typename std::add_pointer::type; + + // delegate the call to get_ptr<>() auto ptr = obj.template get_ptr(); if (ptr != nullptr) { return *ptr; } - else - { - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); - } + + JSON_THROW(std::domain_error("incompatible ReferenceType for get_ref, actual type is " + + obj.type_name())); } public: - /// @name value access + /// Direct access to the stored value of a JSON value. /// @{ + /*! + @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 < + typename BasicJsonType, + detail::enable_if_t::type, + basic_json_t>::value, + int> = 0 > + basic_json get() const + { + return *this; + } + /*! @brief get a value (explicit) - Explicit type conversion between the JSON value and a compatible value. + Explicit type conversion between the JSON value and a compatible value + which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. - @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 function is equivalent to executing + @code {.cpp} + ValueType ret; + JSONSerializer::from_json(*this, ret); + return ret; + @endcode - @return copy of the JSON value, converted to type @a ValueType + 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 @ref basic_json&, ValueType&)`, and + - @ref json_serializer does not have a `from_json()` method of + the form `ValueType from_json(const @ref basic_json&)` - @throw std::domain_error in case passed type @a ValueType is incompatible - to JSON; example: `"type must be object, but is null"` + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type - @complexity Linear in the size of the JSON value. + @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 @@ -2482,23 +3212,75 @@ class basic_json associative containers such as `std::unordered_map`.,get__ValueType_const} - @internal - The idea of using a casted null pointer to choose the correct - implementation is from . - @endinternal - - @sa @ref operator ValueType() const for implicit conversion - @sa @ref get() for pointer-member access - - @since version 1.0.0 + @since version 2.1.0 */ - template::value - , int>::type = 0> - ValueType get() const + template < + typename ValueTypeCV, + typename ValueType = detail::uncvref_t, + detail::enable_if_t < + not std::is_same::value and + detail::has_from_json::value and + not detail::has_non_default_from_json::value, + int > = 0 > + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), std::declval()))) { - return get_impl(static_cast(nullptr)); + // 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(not std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + static_assert(std::is_default_constructible::value, + "types must be DefaultConstructible when used with get()"); + + ValueType ret; + 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](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/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 @ref basic_json&)` + + @note If @ref json_serializer has both overloads of + `from_json()`, this one is chosen. + + @tparam ValueTypeCV the provided value type + @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 ValueTypeCV, + typename ValueType = detail::uncvref_t, + detail::enable_if_t::value and + detail::has_non_default_from_json::value, int> = 0 > + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval()))) + { + static_assert(not std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + return JSONSerializer::from_json(*this); } /*! @@ -2507,11 +3289,12 @@ class basic_json Explicit pointer access to the internally stored JSON value. No copies are made. - @warning The pointer becomes invalid if the underlying JSON object changes. + @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, or @ref - number_float_t. + 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 @@ -2527,10 +3310,8 @@ class basic_json @since version 1.0.0 */ - template::value - , int>::type = 0> + template::value, int>::type = 0> PointerType get() noexcept { // delegate the call to get_ptr @@ -2541,11 +3322,9 @@ class basic_json @brief get a pointer value (explicit) @copydoc get() */ - template::value - , int>::type = 0> - const PointerType get() const noexcept + template::value, int>::type = 0> + constexpr const PointerType get() const noexcept { // delegate the call to get_ptr return get_ptr(); @@ -2561,8 +3340,9 @@ class basic_json state. @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, or @ref - number_float_t. + object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, + @ref number_unsigned_t, or @ref number_float_t. Enforced by a static + assertion. @return pointer to the internally stored JSON value if the requested pointer type @a PointerType fits to the JSON value; `nullptr` otherwise @@ -2576,12 +3356,25 @@ class basic_json @since version 1.0.0 */ - template::value - , int>::type = 0> + template::value, int>::type = 0> PointerType get_ptr() noexcept { + // get the type of the PointerType (remove pointer and const) + using pointee_t = typename std::remove_const::type>::type>::type; + // make sure the type matches the allowed types + static_assert( + std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + , "incompatible pointer type"); + // delegate the call to get_impl_ptr<>() return get_impl_ptr(static_cast(nullptr)); } @@ -2590,13 +3383,26 @@ class basic_json @brief get a pointer value (implicit) @copydoc get_ptr() */ - template::value - and std::is_const::type>::value - , int>::type = 0> - const PointerType get_ptr() const noexcept + template::value and + std::is_const::type>::value, int>::type = 0> + constexpr const PointerType get_ptr() const noexcept { + // get the type of the PointerType (remove pointer and const) + using pointee_t = typename std::remove_const::type>::type>::type; + // make sure the type matches the allowed types + static_assert( + std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + , "incompatible pointer type"); + // delegate the call to get_impl_ptr<>() const return get_impl_ptr(static_cast(nullptr)); } @@ -2604,15 +3410,15 @@ class basic_json /*! @brief get a reference value (implicit) - Implict reference access to the internally stored JSON value. No copies are - made. + Implicit reference access to the internally stored JSON value. No copies + are made. @warning Writing data to the referee of the result yields an undefined state. @tparam ReferenceType reference type; must be a reference to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or - @ref number_float_t. + @ref number_float_t. Enforced by static assertion. @return reference to the internally stored JSON value if the requested reference type @a ReferenceType fits to the JSON value; throws @@ -2627,10 +3433,8 @@ class basic_json @since version 1.1.0 */ - template::value - , int>::type = 0> + template::value, int>::type = 0> ReferenceType get_ref() { // delegate call to get_ref_impl @@ -2641,11 +3445,9 @@ class basic_json @brief get a reference value (implicit) @copydoc get_ref() */ - template::value - and std::is_const::type>::value - , int>::type = 0> + template::value and + std::is_const::type>::value, int>::type = 0> ReferenceType get_ref() const { // delegate call to get_ref_impl @@ -2655,8 +3457,8 @@ class basic_json /*! @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. + 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 @@ -2680,11 +3482,10 @@ class basic_json @since version 1.0.0 */ - template < typename ValueType, typename - std::enable_if < - not std::is_pointer::value - and not std::is_same::value -#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 + template < typename ValueType, typename std::enable_if < + not std::is_pointer::value and + not std::is_same::value +#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value #endif , int >::type = 0 > @@ -2702,6 +3503,7 @@ class basic_json //////////////////// /// @name element access + /// Access to the JSON value. /// @{ /*! @@ -2722,7 +3524,7 @@ class basic_json @complexity Constant. @liveexample{The example below shows how array elements can be read and - written using at.,at__size_type} + written using `at()`.,at__size_type} @since version 1.0.0 */ @@ -2731,28 +3533,27 @@ class basic_json // at only works for arrays if (is_array()) { - try + JSON_TRY { - assert(m_value.array != nullptr); return m_value.array->at(idx); } - catch (std::out_of_range&) + JSON_CATCH (std::out_of_range&) { // create better exception explanation - throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); + JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); } } else { - throw std::domain_error("cannot use at() with " + type_name()); + JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } /*! @brief access specified array element with bounds checking - Returns a const reference to the element at specified location @a idx, with - bounds checking. + Returns a const reference to the element at specified location @a idx, + with bounds checking. @param[in] idx index of the element to access @@ -2766,7 +3567,7 @@ class basic_json @complexity Constant. @liveexample{The example below shows how array elements can be read using - at.,at__size_type_const} + `at()`.,at__size_type_const} @since version 1.0.0 */ @@ -2775,20 +3576,19 @@ class basic_json // at only works for arrays if (is_array()) { - try + JSON_TRY { - assert(m_value.array != nullptr); return m_value.array->at(idx); } - catch (std::out_of_range&) + JSON_CATCH (std::out_of_range&) { // create better exception explanation - throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); + JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); } } else { - throw std::domain_error("cannot use at() with " + type_name()); + JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } @@ -2810,7 +3610,7 @@ class basic_json @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read and - written using at.,at__object_t_key_type} + written using `at()`.,at__object_t_key_type} @sa @ref operator[](const typename object_t::key_type&) for unchecked access by reference @@ -2823,28 +3623,27 @@ class basic_json // at only works for objects if (is_object()) { - try + JSON_TRY { - assert(m_value.object != nullptr); return m_value.object->at(key); } - catch (std::out_of_range&) + JSON_CATCH (std::out_of_range&) { // create better exception explanation - throw std::out_of_range("key '" + key + "' not found"); + JSON_THROW(std::out_of_range("key '" + key + "' not found")); } } else { - throw std::domain_error("cannot use at() with " + type_name()); + JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } /*! @brief access specified object element with bounds checking - Returns a const reference to the element at with specified key @a key, with - bounds checking. + Returns a const reference to the element at with specified key @a key, + with bounds checking. @param[in] key key of the element to access @@ -2858,7 +3657,7 @@ class basic_json @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read using - at.,at__object_t_key_type_const} + `at()`.,at__object_t_key_type_const} @sa @ref operator[](const typename object_t::key_type&) for unchecked access by reference @@ -2871,20 +3670,19 @@ class basic_json // at only works for objects if (is_object()) { - try + JSON_TRY { - assert(m_value.object != nullptr); return m_value.object->at(key); } - catch (std::out_of_range&) + JSON_CATCH (std::out_of_range&) { // create better exception explanation - throw std::out_of_range("key '" + key + "' not found"); + JSON_THROW(std::out_of_range("key '" + key + "' not found")); } } else { - throw std::domain_error("cannot use at() with " + type_name()); + JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } @@ -2901,42 +3699,43 @@ class basic_json @return reference to the element at index @a idx - @throw std::domain_error if JSON is not an array or null; example: `"cannot - use operator[] with null"` + @throw std::domain_error if JSON is not an array or null; example: + `"cannot use operator[] with string"` @complexity Constant if @a idx is in the range of the array. Otherwise linear in `idx - size()`. @liveexample{The example below shows how array elements can be read and - written using [] operator. Note the addition of `null` + written using `[]` operator. Note the addition of `null` values.,operatorarray__size_type} @since version 1.0.0 */ reference operator[](size_type idx) { - // implicitly convert null to object + // implicitly convert null value to an empty array if (is_null()) { m_type = value_t::array; m_value.array = create(); + assert_invariant(); } - // [] only works for arrays + // operator[] only works for arrays if (is_array()) { - assert(m_value.array != nullptr); - for (size_t i = m_value.array->size(); i <= idx; ++i) + // fill up array with null values if given idx is outside range + if (idx >= m_value.array->size()) { - m_value.array->push_back(basic_json()); + m_value.array->insert(m_value.array->end(), + idx - m_value.array->size() + 1, + basic_json()); } return m_value.array->operator[](idx); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @@ -2954,22 +3753,19 @@ class basic_json @complexity Constant. @liveexample{The example below shows how array elements can be read using - the [] operator.,operatorarray__size_type_const} + the `[]` operator.,operatorarray__size_type_const} @since version 1.0.0 */ const_reference operator[](size_type idx) const { - // at only works for arrays + // const operator[] only works for arrays if (is_array()) { - assert(m_value.array != nullptr); return m_value.array->operator[](idx); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @@ -2986,12 +3782,12 @@ class basic_json @return reference to the element at key @a key @throw std::domain_error if JSON is not an object or null; example: - `"cannot use operator[] with null"` + `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read and - written using the [] operator.,operatorarray__key_type} + written using the `[]` operator.,operatorarray__key_type} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @@ -3001,23 +3797,21 @@ class basic_json */ reference operator[](const typename object_t::key_type& key) { - // implicitly convert null to object + // implicitly convert null value to an empty object if (is_null()) { m_type = value_t::object; m_value.object = create(); + assert_invariant(); } - // [] only works for objects + // operator[] only works for objects if (is_object()) { - assert(m_value.object != nullptr); return m_value.object->operator[](key); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @@ -3033,13 +3827,16 @@ class basic_json @return const reference to the element at key @a key + @pre The element with key @a key must exist. **This precondition is + enforced with an assertion.** + @throw std::domain_error if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read using - the [] operator.,operatorarray__key_type_const} + the `[]` operator.,operatorarray__key_type_const} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @@ -3049,17 +3846,14 @@ class basic_json */ const_reference operator[](const typename object_t::key_type& key) const { - // [] only works for objects + // const operator[] only works for objects if (is_object()) { - assert(m_value.object != nullptr); assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @@ -3076,12 +3870,12 @@ class basic_json @return reference to the element at key @a key @throw std::domain_error if JSON is not an object or null; example: - `"cannot use operator[] with null"` + `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read and - written using the [] operator.,operatorarray__key_type} + written using the `[]` operator.,operatorarray__key_type} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @@ -3116,7 +3910,7 @@ class basic_json @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read using - the [] operator.,operatorarray__key_type_const} + the `[]` operator.,operatorarray__key_type_const} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @@ -3144,12 +3938,12 @@ class basic_json @return reference to the element at key @a key @throw std::domain_error if JSON is not an object or null; example: - `"cannot use operator[] with null"` + `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read and - written using the [] operator.,operatorarray__key_type} + written using the `[]` operator.,operatorarray__key_type} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @@ -3165,18 +3959,16 @@ class basic_json { m_type = value_t::object; m_value = value_t::object; + assert_invariant(); } // at only works for objects if (is_object()) { - assert(m_value.object != nullptr); return m_value.object->operator[](key); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @@ -3192,13 +3984,16 @@ class basic_json @return const reference to the element at key @a key + @pre The element with key @a key must exist. **This precondition is + enforced with an assertion.** + @throw std::domain_error if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read using - the [] operator.,operatorarray__key_type_const} + the `[]` operator.,operatorarray__key_type_const} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @@ -3212,21 +4007,18 @@ class basic_json // at only works for objects if (is_object()) { - assert(m_value.object != nullptr); assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @brief access specified object element with default value - Returns either a copy of an object's element at the specified key @a key or - a given default value if no element with key @a key exists. + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. The function is basically equivalent to executing @code {.cpp} @@ -3270,10 +4062,8 @@ class basic_json @since version 1.0.0 */ - template ::value - , int>::type = 0> + template::value, int>::type = 0> ValueType value(const typename object_t::key_type& key, ValueType default_value) const { // at only works for objects @@ -3285,26 +4075,95 @@ class basic_json { return *it; } - else - { - return default_value; - } + + return default_value; } else { - throw std::domain_error("cannot use value() with " + type_name()); + JSON_THROW(std::domain_error("cannot use value() with " + type_name())); } } /*! @brief overload for a default value of type const char* - @copydoc basic_json::value() + @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const */ 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 + + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. + + The function is basically equivalent to executing + @code {.cpp} + try { + return at(ptr); + } catch(std::out_of_range) { + return default_value; + } + @endcode + + @note Unlike @ref at(const json_pointer&), this function does not throw + if the given key @a key was not found. + + @param[in] ptr a JSON pointer to the element to access + @param[in] default_value the value to return if @a ptr found no value + + @tparam ValueType type compatible to JSON values, for instance `int` for + JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for + JSON arrays. Note the type of the expected value at @a key and the default + value @a default_value must be compatible. + + @return copy of the element at key @a key or @a default_value if @a key + is not found + + @throw std::domain_error if JSON is not an object; example: `"cannot use + value() with null"` + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be queried + with a default value.,basic_json__value_ptr} + + @sa @ref operator[](const json_pointer&) for unchecked access by reference + + @since version 2.0.2 + */ + template::value, int>::type = 0> + ValueType value(const json_pointer& ptr, ValueType default_value) const + { + // at only works for objects + if (is_object()) + { + // if pointer resolves a value, return it or use default value + JSON_TRY + { + return ptr.get_checked(this); + } + JSON_CATCH (std::out_of_range&) + { + return default_value; + } + } + + JSON_THROW(std::domain_error("cannot use value() with " + type_name())); + } + + /*! + @brief overload for a default value of type const char* + @copydoc basic_json::value(const json_pointer&, ValueType) const + */ + string_t value(const json_pointer& ptr, const char* default_value) const + { + return value(ptr, string_t(default_value)); + } + /*! @brief access the first element @@ -3312,16 +4171,21 @@ class basic_json container `c`, the expression `c.front()` is equivalent to `*c.begin()`. @return In case of a structured type (array or object), a reference to the - first element is returned. In cast of number, string, or boolean values, a + first element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. - @note Calling `front` on an empty container is undefined. + @pre The JSON value must not be `null` (would throw `std::out_of_range`) + or an empty array or object (undefined behavior, **guarded by + assertions**). + @post The JSON value remains unchanged. - @throw std::out_of_range when called on null value + @throw std::out_of_range when called on `null` value - @liveexample{The following code shows an example for @ref front.,front} + @liveexample{The following code shows an example for `front()`.,front} + + @sa @ref back() -- access the last element @since version 1.0.0 */ @@ -3342,20 +4206,29 @@ class basic_json @brief access the last element Returns a reference to the last element in the container. For a JSON - container `c`, the expression `c.back()` is equivalent to `{ auto tmp = - c.end(); --tmp; return *tmp; }`. + container `c`, the expression `c.back()` is equivalent to + @code {.cpp} + auto tmp = c.end(); + --tmp; + return *tmp; + @endcode @return In case of a structured type (array or object), a reference to the - last element is returned. In cast of number, string, or boolean values, a + last element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. - @note Calling `back` on an empty container is undefined. + @pre The JSON value must not be `null` (would throw `std::out_of_range`) + or an empty array or object (undefined behavior, **guarded by + assertions**). + @post The JSON value remains unchanged. - @throw std::out_of_range when called on null value. + @throw std::out_of_range when called on `null` value. - @liveexample{The following code shows an example for @ref back.,back} + @liveexample{The following code shows an example for `back()`.,back} + + @sa @ref front() -- access the first element @since version 1.0.0 */ @@ -3379,102 +4252,103 @@ class basic_json /*! @brief remove element given an iterator - Removes the element specified by iterator @a pos. Invalidates iterators and - references at or after the point of the erase, including the end() - iterator. The iterator @a pos must be valid and dereferenceable. Thus the - end() iterator (which is valid, but is not dereferenceable) cannot be used - as a value for @a pos. + Removes the element specified by iterator @a pos. The iterator @a pos must + be valid and dereferenceable. Thus the `end()` iterator (which is valid, + but is not dereferenceable) cannot be used as a value for @a pos. - If called on a primitive type other than null, the resulting JSON value + If called on a primitive type other than `null`, the resulting JSON value will be `null`. @param[in] pos iterator to the element to remove - @return Iterator following the last removed element. If the iterator @a pos - refers to the last element, the end() iterator is returned. + @return Iterator following the last removed element. If the iterator @a + pos refers to the last element, the `end()` iterator is returned. - @tparam InteratorType an @ref iterator or @ref const_iterator + @tparam IteratorType an @ref iterator or @ref const_iterator - @throw std::domain_error if called on a `null` value; example: `"cannot use - erase() with null"` + @post Invalidates iterators and references at or after the point of the + erase, including the `end()` iterator. + + @throw std::domain_error if called on a `null` value; example: `"cannot + use erase() with null"` @throw std::domain_error if called on an iterator which does not belong to the current JSON value; example: `"iterator does not fit current value"` @throw std::out_of_range if called on a primitive type with invalid - iterator (i.e., any iterator which is not end()); example: `"iterator out - of range"` + iterator (i.e., any iterator which is not `begin()`); example: `"iterator + out of range"` @complexity The complexity depends on the type: - objects: amortized constant - - arrays: linear in distance between pos and the end of the container + - arrays: linear in distance between @a pos and the end of the container - strings: linear in the length of the string - other types: constant - @liveexample{The example shows the result of erase for different JSON + @liveexample{The example shows the result of `erase()` for different JSON types.,erase__IteratorType} - @sa @ref erase(InteratorType, InteratorType) -- removes the elements in the - given range + @sa @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range @sa @ref erase(const typename object_t::key_type&) -- removes the element from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at the - given index + @sa @ref erase(const size_type) -- removes the element from an array at + the given index @since version 1.0.0 */ - template ::value or - std::is_same::value - , int>::type - = 0> - InteratorType erase(InteratorType pos) + template::value or + std::is_same::value, int>::type + = 0> + IteratorType erase(IteratorType pos) { // make sure iterator fits the current value if (this != pos.m_object) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(std::domain_error("iterator does not fit current value")); } - InteratorType result = end(); + 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: { if (not pos.m_it.primitive_iterator.is_begin()) { - throw std::out_of_range("iterator out of range"); + JSON_THROW(std::out_of_range("iterator out of range")); } if (is_string()) { - delete m_value.string; + AllocatorType alloc; + alloc.destroy(m_value.string); + alloc.deallocate(m_value.string, 1); m_value.string = nullptr; } m_type = value_t::null; + assert_invariant(); break; } case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } default: { - throw std::domain_error("cannot use erase() with " + type_name()); + JSON_THROW(std::domain_error("cannot use erase() with " + type_name())); } } @@ -3484,23 +4358,25 @@ class basic_json /*! @brief remove elements given an iterator range - Removes the element specified by the range `[first; last)`. Invalidates - iterators and references at or after the point of the erase, including the - end() iterator. The iterator @a first does not need to be dereferenceable - if `first == last`: erasing an empty range is a no-op. + Removes the element specified by the range `[first; last)`. The iterator + @a first does not need to be dereferenceable if `first == last`: erasing + an empty range is a no-op. - If called on a primitive type other than null, the resulting JSON value + If called on a primitive type other than `null`, the resulting JSON value will be `null`. @param[in] first iterator to the beginning of the range to remove @param[in] last iterator past the end of the range to remove @return Iterator following the last removed element. If the iterator @a - second refers to the last element, the end() iterator is returned. + second refers to the last element, the `end()` iterator is returned. - @tparam InteratorType an @ref iterator or @ref const_iterator + @tparam IteratorType an @ref iterator or @ref const_iterator - @throw std::domain_error if called on a `null` value; example: `"cannot use - erase() with null"` + @post Invalidates iterators and references at or after the point of the + erase, including the `end()` iterator. + + @throw std::domain_error if called on a `null` value; example: `"cannot + use erase() with null"` @throw std::domain_error if called on iterators which does not belong to the current JSON value; example: `"iterators do not fit current value"` @throw std::out_of_range if called on a primitive type with invalid @@ -3514,58 +4390,59 @@ class basic_json - strings: linear in the length of the string - other types: constant - @liveexample{The example shows the result of erase for different JSON + @liveexample{The example shows the result of `erase()` for different JSON types.,erase__IteratorType_IteratorType} - @sa @ref erase(InteratorType) -- removes the element at a given position + @sa @ref erase(IteratorType) -- removes the element at a given position @sa @ref erase(const typename object_t::key_type&) -- removes the element from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at the - given index + @sa @ref erase(const size_type) -- removes the element from an array at + the given index @since version 1.0.0 */ - template ::value or - std::is_same::value - , int>::type - = 0> - InteratorType erase(InteratorType first, InteratorType last) + template::value or + std::is_same::value, int>::type + = 0> + IteratorType erase(IteratorType first, IteratorType last) { // make sure iterator fits the current value if (this != first.m_object or this != last.m_object) { - throw std::domain_error("iterators do not fit current value"); + JSON_THROW(std::domain_error("iterators do not fit current value")); } - InteratorType result = end(); + 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: { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { - throw std::out_of_range("iterators out of range"); + JSON_THROW(std::out_of_range("iterators out of range")); } if (is_string()) { - delete m_value.string; + AllocatorType alloc; + alloc.destroy(m_value.string); + alloc.deallocate(m_value.string, 1); m_value.string = nullptr; } m_type = value_t::null; + assert_invariant(); break; } case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; @@ -3573,7 +4450,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; @@ -3581,7 +4457,7 @@ class basic_json default: { - throw std::domain_error("cannot use erase() with " + type_name()); + JSON_THROW(std::domain_error("cannot use erase() with " + type_name())); } } @@ -3595,22 +4471,25 @@ class basic_json @param[in] key value of the elements to remove - @return Number of elements removed. If ObjectType is the default `std::map` - type, the return value will always be `0` (@a key was not found) or `1` (@a - key was found). + @return Number of elements removed. If @a ObjectType is the default + `std::map` type, the return value will always be `0` (@a key was not + found) or `1` (@a key was found). + + @post References and iterators to the erased elements are invalidated. + Other references and iterators are not affected. @throw std::domain_error when called on a type other than JSON object; example: `"cannot use erase() with null"` @complexity `log(size()) + count(key)` - @liveexample{The example shows the effect of erase.,erase__key_type} + @liveexample{The example shows the effect of `erase()`.,erase__key_type} - @sa @ref erase(InteratorType) -- removes the element at a given position - @sa @ref erase(InteratorType, InteratorType) -- removes the elements in the - given range - @sa @ref erase(const size_type) -- removes the element from an array at the - given index + @sa @ref erase(IteratorType) -- removes the element at a given position + @sa @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range + @sa @ref erase(const size_type) -- removes the element from an array at + the given index @since version 1.0.0 */ @@ -3619,13 +4498,10 @@ class basic_json // this erase only works for objects if (is_object()) { - assert(m_value.object != nullptr); return m_value.object->erase(key); } - else - { - throw std::domain_error("cannot use erase() with " + type_name()); - } + + JSON_THROW(std::domain_error("cannot use erase() with " + type_name())); } /*! @@ -3637,16 +4513,16 @@ class basic_json @throw std::domain_error when called on a type other than JSON array; example: `"cannot use erase() with null"` - @throw std::out_of_range when `idx >= size()`; example: `"index out of - range"` + @throw std::out_of_range when `idx >= size()`; example: `"array index 17 + is out of range"` @complexity Linear in distance between @a idx and the end of the container. - @liveexample{The example shows the effect of erase.,erase__size_type} + @liveexample{The example shows the effect of `erase()`.,erase__size_type} - @sa @ref erase(InteratorType) -- removes the element at a given position - @sa @ref erase(InteratorType, InteratorType) -- removes the elements in the - given range + @sa @ref erase(IteratorType) -- removes the element at a given position + @sa @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range @sa @ref erase(const typename object_t::key_type&) -- removes the element from an object at the given key @@ -3659,32 +4535,46 @@ class basic_json { if (idx >= size()) { - throw std::out_of_range("index out of range"); + JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); } - assert(m_value.array != nullptr); m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else { - throw std::domain_error("cannot use erase() with " + type_name()); + JSON_THROW(std::domain_error("cannot use erase() with " + type_name())); } } + /// @} + + + //////////// + // lookup // + //////////// + + /// @name lookup + /// @{ + /*! @brief find an element in a JSON object Finds an element in a JSON object with key equivalent to @a key. If the - element is not found or the JSON value is not an object, end() is returned. + element is not found or the JSON value is not an object, end() is + returned. + + @note This method always returns @ref end() when executed on a JSON type + that is not an object. @param[in] key key value of the element to search for @return Iterator to an element with key equivalent to @a key. If no such - element is found, past-the-end (see end()) iterator is returned. + element is found or the JSON value is not an object, past-the-end (see + @ref end()) iterator is returned. @complexity Logarithmic in the size of the JSON object. - @liveexample{The example shows how find is used.,find__key_type} + @liveexample{The example shows how `find()` is used.,find__key_type} @since version 1.0.0 */ @@ -3694,7 +4584,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -3711,7 +4600,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -3725,6 +4613,9 @@ class basic_json default `std::map` type, the return value will always be `0` (@a key was not found) or `1` (@a key was found). + @note This method always returns `0` when executed on a JSON type that is + not an object. + @param[in] key key value of the element to count @return Number of elements with key @a key. If the JSON value is not an @@ -3732,14 +4623,13 @@ class basic_json @complexity Logarithmic in the size of the JSON object. - @liveexample{The example shows how count is used.,count} + @liveexample{The example shows how `count()` is used.,count} @since version 1.0.0 */ size_type count(typename object_t::key_type key) const { // return 0 for all nonobject types - assert(not is_object() or m_value.object != nullptr); return is_object() ? m_value.object->count(key) : 0; } @@ -3764,14 +4654,20 @@ class basic_json @complexity Constant. - @requirement This function satisfies the Container requirements: + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is constant. - @liveexample{The following code shows an example for @ref begin.,begin} + @liveexample{The following code shows an example for `begin()`.,begin} + + @sa @ref cbegin() -- returns a const iterator to the beginning + @sa @ref end() -- returns an iterator to the end + @sa @ref cend() -- returns a const iterator to the end @since version 1.0.0 */ - iterator begin() + iterator begin() noexcept { iterator result(this); result.set_begin(); @@ -3781,7 +4677,7 @@ class basic_json /*! @copydoc basic_json::cbegin() */ - const_iterator begin() const + const_iterator begin() const noexcept { return cbegin(); } @@ -3797,15 +4693,21 @@ class basic_json @complexity Constant. - @requirement This function satisfies the Container requirements: + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is constant. - Has the semantics of `const_cast(*this).begin()`. - @liveexample{The following code shows an example for @ref cbegin.,cbegin} + @liveexample{The following code shows an example for `cbegin()`.,cbegin} + + @sa @ref begin() -- returns an iterator to the beginning + @sa @ref end() -- returns an iterator to the end + @sa @ref cend() -- returns a const iterator to the end @since version 1.0.0 */ - const_iterator cbegin() const + const_iterator cbegin() const noexcept { const_iterator result(this); result.set_begin(); @@ -3823,14 +4725,20 @@ class basic_json @complexity Constant. - @requirement This function satisfies the Container requirements: + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is constant. - @liveexample{The following code shows an example for @ref end.,end} + @liveexample{The following code shows an example for `end()`.,end} + + @sa @ref cend() -- returns a const iterator to the end + @sa @ref begin() -- returns an iterator to the beginning + @sa @ref cbegin() -- returns a const iterator to the beginning @since version 1.0.0 */ - iterator end() + iterator end() noexcept { iterator result(this); result.set_end(); @@ -3840,7 +4748,7 @@ class basic_json /*! @copydoc basic_json::cend() */ - const_iterator end() const + const_iterator end() const noexcept { return cend(); } @@ -3856,15 +4764,21 @@ class basic_json @complexity Constant. - @requirement This function satisfies the Container requirements: + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is constant. - Has the semantics of `const_cast(*this).end()`. - @liveexample{The following code shows an example for @ref cend.,cend} + @liveexample{The following code shows an example for `cend()`.,cend} + + @sa @ref end() -- returns an iterator to the end + @sa @ref begin() -- returns an iterator to the beginning + @sa @ref cbegin() -- returns a const iterator to the beginning @since version 1.0.0 */ - const_iterator cend() const + const_iterator cend() const noexcept { const_iterator result(this); result.set_end(); @@ -3880,15 +4794,21 @@ class basic_json @complexity Constant. - @requirement This function satisfies the ReversibleContainer requirements: + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) + requirements: - The complexity is constant. - Has the semantics of `reverse_iterator(end())`. - @liveexample{The following code shows an example for @ref rbegin.,rbegin} + @liveexample{The following code shows an example for `rbegin()`.,rbegin} + + @sa @ref crbegin() -- returns a const reverse iterator to the beginning + @sa @ref rend() -- returns a reverse iterator to the end + @sa @ref crend() -- returns a const reverse iterator to the end @since version 1.0.0 */ - reverse_iterator rbegin() + reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } @@ -3896,7 +4816,7 @@ class basic_json /*! @copydoc basic_json::crbegin() */ - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const noexcept { return crbegin(); } @@ -3911,15 +4831,21 @@ class basic_json @complexity Constant. - @requirement This function satisfies the ReversibleContainer requirements: + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) + requirements: - The complexity is constant. - Has the semantics of `reverse_iterator(begin())`. - @liveexample{The following code shows an example for @ref rend.,rend} + @liveexample{The following code shows an example for `rend()`.,rend} + + @sa @ref crend() -- returns a const reverse iterator to the end + @sa @ref rbegin() -- returns a reverse iterator to the beginning + @sa @ref crbegin() -- returns a const reverse iterator to the beginning @since version 1.0.0 */ - reverse_iterator rend() + reverse_iterator rend() noexcept { return reverse_iterator(begin()); } @@ -3927,7 +4853,7 @@ class basic_json /*! @copydoc basic_json::crend() */ - const_reverse_iterator rend() const + const_reverse_iterator rend() const noexcept { return crend(); } @@ -3942,15 +4868,21 @@ class basic_json @complexity Constant. - @requirement This function satisfies the ReversibleContainer requirements: + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) + requirements: - The complexity is constant. - Has the semantics of `const_cast(*this).rbegin()`. - @liveexample{The following code shows an example for @ref crbegin.,crbegin} + @liveexample{The following code shows an example for `crbegin()`.,crbegin} + + @sa @ref rbegin() -- returns a reverse iterator to the beginning + @sa @ref rend() -- returns a reverse iterator to the end + @sa @ref crend() -- returns a const reverse iterator to the end @since version 1.0.0 */ - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } @@ -3965,15 +4897,21 @@ class basic_json @complexity Constant. - @requirement This function satisfies the ReversibleContainer requirements: + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) + requirements: - The complexity is constant. - Has the semantics of `const_cast(*this).rend()`. - @liveexample{The following code shows an example for @ref crend.,crend} + @liveexample{The following code shows an example for `crend()`.,crend} + + @sa @ref rend() -- returns a reverse iterator to the end + @sa @ref rbegin() -- returns a reverse iterator to the beginning + @sa @ref crbegin() -- returns a const reverse iterator to the beginning @since version 1.0.0 */ - const_reverse_iterator crend() const + const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } @@ -3987,9 +4925,9 @@ class basic_json @brief wrapper to access iterator member functions in range-based for This function allows to access @ref iterator::key() and @ref - iterator::value() during range-based for loops. In these loops, a reference - to the JSON values is returned, so there is no access to the underlying - iterator. + iterator::value() during range-based for loops. In these loops, a + reference to the JSON values is returned, so there is no access to the + underlying iterator. @note The name of this function is not yet final and may change in the future. @@ -4026,24 +4964,32 @@ class basic_json defined as follows: Value type | return value ----------- | ------------- - null | @c true - boolean | @c false - string | @c false - number | @c false - object | result of function object_t::empty() - array | result of function array_t::empty() + null | `true` + boolean | `false` + string | `false` + number | `false` + object | result of function `object_t::empty()` + array | result of function `array_t::empty()` - @complexity Constant, as long as @ref array_t and @ref object_t satisfy the - Container concept; that is, their empty() functions have constant + @note This function does not return whether a string stored as JSON value + is empty - it returns whether the JSON container itself is empty which is + false in the case of a string. + + @complexity Constant, as long as @ref array_t and @ref object_t satisfy + the Container concept; that is, their `empty()` functions have constant complexity. - @requirement This function satisfies the Container requirements: + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is constant. - Has the semantics of `begin() == end()`. - @liveexample{The following code uses @ref empty to check if a @ref json + @liveexample{The following code uses `empty()` to check if a JSON object contains any elements.,empty} + @sa @ref size() -- returns the number of elements + @since version 1.0.0 */ bool empty() const noexcept @@ -4058,13 +5004,13 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); + // delegate call to array_t::empty() return m_value.array->empty(); } case value_t::object: { - assert(m_value.object != nullptr); + // delegate call to object_t::empty() return m_value.object->empty(); } @@ -4085,23 +5031,33 @@ class basic_json defined as follows: Value type | return value ----------- | ------------- - null | @c 0 - boolean | @c 1 - string | @c 1 - number | @c 1 + null | `0` + boolean | `1` + string | `1` + number | `1` object | result of function object_t::size() array | result of function array_t::size() - @complexity Constant, as long as @ref array_t and @ref object_t satisfy the - Container concept; that is, their size() functions have constant complexity. + @note This function does not return the length of a string stored as JSON + value - it returns the number of elements in the JSON value which is 1 in + the case of a string. - @requirement This function satisfies the Container requirements: + @complexity Constant, as long as @ref array_t and @ref object_t satisfy + the Container concept; that is, their size() functions have constant + complexity. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is constant. - Has the semantics of `std::distance(begin(), end())`. - @liveexample{The following code calls @ref size on the different value + @liveexample{The following code calls `size()` on the different value types.,size} + @sa @ref empty() -- checks whether the container is empty + @sa @ref max_size() -- returns the maximal number of elements + @since version 1.0.0 */ size_type size() const noexcept @@ -4116,13 +5072,13 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); + // delegate call to array_t::size() return m_value.array->size(); } case value_t::object: { - assert(m_value.object != nullptr); + // delegate call to object_t::size() return m_value.object->size(); } @@ -4145,25 +5101,29 @@ class basic_json defined as follows: Value type | return value ----------- | ------------- - null | @c 0 (same as size()) - boolean | @c 1 (same as size()) - string | @c 1 (same as size()) - number | @c 1 (same as size()) - object | result of function object_t::max_size() - array | result of function array_t::max_size() + null | `0` (same as `size()`) + boolean | `1` (same as `size()`) + string | `1` (same as `size()`) + number | `1` (same as `size()`) + object | result of function `object_t::max_size()` + array | result of function `array_t::max_size()` - @complexity Constant, as long as @ref array_t and @ref object_t satisfy the - Container concept; that is, their max_size() functions have constant + @complexity Constant, as long as @ref array_t and @ref object_t satisfy + the Container concept; that is, their `max_size()` functions have constant complexity. - @requirement This function satisfies the Container requirements: + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: - The complexity is constant. - Has the semantics of returning `b.size()` where `b` is the largest possible JSON value. - @liveexample{The following code calls @ref max_size on the different value + @liveexample{The following code calls `max_size()` on the different value types. Note the output is implementation specific.,max_size} + @sa @ref size() -- returns the number of elements + @since version 1.0.0 */ size_type max_size() const noexcept @@ -4172,13 +5132,13 @@ class basic_json { case value_t::array: { - assert(m_value.array != nullptr); + // delegate call to array_t::max_size() return m_value.array->max_size(); } case value_t::object: { - assert(m_value.object != nullptr); + // delegate call to object_t::max_size() return m_value.object->max_size(); } @@ -4215,12 +5175,9 @@ class basic_json object | `{}` array | `[]` - @note Floating-point numbers are set to `0.0` which will be serialized to - `0`. The vale type remains @ref number_float_t. - @complexity Linear in the size of the JSON value. - @liveexample{The example below shows the effect of @ref clear to different + @liveexample{The example below shows the effect of `clear()` to different JSON types.,clear} @since version 1.0.0 @@ -4235,6 +5192,12 @@ class basic_json break; } + case value_t::number_unsigned: + { + m_value.number_unsigned = 0; + break; + } + case value_t::number_float: { m_value.number_float = 0.0; @@ -4249,21 +5212,18 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); m_value.string->clear(); break; } case value_t::array: { - assert(m_value.array != nullptr); m_value.array->clear(); break; } case value_t::object: { - assert(m_value.object != nullptr); m_value.object->clear(); break; } @@ -4282,16 +5242,16 @@ class basic_json function is called on a JSON null value, an empty array is created before appending @a val. - @param val the value to add to the JSON array + @param[in] val the value to add to the JSON array @throw std::domain_error when called on a type other than JSON array or null; example: `"cannot use push_back() with number"` @complexity Amortized constant. - @liveexample{The example shows how `push_back` and `+=` can be used to add - elements to a JSON array. Note how the `null` value was silently converted - to a JSON array.,push_back} + @liveexample{The example shows how `push_back()` and `+=` can be used to + add elements to a JSON array. Note how the `null` value was silently + converted to a JSON array.,push_back} @since version 1.0.0 */ @@ -4300,7 +5260,7 @@ class basic_json // push_back only works for null objects or arrays if (not(is_null() or is_array())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + JSON_THROW(std::domain_error("cannot use push_back() with " + type_name())); } // transform null object into an array @@ -4308,10 +5268,10 @@ class basic_json { m_type = value_t::array; m_value = value_t::array; + assert_invariant(); } // add element to array (move semantics) - assert(m_value.array != nullptr); m_value.array->push_back(std::move(val)); // invalidate object val.m_type = value_t::null; @@ -4336,7 +5296,7 @@ class basic_json // push_back only works for null objects or arrays if (not(is_null() or is_array())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + JSON_THROW(std::domain_error("cannot use push_back() with " + type_name())); } // transform null object into an array @@ -4344,10 +5304,10 @@ class basic_json { m_type = value_t::array; m_value = value_t::array; + assert_invariant(); } // add element to array - assert(m_value.array != nullptr); m_value.array->push_back(val); } @@ -4365,8 +5325,8 @@ class basic_json @brief add an object to an object Inserts the given element @a val to the JSON object. If the function is - called on a JSON null value, an empty object is created before inserting @a - val. + called on a JSON null value, an empty object is created before inserting + @a val. @param[in] val the value to add to the JSON object @@ -4375,9 +5335,9 @@ class basic_json @complexity Logarithmic in the size of the container, O(log(`size()`)). - @liveexample{The example shows how `push_back` and `+=` can be used to add - elements to a JSON object. Note how the `null` value was silently converted - to a JSON object.,push_back__object_t__value} + @liveexample{The example shows how `push_back()` and `+=` can be used to + add elements to a JSON object. Note how the `null` value was silently + converted to a JSON object.,push_back__object_t__value} @since version 1.0.0 */ @@ -4386,7 +5346,7 @@ class basic_json // push_back only works for null objects or objects if (not(is_null() or is_object())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + JSON_THROW(std::domain_error("cannot use push_back() with " + type_name())); } // transform null object into an object @@ -4394,10 +5354,10 @@ class basic_json { m_type = value_t::object; m_value = value_t::object; + assert_invariant(); } // add element to array - assert(m_value.object != nullptr); m_value.object->insert(val); } @@ -4408,7 +5368,151 @@ class basic_json reference operator+=(const typename object_t::value_type& val) { push_back(val); - return operator[](val.first); + return *this; + } + + /*! + @brief add an object to an object + + This function allows to use `push_back` with an initializer list. In case + + 1. the current value is an object, + 2. the initializer list @a init contains only two elements, and + 3. the first element of @a init is a string, + + @a init is converted into an object element and added using + @ref push_back(const typename object_t::value_type&). Otherwise, @a init + is converted to a JSON value and added using @ref push_back(basic_json&&). + + @param init an initializer list + + @complexity Linear in the size of the initializer list @a init. + + @note This function is required to resolve an ambiguous overload error, + because pairs like `{"key", "value"}` can be both interpreted as + `object_t::value_type` or `std::initializer_list`, see + https://github.com/nlohmann/json/issues/235 for more information. + + @liveexample{The example shows how initializer lists are treated as + objects when possible.,push_back__initializer_list} + */ + void push_back(std::initializer_list init) + { + if (is_object() and init.size() == 2 and init.begin()->is_string()) + { + const string_t key = *init.begin(); + push_back(typename object_t::value_type(key, *(init.begin() + 1))); + } + else + { + push_back(basic_json(init)); + } + } + + /*! + @brief add an object to an object + @copydoc push_back(std::initializer_list) + */ + reference operator+=(std::initializer_list init) + { + push_back(init); + return *this; + } + + /*! + @brief add an object to an array + + Creates a JSON value from the passed parameters @a args to the end of the + JSON value. If the function is called on a JSON null value, an empty array + is created before appending the value created from @a args. + + @param[in] args arguments to forward to a constructor of @ref basic_json + @tparam Args compatible types to create a @ref basic_json object + + @throw std::domain_error when called on a type other than JSON array or + null; example: `"cannot use emplace_back() with number"` + + @complexity Amortized constant. + + @liveexample{The example shows how `push_back()` can be used to add + elements to a JSON array. Note how the `null` value was silently converted + to a JSON array.,emplace_back} + + @since version 2.0.8 + */ + template + void emplace_back(Args&& ... args) + { + // emplace_back only works for null objects or arrays + if (not(is_null() or is_array())) + { + JSON_THROW(std::domain_error("cannot use emplace_back() with " + type_name())); + } + + // 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) + m_value.array->emplace_back(std::forward(args)...); + } + + /*! + @brief add an object to an object if key does not exist + + Inserts a new element into a JSON object constructed in-place with the + given @a args if there is no element with the key in the container. If the + function is called on a JSON null value, an empty object is created before + appending the value created from @a args. + + @param[in] args arguments to forward to a constructor of @ref basic_json + @tparam Args compatible types to create a @ref basic_json object + + @return a pair consisting of an iterator to the inserted element, or the + already-existing element if no insertion happened, and a bool + denoting whether the insertion took place. + + @throw std::domain_error when called on a type other than JSON object or + null; example: `"cannot use emplace() with number"` + + @complexity Logarithmic in the size of the container, O(log(`size()`)). + + @liveexample{The example shows how `emplace()` can be used to add elements + to a JSON object. Note how the `null` value was silently converted to a + JSON object. Further note how no value is added if there was already one + value stored with the same key.,emplace} + + @since version 2.0.8 + */ + template + std::pair emplace(Args&& ... args) + { + // emplace only works for null objects or arrays + if (not(is_null() or is_object())) + { + JSON_THROW(std::domain_error("cannot use emplace() with " + type_name())); + } + + // 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)...); + // 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}; } /*! @@ -4426,10 +5530,10 @@ class basic_json @throw std::domain_error if @a pos is not an iterator of *this; example: `"iterator does not fit current value"` - @complexity Constant plus linear in the distance between pos and end of the - container. + @complexity Constant plus linear in the distance between @a pos and end of + the container. - @liveexample{The example shows how insert is used.,insert} + @liveexample{The example shows how `insert()` is used.,insert} @since version 1.0.0 */ @@ -4441,19 +5545,16 @@ class basic_json // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(std::domain_error("iterator does not fit current value")); } // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } - else - { - throw std::domain_error("cannot use insert() with " + type_name()); - } + + JSON_THROW(std::domain_error("cannot use insert() with " + type_name())); } /*! @@ -4485,7 +5586,7 @@ class basic_json @complexity Linear in @a cnt plus linear in the distance between @a pos and end of the container. - @liveexample{The example shows how insert is used.,insert__count} + @liveexample{The example shows how `insert()` is used.,insert__count} @since version 1.0.0 */ @@ -4497,19 +5598,16 @@ class basic_json // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(std::domain_error("iterator does not fit current value")); } // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } - else - { - throw std::domain_error("cannot use insert() with " + type_name()); - } + + JSON_THROW(std::domain_error("cannot use insert() with " + type_name())); } /*! @@ -4538,7 +5636,7 @@ class basic_json @complexity Linear in `std::distance(first, last)` plus linear in the distance between @a pos and end of the container. - @liveexample{The example shows how insert is used.,insert__range} + @liveexample{The example shows how `insert()` is used.,insert__range} @since version 1.0.0 */ @@ -4547,28 +5645,28 @@ class basic_json // insert only works for arrays if (not is_array()) { - throw std::domain_error("cannot use insert() with " + type_name()); + JSON_THROW(std::domain_error("cannot use insert() with " + type_name())); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(std::domain_error("iterator does not fit current value")); } + // check if range iterators belong to the same JSON object if (first.m_object != last.m_object) { - throw std::domain_error("iterators do not fit"); + JSON_THROW(std::domain_error("iterators do not fit")); } if (first.m_object == this or last.m_object == this) { - throw std::domain_error("passed iterators may not belong to container"); + JSON_THROW(std::domain_error("passed iterators may not belong to container")); } // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert( pos.m_it.array_iterator, first.m_it.array_iterator, @@ -4593,10 +5691,10 @@ class basic_json @return iterator pointing to the first element inserted, or @a pos if `ilist` is empty - @complexity Linear in `ilist.size()` plus linear in the distance between @a - pos and end of the container. + @complexity Linear in `ilist.size()` plus linear in the distance between + @a pos and end of the container. - @liveexample{The example shows how insert is used.,insert__ilist} + @liveexample{The example shows how `insert()` is used.,insert__ilist} @since version 1.0.0 */ @@ -4605,18 +5703,17 @@ class basic_json // insert only works for arrays if (not is_array()) { - throw std::domain_error("cannot use insert() with " + type_name()); + JSON_THROW(std::domain_error("cannot use insert() with " + type_name())); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + JSON_THROW(std::domain_error("iterator does not fit current value")); } // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); return result; } @@ -4633,8 +5730,8 @@ class basic_json @complexity Constant. - @liveexample{The example below shows how JSON arrays can be - swapped.,swap__reference} + @liveexample{The example below shows how JSON values can be swapped with + `swap()`.,swap__reference} @since version 1.0.0 */ @@ -4647,6 +5744,7 @@ class basic_json { std::swap(m_type, other.m_type); std::swap(m_value, other.m_value); + assert_invariant(); } /*! @@ -4659,13 +5757,13 @@ class basic_json @param[in,out] other array to exchange the contents with - @throw std::domain_error when JSON value is not an array; example: `"cannot - use swap() with string"` + @throw std::domain_error when JSON value is not an array; example: + `"cannot use swap() with string"` @complexity Constant. - @liveexample{The example below shows how JSON values can be - swapped.,swap__array_t} + @liveexample{The example below shows how arrays can be swapped with + `swap()`.,swap__array_t} @since version 1.0.0 */ @@ -4674,12 +5772,11 @@ class basic_json // swap only works for arrays if (is_array()) { - assert(m_value.array != nullptr); std::swap(*(m_value.array), other); } else { - throw std::domain_error("cannot use swap() with " + type_name()); + JSON_THROW(std::domain_error("cannot use swap() with " + type_name())); } } @@ -4698,8 +5795,8 @@ class basic_json @complexity Constant. - @liveexample{The example below shows how JSON values can be - swapped.,swap__object_t} + @liveexample{The example below shows how objects can be swapped with + `swap()`.,swap__object_t} @since version 1.0.0 */ @@ -4708,12 +5805,11 @@ class basic_json // swap only works for objects if (is_object()) { - assert(m_value.object != nullptr); std::swap(*(m_value.object), other); } else { - throw std::domain_error("cannot use swap() with " + type_name()); + JSON_THROW(std::domain_error("cannot use swap() with " + type_name())); } } @@ -4732,8 +5828,8 @@ class basic_json @complexity Constant. - @liveexample{The example below shows how JSON values can be - swapped.,swap__string_t} + @liveexample{The example below shows how strings can be swapped with + `swap()`.,swap__string_t} @since version 1.0.0 */ @@ -4742,18 +5838,17 @@ class basic_json // swap only works for strings if (is_string()) { - assert(m_value.string != nullptr); std::swap(*(m_value.string), other); } else { - throw std::domain_error("cannot use swap() with " + type_name()); + JSON_THROW(std::domain_error("cannot use swap() with " + type_name())); } } /// @} - + public: ////////////////////////////////////////// // lexicographical comparison operators // ////////////////////////////////////////// @@ -4761,39 +5856,6 @@ class basic_json /// @name lexicographical comparison operators /// @{ - private: - /*! - @brief comparison operator for JSON types - - Returns an ordering that is similar to Python: - - order: null < boolean < number < object < array < string - - furthermore, each type is not smaller than itself - - @since version 1.0.0 - */ - friend bool operator<(const value_t lhs, const value_t rhs) - { - static constexpr std::array order = {{ - 0, // null - 3, // object - 4, // array - 5, // string - 1, // boolean - 2, // integer - 2 // float - } - }; - - // discarded values are not comparable - if (lhs == value_t::discarded or rhs == value_t::discarded) - { - return false; - } - - return order[static_cast(lhs)] < order[static_cast(rhs)]; - } - - public: /*! @brief comparison: equal @@ -4828,14 +5890,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array == *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object == *rhs.m_value.object; } case value_t::null: @@ -4844,8 +5902,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string == *rhs.m_value.string; } case value_t::boolean: @@ -4856,6 +5912,10 @@ class basic_json { 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; @@ -4874,39 +5934,46 @@ class basic_json { return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); } + else if (lhs_type == value_t::number_unsigned and 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 and 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 and 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 and rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); + } + return false; } /*! @brief comparison: equal - - The functions compares the given JSON value against a null pointer. As the - null pointer can be used to initialize a JSON value to null, a comparison - of JSON value @a v with a null pointer should be equivalent to call - `v.is_null()`. - - @param[in] v JSON value to consider - @return whether @a v is null - - @complexity Constant. - - @liveexample{The example compares several JSON types to the null pointer. - ,operator__equal__nullptr_t} - - @since version 1.0.0 + @copydoc operator==(const_reference, const_reference) */ - friend bool operator==(const_reference v, std::nullptr_t) noexcept + template::value, int>::type = 0> + friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept { - return v.is_null(); + return (lhs == basic_json(rhs)); } /*! @brief comparison: equal - @copydoc operator==(const_reference, std::nullptr_t) + @copydoc operator==(const_reference, const_reference) */ - friend bool operator==(std::nullptr_t, const_reference v) noexcept + template::value, int>::type = 0> + friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept { - return v.is_null(); + return (basic_json(lhs) == rhs); } /*! @@ -4932,34 +5999,24 @@ class basic_json /*! @brief comparison: not equal - - The functions compares the given JSON value against a null pointer. As the - null pointer can be used to initialize a JSON value to null, a comparison - of JSON value @a v with a null pointer should be equivalent to call - `not v.is_null()`. - - @param[in] v JSON value to consider - @return whether @a v is not null - - @complexity Constant. - - @liveexample{The example compares several JSON types to the null pointer. - ,operator__notequal__nullptr_t} - - @since version 1.0.0 + @copydoc operator!=(const_reference, const_reference) */ - friend bool operator!=(const_reference v, std::nullptr_t) noexcept + template::value, int>::type = 0> + friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept { - return not v.is_null(); + return (lhs != basic_json(rhs)); } /*! @brief comparison: not equal - @copydoc operator!=(const_reference, std::nullptr_t) + @copydoc operator!=(const_reference, const_reference) */ - friend bool operator!=(std::nullptr_t, const_reference v) noexcept + template::value, int>::type = 0> + friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept { - return not v.is_null(); + return (basic_json(lhs) != rhs); } /*! @@ -4997,14 +6054,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array < *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object < *rhs.m_value.object; } case value_t::null: @@ -5013,8 +6066,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string < *rhs.m_value.string; } case value_t::boolean: @@ -5025,6 +6076,10 @@ class basic_json { 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; @@ -5037,13 +6092,27 @@ class basic_json } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) { - return static_cast(lhs.m_value.number_integer) < - rhs.m_value.number_float; + return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) { - return lhs.m_value.number_float < - static_cast(rhs.m_value.number_integer); + return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_unsigned and 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 and 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 and 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 and 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, @@ -5161,6 +6230,7 @@ class basic_json // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); + return o; } @@ -5184,10 +6254,16 @@ class basic_json /// @{ /*! - @brief deserialize from string + @brief deserialize from an array - @param[in] s string to read a serialized JSON value from - @param[in] cb a parser callback function of type @ref parser_callback_t + This function reads from an array of 1-byte values. + + @pre Each element of the container has a size of 1 byte. Violating this + precondition yields undefined behavior. **This precondition is enforced + with a static assertion.** + + @param[in] array array to read from + @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) @@ -5199,17 +6275,54 @@ class basic_json @note A UTF-8 byte order mark is silently ignored. - @liveexample{The example below demonstrates the parse function with and - without callback function.,parse__string__parser_callback_t} + @liveexample{The example below demonstrates the `parse()` function reading + from an array.,parse__array__parser_callback_t} - @sa @ref parse(std::istream&, parser_callback_t) for a version that reads - from an input stream - - @since version 1.0.0 + @since version 2.0.3 */ - static basic_json parse(const string_t& s, parser_callback_t cb = nullptr) + template + static basic_json parse(T (&array)[N], + const parser_callback_t cb = nullptr) { - return parser(s, cb).parse(); + // delegate the call to the iterator-range parse overload + return parse(std::begin(array), std::end(array), cb); + } + + /*! + @brief deserialize from string literal + + @tparam CharT character/literal type with size of 1 byte + @param[in] s string literal to read a serialized JSON value from + @param[in] cb a parser callback function of type @ref parser_callback_t + which is used to control the deserialization by filtering unwanted values + (optional) + + @return result of the deserialization + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. The complexity can be higher if the parser callback function + @a cb has a super-linear complexity. + + @note A UTF-8 byte order mark is silently ignored. + @note String containers like `std::string` or @ref string_t can be parsed + with @ref parse(const ContiguousContainer&, const parser_callback_t) + + @liveexample{The example below demonstrates the `parse()` function with + and without callback function.,parse__string__parser_callback_t} + + @sa @ref parse(std::istream&, const parser_callback_t) for a version that + reads from an input stream + + @since version 1.0.0 (originally for @ref string_t) + */ + template::value and + std::is_integral::type>::value and + sizeof(typename std::remove_pointer::type) == 1, int>::type = 0> + static basic_json parse(const CharT s, + const parser_callback_t cb = nullptr) + { + return parser(reinterpret_cast(s), cb).parse(); } /*! @@ -5228,27 +6341,153 @@ class basic_json @note A UTF-8 byte order mark is silently ignored. - @liveexample{The example below demonstrates the parse function with and - without callback function.,parse__istream__parser_callback_t} + @liveexample{The example below demonstrates the `parse()` function with + and without callback function.,parse__istream__parser_callback_t} - @sa @ref parse(const string_t&, parser_callback_t) for a version that reads - from a string + @sa @ref parse(const CharT, const parser_callback_t) for a version + that reads from a string @since version 1.0.0 */ - static basic_json parse(std::istream& i, parser_callback_t cb = nullptr) + static basic_json parse(std::istream& i, + const parser_callback_t cb = nullptr) { return parser(i, cb).parse(); } /*! - @copydoc parse(std::istream&, parser_callback_t) + @copydoc parse(std::istream&, const parser_callback_t) */ - static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr) + static basic_json parse(std::istream&& i, + const parser_callback_t cb = nullptr) { return parser(i, cb).parse(); } + /*! + @brief deserialize from an iterator range with contiguous storage + + This function reads from an iterator range of a container with contiguous + storage of 1-byte values. Compatible container types include + `std::vector`, `std::string`, `std::array`, `std::valarray`, and + `std::initializer_list`. Furthermore, C-style arrays can be used with + `std::begin()`/`std::end()`. User-defined containers can be used as long + as they implement random-access iterators and a contiguous storage. + + @pre The iterator range is contiguous. Violating this precondition yields + undefined behavior. **This precondition is enforced with an assertion.** + @pre Each element in the range has a size of 1 byte. Violating this + precondition yields undefined behavior. **This precondition is enforced + with a static assertion.** + + @warning There is no way to enforce all preconditions at compile-time. If + the function is called with noncompliant iterators and with + assertions switched off, the behavior is undefined and will most + likely yield segmentation violation. + + @tparam IteratorType iterator of container with contiguous storage + @param[in] first begin of the range to parse (included) + @param[in] last end of the range to parse (excluded) + @param[in] cb a parser callback function of type @ref parser_callback_t + which is used to control the deserialization by filtering unwanted values + (optional) + + @return result of the deserialization + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. The complexity can be higher if the parser callback function + @a cb has a super-linear complexity. + + @note A UTF-8 byte order mark is silently ignored. + + @liveexample{The example below demonstrates the `parse()` function reading + from an iterator range.,parse__iteratortype__parser_callback_t} + + @since version 2.0.3 + */ + template::iterator_category>::value, int>::type = 0> + static basic_json parse(IteratorType first, IteratorType last, + const parser_callback_t cb = nullptr) + { + // assertion to check that the iterator range is indeed contiguous, + // see http://stackoverflow.com/a/35008842/266378 for more discussion + assert(std::accumulate(first, last, std::pair(true, 0), + [&first](std::pair res, decltype(*first) val) + { + res.first &= (val == *(std::next(std::addressof(*first), res.second++))); + return res; + }).first); + + // assertion to check that each element is 1 byte long + static_assert(sizeof(typename std::iterator_traits::value_type) == 1, + "each element in the iterator range must have the size of 1 byte"); + + // if iterator range is empty, create a parser with an empty string + // to generate "unexpected EOF" error message + if (std::distance(first, last) <= 0) + { + return parser("").parse(); + } + + return parser(first, last, cb).parse(); + } + + /*! + @brief deserialize from a container with contiguous storage + + This function reads from a container with contiguous storage of 1-byte + values. Compatible container types include `std::vector`, `std::string`, + `std::array`, and `std::initializer_list`. User-defined containers can be + used as long as they implement random-access iterators and a contiguous + storage. + + @pre The container storage is contiguous. Violating this precondition + yields undefined behavior. **This precondition is enforced with an + assertion.** + @pre Each element of the container has a size of 1 byte. Violating this + precondition yields undefined behavior. **This precondition is enforced + with a static assertion.** + + @warning There is no way to enforce all preconditions at compile-time. If + the function is called with a noncompliant container and with + assertions switched off, the behavior is undefined and will most + likely yield segmentation violation. + + @tparam ContiguousContainer container type with contiguous storage + @param[in] c container to read from + @param[in] cb a parser callback function of type @ref parser_callback_t + which is used to control the deserialization by filtering unwanted values + (optional) + + @return result of the deserialization + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. The complexity can be higher if the parser callback function + @a cb has a super-linear complexity. + + @note A UTF-8 byte order mark is silently ignored. + + @liveexample{The example below demonstrates the `parse()` function reading + from a contiguous container.,parse__contiguouscontainer__parser_callback_t} + + @since version 2.0.3 + */ + template::value and + std::is_base_of< + std::random_access_iterator_tag, + typename std::iterator_traits()))>::iterator_category>::value + , int>::type = 0> + static basic_json parse(const ContiguousContainer& c, + const parser_callback_t cb = nullptr) + { + // delegate the call to the iterator-range parse overload + return parse(std::begin(c), std::end(c), cb); + } + /*! @brief deserialize from stream @@ -5267,8 +6506,8 @@ class basic_json @liveexample{The example below shows how a JSON value is constructed by reading a serialization from a stream.,operator_deserialize} - @sa parse(std::istream&, parser_callback_t) for a variant with a parser - callback function to filter values while parsing + @sa parse(std::istream&, const parser_callback_t) for a variant with a + parser callback function to filter values while parsing @since version 1.0.0 */ @@ -5290,34 +6529,1563 @@ class basic_json /// @} + ////////////////////////////////////////// + // binary serialization/deserialization // + ////////////////////////////////////////// + + /// @name binary serialization/deserialization support + /// @{ private: + /*! + @note Some code in the switch cases has been copied, because otherwise + copilers would complain about implicit fallthrough and there is no + portable attribute to mute such warnings. + */ + template + static void add_to_vector(std::vector& vec, size_t bytes, const T number) + { + assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8); + + switch (bytes) + { + case 8: + { + vec.push_back(static_cast((static_cast(number) >> 070) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 060) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 050) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 040) & 0xff)); + vec.push_back(static_cast((number >> 030) & 0xff)); + vec.push_back(static_cast((number >> 020) & 0xff)); + vec.push_back(static_cast((number >> 010) & 0xff)); + vec.push_back(static_cast(number & 0xff)); + break; + } + + case 4: + { + vec.push_back(static_cast((number >> 030) & 0xff)); + vec.push_back(static_cast((number >> 020) & 0xff)); + vec.push_back(static_cast((number >> 010) & 0xff)); + vec.push_back(static_cast(number & 0xff)); + break; + } + + case 2: + { + vec.push_back(static_cast((number >> 010) & 0xff)); + vec.push_back(static_cast(number & 0xff)); + break; + } + + case 1: + { + vec.push_back(static_cast(number & 0xff)); + break; + } + } + } + + /*! + @brief take sufficient bytes from a vector to fill an integer variable + + In the context of binary serialization formats, we need to read several + bytes from a byte vector and combine them to multi-byte integral data + types. + + @param[in] vec byte vector to read from + @param[in] current_index the position in the vector after which to read + + @return the next sizeof(T) bytes from @a vec, in reverse order as T + + @tparam T the integral return type + + @throw std::out_of_range if there are less than sizeof(T)+1 bytes in the + vector @a vec to read + + In the for loop, the bytes from the vector are copied in reverse order into + the return value. In the figures below, let sizeof(T)=4 and `i` be the loop + variable. + + Precondition: + + vec: | | | a | b | c | d | T: | | | | | + ^ ^ ^ ^ + current_index i ptr sizeof(T) + + Postcondition: + + vec: | | | a | b | c | d | T: | d | c | b | a | + ^ ^ ^ + | i ptr + current_index + + @sa Code adapted from . + */ + template + static T get_from_vector(const std::vector& vec, const size_t current_index) + { + if (current_index + sizeof(T) + 1 > vec.size()) + { + JSON_THROW(std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector")); + } + + T result; + auto* ptr = reinterpret_cast(&result); + for (size_t i = 0; i < sizeof(T); ++i) + { + *ptr++ = vec[current_index + sizeof(T) - i]; + } + return result; + } + + /*! + @brief create a MessagePack serialization of a given JSON value + + This is a straightforward implementation of the MessagePack specification. + + @param[in] j JSON value to serialize + @param[in,out] v byte vector to write the serialization to + + @sa https://github.com/msgpack/msgpack/blob/master/spec.md + */ + static void to_msgpack_internal(const basic_json& j, std::vector& v) + { + switch (j.type()) + { + case value_t::null: + { + // nil + v.push_back(0xc0); + break; + } + + case value_t::boolean: + { + // true and false + v.push_back(j.m_value.boolean ? 0xc3 : 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 + add_to_vector(v, 1, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) + { + // uint 8 + v.push_back(0xcc); + add_to_vector(v, 1, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) + { + // uint 16 + v.push_back(0xcd); + add_to_vector(v, 2, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) + { + // uint 32 + v.push_back(0xce); + add_to_vector(v, 4, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) + { + // uint 64 + v.push_back(0xcf); + add_to_vector(v, 8, j.m_value.number_unsigned); + } + } + else + { + if (j.m_value.number_integer >= -32) + { + // negative fixnum + add_to_vector(v, 1, j.m_value.number_integer); + } + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) + { + // int 8 + v.push_back(0xd0); + add_to_vector(v, 1, j.m_value.number_integer); + } + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) + { + // int 16 + v.push_back(0xd1); + add_to_vector(v, 2, j.m_value.number_integer); + } + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) + { + // int 32 + v.push_back(0xd2); + add_to_vector(v, 4, j.m_value.number_integer); + } + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) + { + // int 64 + v.push_back(0xd3); + add_to_vector(v, 8, j.m_value.number_integer); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned < 128) + { + // positive fixnum + add_to_vector(v, 1, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) + { + // uint 8 + v.push_back(0xcc); + add_to_vector(v, 1, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) + { + // uint 16 + v.push_back(0xcd); + add_to_vector(v, 2, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) + { + // uint 32 + v.push_back(0xce); + add_to_vector(v, 4, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) + { + // uint 64 + v.push_back(0xcf); + add_to_vector(v, 8, j.m_value.number_unsigned); + } + break; + } + + case value_t::number_float: + { + // float 64 + v.push_back(0xcb); + const auto* helper = reinterpret_cast(&(j.m_value.number_float)); + for (size_t i = 0; i < 8; ++i) + { + v.push_back(helper[7 - i]); + } + break; + } + + case value_t::string: + { + const auto N = j.m_value.string->size(); + if (N <= 31) + { + // fixstr + v.push_back(static_cast(0xa0 | N)); + } + else if (N <= 255) + { + // str 8 + v.push_back(0xd9); + add_to_vector(v, 1, N); + } + else if (N <= 65535) + { + // str 16 + v.push_back(0xda); + add_to_vector(v, 2, N); + } + else if (N <= 4294967295) + { + // str 32 + v.push_back(0xdb); + add_to_vector(v, 4, N); + } + + // append string + std::copy(j.m_value.string->begin(), j.m_value.string->end(), + std::back_inserter(v)); + break; + } + + case value_t::array: + { + const auto N = j.m_value.array->size(); + if (N <= 15) + { + // fixarray + v.push_back(static_cast(0x90 | N)); + } + else if (N <= 0xffff) + { + // array 16 + v.push_back(0xdc); + add_to_vector(v, 2, N); + } + else if (N <= 0xffffffff) + { + // array 32 + v.push_back(0xdd); + add_to_vector(v, 4, N); + } + + // append each element + for (const auto& el : *j.m_value.array) + { + to_msgpack_internal(el, v); + } + break; + } + + case value_t::object: + { + const auto N = j.m_value.object->size(); + if (N <= 15) + { + // fixmap + v.push_back(static_cast(0x80 | (N & 0xf))); + } + else if (N <= 65535) + { + // map 16 + v.push_back(0xde); + add_to_vector(v, 2, N); + } + else if (N <= 4294967295) + { + // map 32 + v.push_back(0xdf); + add_to_vector(v, 4, N); + } + + // append each element + for (const auto& el : *j.m_value.object) + { + to_msgpack_internal(el.first, v); + to_msgpack_internal(el.second, v); + } + break; + } + + default: + { + break; + } + } + } + + /*! + @brief create a CBOR serialization of a given JSON value + + This is a straightforward implementation of the CBOR specification. + + @param[in] j JSON value to serialize + @param[in,out] v byte vector to write the serialization to + + @sa https://tools.ietf.org/html/rfc7049 + */ + static void to_cbor_internal(const basic_json& j, std::vector& v) + { + switch (j.type()) + { + case value_t::null: + { + v.push_back(0xf6); + break; + } + + case value_t::boolean: + { + v.push_back(j.m_value.boolean ? 0xf5 : 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) + { + add_to_vector(v, 1, j.m_value.number_integer); + } + else if (j.m_value.number_integer <= std::numeric_limits::max()) + { + v.push_back(0x18); + // one-byte uint8_t + add_to_vector(v, 1, j.m_value.number_integer); + } + else if (j.m_value.number_integer <= std::numeric_limits::max()) + { + v.push_back(0x19); + // two-byte uint16_t + add_to_vector(v, 2, j.m_value.number_integer); + } + else if (j.m_value.number_integer <= std::numeric_limits::max()) + { + v.push_back(0x1a); + // four-byte uint32_t + add_to_vector(v, 4, j.m_value.number_integer); + } + else + { + v.push_back(0x1b); + // eight-byte uint64_t + add_to_vector(v, 8, 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) + { + v.push_back(static_cast(0x20 + positive_number)); + } + else if (positive_number <= std::numeric_limits::max()) + { + // int 8 + v.push_back(0x38); + add_to_vector(v, 1, positive_number); + } + else if (positive_number <= std::numeric_limits::max()) + { + // int 16 + v.push_back(0x39); + add_to_vector(v, 2, positive_number); + } + else if (positive_number <= std::numeric_limits::max()) + { + // int 32 + v.push_back(0x3a); + add_to_vector(v, 4, positive_number); + } + else + { + // int 64 + v.push_back(0x3b); + add_to_vector(v, 8, positive_number); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned <= 0x17) + { + v.push_back(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= 0xff) + { + v.push_back(0x18); + // one-byte uint8_t + add_to_vector(v, 1, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= 0xffff) + { + v.push_back(0x19); + // two-byte uint16_t + add_to_vector(v, 2, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= 0xffffffff) + { + v.push_back(0x1a); + // four-byte uint32_t + add_to_vector(v, 4, j.m_value.number_unsigned); + } + else if (j.m_value.number_unsigned <= 0xffffffffffffffff) + { + v.push_back(0x1b); + // eight-byte uint64_t + add_to_vector(v, 8, j.m_value.number_unsigned); + } + break; + } + + case value_t::number_float: + { + // Double-Precision Float + v.push_back(0xfb); + const auto* helper = reinterpret_cast(&(j.m_value.number_float)); + for (size_t i = 0; i < 8; ++i) + { + v.push_back(helper[7 - i]); + } + break; + } + + case value_t::string: + { + const auto N = j.m_value.string->size(); + if (N <= 0x17) + { + v.push_back(0x60 + static_cast(N)); // 1 byte for string + size + } + else if (N <= 0xff) + { + v.push_back(0x78); // one-byte uint8_t for N + add_to_vector(v, 1, N); + } + else if (N <= 0xffff) + { + v.push_back(0x79); // two-byte uint16_t for N + add_to_vector(v, 2, N); + } + else if (N <= 0xffffffff) + { + v.push_back(0x7a); // four-byte uint32_t for N + add_to_vector(v, 4, N); + } + // LCOV_EXCL_START + else if (N <= 0xffffffffffffffff) + { + v.push_back(0x7b); // eight-byte uint64_t for N + add_to_vector(v, 8, N); + } + // LCOV_EXCL_STOP + + // append string + std::copy(j.m_value.string->begin(), j.m_value.string->end(), + std::back_inserter(v)); + break; + } + + case value_t::array: + { + const auto N = j.m_value.array->size(); + if (N <= 0x17) + { + v.push_back(0x80 + static_cast(N)); // 1 byte for array + size + } + else if (N <= 0xff) + { + v.push_back(0x98); // one-byte uint8_t for N + add_to_vector(v, 1, N); + } + else if (N <= 0xffff) + { + v.push_back(0x99); // two-byte uint16_t for N + add_to_vector(v, 2, N); + } + else if (N <= 0xffffffff) + { + v.push_back(0x9a); // four-byte uint32_t for N + add_to_vector(v, 4, N); + } + // LCOV_EXCL_START + else if (N <= 0xffffffffffffffff) + { + v.push_back(0x9b); // eight-byte uint64_t for N + add_to_vector(v, 8, N); + } + // LCOV_EXCL_STOP + + // append each element + for (const auto& el : *j.m_value.array) + { + to_cbor_internal(el, v); + } + break; + } + + case value_t::object: + { + const auto N = j.m_value.object->size(); + if (N <= 0x17) + { + v.push_back(0xa0 + static_cast(N)); // 1 byte for object + size + } + else if (N <= 0xff) + { + v.push_back(0xb8); + add_to_vector(v, 1, N); // one-byte uint8_t for N + } + else if (N <= 0xffff) + { + v.push_back(0xb9); + add_to_vector(v, 2, N); // two-byte uint16_t for N + } + else if (N <= 0xffffffff) + { + v.push_back(0xba); + add_to_vector(v, 4, N); // four-byte uint32_t for N + } + // LCOV_EXCL_START + else if (N <= 0xffffffffffffffff) + { + v.push_back(0xbb); + add_to_vector(v, 8, N); // eight-byte uint64_t for N + } + // LCOV_EXCL_STOP + + // append each element + for (const auto& el : *j.m_value.object) + { + to_cbor_internal(el.first, v); + to_cbor_internal(el.second, v); + } + break; + } + + default: + { + break; + } + } + } + + + /* + @brief checks if given lengths do not exceed the size of a given vector + + To secure the access to the byte vector during CBOR/MessagePack + deserialization, bytes are copied from the vector into buffers. This + function checks if the number of bytes to copy (@a len) does not exceed + the size @s size of the vector. Additionally, an @a offset is given from + where to start reading the bytes. + + This function checks whether reading the bytes is safe; that is, offset is + a valid index in the vector, offset+len + + @param[in] size size of the byte vector + @param[in] len number of bytes to read + @param[in] offset offset where to start reading + + vec: x x x x x X X X X X + ^ ^ ^ + 0 offset len + + @throws out_of_range if `len > v.size()` + */ + static void check_length(const size_t size, const size_t len, const size_t offset) + { + // simple case: requested length is greater than the vector's length + if (len > size or offset > size) + { + JSON_THROW(std::out_of_range("len out of range")); + } + + // second case: adding offset would result in overflow + if ((size > (std::numeric_limits::max() - offset))) + { + JSON_THROW(std::out_of_range("len+offset out of range")); + } + + // last case: reading past the end of the vector + if (len + offset > size) + { + JSON_THROW(std::out_of_range("len+offset out of range")); + } + } + + /*! + @brief create a JSON value from a given MessagePack vector + + @param[in] v MessagePack serialization + @param[in] idx byte index to start reading from @a v + + @return deserialized JSON value + + @throw std::invalid_argument if unsupported features from MessagePack were + used in the given vector @a v or if the input is not valid MessagePack + @throw std::out_of_range if the given vector ends prematurely + + @sa https://github.com/msgpack/msgpack/blob/master/spec.md + */ + static basic_json from_msgpack_internal(const std::vector& v, size_t& idx) + { + // make sure reading 1 byte is safe + check_length(v.size(), 1, idx); + + // store and increment index + const size_t current_idx = idx++; + + if (v[current_idx] <= 0xbf) + { + if (v[current_idx] <= 0x7f) // positive fixint + { + return v[current_idx]; + } + if (v[current_idx] <= 0x8f) // fixmap + { + basic_json result = value_t::object; + const size_t len = v[current_idx] & 0x0f; + for (size_t i = 0; i < len; ++i) + { + std::string key = from_msgpack_internal(v, idx); + result[key] = from_msgpack_internal(v, idx); + } + return result; + } + else if (v[current_idx] <= 0x9f) // fixarray + { + basic_json result = value_t::array; + const size_t len = v[current_idx] & 0x0f; + for (size_t i = 0; i < len; ++i) + { + result.push_back(from_msgpack_internal(v, idx)); + } + return result; + } + else // fixstr + { + const size_t len = v[current_idx] & 0x1f; + const size_t offset = current_idx + 1; + idx += len; // skip content bytes + check_length(v.size(), len, offset); + return std::string(reinterpret_cast(v.data()) + offset, len); + } + } + else if (v[current_idx] >= 0xe0) // negative fixint + { + return static_cast(v[current_idx]); + } + else + { + switch (v[current_idx]) + { + case 0xc0: // nil + { + return value_t::null; + } + + case 0xc2: // false + { + return false; + } + + case 0xc3: // true + { + return true; + } + + case 0xca: // float 32 + { + // copy bytes in reverse order into the double variable + float res; + for (size_t byte = 0; byte < sizeof(float); ++byte) + { + reinterpret_cast(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte); + } + idx += sizeof(float); // skip content bytes + return res; + } + + case 0xcb: // float 64 + { + // copy bytes in reverse order into the double variable + double res; + for (size_t byte = 0; byte < sizeof(double); ++byte) + { + reinterpret_cast(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte); + } + idx += sizeof(double); // skip content bytes + return res; + } + + case 0xcc: // uint 8 + { + idx += 1; // skip content byte + return get_from_vector(v, current_idx); + } + + case 0xcd: // uint 16 + { + idx += 2; // skip 2 content bytes + return get_from_vector(v, current_idx); + } + + case 0xce: // uint 32 + { + idx += 4; // skip 4 content bytes + return get_from_vector(v, current_idx); + } + + case 0xcf: // uint 64 + { + idx += 8; // skip 8 content bytes + return get_from_vector(v, current_idx); + } + + case 0xd0: // int 8 + { + idx += 1; // skip content byte + return get_from_vector(v, current_idx); + } + + case 0xd1: // int 16 + { + idx += 2; // skip 2 content bytes + return get_from_vector(v, current_idx); + } + + case 0xd2: // int 32 + { + idx += 4; // skip 4 content bytes + return get_from_vector(v, current_idx); + } + + case 0xd3: // int 64 + { + idx += 8; // skip 8 content bytes + return get_from_vector(v, current_idx); + } + + case 0xd9: // str 8 + { + const auto len = static_cast(get_from_vector(v, current_idx)); + const size_t offset = current_idx + 2; + idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); + return std::string(reinterpret_cast(v.data()) + offset, len); + } + + case 0xda: // str 16 + { + const auto len = static_cast(get_from_vector(v, current_idx)); + const size_t offset = current_idx + 3; + idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); + return std::string(reinterpret_cast(v.data()) + offset, len); + } + + case 0xdb: // str 32 + { + const auto len = static_cast(get_from_vector(v, current_idx)); + const size_t offset = current_idx + 5; + idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); + return std::string(reinterpret_cast(v.data()) + offset, len); + } + + case 0xdc: // array 16 + { + basic_json result = value_t::array; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 2; // skip 2 size bytes + for (size_t i = 0; i < len; ++i) + { + result.push_back(from_msgpack_internal(v, idx)); + } + return result; + } + + case 0xdd: // array 32 + { + basic_json result = value_t::array; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 4; // skip 4 size bytes + for (size_t i = 0; i < len; ++i) + { + result.push_back(from_msgpack_internal(v, idx)); + } + return result; + } + + case 0xde: // map 16 + { + basic_json result = value_t::object; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 2; // skip 2 size bytes + for (size_t i = 0; i < len; ++i) + { + std::string key = from_msgpack_internal(v, idx); + result[key] = from_msgpack_internal(v, idx); + } + return result; + } + + case 0xdf: // map 32 + { + basic_json result = value_t::object; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 4; // skip 4 size bytes + for (size_t i = 0; i < len; ++i) + { + std::string key = from_msgpack_internal(v, idx); + result[key] = from_msgpack_internal(v, idx); + } + return result; + } + + default: + { + JSON_THROW(std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast(v[current_idx])))); + } + } + } + } + + /*! + @brief create a JSON value from a given CBOR vector + + @param[in] v CBOR serialization + @param[in] idx byte index to start reading from @a v + + @return deserialized JSON value + + @throw std::invalid_argument if unsupported features from CBOR were used in + the given vector @a v or if the input is not valid CBOR + @throw std::out_of_range if the given vector ends prematurely + + @sa https://tools.ietf.org/html/rfc7049 + */ + static basic_json from_cbor_internal(const std::vector& v, size_t& idx) + { + // store and increment index + const size_t current_idx = idx++; + + switch (v.at(current_idx)) + { + // 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 v[current_idx]; + } + + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + idx += 1; // skip content byte + return get_from_vector(v, current_idx); + } + + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + idx += 2; // skip 2 content bytes + return get_from_vector(v, current_idx); + } + + case 0x1a: // Unsigned integer (four-byte uint32_t follows) + { + idx += 4; // skip 4 content bytes + return get_from_vector(v, current_idx); + } + + case 0x1b: // Unsigned integer (eight-byte uint64_t follows) + { + idx += 8; // skip 8 content bytes + return get_from_vector(v, current_idx); + } + + // 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 static_cast(0x20 - 1 - v[current_idx]); + } + + case 0x38: // Negative integer (one-byte uint8_t follows) + { + idx += 1; // skip content byte + // must be uint8_t ! + return static_cast(-1) - get_from_vector(v, current_idx); + } + + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + idx += 2; // skip 2 content bytes + return static_cast(-1) - get_from_vector(v, current_idx); + } + + case 0x3a: // Negative integer -1-n (four-byte uint32_t follows) + { + idx += 4; // skip 4 content bytes + return static_cast(-1) - get_from_vector(v, current_idx); + } + + case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows) + { + idx += 8; // skip 8 content bytes + return static_cast(-1) - static_cast(get_from_vector(v, current_idx)); + } + + // 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: + { + const auto len = static_cast(v[current_idx] - 0x60); + const size_t offset = current_idx + 1; + idx += len; // skip content bytes + check_length(v.size(), len, offset); + return std::string(reinterpret_cast(v.data()) + offset, len); + } + + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + const auto len = static_cast(get_from_vector(v, current_idx)); + const size_t offset = current_idx + 2; + idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); + return std::string(reinterpret_cast(v.data()) + offset, len); + } + + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + const auto len = static_cast(get_from_vector(v, current_idx)); + const size_t offset = current_idx + 3; + idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); + return std::string(reinterpret_cast(v.data()) + offset, len); + } + + case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) + { + const auto len = static_cast(get_from_vector(v, current_idx)); + const size_t offset = current_idx + 5; + idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); + return std::string(reinterpret_cast(v.data()) + offset, len); + } + + case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) + { + const auto len = static_cast(get_from_vector(v, current_idx)); + const size_t offset = current_idx + 9; + idx += len + 8; // skip 8 size bytes + content bytes + check_length(v.size(), len, offset); + return std::string(reinterpret_cast(v.data()) + offset, len); + } + + case 0x7f: // UTF-8 string (indefinite length) + { + std::string result; + while (v.at(idx) != 0xff) + { + string_t s = from_cbor_internal(v, idx); + result += s; + } + // skip break byte (0xFF) + idx += 1; + return result; + } + + // 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: + { + basic_json result = value_t::array; + const auto len = static_cast(v[current_idx] - 0x80); + for (size_t i = 0; i < len; ++i) + { + result.push_back(from_cbor_internal(v, idx)); + } + return result; + } + + case 0x98: // array (one-byte uint8_t for n follows) + { + basic_json result = value_t::array; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 1; // skip 1 size byte + for (size_t i = 0; i < len; ++i) + { + result.push_back(from_cbor_internal(v, idx)); + } + return result; + } + + case 0x99: // array (two-byte uint16_t for n follow) + { + basic_json result = value_t::array; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 2; // skip 4 size bytes + for (size_t i = 0; i < len; ++i) + { + result.push_back(from_cbor_internal(v, idx)); + } + return result; + } + + case 0x9a: // array (four-byte uint32_t for n follow) + { + basic_json result = value_t::array; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 4; // skip 4 size bytes + for (size_t i = 0; i < len; ++i) + { + result.push_back(from_cbor_internal(v, idx)); + } + return result; + } + + case 0x9b: // array (eight-byte uint64_t for n follow) + { + basic_json result = value_t::array; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 8; // skip 8 size bytes + for (size_t i = 0; i < len; ++i) + { + result.push_back(from_cbor_internal(v, idx)); + } + return result; + } + + case 0x9f: // array (indefinite length) + { + basic_json result = value_t::array; + while (v.at(idx) != 0xff) + { + result.push_back(from_cbor_internal(v, idx)); + } + // skip break byte (0xFF) + idx += 1; + return result; + } + + // 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: + { + basic_json result = value_t::object; + const auto len = static_cast(v[current_idx] - 0xa0); + for (size_t i = 0; i < len; ++i) + { + std::string key = from_cbor_internal(v, idx); + result[key] = from_cbor_internal(v, idx); + } + return result; + } + + case 0xb8: // map (one-byte uint8_t for n follows) + { + basic_json result = value_t::object; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 1; // skip 1 size byte + for (size_t i = 0; i < len; ++i) + { + std::string key = from_cbor_internal(v, idx); + result[key] = from_cbor_internal(v, idx); + } + return result; + } + + case 0xb9: // map (two-byte uint16_t for n follow) + { + basic_json result = value_t::object; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 2; // skip 2 size bytes + for (size_t i = 0; i < len; ++i) + { + std::string key = from_cbor_internal(v, idx); + result[key] = from_cbor_internal(v, idx); + } + return result; + } + + case 0xba: // map (four-byte uint32_t for n follow) + { + basic_json result = value_t::object; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 4; // skip 4 size bytes + for (size_t i = 0; i < len; ++i) + { + std::string key = from_cbor_internal(v, idx); + result[key] = from_cbor_internal(v, idx); + } + return result; + } + + case 0xbb: // map (eight-byte uint64_t for n follow) + { + basic_json result = value_t::object; + const auto len = static_cast(get_from_vector(v, current_idx)); + idx += 8; // skip 8 size bytes + for (size_t i = 0; i < len; ++i) + { + std::string key = from_cbor_internal(v, idx); + result[key] = from_cbor_internal(v, idx); + } + return result; + } + + case 0xbf: // map (indefinite length) + { + basic_json result = value_t::object; + while (v.at(idx) != 0xff) + { + std::string key = from_cbor_internal(v, idx); + result[key] = from_cbor_internal(v, idx); + } + // skip break byte (0xFF) + idx += 1; + return result; + } + + case 0xf4: // false + { + return false; + } + + case 0xf5: // true + { + return true; + } + + case 0xf6: // null + { + return value_t::null; + } + + case 0xf9: // Half-Precision Float (two-byte IEEE 754) + { + idx += 2; // skip two content bytes + + // 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 int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2); + const int exp = (half >> 10) & 0x1f; + const int mant = half & 0x3ff; + double val; + if (exp == 0) + { + val = std::ldexp(mant, -24); + } + else if (exp != 31) + { + val = std::ldexp(mant + 1024, exp - 25); + } + else + { + val = mant == 0 + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + } + return (half & 0x8000) != 0 ? -val : val; + } + + case 0xfa: // Single-Precision Float (four-byte IEEE 754) + { + // copy bytes in reverse order into the float variable + float res; + for (size_t byte = 0; byte < sizeof(float); ++byte) + { + reinterpret_cast(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte); + } + idx += sizeof(float); // skip content bytes + return res; + } + + case 0xfb: // Double-Precision Float (eight-byte IEEE 754) + { + // copy bytes in reverse order into the double variable + double res; + for (size_t byte = 0; byte < sizeof(double); ++byte) + { + reinterpret_cast(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte); + } + idx += sizeof(double); // skip content bytes + return res; + } + + default: // anything else (0xFF is handled inside the other types) + { + JSON_THROW(std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast(v[current_idx])))); + } + } + } + + public: + /*! + @brief create a MessagePack serialization of a given JSON value + + Serializes a given JSON value @a j to a byte vector using the MessagePack + serialization format. MessagePack is a binary serialization format which + aims to be more compact than JSON itself, yet more efficient to parse. + + @param[in] j JSON value to serialize + @return MessagePack serialization as byte vector + + @complexity Linear in the size of the JSON value @a j. + + @liveexample{The example shows the serialization of a JSON value to a byte + vector in MessagePack format.,to_msgpack} + + @sa http://msgpack.org + @sa @ref from_msgpack(const std::vector&, const size_t) for the + analogous deserialization + @sa @ref to_cbor(const basic_json& for the related CBOR format + + @since version 2.0.9 + */ + static std::vector to_msgpack(const basic_json& j) + { + std::vector result; + to_msgpack_internal(j, result); + return result; + } + + /*! + @brief create a JSON value from a byte vector in MessagePack format + + Deserializes a given byte vector @a v to a JSON value using the MessagePack + serialization format. + + @param[in] v a byte vector in MessagePack format + @param[in] start_index the index to start reading from @a v (0 by default) + @return deserialized JSON value + + @throw std::invalid_argument if unsupported features from MessagePack were + used in the given vector @a v or if the input is not valid MessagePack + @throw std::out_of_range if the given vector ends prematurely + + @complexity Linear in the size of the byte vector @a v. + + @liveexample{The example shows the deserialization of a byte vector in + MessagePack format to a JSON value.,from_msgpack} + + @sa http://msgpack.org + @sa @ref to_msgpack(const basic_json&) for the analogous serialization + @sa @ref from_cbor(const std::vector&, const size_t) for the + related CBOR format + + @since version 2.0.9, parameter @a start_index since 2.1.1 + */ + static basic_json from_msgpack(const std::vector& v, + const size_t start_index = 0) + { + size_t i = start_index; + return from_msgpack_internal(v, i); + } + + /*! + @brief create a MessagePack serialization of a given JSON value + + Serializes a given JSON value @a j to a byte vector using the CBOR (Concise + Binary Object Representation) serialization format. CBOR is a binary + serialization format which aims to be more compact than JSON itself, yet + more efficient to parse. + + @param[in] j JSON value to serialize + @return MessagePack serialization as byte vector + + @complexity Linear in the size of the JSON value @a j. + + @liveexample{The example shows the serialization of a JSON value to a byte + vector in CBOR format.,to_cbor} + + @sa http://cbor.io + @sa @ref from_cbor(const std::vector&, const size_t) for the + analogous deserialization + @sa @ref to_msgpack(const basic_json& for the related MessagePack format + + @since version 2.0.9 + */ + static std::vector to_cbor(const basic_json& j) + { + std::vector result; + to_cbor_internal(j, result); + return result; + } + + /*! + @brief create a JSON value from a byte vector in CBOR format + + Deserializes a given byte vector @a v to a JSON value using the CBOR + (Concise Binary Object Representation) serialization format. + + @param[in] v a byte vector in CBOR format + @param[in] start_index the index to start reading from @a v (0 by default) + @return deserialized JSON value + + @throw std::invalid_argument if unsupported features from CBOR were used in + the given vector @a v or if the input is not valid MessagePack + @throw std::out_of_range if the given vector ends prematurely + + @complexity Linear in the size of the byte vector @a v. + + @liveexample{The example shows the deserialization of a byte vector in CBOR + format to a JSON value.,from_cbor} + + @sa http://cbor.io + @sa @ref to_cbor(const basic_json&) for the analogous serialization + @sa @ref from_msgpack(const std::vector&, const size_t) for the + related MessagePack format + + @since version 2.0.9, parameter @a start_index since 2.1.1 + */ + static basic_json from_cbor(const std::vector& v, + const size_t start_index = 0) + { + size_t i = start_index; + return from_cbor_internal(v, i); + } + + /// @} + /////////////////////////// // convenience functions // /////////////////////////// - /// return the type as string - string_t type_name() const + /*! + @brief return the type as string + + Returns the type name as string to be used in error messages - usually to + indicate that a function was called on a wrong JSON type. + + @return basically a string representation of a the @a m_type member + + @complexity Constant. + + @liveexample{The following code exemplifies `type_name()` for all JSON + types.,type_name} + + @since version 1.0.0, public since 2.1.0 + */ + std::string type_name() const { - 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::discarded: - return "discarded"; - default: - return "number"; + 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::discarded: + return "discarded"; + default: + return "number"; + } } } + private: /*! @brief calculates the extra space to escape a JSON string @@ -5328,9 +8096,8 @@ class basic_json */ static std::size_t extra_space(const string_t& s) noexcept { - std::size_t result = 0; - - for (const auto& c : s) + return std::accumulate(s.begin(), s.end(), size_t{}, + [](size_t res, typename string_t::value_type c) { switch (c) { @@ -5343,8 +8110,7 @@ class basic_json case '\t': { // from c (1 byte) to \x (2 bytes) - result += 1; - break; + return res + 1; } default: @@ -5352,21 +8118,20 @@ class basic_json if (c >= 0x00 and c <= 0x1f) { // from c (1 byte) to \uxxxx (6 bytes) - result += 5; + return res + 5; } - break; + + return res; } } - } - - return result; + }); } /*! @brief escape a string - Escape a string by replacing certain special characters by a sequence of an - escape character (backslash) and another character and other control + 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. @@ -5375,7 +8140,7 @@ class basic_json @complexity Linear in the length of string @a s. */ - static string_t escape_string(const string_t& s) noexcept + static string_t escape_string(const string_t& s) { const auto space = extra_space(s); if (space == 0) @@ -5451,15 +8216,17 @@ class basic_json { if (c >= 0x00 and c <= 0x1f) { - // convert a number 0..15 to its hex representation (0..f) - auto hexify = [](const char v) -> char + // convert a number 0..15 to its hex representation + // (0..f) + static const char hexify[16] = { - return (v < 10) ? ('0' + v) : ('a' + v - 10); + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; // print character c as \uxxxx for (const char m : - { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f) + { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f] }) { result[++pos] = m; @@ -5480,17 +8247,165 @@ class basic_json return result; } + + /*! + @brief locale-independent serialization for built-in arithmetic types + */ + struct numtostr + { + public: + template + numtostr(NumberType value) + { + x_write(value, std::is_integral()); + } + + const char* c_str() const + { + return m_buf.data(); + } + + private: + /// a (hopefully) large enough character buffer + std::array < char, 64 > m_buf{{}}; + + template + void x_write(NumberType x, /*is_integral=*/std::true_type) + { + // special case for "0" + if (x == 0) + { + m_buf[0] = '0'; + return; + } + + const bool is_negative = x < 0; + size_t i = 0; + + // spare 1 byte for '\0' + while (x != 0 and i < m_buf.size() - 1) + { + const auto digit = std::labs(static_cast(x % 10)); + m_buf[i++] = static_cast('0' + digit); + x /= 10; + } + + // make sure the number has been processed completely + assert(x == 0); + + if (is_negative) + { + // make sure there is capacity for the '-' + assert(i < m_buf.size() - 2); + m_buf[i++] = '-'; + } + + std::reverse(m_buf.begin(), m_buf.begin() + i); + } + + template + void x_write(NumberType x, /*is_integral=*/std::false_type) + { + // special case for 0.0 and -0.0 + if (x == 0) + { + size_t i = 0; + if (std::signbit(x)) + { + m_buf[i++] = '-'; + } + m_buf[i++] = '0'; + m_buf[i++] = '.'; + m_buf[i] = '0'; + return; + } + + // get number of digits for a text -> float -> text round-trip + static constexpr auto d = std::numeric_limits::digits10; + + // the actual conversion + const auto written_bytes = snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); + + // negative value indicates an error + assert(written_bytes > 0); + // check if buffer was large enough + assert(static_cast(written_bytes) < m_buf.size()); + + // read information from locale + const auto loc = localeconv(); + assert(loc != nullptr); + const char thousands_sep = !loc->thousands_sep ? '\0' + : loc->thousands_sep[0]; + + const char decimal_point = !loc->decimal_point ? '\0' + : loc->decimal_point[0]; + + // erase thousands separator + if (thousands_sep != '\0') + { + const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep); + std::fill(end, m_buf.end(), '\0'); + } + + // convert decimal point to '.' + if (decimal_point != '\0' and decimal_point != '.') + { + for (auto& c : m_buf) + { + if (c == decimal_point) + { + c = '.'; + break; + } + } + } + + // determine if need to append ".0" + size_t i = 0; + bool value_is_int_like = true; + for (i = 0; i < m_buf.size(); ++i) + { + // break when end of number is reached + if (m_buf[i] == '\0') + { + break; + } + + // check if we find non-int character + value_is_int_like = value_is_int_like and m_buf[i] != '.' and + m_buf[i] != 'e' and m_buf[i] != 'E'; + } + + if (value_is_int_like) + { + // there must be 2 bytes left for ".0" + assert((i + 2) < m_buf.size()); + // we write to the end of the number + assert(m_buf[i] == '\0'); + assert(m_buf[i - 1] != '\0'); + + // add ".0" + m_buf[i] = '.'; + m_buf[i + 1] = '0'; + + // the resulting string is properly terminated + assert(m_buf[i + 2] == '\0'); + } + } + }; + + /*! @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. Note that + additional parameter. In case of arrays and objects, the function is + called recursively. Note that - - 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 + - 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 @param[out] o stream to write to @param[in] pretty_print whether the output shall be pretty-printed @@ -5509,8 +8424,6 @@ class basic_json { case value_t::object: { - assert(m_value.object != nullptr); - if (m_value.object->empty()) { o << "{}"; @@ -5551,8 +8464,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); - if (m_value.array->empty()) { o << "[]"; @@ -5591,7 +8502,6 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); o << string_t("\"") << escape_string(*m_value.string) << "\""; return; } @@ -5604,29 +8514,19 @@ class basic_json case value_t::number_integer: { - o << m_value.number_integer; + o << numtostr(m_value.number_integer).c_str(); + return; + } + + case value_t::number_unsigned: + { + o << numtostr(m_value.number_unsigned).c_str(); return; } case value_t::number_float: { - // If the number is an integer then output as a fixed with with - // precision 1 to output "0.0", "1.0" etc as expected for some - // round trip tests otherwise 15 digits of precision allows - // round-trip IEEE 754 string->double->string; to be safe, we - // read this value from - // std::numeric_limits::digits10 - if (std::fmod(m_value.number_float, 1) == 0) - { - o << std::fixed << std::setprecision(1); - } - else - { - // std::defaultfloat not supported in gcc version < 5 - o.unsetf(std::ios_base::floatfield); - o << std::setprecision(std::numeric_limits::digits10); - } - o << m_value.number_float; + o << numtostr(m_value.number_float).c_str(); return; } @@ -5673,40 +8573,118 @@ class basic_json class primitive_iterator_t { public: + + difference_type get_value() const noexcept + { + return m_it; + } /// set iterator to a defined beginning - void set_begin() + void set_begin() noexcept { m_it = begin_value; } /// set iterator to a defined past the end - void set_end() + void set_end() noexcept { m_it = end_value; } /// return whether the iterator can be dereferenced - bool is_begin() const + constexpr bool is_begin() const noexcept { return (m_it == begin_value); } /// return whether the iterator is at end - bool is_end() const + constexpr bool is_end() const noexcept { return (m_it == end_value); } - /// return reference to the value to change and compare - operator difference_type& () + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { - return m_it; + return lhs.m_it == rhs.m_it; } - /// return value to compare - operator difference_type () const + friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { - return m_it; + return !(lhs == rhs); + } + + 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; + } + + 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 i) + { + auto result = *this; + result += i; + return result; + } + + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it - rhs.m_it; + } + + friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it) + { + return os << it.m_it; + } + + primitive_iterator_t& operator++() + { + ++m_it; + return *this; + } + + primitive_iterator_t operator++(int) + { + auto result = *this; + m_it++; + return result; + } + + primitive_iterator_t& operator--() + { + --m_it; + return *this; + } + + primitive_iterator_t operator--(int) + { + auto result = *this; + m_it--; + return result; + } + + primitive_iterator_t& operator+=(difference_type n) + { + m_it += n; + return *this; + } + + primitive_iterator_t& operator-=(difference_type n) + { + m_it -= n; + return *this; } private: @@ -5734,7 +8712,7 @@ class basic_json primitive_iterator_t primitive_iterator; /// create an uninitialized internal_iterator - internal_iterator() + internal_iterator() noexcept : object_iterator(), array_iterator(), primitive_iterator() {} }; @@ -5754,7 +8732,7 @@ class basic_json size_t array_index = 0; public: - iteration_proxy_internal(IteratorType it) + explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {} @@ -5818,18 +8796,18 @@ class basic_json public: /// construct iteration proxy from a container - iteration_proxy(typename IteratorType::reference cont) + explicit iteration_proxy(typename IteratorType::reference cont) : container(cont) {} /// return iterator begin (needed for range-based for) - iteration_proxy_internal begin() + iteration_proxy_internal begin() noexcept { return iteration_proxy_internal(container.begin()); } /// return iterator end (needed for range-based for) - iteration_proxy_internal end() + iteration_proxy_internal end() noexcept { return iteration_proxy_internal(container.end()); } @@ -5837,40 +8815,62 @@ class basic_json public: /*! - @brief a const random access iterator for the @ref basic_json class + @brief a template for a random access iterator for the @ref basic_json class - This class implements a const iterator for the @ref basic_json class. From - this class, the @ref iterator class is derived. + 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: - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): The iterator that can be moved to point (forward and backward) to any element in constant time. - @since version 1.0.0 + @since version 1.0.0, simplified in version 2.0.9 */ - class const_iterator : public std::iterator + template + class iter_impl : public std::iterator { /// allow basic_json to access private members friend class basic_json; + // make sure U is basic_json or const basic_json + static_assert(std::is_same::value + or std::is_same::value, + "iter_impl only accepts (const) basic_json"); + public: /// the type of the values when the iterator is dereferenced using value_type = typename basic_json::value_type; /// a type to represent differences between iterators using difference_type = typename basic_json::difference_type; /// defines a pointer to the type iterated over (value_type) - using pointer = typename basic_json::const_pointer; + using pointer = typename std::conditional::value, + typename basic_json::const_pointer, + typename basic_json::pointer>::type; /// defines a reference to the type iterated over (value_type) - using reference = typename basic_json::const_reference; + using reference = typename std::conditional::value, + typename basic_json::const_reference, + typename basic_json::reference>::type; /// the category of the iterator using iterator_category = std::bidirectional_iterator_tag; /// default constructor - const_iterator() = default; + iter_impl() = default; - /// constructor for a given JSON instance - const_iterator(pointer object) : m_object(object) + /*! + @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) { assert(m_object != nullptr); @@ -5896,40 +8896,42 @@ class basic_json } } - /// copy constructor given a nonconst iterator - const_iterator(const iterator& other) : m_object(other.m_object) + /* + Use operator `const_iterator` instead of `const_iterator(const iterator& + other) noexcept` to avoid two class definitions for @ref iterator and + @ref const_iterator. + + This function is only called if this class is an @ref iterator. If this + class is a @ref const_iterator this function is not called. + */ + operator const_iterator() const { - assert(m_object != nullptr); + const_iterator ret; - switch (m_object->m_type) + if (m_object) { - case basic_json::value_t::object: - { - m_it.object_iterator = other.m_it.object_iterator; - break; - } - - case basic_json::value_t::array: - { - m_it.array_iterator = other.m_it.array_iterator; - break; - } - - default: - { - m_it.primitive_iterator = other.m_it.primitive_iterator; - break; - } + ret.m_object = m_object; + ret.m_it = m_it; } + + return ret; } - /// copy constructor - const_iterator(const const_iterator& other) noexcept + /*! + @brief copy constructor + @param[in] other iterator to copy from + @note It is not checked whether @a other is initialized. + */ + iter_impl(const iter_impl& other) noexcept : m_object(other.m_object), m_it(other.m_it) {} - /// copy assignment - const_iterator& operator=(const_iterator other) noexcept( + /*! + @brief copy assignment + @param[in,out] other iterator to copy from + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(iter_impl other) noexcept( std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value and std::is_nothrow_move_constructible::value and @@ -5942,8 +8944,11 @@ class basic_json } private: - /// set the iterator to the first value - void set_begin() + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_begin() noexcept { assert(m_object != nullptr); @@ -5951,14 +8956,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object != nullptr); m_it.object_iterator = m_object->m_value.object->begin(); break; } case basic_json::value_t::array: { - assert(m_object->m_value.array != nullptr); m_it.array_iterator = m_object->m_value.array->begin(); break; } @@ -5978,8 +8981,11 @@ class basic_json } } - /// set the iterator past the last value - void set_end() + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_end() noexcept { assert(m_object != nullptr); @@ -5987,14 +8993,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object != nullptr); m_it.object_iterator = m_object->m_value.object->end(); break; } case basic_json::value_t::array: { - assert(m_object->m_value.array != nullptr); m_it.array_iterator = m_object->m_value.array->end(); break; } @@ -6008,7 +9012,10 @@ class basic_json } public: - /// return a reference to the value pointed to by the iterator + /*! + @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 { assert(m_object != nullptr); @@ -6017,21 +9024,19 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object); assert(m_it.object_iterator != m_object->m_value.object->end()); return m_it.object_iterator->second; } case basic_json::value_t::array: { - assert(m_object->m_value.array); assert(m_it.array_iterator != m_object->m_value.array->end()); return *m_it.array_iterator; } case basic_json::value_t::null: { - throw std::out_of_range("cannot get value"); + JSON_THROW(std::out_of_range("cannot get value")); } default: @@ -6040,15 +9045,16 @@ class basic_json { return *m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + JSON_THROW(std::out_of_range("cannot get value")); } } } - /// dereference the iterator + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ pointer operator->() const { assert(m_object != nullptr); @@ -6057,14 +9063,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object); assert(m_it.object_iterator != m_object->m_value.object->end()); return &(m_it.object_iterator->second); } case basic_json::value_t::array: { - assert(m_object->m_value.array); assert(m_it.array_iterator != m_object->m_value.array->end()); return &*m_it.array_iterator; } @@ -6075,24 +9079,28 @@ class basic_json { return m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + JSON_THROW(std::out_of_range("cannot get value")); } } } - /// post-increment (it++) - const_iterator operator++(int) + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator++(int) { auto result = *this; ++(*this); return result; } - /// pre-increment (++it) - const_iterator& operator++() + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator++() { assert(m_object != nullptr); @@ -6100,13 +9108,13 @@ class basic_json { case basic_json::value_t::object: { - ++m_it.object_iterator; + std::advance(m_it.object_iterator, 1); break; } case basic_json::value_t::array: { - ++m_it.array_iterator; + std::advance(m_it.array_iterator, 1); break; } @@ -6120,16 +9128,22 @@ class basic_json return *this; } - /// post-decrement (it--) - const_iterator operator--(int) + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator--(int) { auto result = *this; --(*this); return result; } - /// pre-decrement (--it) - const_iterator& operator--() + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator--() { assert(m_object != nullptr); @@ -6137,13 +9151,13 @@ class basic_json { case basic_json::value_t::object: { - --m_it.object_iterator; + std::advance(m_it.object_iterator, -1); break; } case basic_json::value_t::array: { - --m_it.array_iterator; + std::advance(m_it.array_iterator, -1); break; } @@ -6157,13 +9171,16 @@ class basic_json return *this; } - /// comparison: equal - bool operator==(const const_iterator& other) const + /*! + @brief comparison: equal + @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 (m_object != other.m_object) { - throw std::domain_error("cannot compare iterators of different containers"); + JSON_THROW(std::domain_error("cannot compare iterators of different containers")); } assert(m_object != nullptr); @@ -6187,19 +9204,25 @@ class basic_json } } - /// comparison: not equal - bool operator!=(const const_iterator& other) const + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator!=(const iter_impl& other) const { return not operator==(other); } - /// comparison: smaller - bool operator<(const const_iterator& other) const + /*! + @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 (m_object != other.m_object) { - throw std::domain_error("cannot compare iterators of different containers"); + JSON_THROW(std::domain_error("cannot compare iterators of different containers")); } assert(m_object != nullptr); @@ -6208,7 +9231,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot compare order of object iterators"); + JSON_THROW(std::domain_error("cannot compare order of object iterators")); } case basic_json::value_t::array: @@ -6223,26 +9246,38 @@ class basic_json } } - /// comparison: less than or equal - bool operator<=(const const_iterator& other) const + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<=(const iter_impl& other) const { return not other.operator < (*this); } - /// comparison: greater than - bool operator>(const const_iterator& other) const + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>(const iter_impl& other) const { return not operator<=(other); } - /// comparison: greater than or equal - bool operator>=(const const_iterator& other) const + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>=(const iter_impl& other) const { return not operator<(other); } - /// add to iterator - const_iterator& operator+=(difference_type i) + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator+=(difference_type i) { assert(m_object != nullptr); @@ -6250,12 +9285,12 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use offsets with object iterators"); + JSON_THROW(std::domain_error("cannot use offsets with object iterators")); } case basic_json::value_t::array: { - m_it.array_iterator += i; + std::advance(m_it.array_iterator, i); break; } @@ -6269,30 +9304,42 @@ class basic_json return *this; } - /// subtract from iterator - const_iterator& operator-=(difference_type i) + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator-=(difference_type i) { return operator+=(-i); } - /// add to iterator - const_iterator operator+(difference_type i) + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator+(difference_type i) { auto result = *this; result += i; return result; } - /// subtract from iterator - const_iterator operator-(difference_type i) + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator-(difference_type i) { auto result = *this; result -= i; return result; } - /// return difference - difference_type operator-(const const_iterator& other) const + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + difference_type operator-(const iter_impl& other) const { assert(m_object != nullptr); @@ -6300,7 +9347,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use offsets with object iterators"); + JSON_THROW(std::domain_error("cannot use offsets with object iterators")); } case basic_json::value_t::array: @@ -6315,7 +9362,10 @@ class basic_json } } - /// access to successor + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ reference operator[](difference_type n) const { assert(m_object != nullptr); @@ -6324,34 +9374,35 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator[] for object iterators"); + JSON_THROW(std::domain_error("cannot use operator[] for object iterators")); } case basic_json::value_t::array: { - return *(m_it.array_iterator + n); + return *std::next(m_it.array_iterator, n); } case basic_json::value_t::null: { - throw std::out_of_range("cannot get value"); + JSON_THROW(std::out_of_range("cannot get value")); } default: { - if (m_it.primitive_iterator == -n) + if (m_it.primitive_iterator.get_value() == -n) { return *m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + JSON_THROW(std::out_of_range("cannot get value")); } } } - /// return the key of an object iterator + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ typename object_t::key_type key() const { assert(m_object != nullptr); @@ -6360,13 +9411,14 @@ class basic_json { return m_it.object_iterator->first; } - else - { - throw std::domain_error("cannot use key() for non-object iterators"); - } + + JSON_THROW(std::domain_error("cannot use key() for non-object iterators")); } - /// return the value of an iterator + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ reference value() const { return operator*(); @@ -6379,140 +9431,6 @@ class basic_json internal_iterator m_it = internal_iterator(); }; - /*! - @brief a mutable random access iterator for the @ref basic_json class - - @requirement The class satisfies the following concept requirements: - - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): - The iterator that can be moved to point (forward and backward) to any - element in constant time. - - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator): - It is possible to write to the pointed-to element. - - @since version 1.0.0 - */ - class iterator : public const_iterator - { - public: - using base_iterator = const_iterator; - using pointer = typename basic_json::pointer; - using reference = typename basic_json::reference; - - /// default constructor - iterator() = default; - - /// constructor for a given JSON instance - iterator(pointer object) noexcept - : base_iterator(object) - {} - - /// copy constructor - iterator(const iterator& other) noexcept - : base_iterator(other) - {} - - /// copy assignment - iterator& operator=(iterator other) noexcept( - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value and - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value - ) - { - base_iterator::operator=(other); - return *this; - } - - /// return a reference to the value pointed to by the iterator - reference operator*() - { - return const_cast(base_iterator::operator*()); - } - - /// dereference the iterator - pointer operator->() - { - return const_cast(base_iterator::operator->()); - } - - /// post-increment (it++) - iterator operator++(int) - { - iterator result = *this; - base_iterator::operator++(); - return result; - } - - /// pre-increment (++it) - iterator& operator++() - { - base_iterator::operator++(); - return *this; - } - - /// post-decrement (it--) - iterator operator--(int) - { - iterator result = *this; - base_iterator::operator--(); - return result; - } - - /// pre-decrement (--it) - iterator& operator--() - { - base_iterator::operator--(); - return *this; - } - - /// add to iterator - iterator& operator+=(difference_type i) - { - base_iterator::operator+=(i); - return *this; - } - - /// subtract from iterator - iterator& operator-=(difference_type i) - { - base_iterator::operator-=(i); - return *this; - } - - /// add to iterator - iterator operator+(difference_type i) - { - auto result = *this; - result += i; - return result; - } - - /// subtract from iterator - iterator operator-(difference_type i) - { - auto result = *this; - result -= i; - return result; - } - - difference_type operator-(const iterator& other) const - { - return base_iterator::operator-(other); - } - - /// access to successor - reference operator[](difference_type n) const - { - return const_cast(base_iterator::operator[](n)); - } - - /// return the value of an iterator - reference value() const - { - return const_cast(base_iterator::value()); - } - }; - /*! @brief a template for a reverse iterator class @@ -6540,12 +9458,12 @@ class basic_json using reference = typename Base::reference; /// create reverse iterator from iterator - json_reverse_iterator(const typename base_iterator::iterator_type& it) + json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept : base_iterator(it) {} /// create reverse iterator from base class - json_reverse_iterator(const base_iterator& it) + json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} @@ -6635,8 +9553,8 @@ class basic_json @brief lexical analysis This class organizes the lexical analysis during JSON deserialization. The - core of it is a scanner generated by re2c that processes - a buffer and recognizes tokens according to RFC 7159. + core of it is a scanner generated by [re2c](http://re2c.org) that + processes a buffer and recognizes tokens according to RFC 7159. */ class lexer { @@ -6644,75 +9562,90 @@ class basic_json /// 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_number, ///< a number -- use get_number() 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 + 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() for actual value + value_integer, ///< a signed integer -- use get_number() for actual value + value_float, ///< an floating point number -- use get_number() 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 }; /// the char type to use in the lexer using lexer_char_t = unsigned char; - /// constructor with a given buffer - explicit lexer(const string_t& s) noexcept - : m_stream(nullptr), m_buffer(s) + /// a lexer from a buffer with given length + lexer(const lexer_char_t* buff, const size_t len) noexcept + : m_content(buff) { - m_content = reinterpret_cast(s.c_str()); assert(m_content != nullptr); m_start = m_cursor = m_content; - m_limit = m_content + s.size(); + m_limit = m_content + len; } - /// constructor with a given stream - explicit lexer(std::istream* s) noexcept - : m_stream(s), m_buffer() + /// a lexer from an input stream + explicit lexer(std::istream& s) + : m_stream(&s), m_line_buffer() { - assert(m_stream != nullptr); - getline(*m_stream, m_buffer); - m_content = reinterpret_cast(m_buffer.c_str()); - assert(m_content != nullptr); - m_start = m_cursor = m_content; - m_limit = m_content + m_buffer.size(); + // immediately abort if stream is erroneous + if (s.fail()) + { + JSON_THROW(std::invalid_argument("stream error")); + } + + // fill buffer + fill_line_buffer(); + + // skip UTF-8 byte-order mark + if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF") + { + m_line_buffer[0] = ' '; + m_line_buffer[1] = ' '; + m_line_buffer[2] = ' '; + } } - /// default constructor - lexer() = default; - - // switch off unwanted functions + // switch off unwanted functions (due to pointer members) + lexer() = delete; lexer(const lexer&) = delete; lexer operator=(const lexer&) = delete; /*! - @brief create a string from a Unicode code point + @brief create a string from one or two Unicode code points + + There are two cases: (1) @a codepoint1 is in the Basic Multilingual + Plane (U+0000 through U+FFFF) and @a codepoint2 is 0, or (2) + @a codepoint1 and @a codepoint2 are a UTF-16 surrogate pair to + represent a code point above U+FFFF. @param[in] codepoint1 the code point (can be high surrogate) @param[in] codepoint2 the code point (can be low surrogate or 0) - @return string representation of the code point + @return string representation of the code point; the length of the + result string is between 1 and 4 characters. - @throw std::out_of_range if code point is >0x10ffff; example: `"code + @throw std::out_of_range if code point is > 0x10ffff; example: `"code points above 0x10FFFF are invalid"` @throw std::invalid_argument if the low surrogate is invalid; example: `""missing or wrong low surrogate""` + @complexity Constant. + @see */ static string_t to_unicode(const std::size_t codepoint1, const std::size_t codepoint2 = 0) { - string_t result; - - // calculate the codepoint from the given code points + // calculate the code point from the given code points std::size_t codepoint = codepoint1; // check if codepoint1 is a high surrogate @@ -6733,10 +9666,12 @@ class basic_json } else { - throw std::invalid_argument("missing or wrong low surrogate"); + JSON_THROW(std::invalid_argument("missing or wrong low surrogate")); } } + string_t result; + if (codepoint < 0x80) { // 1-byte characters: 0xxxxxxx (ASCII) @@ -6765,14 +9700,14 @@ class basic_json } else { - throw std::out_of_range("code points above 0x10FFFF are invalid"); + JSON_THROW(std::out_of_range("code points above 0x10FFFF are invalid")); } return result; } /// return name of values of type token_type (only used for errors) - static std::string token_type_name(token_type t) + static std::string token_type_name(const token_type t) { switch (t) { @@ -6786,7 +9721,9 @@ class basic_json return "null literal"; case token_type::value_string: return "string literal"; - case token_type::value_number: + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: + case lexer::token_type::value_float: return "number literal"; case token_type::begin_array: return "'['"; @@ -6815,837 +9752,1163 @@ class basic_json /*! This function implements a scanner for JSON. It is specified using regular expressions that try to follow RFC 7159 as close as possible. - These regular expressions are then translated into a deterministic - finite automaton (DFA) by the tool re2c . As a result, - the translated code for this function consists of a large block of code - with goto jumps. + These regular expressions are then translated into a minimized + deterministic finite automaton (DFA) by the tool + [re2c](http://re2c.org). As a result, the translated code for this + function consists of a large block of code with `goto` jumps. @return the class of the next token read from the buffer + + @complexity Linear in the length of the input.\n + + Proposition: The loop below will always terminate for finite input.\n + + Proof (by contradiction): Assume a finite input. To loop forever, the + loop must never hit code with a `break` statement. The only code + snippets without a `break` statement are the continue statements for + whitespace and byte-order-marks. To loop forever, the input must be an + infinite sequence of whitespace or byte-order-marks. This contradicts + the assumption of finite input, q.e.d. */ - token_type scan() noexcept + token_type scan() { - // pointer for backtracking information - m_marker = nullptr; - - // remember the begin of the token - m_start = m_cursor; - assert(m_start != nullptr); - - + while (true) { - lexer_char_t yych; - unsigned int yyaccept = 0; - static const unsigned char yybm[] = + // pointer for backtracking information + m_marker = nullptr; + + // remember the begin of the token + m_start = m_cursor; + assert(m_start != nullptr); + + { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 32, 0, 0, 32, 0, 0, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 96, 64, 0, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 0, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - }; - if ((m_limit - m_cursor) < 5) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= ':') - { - if (yych <= ' ') + lexer_char_t yych; + unsigned int yyaccept = 0; + static const unsigned char yybm[] = { - if (yych <= '\n') + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 32, 0, 0, 32, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 160, 128, 0, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 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, + 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, + 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, + 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, + }; + if ((m_limit - m_cursor) < 5) + { + fill_line_buffer(5); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yybm[0 + yych] & 32) + { + goto basic_json_parser_6; + } + if (yych <= '[') + { + if (yych <= '-') { - if (yych <= 0x00) + if (yych <= '"') { - goto basic_json_parser_28; + if (yych <= 0x00) + { + goto basic_json_parser_2; + } + if (yych <= '!') + { + goto basic_json_parser_4; + } + goto basic_json_parser_9; } - if (yych <= 0x08) + else { - goto basic_json_parser_30; - } - if (yych >= '\n') - { - goto basic_json_parser_4; + if (yych <= '+') + { + goto basic_json_parser_4; + } + if (yych <= ',') + { + goto basic_json_parser_10; + } + goto basic_json_parser_12; } } else { - if (yych == '\r') + if (yych <= '9') { - goto basic_json_parser_2; + if (yych <= '/') + { + goto basic_json_parser_4; + } + if (yych <= '0') + { + goto basic_json_parser_13; + } + goto basic_json_parser_15; } - if (yych <= 0x1F) + else { - goto basic_json_parser_30; + if (yych <= ':') + { + goto basic_json_parser_17; + } + if (yych <= 'Z') + { + goto basic_json_parser_4; + } + goto basic_json_parser_19; } } } else { - if (yych <= ',') + if (yych <= 'n') { - if (yych == '"') + if (yych <= 'e') { - goto basic_json_parser_27; + if (yych == ']') + { + goto basic_json_parser_21; + } + goto basic_json_parser_4; } - if (yych <= '+') + else { - goto basic_json_parser_30; - } - goto basic_json_parser_16; - } - else - { - if (yych <= '/') - { - if (yych <= '-') + if (yych <= 'f') { goto basic_json_parser_23; } - goto basic_json_parser_30; + if (yych <= 'm') + { + goto basic_json_parser_4; + } + goto basic_json_parser_24; + } + } + else + { + if (yych <= 'z') + { + if (yych == 't') + { + goto basic_json_parser_25; + } + goto basic_json_parser_4; } else { - if (yych <= '0') - { - goto basic_json_parser_24; - } - if (yych <= '9') + if (yych <= '{') { goto basic_json_parser_26; } - goto basic_json_parser_18; - } - } - } - } - else - { - if (yych <= 'n') - { - if (yych <= ']') - { - if (yych == '[') - { - goto basic_json_parser_8; - } - if (yych <= '\\') - { - goto basic_json_parser_30; - } - goto basic_json_parser_10; - } - else - { - if (yych == 'f') - { - goto basic_json_parser_22; - } - if (yych <= 'm') - { - goto basic_json_parser_30; - } - goto basic_json_parser_20; - } - } - else - { - if (yych <= '{') - { - if (yych == 't') - { - goto basic_json_parser_21; - } - if (yych <= 'z') - { - goto basic_json_parser_30; - } - goto basic_json_parser_12; - } - else - { - if (yych <= '}') - { - if (yych <= '|') + if (yych == '}') { - goto basic_json_parser_30; + goto basic_json_parser_28; } - goto basic_json_parser_14; - } - else - { - if (yych == 0xEF) - { - goto basic_json_parser_6; - } - goto basic_json_parser_30; + goto basic_json_parser_4; } } } - } basic_json_parser_2: - ++m_cursor; - yych = *m_cursor; - goto basic_json_parser_5; -basic_json_parser_3: - { - return scan(); - } + ++m_cursor; + { + last_token_type = token_type::end_of_input; + break; + } basic_json_parser_4: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; + ++m_cursor; basic_json_parser_5: - if (yybm[0 + yych] & 32) - { - goto basic_json_parser_4; - } - goto basic_json_parser_3; + { + last_token_type = token_type::parse_error; + break; + } basic_json_parser_6: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 0xBB) - { - goto basic_json_parser_64; - } -basic_json_parser_7: - { - return token_type::parse_error; - } -basic_json_parser_8: - ++m_cursor; - { - return token_type::begin_array; - } + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yybm[0 + yych] & 32) + { + goto basic_json_parser_6; + } + { + continue; + } +basic_json_parser_9: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych <= 0x1F) + { + goto basic_json_parser_5; + } + if (yych <= 0x7F) + { + goto basic_json_parser_31; + } + if (yych <= 0xC1) + { + goto basic_json_parser_5; + } + if (yych <= 0xF4) + { + goto basic_json_parser_31; + } + goto basic_json_parser_5; basic_json_parser_10: - ++m_cursor; - { - return token_type::end_array; - } + ++m_cursor; + { + last_token_type = token_type::value_separator; + break; + } basic_json_parser_12: - ++m_cursor; - { - return token_type::begin_object; - } -basic_json_parser_14: - ++m_cursor; - { - return token_type::end_object; - } -basic_json_parser_16: - ++m_cursor; - { - return token_type::value_separator; - } -basic_json_parser_18: - ++m_cursor; - { - return token_type::name_separator; - } -basic_json_parser_20: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'u') - { - goto basic_json_parser_60; - } - goto basic_json_parser_7; -basic_json_parser_21: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'r') - { - goto basic_json_parser_56; - } - goto basic_json_parser_7; -basic_json_parser_22: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'a') - { - goto basic_json_parser_51; - } - goto basic_json_parser_7; -basic_json_parser_23: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_7; - } - if (yych <= '0') - { - goto basic_json_parser_50; - } - if (yych <= '9') - { - goto basic_json_parser_41; - } - goto basic_json_parser_7; -basic_json_parser_24: - yyaccept = 1; - yych = *(m_marker = ++m_cursor); - if (yych <= 'D') - { - if (yych == '.') + yych = *++m_cursor; + if (yych <= '/') + { + goto basic_json_parser_5; + } + if (yych <= '0') { goto basic_json_parser_43; } - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_44; - } - if (yych == 'e') - { - goto basic_json_parser_44; - } - } -basic_json_parser_25: - { - return token_type::value_number; - } -basic_json_parser_26: - yyaccept = 1; - yych = *(m_marker = ++m_cursor); - goto basic_json_parser_42; -basic_json_parser_27: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych <= 0x0F) - { - goto basic_json_parser_7; - } - goto basic_json_parser_32; -basic_json_parser_28: - ++m_cursor; - { - return token_type::end_of_input; - } -basic_json_parser_30: - yych = *++m_cursor; - goto basic_json_parser_7; -basic_json_parser_31: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; -basic_json_parser_32: - if (yybm[0 + yych] & 64) - { - goto basic_json_parser_31; - } - if (yych <= 0x0F) - { - goto basic_json_parser_33; - } - if (yych <= '"') - { - goto basic_json_parser_35; - } - goto basic_json_parser_34; -basic_json_parser_33: - m_cursor = m_marker; - if (yyaccept == 0) - { - goto basic_json_parser_7; - } - else - { - goto basic_json_parser_25; - } -basic_json_parser_34: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= 'e') - { - if (yych <= '/') - { - if (yych == '"') - { - goto basic_json_parser_31; - } - if (yych <= '.') - { - goto basic_json_parser_33; - } - goto basic_json_parser_31; - } - else - { - if (yych <= '\\') - { - if (yych <= '[') - { - goto basic_json_parser_33; - } - goto basic_json_parser_31; - } - else - { - if (yych == 'b') - { - goto basic_json_parser_31; - } - goto basic_json_parser_33; - } - } - } - else - { - if (yych <= 'q') - { - if (yych <= 'f') - { - goto basic_json_parser_31; - } - if (yych == 'n') - { - goto basic_json_parser_31; - } - goto basic_json_parser_33; - } - else - { - if (yych <= 's') - { - if (yych <= 'r') - { - goto basic_json_parser_31; - } - goto basic_json_parser_33; - } - else - { - if (yych <= 't') - { - goto basic_json_parser_31; - } - if (yych <= 'u') - { - goto basic_json_parser_37; - } - goto basic_json_parser_33; - } - } - } -basic_json_parser_35: - ++m_cursor; - { - return token_type::value_string; - } -basic_json_parser_37: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_33; - } - if (yych >= ':') - { - goto basic_json_parser_33; - } - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_38; - } - if (yych <= '`') - { - goto basic_json_parser_33; - } - if (yych >= 'g') - { - goto basic_json_parser_33; - } - } -basic_json_parser_38: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_33; - } - if (yych >= ':') - { - goto basic_json_parser_33; - } - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_39; - } - if (yych <= '`') - { - goto basic_json_parser_33; - } - if (yych >= 'g') - { - goto basic_json_parser_33; - } - } -basic_json_parser_39: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_33; - } - if (yych >= ':') - { - goto basic_json_parser_33; - } - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_40; - } - if (yych <= '`') - { - goto basic_json_parser_33; - } - if (yych >= 'g') - { - goto basic_json_parser_33; - } - } -basic_json_parser_40: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_33; - } if (yych <= '9') - { - goto basic_json_parser_31; - } - goto basic_json_parser_33; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_31; - } - if (yych <= '`') - { - goto basic_json_parser_33; - } - if (yych <= 'f') - { - goto basic_json_parser_31; - } - goto basic_json_parser_33; - } -basic_json_parser_41: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; -basic_json_parser_42: - if (yybm[0 + yych] & 128) - { - goto basic_json_parser_41; - } - if (yych <= 'D') - { - if (yych != '.') - { - goto basic_json_parser_25; - } - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_44; - } - if (yych == 'e') - { - goto basic_json_parser_44; - } - goto basic_json_parser_25; - } -basic_json_parser_43: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_33; - } - if (yych <= '9') - { - goto basic_json_parser_48; - } - goto basic_json_parser_33; -basic_json_parser_44: - yych = *++m_cursor; - if (yych <= ',') - { - if (yych != '+') - { - goto basic_json_parser_33; - } - } - else - { - if (yych <= '-') { goto basic_json_parser_45; } + goto basic_json_parser_5; +basic_json_parser_13: + yyaccept = 1; + yych = *(m_marker = ++m_cursor); + if (yych <= '9') + { + if (yych == '.') + { + goto basic_json_parser_47; + } + if (yych >= '0') + { + goto basic_json_parser_48; + } + } + else + { + if (yych <= 'E') + { + if (yych >= 'E') + { + goto basic_json_parser_51; + } + } + else + { + if (yych == 'e') + { + goto basic_json_parser_51; + } + } + } +basic_json_parser_14: + { + last_token_type = token_type::value_unsigned; + break; + } +basic_json_parser_15: + yyaccept = 1; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) + { + fill_line_buffer(3); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yybm[0 + yych] & 64) + { + goto basic_json_parser_15; + } + if (yych <= 'D') + { + if (yych == '.') + { + goto basic_json_parser_47; + } + goto basic_json_parser_14; + } + else + { + if (yych <= 'E') + { + goto basic_json_parser_51; + } + if (yych == 'e') + { + goto basic_json_parser_51; + } + goto basic_json_parser_14; + } +basic_json_parser_17: + ++m_cursor; + { + last_token_type = token_type::name_separator; + break; + } +basic_json_parser_19: + ++m_cursor; + { + last_token_type = token_type::begin_array; + break; + } +basic_json_parser_21: + ++m_cursor; + { + last_token_type = token_type::end_array; + break; + } +basic_json_parser_23: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'a') + { + goto basic_json_parser_52; + } + goto basic_json_parser_5; +basic_json_parser_24: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'u') + { + goto basic_json_parser_53; + } + goto basic_json_parser_5; +basic_json_parser_25: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'r') + { + goto basic_json_parser_54; + } + goto basic_json_parser_5; +basic_json_parser_26: + ++m_cursor; + { + last_token_type = token_type::begin_object; + break; + } +basic_json_parser_28: + ++m_cursor; + { + last_token_type = token_type::end_object; + break; + } +basic_json_parser_30: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; +basic_json_parser_31: + if (yybm[0 + yych] & 128) + { + goto basic_json_parser_30; + } + if (yych <= 0xE0) + { + if (yych <= '\\') + { + if (yych <= 0x1F) + { + goto basic_json_parser_32; + } + if (yych <= '"') + { + goto basic_json_parser_33; + } + goto basic_json_parser_35; + } + else + { + if (yych <= 0xC1) + { + goto basic_json_parser_32; + } + if (yych <= 0xDF) + { + goto basic_json_parser_36; + } + goto basic_json_parser_37; + } + } + else + { + if (yych <= 0xEF) + { + if (yych == 0xED) + { + goto basic_json_parser_39; + } + goto basic_json_parser_38; + } + else + { + if (yych <= 0xF0) + { + goto basic_json_parser_40; + } + if (yych <= 0xF3) + { + goto basic_json_parser_41; + } + if (yych <= 0xF4) + { + goto basic_json_parser_42; + } + } + } +basic_json_parser_32: + m_cursor = m_marker; + if (yyaccept <= 1) + { + if (yyaccept == 0) + { + goto basic_json_parser_5; + } + else + { + goto basic_json_parser_14; + } + } + else + { + if (yyaccept == 2) + { + goto basic_json_parser_44; + } + else + { + goto basic_json_parser_58; + } + } +basic_json_parser_33: + ++m_cursor; + { + last_token_type = token_type::value_string; + break; + } +basic_json_parser_35: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 'e') + { + if (yych <= '/') + { + if (yych == '"') + { + goto basic_json_parser_30; + } + if (yych <= '.') + { + goto basic_json_parser_32; + } + goto basic_json_parser_30; + } + else + { + if (yych <= '\\') + { + if (yych <= '[') + { + goto basic_json_parser_32; + } + goto basic_json_parser_30; + } + else + { + if (yych == 'b') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; + } + } + } + else + { + if (yych <= 'q') + { + if (yych <= 'f') + { + goto basic_json_parser_30; + } + if (yych == 'n') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 's') + { + if (yych <= 'r') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 't') + { + goto basic_json_parser_30; + } + if (yych <= 'u') + { + goto basic_json_parser_55; + } + goto basic_json_parser_32; + } + } + } +basic_json_parser_36: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; +basic_json_parser_37: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x9F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_36; + } + goto basic_json_parser_32; +basic_json_parser_38: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_36; + } + goto basic_json_parser_32; +basic_json_parser_39: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0x9F) + { + goto basic_json_parser_36; + } + goto basic_json_parser_32; +basic_json_parser_40: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x8F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_38; + } + goto basic_json_parser_32; +basic_json_parser_41: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_38; + } + goto basic_json_parser_32; +basic_json_parser_42: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0x8F) + { + goto basic_json_parser_38; + } + goto basic_json_parser_32; +basic_json_parser_43: + yyaccept = 2; + yych = *(m_marker = ++m_cursor); + if (yych <= '9') + { + if (yych == '.') + { + goto basic_json_parser_47; + } + if (yych >= '0') + { + goto basic_json_parser_48; + } + } + else + { + if (yych <= 'E') + { + if (yych >= 'E') + { + goto basic_json_parser_51; + } + } + else + { + if (yych == 'e') + { + goto basic_json_parser_51; + } + } + } +basic_json_parser_44: + { + last_token_type = token_type::value_integer; + break; + } +basic_json_parser_45: + yyaccept = 2; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) + { + fill_line_buffer(3); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '9') + { + if (yych == '.') + { + goto basic_json_parser_47; + } + if (yych <= '/') + { + goto basic_json_parser_44; + } + goto basic_json_parser_45; + } + else + { + if (yych <= 'E') + { + if (yych <= 'D') + { + goto basic_json_parser_44; + } + goto basic_json_parser_51; + } + else + { + if (yych == 'e') + { + goto basic_json_parser_51; + } + goto basic_json_parser_44; + } + } +basic_json_parser_47: + yych = *++m_cursor; if (yych <= '/') { - goto basic_json_parser_33; + goto basic_json_parser_32; } if (yych <= '9') { - goto basic_json_parser_46; + goto basic_json_parser_56; } - goto basic_json_parser_33; - } -basic_json_parser_45: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_33; - } - if (yych >= ':') - { - goto basic_json_parser_33; - } -basic_json_parser_46: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '/') - { - goto basic_json_parser_25; - } - if (yych <= '9') - { - goto basic_json_parser_46; - } - goto basic_json_parser_25; + goto basic_json_parser_32; basic_json_parser_48: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= 'D') - { + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; if (yych <= '/') { - goto basic_json_parser_25; + goto basic_json_parser_50; } if (yych <= '9') { goto basic_json_parser_48; } - goto basic_json_parser_25; - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_44; - } - if (yych == 'e') - { - goto basic_json_parser_44; - } - goto basic_json_parser_25; - } basic_json_parser_50: - yyaccept = 1; - yych = *(m_marker = ++m_cursor); - if (yych <= 'D') - { - if (yych == '.') { - goto basic_json_parser_43; + last_token_type = token_type::parse_error; + break; } - goto basic_json_parser_25; - } - else - { - if (yych <= 'E') +basic_json_parser_51: + yych = *++m_cursor; + if (yych <= ',') { - goto basic_json_parser_44; + if (yych == '+') + { + goto basic_json_parser_59; + } + goto basic_json_parser_32; } + else + { + if (yych <= '-') + { + goto basic_json_parser_59; + } + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_60; + } + goto basic_json_parser_32; + } +basic_json_parser_52: + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_62; + } + goto basic_json_parser_32; +basic_json_parser_53: + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_63; + } + goto basic_json_parser_32; +basic_json_parser_54: + yych = *++m_cursor; + if (yych == 'u') + { + goto basic_json_parser_64; + } + goto basic_json_parser_32; +basic_json_parser_55: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_65; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_65; + } + if (yych <= '`') + { + goto basic_json_parser_32; + } + if (yych <= 'f') + { + goto basic_json_parser_65; + } + goto basic_json_parser_32; + } +basic_json_parser_56: + yyaccept = 3; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) + { + fill_line_buffer(3); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 'D') + { + if (yych <= '/') + { + goto basic_json_parser_58; + } + if (yych <= '9') + { + goto basic_json_parser_56; + } + } + else + { + if (yych <= 'E') + { + goto basic_json_parser_51; + } + if (yych == 'e') + { + goto basic_json_parser_51; + } + } +basic_json_parser_58: + { + last_token_type = token_type::value_float; + break; + } +basic_json_parser_59: + yych = *++m_cursor; + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych >= ':') + { + goto basic_json_parser_32; + } +basic_json_parser_60: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '/') + { + goto basic_json_parser_58; + } + if (yych <= '9') + { + goto basic_json_parser_60; + } + goto basic_json_parser_58; +basic_json_parser_62: + yych = *++m_cursor; + if (yych == 's') + { + goto basic_json_parser_66; + } + goto basic_json_parser_32; +basic_json_parser_63: + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_67; + } + goto basic_json_parser_32; +basic_json_parser_64: + yych = *++m_cursor; if (yych == 'e') { - goto basic_json_parser_44; + goto basic_json_parser_69; + } + goto basic_json_parser_32; +basic_json_parser_65: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_71; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_71; + } + if (yych <= '`') + { + goto basic_json_parser_32; + } + if (yych <= 'f') + { + goto basic_json_parser_71; + } + goto basic_json_parser_32; + } +basic_json_parser_66: + yych = *++m_cursor; + if (yych == 'e') + { + goto basic_json_parser_72; + } + goto basic_json_parser_32; +basic_json_parser_67: + ++m_cursor; + { + last_token_type = token_type::literal_null; + break; + } +basic_json_parser_69: + ++m_cursor; + { + last_token_type = token_type::literal_true; + break; + } +basic_json_parser_71: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_74; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_74; + } + if (yych <= '`') + { + goto basic_json_parser_32; + } + if (yych <= 'f') + { + goto basic_json_parser_74; + } + goto basic_json_parser_32; + } +basic_json_parser_72: + ++m_cursor; + { + last_token_type = token_type::literal_false; + break; + } +basic_json_parser_74: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_30; + } + if (yych <= '`') + { + goto basic_json_parser_32; + } + if (yych <= 'f') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; } - goto basic_json_parser_25; - } -basic_json_parser_51: - yych = *++m_cursor; - if (yych != 'l') - { - goto basic_json_parser_33; - } - yych = *++m_cursor; - if (yych != 's') - { - goto basic_json_parser_33; - } - yych = *++m_cursor; - if (yych != 'e') - { - goto basic_json_parser_33; - } - ++m_cursor; - { - return token_type::literal_false; - } -basic_json_parser_56: - yych = *++m_cursor; - if (yych != 'u') - { - goto basic_json_parser_33; - } - yych = *++m_cursor; - if (yych != 'e') - { - goto basic_json_parser_33; - } - ++m_cursor; - { - return token_type::literal_true; - } -basic_json_parser_60: - yych = *++m_cursor; - if (yych != 'l') - { - goto basic_json_parser_33; - } - yych = *++m_cursor; - if (yych != 'l') - { - goto basic_json_parser_33; - } - ++m_cursor; - { - return token_type::literal_null; - } -basic_json_parser_64: - yych = *++m_cursor; - if (yych != 0xBF) - { - goto basic_json_parser_33; - } - ++m_cursor; - { - return scan(); } + } - + return last_token_type; } - /// append data from the stream to the internal buffer - void yyfill() noexcept + /*! + @brief append data from the stream to the line buffer + + This function is called by the scan() function when the end of the + buffer (`m_limit`) is reached and the `m_cursor` pointer cannot be + incremented without leaving the limits of the line buffer. Note re2c + decides when to call this function. + + If the lexer reads from contiguous storage, there is no trailing null + byte. Therefore, this function must make sure to add these padding + null bytes. + + If the lexer reads from an input stream, this function reads the next + line of the input. + + @pre + p p p p p p u u u u u x . . . . . . + ^ ^ ^ ^ + m_content m_start | m_limit + m_cursor + + @post + u u u u u x x x x x x x . . . . . . + ^ ^ ^ + | m_cursor m_limit + m_start + m_content + */ + void fill_line_buffer(size_t n = 0) { - if (m_stream == nullptr or not * m_stream) + // if line buffer is used, m_content points to its data + assert(m_line_buffer.empty() + or m_content == reinterpret_cast(m_line_buffer.data())); + + // if line buffer is used, m_limit is set past the end of its data + assert(m_line_buffer.empty() + or m_limit == m_content + m_line_buffer.size()); + + // pointer relationships + assert(m_content <= m_start); + assert(m_start <= m_cursor); + assert(m_cursor <= m_limit); + assert(m_marker == nullptr or m_marker <= m_limit); + + // number of processed characters (p) + const auto num_processed_chars = static_cast(m_start - m_content); + // offset for m_marker wrt. to m_start + const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; + // number of unprocessed characters (u) + const auto offset_cursor = m_cursor - m_start; + + // no stream is used or end of file is reached + if (m_stream == nullptr or m_stream->eof()) { - return; + // m_start may or may not be pointing into m_line_buffer at + // this point. We trust the standard library to do the right + // thing. See http://stackoverflow.com/q/28142011/266378 + m_line_buffer.assign(m_start, m_limit); + + // append n characters to make sure that there is sufficient + // space between m_cursor and m_limit + m_line_buffer.append(1, '\x00'); + if (n > 0) + { + m_line_buffer.append(n - 1, '\x01'); + } + } + else + { + // delete processed characters from line buffer + m_line_buffer.erase(0, num_processed_chars); + // read next line from input stream + m_line_buffer_tmp.clear(); + std::getline(*m_stream, m_line_buffer_tmp, '\n'); + + // add line with newline symbol to the line buffer + m_line_buffer += m_line_buffer_tmp; + m_line_buffer.push_back('\n'); } - const ssize_t offset_start = m_start - m_content; - const ssize_t offset_marker = m_marker - m_start; - const ssize_t offset_cursor = m_cursor - m_start; - - m_buffer.erase(0, static_cast(offset_start)); - std::string line; - assert(m_stream != nullptr); - std::getline(*m_stream, line); - m_buffer += "\n" + line; // add line with newline symbol - - m_content = reinterpret_cast(m_buffer.c_str()); + // set pointers + m_content = reinterpret_cast(m_line_buffer.data()); assert(m_content != nullptr); m_start = m_content; m_marker = m_start + offset_marker; m_cursor = m_start + offset_cursor; - m_limit = m_start + m_buffer.size() - 1; + m_limit = m_start + m_line_buffer.size(); } /// return string representation of last read token - string_t get_token() const noexcept + string_t get_token_string() const { assert(m_start != nullptr); return string_t(reinterpret_cast(m_start), @@ -7664,26 +10927,75 @@ basic_json_parser_64: 1. Escaped characters. In this case, a new character is constructed according to the nature of the escape. Some escapes create new - characters (e.g., @c "\\n" is replaced by @c "\n"), some are copied - as is (e.g., @c "\\\\"). Furthermore, Unicode escapes of the shape - @c "\\uxxxx" need special care. In this case, to_unicode takes care + characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied + as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape + `"\\uxxxx"` need special care. In this case, to_unicode takes care of the construction of the values. 2. Unescaped characters are copied as is. - @return string value of current token without opening and closing quotes + @pre `m_cursor - m_start >= 2`, meaning the length of the last token + is at least 2 bytes which is trivially true for any string (which + consists of at least two quotes). + + " c1 c2 c3 ... " + ^ ^ + m_start m_cursor + + @complexity Linear in the length of the string.\n + + Lemma: The loop body will always terminate.\n + + Proof (by contradiction): Assume the loop body does not terminate. As + the loop body does not contain another loop, one of the called + functions must never return. The called functions are `std::strtoul` + and to_unicode. Neither function can loop forever, so the loop body + will never loop forever which contradicts the assumption that the loop + body does not terminate, q.e.d.\n + + Lemma: The loop condition for the for loop is eventually false.\n + + Proof (by contradiction): Assume the loop does not terminate. Due to + the above lemma, this can only be due to a tautological loop + condition; that is, the loop condition i < m_cursor - 1 must always be + true. Let x be the change of i for any loop iteration. Then + m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This + can be rephrased to m_cursor - m_start - 2 > x. With the + precondition, we x <= 0, meaning that the loop condition holds + indefinitely if i is always decreased. However, observe that the value + of i is strictly increasing with each iteration, as it is incremented + by 1 in the iteration expression and never decremented inside the loop + body. Hence, the loop condition will eventually be false which + contradicts the assumption that the loop condition is a tautology, + q.e.d. + + @return string value of current token without opening and closing + quotes @throw std::out_of_range if to_unicode fails */ string_t get_string() const { + assert(m_cursor - m_start >= 2); + string_t result; result.reserve(static_cast(m_cursor - m_start - 2)); // iterate the result between the quotes for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i) { - // process escaped characters - if (*i == '\\') + // find next escape character + auto e = std::find(i, m_cursor - 1, '\\'); + if (e != i) { + // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705 + for (auto k = i; k < e; k++) + { + result.push_back(static_cast(*k)); + } + i = e - 1; // -1 because of ++i + } + else + { + // processing escaped character // read next character ++i; @@ -7744,7 +11056,7 @@ basic_json_parser_64: // make sure there is a subsequent unicode if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u') { - throw std::invalid_argument("missing low surrogate"); + JSON_THROW(std::invalid_argument("missing low surrogate")); } // get code yyyy from uxxxx\uyyyy @@ -7754,6 +11066,11 @@ basic_json_parser_64: // skip the next 10 characters (xxxx\uyyyy) i += 10; } + else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF) + { + // we found a lone low surrogate + JSON_THROW(std::invalid_argument("missing high surrogate")); + } else { // add unicode character(s) @@ -7765,88 +11082,255 @@ basic_json_parser_64: } } } - else - { - // all other characters are just copied to the end of the - // string - result.append(1, static_cast(*i)); - } } return result; } + /*! - @brief parse floating point number + @brief parse string into a built-in arithmetic type as if the current + locale is POSIX. - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function (i.e., `std::strtof`, - `std::strtod`, or `std::strtold`) based on the type supplied via the - first parameter. Set this to @a static_cast(nullptr). + @note in floating-point case strtod may parse past the token's end - + this is not an error - @param[in] type the @ref number_float_t in use - - @param[in,out] endptr recieves a pointer to the first character after - the number - - @return the floating point number - - @bug This function uses `std::strtof`, `std::strtod`, or `std::strtold` - which use the current C locale to determine which character is used as - decimal point character. This may yield to parse errors if the locale - does not used `.`. + @note any leading blanks are not handled */ - long double str_to_float_t(long double* /* type */, char** endptr) const + struct strtonum { - return std::strtold(reinterpret_cast(m_start), endptr); - } + public: + strtonum(const char* start, const char* end) + : m_start(start), m_end(end) + {} - /// @copydoc str_to_float_t - double str_to_float_t(double*, char** endptr) const - { - return std::strtod(reinterpret_cast(m_start), endptr); - } + /*! + @return true iff parsed successfully as number of type T - /// @copydoc str_to_float_t - float str_to_float_t(float*, char** endptr) const - { - return std::strtof(reinterpret_cast(m_start), endptr); - } + @param[in,out] val shall contain parsed value, or undefined value + if could not parse + */ + template::value>::type> + bool to(T& val) const + { + return parse(val, std::is_integral()); + } + + private: + const char* const m_start = nullptr; + const char* const m_end = nullptr; + + // floating-point conversion + + // overloaded wrappers for strtod/strtof/strtold + // that will be called from parse + static void strtof(float& f, const char* str, char** endptr) + { + f = std::strtof(str, endptr); + } + + static void strtof(double& f, const char* str, char** endptr) + { + f = std::strtod(str, endptr); + } + + static void strtof(long double& f, const char* str, char** endptr) + { + f = std::strtold(str, endptr); + } + + template + bool parse(T& value, /*is_integral=*/std::false_type) const + { + // replace decimal separator with locale-specific version, + // when necessary; data will point to either the original + // string, or buf, or tempstr containing the fixed string. + std::string tempstr; + std::array buf; + const size_t len = static_cast(m_end - m_start); + + // lexer will reject empty numbers + assert(len > 0); + + // since dealing with strtod family of functions, we're + // getting the decimal point char from the C locale facilities + // instead of C++'s numpunct facet of the current std::locale + const auto loc = localeconv(); + assert(loc != nullptr); + const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0]; + + const char* data = m_start; + + if (decimal_point_char != '.') + { + const size_t ds_pos = static_cast(std::find(m_start, m_end, '.') - m_start); + + if (ds_pos != len) + { + // copy the data into the local buffer or tempstr, if + // buffer is too small; replace decimal separator, and + // update data to point to the modified bytes + if ((len + 1) < buf.size()) + { + std::copy(m_start, m_end, buf.begin()); + buf[len] = 0; + buf[ds_pos] = decimal_point_char; + data = buf.data(); + } + else + { + tempstr.assign(m_start, m_end); + tempstr[ds_pos] = decimal_point_char; + data = tempstr.c_str(); + } + } + } + + char* endptr = nullptr; + value = 0; + // this calls appropriate overload depending on T + strtof(value, data, &endptr); + + // parsing was successful iff strtof parsed exactly the number + // of characters determined by the lexer (len) + const bool ok = (endptr == (data + len)); + + if (ok and (value == static_cast(0.0)) and (*data == '-')) + { + // some implementations forget to negate the zero + value = -0.0; + } + + return ok; + } + + // integral conversion + + signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const + { + return std::strtoll(m_start, endptr, 10); + } + + unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const + { + return std::strtoull(m_start, endptr, 10); + } + + template + bool parse(T& value, /*is_integral=*/std::true_type) const + { + char* endptr = nullptr; + errno = 0; // these are thread-local + const auto x = parse_integral(&endptr, std::is_signed()); + + // called right overload? + static_assert(std::is_signed() == std::is_signed(), ""); + + value = static_cast(x); + + return (x == static_cast(value)) // x fits into destination T + and (x < 0) == (value < 0) // preserved sign + //and ((x != 0) or is_integral()) // strto[u]ll did nto fail + and (errno == 0) // strto[u]ll did not overflow + and (m_start < m_end) // token was not empty + and (endptr == m_end); // parsed entire token exactly + } + }; /*! @brief return number value for number tokens - This function translates the last token into a floating point number. - The pointer m_start points to the beginning of the parsed number. We - pass this pointer to std::strtod which sets endptr to the first - character past the converted number. If this pointer is not the same as - m_cursor, then either more or less characters have been used during the - comparison. This can happen for inputs like "01" which will be treated - like number 0 followed by number 1. + This function translates the last token into the most appropriate + number type (either integer, unsigned integer or floating point), + which is passed back to the caller via the result parameter. - @return the result of the number conversion or NAN if the conversion - read past the current token. The latter case needs to be treated by the - caller function. + integral numbers that don't fit into the the range of the respective + type are parsed as number_float_t - @throw std::range_error if passed value is out of range + floating-point values do not satisfy std::isfinite predicate + are converted to value_t::null + + throws if the entire string [m_start .. m_cursor) cannot be + interpreted as a number + + @param[out] result @ref basic_json object to receive the number. + @param[in] token the type of the number token */ - number_float_t get_number() const + bool get_number(basic_json& result, const token_type token) const { - // conversion - typename string_t::value_type* endptr; assert(m_start != nullptr); - number_float_t float_val = str_to_float_t(static_cast(nullptr), &endptr); + assert(m_start < m_cursor); + assert((token == token_type::value_unsigned) or + (token == token_type::value_integer) or + (token == token_type::value_float)); - // return float_val if the whole number was translated and NAN - // otherwise - return (reinterpret_cast(endptr) == m_cursor) ? float_val : NAN; + strtonum num_converter(reinterpret_cast(m_start), + reinterpret_cast(m_cursor)); + + switch (token) + { + case lexer::token_type::value_unsigned: + { + number_unsigned_t val; + if (num_converter.to(val)) + { + // parsing successful + result.m_type = value_t::number_unsigned; + result.m_value = val; + return true; + } + break; + } + + case lexer::token_type::value_integer: + { + number_integer_t val; + if (num_converter.to(val)) + { + // parsing successful + result.m_type = value_t::number_integer; + result.m_value = val; + return true; + } + break; + } + + default: + { + break; + } + } + + // parse float (either explicitly or because a previous conversion + // failed) + number_float_t val; + if (num_converter.to(val)) + { + // parsing successful + result.m_type = value_t::number_float; + result.m_value = val; + + // replace infinity and NAN by null + if (not std::isfinite(result.m_value.number_float)) + { + result.m_type = value_t::null; + result.m_value = basic_json::json_value(); + } + + return true; + } + + // couldn't parse number in any format + return false; } private: /// optional input stream std::istream* m_stream = nullptr; - /// the buffer - string_t m_buffer; + /// line buffer buffer for m_stream + string_t m_line_buffer {}; + /// used for filling m_line_buffer + string_t m_line_buffer_tmp {}; /// the buffer pointer const lexer_char_t* m_content = nullptr; /// pointer to the beginning of the current symbol @@ -7857,6 +11341,8 @@ basic_json_parser_64: const lexer_char_t* m_cursor = nullptr; /// pointer to the end of the buffer const lexer_char_t* m_limit = nullptr; + /// the last token type + token_type last_token_type = token_type::end_of_input; }; /*! @@ -7867,32 +11353,42 @@ basic_json_parser_64: class parser { public: - /// constructor for strings - parser(const string_t& s, parser_callback_t cb = nullptr) - : callback(cb), m_lexer(s) - { - // read first token - get_token(); - } + /// a parser reading from a string literal + parser(const char* buff, const parser_callback_t cb = nullptr) + : callback(cb), + m_lexer(reinterpret_cast(buff), std::strlen(buff)) + {} /// a parser reading from an input stream - parser(std::istream& _is, parser_callback_t cb = nullptr) - : callback(cb), m_lexer(&_is) - { - // read first token - get_token(); - } + parser(std::istream& is, const parser_callback_t cb = nullptr) + : callback(cb), m_lexer(is) + {} + + /// a parser reading from an iterator range with contiguous storage + template::iterator_category, std::random_access_iterator_tag>::value + , int>::type + = 0> + parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) + : callback(cb), + m_lexer(reinterpret_cast(&(*first)), + static_cast(std::distance(first, last))) + {} /// public parser interface basic_json parse() { + // read first token + get_token(); + basic_json result = parse_internal(true); + result.assert_invariant(); expect(lexer::token_type::end_of_input); // return parser result and replace it with null in case the // top-level value was discarded by the callback function - return result.is_discarded() ? basic_json() : result; + return result.is_discarded() ? basic_json() : std::move(result); } private: @@ -7905,11 +11401,12 @@ basic_json_parser_64: { case lexer::token_type::begin_object: { - if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result)))) + if (keep and (not callback + or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0))) { // explicitly set result to object to cope with {} result.m_type = value_t::object; - result.m_value = json_value(value_t::object); + result.m_value = value_t::object; } // read next token @@ -7983,11 +11480,12 @@ basic_json_parser_64: case lexer::token_type::begin_array: { - if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result)))) + if (keep and (not callback + or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0))) { // explicitly set result to object to cope with [] result.m_type = value_t::array; - result.m_value = json_value(value_t::array); + result.m_value = value_t::array; } // read next token @@ -8067,34 +11565,12 @@ basic_json_parser_64: break; } - case lexer::token_type::value_number: + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: + case lexer::token_type::value_float: { - result.m_value = m_lexer.get_number(); - - // NAN is returned if token could not be translated - // completely - if (std::isnan(result.m_value.number_float)) - { - throw std::invalid_argument(std::string("parse error - ") + - m_lexer.get_token() + " is not a number"); - } - + m_lexer.get_number(result, last_token); get_token(); - - // check if conversion loses precision (special case -0.0 always loses precision) - const auto int_val = static_cast(result.m_value.number_float); - if (result.m_value.number_float == static_cast(int_val) and - result.m_value.number_integer != json_value(-0.0f).number_integer) - { - // we would not lose precision -> return int - result.m_type = value_t::number_integer; - result.m_value = int_val; - } - else - { - // we would lose precision -> return float - result.m_type = value_t::number_float; - } break; } @@ -8124,10 +11600,11 @@ basic_json_parser_64: if (t != last_token) { std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + + "'") : lexer::token_type_name(last_token)); error_msg += "; expected " + lexer::token_type_name(t); - throw std::invalid_argument(error_msg); + JSON_THROW(std::invalid_argument(error_msg)); } } @@ -8136,9 +11613,10 @@ basic_json_parser_64: if (t == last_token) { std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + + "'") : lexer::token_type_name(last_token)); - throw std::invalid_argument(error_msg); + JSON_THROW(std::invalid_argument(error_msg)); } } @@ -8146,14 +11624,1278 @@ basic_json_parser_64: /// current level of recursion int depth = 0; /// callback function - parser_callback_t callback; + const parser_callback_t callback = nullptr; /// the type of the last read token typename lexer::token_type last_token = lexer::token_type::uninitialized; /// the lexer lexer m_lexer; }; -}; + public: + /*! + @brief JSON Pointer + + A JSON pointer defines a string syntax for identifying a specific value + within a JSON document. It can be used with functions `at` and + `operator[]`. Furthermore, JSON pointers are the base for JSON patches. + + @sa [RFC 6901](https://tools.ietf.org/html/rfc6901) + + @since version 2.0.0 + */ + class json_pointer + { + /// allow basic_json to access private members + friend class basic_json; + + public: + /*! + @brief create JSON pointer + + Create a JSON pointer according to the syntax described in + [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). + + @param[in] s string representing the JSON pointer; if omitted, the + empty string is assumed which references the whole JSON + value + + @throw std::domain_error if reference token is nonempty and does not + begin with a slash (`/`); example: `"JSON pointer must be empty or + begin with /"` + @throw std::domain_error if a tilde (`~`) is not followed by `0` + (representing `~`) or `1` (representing `/`); example: `"escape error: + ~ must be followed with 0 or 1"` + + @liveexample{The example shows the construction several valid JSON + pointers as well as the exceptional behavior.,json_pointer} + + @since version 2.0.0 + */ + explicit json_pointer(const std::string& s = "") + : reference_tokens(split(s)) + {} + + /*! + @brief return a string representation of the JSON pointer + + @invariant For each JSON pointer `ptr`, it holds: + @code {.cpp} + ptr == json_pointer(ptr.to_string()); + @endcode + + @return a string representation of the JSON pointer + + @liveexample{The example shows the result of `to_string`., + json_pointer__to_string} + + @since version 2.0.0 + */ + std::string to_string() const noexcept + { + return std::accumulate(reference_tokens.begin(), + reference_tokens.end(), std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + escape(b); + }); + } + + /// @copydoc to_string() + operator std::string() const + { + return to_string(); + } + + private: + /// remove and return last reference pointer + std::string pop_back() + { + if (is_root()) + { + JSON_THROW(std::domain_error("JSON pointer has no parent")); + } + + auto last = reference_tokens.back(); + reference_tokens.pop_back(); + return last; + } + + /// return whether pointer points to the root document + bool is_root() const + { + return reference_tokens.empty(); + } + + json_pointer top() const + { + if (is_root()) + { + JSON_THROW(std::domain_error("JSON pointer has no parent")); + } + + json_pointer result = *this; + result.reference_tokens = {reference_tokens[0]}; + return result; + } + + /*! + @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. + */ + reference get_and_create(reference j) const + { + pointer 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->m_type) + { + case 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 value_t::object: + { + // create an entry in the object + result = &result->operator[](reference_token); + break; + } + + case value_t::array: + { + // create an entry in the array + result = &result->operator[](static_cast(std::stoi(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. + */ + default: + { + JSON_THROW(std::domain_error("invalid value to unflatten")); + } + } + } + + 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 std::out_of_range if the JSON pointer can not be resolved + @throw std::domain_error if an array index begins with '0' + @throw std::invalid_argument if an array index was not a number + */ + reference get_unchecked(pointer ptr) const + { + for (const auto& reference_token : reference_tokens) + { + // convert null values to arrays or objects before continuing + if (ptr->m_type == value_t::null) + { + // check if reference token is a number + const bool nums = std::all_of(reference_token.begin(), + reference_token.end(), + [](const char x) + { + return std::isdigit(x); + }); + + // change value to array for numbers or "-" or to object + // otherwise + if (nums or reference_token == "-") + { + *ptr = value_t::array; + } + else + { + *ptr = value_t::object; + } + } + + switch (ptr->m_type) + { + case value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case value_t::array: + { + // error condition (cf. RFC 6901, Sect. 4) + if (reference_token.size() > 1 and reference_token[0] == '0') + { + JSON_THROW(std::domain_error("array index must not begin with '0'")); + } + + 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[](static_cast(std::stoi(reference_token))); + } + break; + } + + default: + { + JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'")); + } + } + } + + return *ptr; + } + + reference get_checked(pointer ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->m_type) + { + case value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case value_t::array: + { + if (reference_token == "-") + { + // "-" always fails the range check + JSON_THROW(std::out_of_range("array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (reference_token.size() > 1 and reference_token[0] == '0') + { + JSON_THROW(std::domain_error("array index must not begin with '0'")); + } + + // note: at performs range check + ptr = &ptr->at(static_cast(std::stoi(reference_token))); + break; + } + + default: + { + JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'")); + } + } + } + + 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 + */ + const_reference get_unchecked(const_pointer ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->m_type) + { + case value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case value_t::array: + { + if (reference_token == "-") + { + // "-" cannot be used for const access + JSON_THROW(std::out_of_range("array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (reference_token.size() > 1 and reference_token[0] == '0') + { + JSON_THROW(std::domain_error("array index must not begin with '0'")); + } + + // use unchecked array access + ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); + break; + } + + default: + { + JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'")); + } + } + } + + return *ptr; + } + + const_reference get_checked(const_pointer ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->m_type) + { + case value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case value_t::array: + { + if (reference_token == "-") + { + // "-" always fails the range check + JSON_THROW(std::out_of_range("array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (reference_token.size() > 1 and reference_token[0] == '0') + { + JSON_THROW(std::domain_error("array index must not begin with '0'")); + } + + // note: at performs range check + ptr = &ptr->at(static_cast(std::stoi(reference_token))); + break; + } + + default: + { + JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'")); + } + } + } + + return *ptr; + } + + /// split the string input to reference tokens + 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 (reference_string[0] != '/') + { + JSON_THROW(std::domain_error("JSON pointer must be empty or begin with '/'")); + } + + // 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 + size_t slash = reference_string.find_first_of('/', 1), + // set the beginning of the first reference token + start = 1; + // we can stop if start == string::npos+1 = 0 + start != 0; + // set the beginning of the next reference token + // (will eventually be 0 if slash == std::string::npos) + start = 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 (size_t pos = reference_token.find_first_of('~'); + pos != std::string::npos; + pos = reference_token.find_first_of('~', pos + 1)) + { + assert(reference_token[pos] == '~'); + + // ~ must be followed by 0 or 1 + if (pos == reference_token.size() - 1 or + (reference_token[pos + 1] != '0' and + reference_token[pos + 1] != '1')) + { + JSON_THROW(std::domain_error("escape error: '~' must be followed with '0' or '1'")); + } + } + + // finally, store the reference token + unescape(reference_token); + result.push_back(reference_token); + } + + return result; + } + + private: + /*! + @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. + + @since version 2.0.0 + */ + static void replace_substring(std::string& s, + const std::string& f, + const std::string& t) + { + assert(not f.empty()); + + for ( + size_t 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 + pos = s.find(f, pos + t.size()) // find next occurrence of f + ); + } + + /// escape tilde and slash + static std::string escape(std::string s) + { + // escape "~"" to "~0" and "/" to "~1" + replace_substring(s, "~", "~0"); + replace_substring(s, "/", "~1"); + return s; + } + + /// unescape tilde and slash + static void unescape(std::string& s) + { + // first transform any occurrence of the sequence '~1' to '/' + replace_substring(s, "~1", "/"); + // then transform any occurrence of the sequence '~0' to '~' + replace_substring(s, "~0", "~"); + } + + /*! + @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 basic_json& value, + basic_json& result) + { + switch (value.m_type) + { + case 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 (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 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 + "/" + escape(element.first), + element.second, result); + } + } + break; + } + + default: + { + // add primitive value with its reference string + result[reference_string] = value; + break; + } + } + } + + /*! + @param[in] value flattened JSON + + @return unflattened JSON + */ + static basic_json unflatten(const basic_json& value) + { + if (not value.is_object()) + { + JSON_THROW(std::domain_error("only objects can be unflattened")); + } + + basic_json result; + + // iterate the JSON object values + for (const auto& element : *value.m_value.object) + { + if (not element.second.is_primitive()) + { + JSON_THROW(std::domain_error("values in object must be primitive")); + } + + // 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; + } + + private: + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return lhs.reference_tokens == rhs.reference_tokens; + } + + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return !(lhs == rhs); + } + + /// the reference tokens + std::vector reference_tokens {}; + }; + + ////////////////////////// + // JSON Pointer support // + ////////////////////////// + + /// @name JSON Pointer functions + /// @{ + + /*! + @brief access specified element via JSON Pointer + + Uses a JSON pointer to retrieve a reference to the respective JSON value. + No bound checking is performed. Similar to @ref operator[](const typename + object_t::key_type&), `null` values are created in arrays and objects if + necessary. + + In particular: + - If the JSON pointer points to an object key that does not exist, it + is created an filled with a `null` value before a reference to it + is returned. + - If the JSON pointer points to an array index that does not exist, it + is created an filled with a `null` value before a reference to it + is returned. All indices between the current maximum and the given + index are also filled with `null`. + - The special value `-` is treated as a synonym for the index past the + end. + + @param[in] ptr a JSON pointer + + @return reference to the element pointed to by @a ptr + + @complexity Constant. + + @throw std::out_of_range if the JSON pointer can not be resolved + @throw std::domain_error if an array index begins with '0' + @throw std::invalid_argument if an array index was not a number + + @liveexample{The behavior is shown in the example.,operatorjson_pointer} + + @since version 2.0.0 + */ + reference operator[](const json_pointer& ptr) + { + return ptr.get_unchecked(this); + } + + /*! + @brief access specified element via JSON Pointer + + Uses a JSON pointer to retrieve a reference to the respective JSON value. + No bound checking is performed. The function does not change the JSON + value; no `null` values are created. In particular, the the special value + `-` yields an exception. + + @param[in] ptr JSON pointer to the desired element + + @return const reference to the element pointed to by @a ptr + + @complexity Constant. + + @throw std::out_of_range if the JSON pointer can not be resolved + @throw std::domain_error if an array index begins with '0' + @throw std::invalid_argument if an array index was not a number + + @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} + + @since version 2.0.0 + */ + const_reference operator[](const json_pointer& ptr) const + { + return ptr.get_unchecked(this); + } + + /*! + @brief access specified element via JSON Pointer + + Returns a reference to the element at with specified JSON pointer @a ptr, + with bounds checking. + + @param[in] ptr JSON pointer to the desired element + + @return reference to the element pointed to by @a ptr + + @complexity Constant. + + @throw std::out_of_range if the JSON pointer can not be resolved + @throw std::domain_error if an array index begins with '0' + @throw std::invalid_argument if an array index was not a number + + @liveexample{The behavior is shown in the example.,at_json_pointer} + + @since version 2.0.0 + */ + reference at(const json_pointer& ptr) + { + return ptr.get_checked(this); + } + + /*! + @brief access specified element via JSON Pointer + + Returns a const reference to the element at with specified JSON pointer @a + ptr, with bounds checking. + + @param[in] ptr JSON pointer to the desired element + + @return reference to the element pointed to by @a ptr + + @complexity Constant. + + @throw std::out_of_range if the JSON pointer can not be resolved + @throw std::domain_error if an array index begins with '0' + @throw std::invalid_argument if an array index was not a number + + @liveexample{The behavior is shown in the example.,at_json_pointer_const} + + @since version 2.0.0 + */ + const_reference at(const json_pointer& ptr) const + { + return ptr.get_checked(this); + } + + /*! + @brief return flattened JSON value + + The function creates a JSON object whose keys are JSON pointers (see [RFC + 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all + primitive. The original JSON value can be restored using the @ref + unflatten() function. + + @return an object that maps JSON pointers to primitive values + + @note Empty objects and arrays are flattened to `null` and will not be + reconstructed correctly by the @ref unflatten() function. + + @complexity Linear in the size the JSON value. + + @liveexample{The following code shows how a JSON object is flattened to an + object whose keys consist of JSON pointers.,flatten} + + @sa @ref unflatten() for the reverse function + + @since version 2.0.0 + */ + basic_json flatten() const + { + basic_json result(value_t::object); + json_pointer::flatten("", *this, result); + return result; + } + + /*! + @brief unflatten a previously flattened JSON value + + The function restores the arbitrary nesting of a JSON value that has been + flattened before using the @ref flatten() function. The JSON value must + meet certain constraints: + 1. The value must be an object. + 2. The keys must be JSON pointers (see + [RFC 6901](https://tools.ietf.org/html/rfc6901)) + 3. The mapped values must be primitive JSON types. + + @return the original JSON from a flattened version + + @note Empty objects and arrays are flattened by @ref flatten() to `null` + values and can not unflattened to their original type. Apart from + this example, for a JSON value `j`, the following is always true: + `j == j.flatten().unflatten()`. + + @complexity Linear in the size the JSON value. + + @liveexample{The following code shows how a flattened JSON object is + unflattened into the original nested JSON object.,unflatten} + + @sa @ref flatten() for the reverse function + + @since version 2.0.0 + */ + basic_json unflatten() const + { + return json_pointer::unflatten(*this); + } + + /// @} + + ////////////////////////// + // JSON Patch functions // + ////////////////////////// + + /// @name JSON Patch functions + /// @{ + + /*! + @brief applies a JSON patch + + [JSON Patch](http://jsonpatch.com) defines a JSON document structure for + expressing a sequence of operations to apply to a JSON) document. With + this function, a JSON Patch is applied to the current JSON value by + executing all operations from the patch. + + @param[in] json_patch JSON patch document + @return patched document + + @note The application of a patch is atomic: Either all operations succeed + and the patched document is returned or an exception is thrown. In + any case, the original value is not changed: the patch is applied + to a copy of the value. + + @throw std::out_of_range if a JSON pointer inside the patch could not + be resolved successfully in the current JSON value; example: `"key baz + not found"` + @throw invalid_argument if the JSON patch is malformed (e.g., mandatory + attributes are missing); example: `"operation add must have member path"` + + @complexity Linear in the size of the JSON value and the length of the + JSON patch. As usually only a fraction of the JSON value is affected by + the patch, the complexity can usually be neglected. + + @liveexample{The following code shows how a JSON patch is applied to a + value.,patch} + + @sa @ref diff -- create a JSON patch by comparing two JSON values + + @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) + @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) + + @since version 2.0.0 + */ + 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.is_root()) + { + result = val; + } + else + { + // 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.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 = std::stoi(last_path); + if (static_cast(idx) > parent.size()) + { + // avoid undefined behavior + JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); + } + else + { + // default case: insert add offset + parent.insert(parent.begin() + static_cast(idx), val); + } + } + break; + } + + default: + { + // if there exists a parent it cannot be primitive + assert(false); // LCOV_EXCL_LINE + } + } + } + }; + + // wrapper for "remove" operation; remove value at ptr + const auto operation_remove = [&result](json_pointer & ptr) + { + // get reference to parent of JSON pointer ptr + const auto last_path = 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 (it != parent.end()) + { + parent.erase(it); + } + else + { + JSON_THROW(std::out_of_range("key '" + last_path + "' not found")); + } + } + else if (parent.is_array()) + { + // note erase performs range check + parent.erase(static_cast(std::stoi(last_path))); + } + }; + + // type check + if (not json_patch.is_array()) + { + // a JSON patch must be an array of objects + JSON_THROW(std::invalid_argument("JSON patch must be an array of objects")); + } + + // 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 (it == val.m_value.object->end()) + { + JSON_THROW(std::invalid_argument(error_msg + " must have member '" + member + "'")); + } + + // check if result is of type string + if (string_type and not it->second.is_string()) + { + JSON_THROW(std::invalid_argument(error_msg + " must have string member '" + member + "'")); + } + + // no error: return value + return it->second; + }; + + // type check + if (not val.is_object()) + { + JSON_THROW(std::invalid_argument("JSON patch must be an array of objects")); + } + + // collect mandatory members + const std::string op = get_value("op", "op", true); + const std::string path = get_value(op, "path", true); + 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 std::string from_path = get_value("move", "from", true); + 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 std::string from_path = get_value("copy", "from", true);; + const json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + result[ptr] = result.at(from_ptr); + 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_CATCH (std::out_of_range&) + { + // ignore out of range errors: success remains false + } + + // throw an exception if test fails + if (not success) + { + JSON_THROW(std::domain_error("unsuccessful: " + val.dump())); + } + + break; + } + + case patch_operations::invalid: + { + // op must be "add", "remove", "replace", "move", "copy", or + // "test" + JSON_THROW(std::invalid_argument("operation value '" + op + "' is invalid")); + } + } + } + + return result; + } + + /*! + @brief creates a diff as a JSON patch + + Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can + be changed into the value @a target by calling @ref patch function. + + @invariant For two JSON values @a source and @a target, the following code + yields always `true`: + @code {.cpp} + source.patch(diff(source, target)) == target; + @endcode + + @note Currently, only `remove`, `add`, and `replace` operations are + generated. + + @param[in] source JSON value to compare from + @param[in] target JSON value to compare against + @param[in] path helper value to create JSON pointers + + @return a JSON patch to convert the @a source to @a target + + @complexity Linear in the lengths of @a source and @a target. + + @liveexample{The following code shows how a JSON patch is created as a + diff for two JSON values.,diff} + + @sa @ref patch -- apply a JSON patch + + @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) + + @since version 2.0.0 + */ + 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} + }); + } + else + { + switch (source.type()) + { + case value_t::array: + { + // first pass: traverse common elements + size_t i = 0; + while (i < source.size() and 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; + } + + // i 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 + "/" + std::to_string(i)}, + {"value", target[i]} + }); + ++i; + } + + break; + } + + case value_t::object: + { + // first pass: traverse this object's elements + for (auto it = source.begin(); it != source.end(); ++it) + { + // escape the key name to be used in a JSON patch + const auto key = json_pointer::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.begin(); it != target.end(); ++it) + { + if (source.find(it.key()) == source.end()) + { + // found a key that is not in this -> add it + const auto key = json_pointer::escape(it.key()); + result.push_back( + { + {"op", "add"}, + {"path", path + "/" + key}, + {"value", it.value()} + }); + } + } + + break; + } + + default: + { + // both primitive type: replace value + result.push_back( + { + {"op", "replace"}, + {"path", path}, + {"value", target} + }); + break; + } + } + } + + return result; + } + + /// @} +}; ///////////// // presets // @@ -8162,18 +12904,18 @@ basic_json_parser_64: /*! @brief default JSON class -This type is the default specialization of the @ref basic_json class which uses -the standard template types. +This type is the default specialization of the @ref basic_json class which +uses the standard template types. @since version 1.0.0 */ using json = basic_json<>; -} +} // namespace nlohmann -///////////////////////// -// nonmember functions // -///////////////////////// +/////////////////////// +// nonmember support // +/////////////////////// // specialization of std::swap, and std::hash namespace std @@ -8183,7 +12925,7 @@ namespace std @since version 1.0.0 */ -template <> +template<> inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( is_nothrow_move_constructible::value and @@ -8194,7 +12936,7 @@ inline void swap(nlohmann::json& j1, } /// hash value for JSON objects -template <> +template<> struct hash { /*! @@ -8209,23 +12951,42 @@ struct hash return h(j.dump()); } }; -} +} // namespace std /*! @brief user-defined string literal for JSON values -This operator implements a user-defined string literal for JSON objects. It can -be used by adding \p "_json" to a string literal and returns a JSON object if -no parse error occurred. +This operator implements a user-defined string literal for JSON objects. It +can be used by adding `"_json"` to a string literal and returns a JSON object +if no parse error occurred. @param[in] s a string representation of a JSON object +@param[in] n the length of string @a s @return a JSON object @since version 1.0.0 */ -inline nlohmann::json operator "" _json(const char* s, std::size_t) +inline nlohmann::json operator "" _json(const char* s, std::size_t n) { - return nlohmann::json::parse(reinterpret_cast(s)); + return nlohmann::json::parse(s, s + n); +} + +/*! +@brief user-defined string literal for JSON pointer + +This operator implements a user-defined string literal for JSON Pointers. It +can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer +object if no parse error occurred. + +@param[in] s a string representation of a JSON Pointer +@param[in] n the length of string @a s +@return a JSON pointer object + +@since version 2.0.0 +*/ +inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) +{ + return nlohmann::json::json_pointer(std::string(s, n)); } // restore GCC/clang diagnostic settings @@ -8233,4 +12994,10 @@ inline nlohmann::json operator "" _json(const char* s, std::size_t) #pragma GCC diagnostic pop #endif +// clean up +#undef JSON_CATCH +#undef JSON_DEPRECATED +#undef JSON_THROW +#undef JSON_TRY + #endif From 5575f17b467760f4a5e171e4438390008cea4926 Mon Sep 17 00:00:00 2001 From: Kalle Bladin Date: Wed, 7 Jun 2017 16:30:41 +0200 Subject: [PATCH 09/12] Feature/gdalcrashfix (#331) Saving GDAL dataset values upon initialization of dataset to avoid calling GDAL functions afterwards since it can be done concurrently. Not done for the data reading since some (not all) GDAL dataset drivers support concurrent reading. The WMS driver does not support concurrent reading, which is why we only use one worker thread per AsyncTileDataReader. Perhaps something for the future if GDAL will ensure thread saefty. Protecting GdalRawTileDataReader with mutex lock when initializing. Make sure read only functions in RawTileDataReader are const. Protecting ConcurrentJobManager with mutex lock when pushing and popping to finished jobs. --- .../other/concurrentjobmanager.h | 3 + .../other/concurrentjobmanager.inl | 2 + .../other/prioritizingconcurrentjobmanager.h | 3 + .../prioritizingconcurrentjobmanager.inl | 5 +- .../gdalrawtiledatareader.cpp | 119 ++++++------------ .../rawtiledatareader/gdalrawtiledatareader.h | 33 +++-- .../rawtiledatareader/rawtiledatareader.cpp | 24 ++-- .../rawtiledatareader/rawtiledatareader.h | 11 +- .../simplerawtiledatareader.cpp | 4 +- .../simplerawtiledatareader.h | 2 +- 10 files changed, 96 insertions(+), 110 deletions(-) diff --git a/modules/globebrowsing/other/concurrentjobmanager.h b/modules/globebrowsing/other/concurrentjobmanager.h index c90b9576d0..910a02ef1f 100644 --- a/modules/globebrowsing/other/concurrentjobmanager.h +++ b/modules/globebrowsing/other/concurrentjobmanager.h @@ -28,6 +28,8 @@ #include #include +#include + namespace openspace { namespace globebrowsing { @@ -62,6 +64,7 @@ public: private: ConcurrentQueue>> _finishedJobs; std::shared_ptr threadPool; + std::mutex _finishedJobsMutex; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/other/concurrentjobmanager.inl b/modules/globebrowsing/other/concurrentjobmanager.inl index e1c3b5244c..a522216f5b 100644 --- a/modules/globebrowsing/other/concurrentjobmanager.inl +++ b/modules/globebrowsing/other/concurrentjobmanager.inl @@ -42,6 +42,7 @@ template void ConcurrentJobManager

::enqueueJob(std::shared_ptr> job) { threadPool->enqueue([this, job]() { job->execute(); + std::lock_guard lock(_finishedJobsMutex); _finishedJobs.push(job); }); } @@ -54,6 +55,7 @@ void ConcurrentJobManager

::clearEnqueuedJobs() { template std::shared_ptr> ConcurrentJobManager

::popFinishedJob() { ghoul_assert(_finishedJobs.size() > 0, "There is no finished job to pop!"); + std::lock_guard lock(_finishedJobsMutex); return _finishedJobs.pop(); } diff --git a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h index ed2cd70841..f2314b07f5 100644 --- a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h +++ b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h @@ -29,6 +29,8 @@ #include #include +#include + namespace openspace { namespace globebrowsing { @@ -85,6 +87,7 @@ private: ConcurrentQueue>> _finishedJobs; /// An LRU thread pool is used since the jobs can be bumped and hence prioritized. std::shared_ptr> _threadPool; + std::mutex _finishedJobsMutex; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl index 1a4444e0eb..ebe0147947 100644 --- a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl +++ b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl @@ -39,6 +39,7 @@ void PrioritizingConcurrentJobManager::enqueueJob(std::shared_ptrenqueue([this, job]() { job->execute(); + std::lock_guard lock(_finishedJobsMutex); _finishedJobs.push(job); }, key); } @@ -68,7 +69,9 @@ void PrioritizingConcurrentJobManager::clearEnqueuedJobs() { template std::shared_ptr> PrioritizingConcurrentJobManager::popFinishedJob() { ghoul_assert(_finishedJobs.size() > 0, "There is no finished job to pop!"); - return _finishedJobs.pop(); + std::lock_guard lock(_finishedJobsMutex); + std::shared_ptr> result = _finishedJobs.pop(); + return result; } template diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp index 8eb7e070a2..904cbe2b13 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp @@ -65,10 +65,15 @@ GdalRawTileDataReader::GdalRawTileDataReader(const std::string& filePath, { _initDirectory = baseDirectory.empty() ? CPLGetCurrentDir() : baseDirectory; _datasetFilePath = filePath; - ensureInitialized(); + + { // Aquire lock + std::lock_guard lockGuard(_datasetLock); + initialize(); + } } GdalRawTileDataReader::~GdalRawTileDataReader() { + std::lock_guard lockGuard(_datasetLock); if (_dataset != nullptr) { GDALClose(_dataset); _dataset = nullptr; @@ -76,6 +81,7 @@ GdalRawTileDataReader::~GdalRawTileDataReader() { } void GdalRawTileDataReader::reset() { + std::lock_guard lockGuard(_datasetLock); _cached._maxLevel = -1; if (_dataset != nullptr) { GDALClose(_dataset); @@ -84,52 +90,32 @@ void GdalRawTileDataReader::reset() { initialize(); } -int GdalRawTileDataReader::maxChunkLevel() { - ensureInitialized(); - if (_cached._maxLevel < 0) { - int numOverviews = _dataset->GetRasterBand(1)->GetOverviewCount(); - _cached._maxLevel = -_cached._tileLevelDifference; - if (numOverviews > 0) { - _cached._maxLevel += numOverviews - 1; - } - } +int GdalRawTileDataReader::maxChunkLevel() const { return _cached._maxLevel; } float GdalRawTileDataReader::noDataValueAsFloat() const { - float noDataValue; - if (_dataset && _dataset->GetRasterBand(1)) { - noDataValue = _dataset->GetRasterBand(1)->GetNoDataValue(); - } - else { - noDataValue = std::numeric_limits::min(); - } - return noDataValue; + return _gdalDatasetMetaDataCached.noDataValue; } int GdalRawTileDataReader::rasterXSize() const { - return _dataset->GetRasterXSize(); + return _gdalDatasetMetaDataCached.rasterXSize; } int GdalRawTileDataReader::rasterYSize() const { - return _dataset->GetRasterYSize(); + return _gdalDatasetMetaDataCached.rasterYSize; } float GdalRawTileDataReader::depthOffset() const { - return _dataset->GetRasterBand(1)->GetOffset(); + return _gdalDatasetMetaDataCached.offset; } float GdalRawTileDataReader::depthScale() const { - return _dataset->GetRasterBand(1)->GetScale(); + return _gdalDatasetMetaDataCached.scale; } std::array GdalRawTileDataReader::getGeoTransform() const { - std::array padfTransform; - CPLErr err = _dataset->GetGeoTransform(&padfTransform[0]); - if (err == CE_Failure) { - return RawTileDataReader::getGeoTransform(); - } - return padfTransform; + return _gdalDatasetMetaDataCached.padfTransform; } IODescription GdalRawTileDataReader::getIODescription(const TileIndex& tileIndex) const { @@ -142,8 +128,7 @@ IODescription GdalRawTileDataReader::getIODescription(const TileIndex& tileIndex _initData.dimensionsWithoutPadding().x, _initData.dimensionsWithoutPadding().y); io.read.overview = 0; - io.read.fullRegion = gdalPixelRegion( - _dataset->GetRasterBand(1)); + io.read.fullRegion = fullPixelRegion(); // For correct sampling in dataset, we need to pad the texture tile PixelRegion scaledPadding = padding; @@ -169,18 +154,35 @@ void GdalRawTileDataReader::initialize() { _dataset = openGdalDataset(_datasetFilePath); // Assume all raster bands have the same data type - _gdalType = tiledatatype::getGdalDataType(_initData.glType()); + _gdalDatasetMetaDataCached.rasterCount = _dataset->GetRasterCount(); + _gdalDatasetMetaDataCached.scale = _dataset->GetRasterBand(1)->GetScale(); + _gdalDatasetMetaDataCached.offset = _dataset->GetRasterBand(1)->GetOffset(); + _gdalDatasetMetaDataCached.rasterXSize = _dataset->GetRasterXSize(); + _gdalDatasetMetaDataCached.rasterYSize = _dataset->GetRasterYSize(); + _gdalDatasetMetaDataCached.noDataValue = _dataset->GetRasterBand(1)->GetNoDataValue(); + _gdalDatasetMetaDataCached.dataType = tiledatatype::getGdalDataType(_initData.glType()); + CPLErr err = _dataset->GetGeoTransform(&_gdalDatasetMetaDataCached.padfTransform[0]); + if (err == CE_Failure) { + _gdalDatasetMetaDataCached.padfTransform = RawTileDataReader::getGeoTransform(); + } + _depthTransform = calculateTileDepthTransform(); _cached._tileLevelDifference = calculateTileLevelDifference(_initData.dimensionsWithoutPadding().x); + + int numOverviews = _dataset->GetRasterBand(1)->GetOverviewCount(); + _cached._maxLevel = -_cached._tileLevelDifference; + if (numOverviews > 0) { + _cached._maxLevel += numOverviews - 1; + } } void GdalRawTileDataReader::readImageData( IODescription& io, RawTile::ReadError& worstError, char* imageDataDest) const { // Only read the minimum number of rasters - int nRastersToRead = std::min(_dataset->GetRasterCount(), + int nRastersToRead = std::min(_gdalDatasetMetaDataCached.rasterCount, static_cast(_initData.nRasters())); switch (_initData.ghoulTextureFormat()) { @@ -270,7 +272,8 @@ RawTile::ReadError GdalRawTileDataReader::rasterRead( dataDest += io.write.region.start.x * _initData.bytesPerPixel(); GDALRasterBand* gdalRasterBand = _dataset->GetRasterBand(rasterBand); - CPLErr readError = gdalRasterBand->RasterIO( + CPLErr readError = CE_Failure; + readError = gdalRasterBand->RasterIO( GF_Read, io.read.region.start.x, // Begin read x io.read.region.start.y, // Begin read y @@ -279,7 +282,7 @@ RawTile::ReadError GdalRawTileDataReader::rasterRead( dataDest, // Where to put data io.write.region.numPixels.x, // width to write x in destination io.write.region.numPixels.y, // width to write y in destination - _gdalType, // Type + _gdalDatasetMetaDataCached.dataType, // Type _initData.bytesPerPixel(), // Pixel spacing -io.write.bytesPerLine // Line spacing ); @@ -314,7 +317,7 @@ GDALDataset* GdalRawTileDataReader::openGdalDataset(const std::string& filePath) return dataset; } -int GdalRawTileDataReader::calculateTileLevelDifference(int minimumPixelSize) { +int GdalRawTileDataReader::calculateTileLevelDifference(int minimumPixelSize) const { GDALRasterBand* firstBand = _dataset->GetRasterBand(1); GDALRasterBand* maxOverview; int numOverviews = firstBand->GetOverviewCount(); @@ -330,52 +333,6 @@ int GdalRawTileDataReader::calculateTileLevelDifference(int minimumPixelSize) { return diff; } -bool GdalRawTileDataReader::gdalHasOverviews() const { - return _dataset->GetRasterBand(1)->GetOverviewCount() > 0; -} - -int GdalRawTileDataReader::gdalOverview( - const PixelRegion::PixelRange& regionSizeOverviewZero) const { - GDALRasterBand* firstBand = _dataset->GetRasterBand(1); - - int minNumPixels0 = glm::min(regionSizeOverviewZero.x, regionSizeOverviewZero.y); - - int overviews = firstBand->GetOverviewCount(); - GDALRasterBand* maxOverview = - overviews ? firstBand->GetOverview(overviews - 1) : firstBand; - - int sizeLevel0 = maxOverview->GetXSize(); - // The dataset itself may not have overviews but even if it does not, an overview - // for the data region can be calculated and possibly be used to sample greater - // Regions of the original dataset. - int ov = std::log2(minNumPixels0) - std::log2(sizeLevel0 + 1) - - _cached._tileLevelDifference; - ov = glm::clamp(ov, 0, overviews - 1); - - return ov; -} - -int GdalRawTileDataReader::gdalOverview(const TileIndex& tileIndex) const { - int overviews = _dataset->GetRasterBand(1)->GetOverviewCount(); - int ov = overviews - (tileIndex.level + _cached._tileLevelDifference + 1); - return glm::clamp(ov, 0, overviews - 1); -} - -int GdalRawTileDataReader::gdalVirtualOverview(const TileIndex& tileIndex) const { - int overviews = _dataset->GetRasterBand(1)->GetOverviewCount(); - int ov = overviews - (tileIndex.level + _cached._tileLevelDifference + 1); - return ov; -} - -PixelRegion GdalRawTileDataReader::gdalPixelRegion(GDALRasterBand* rasterBand) const { - PixelRegion gdalRegion; - gdalRegion.start.x = 0; - gdalRegion.start.y = 0; - gdalRegion.numPixels.x = rasterBand->GetXSize(); - gdalRegion.numPixels.y = rasterBand->GetYSize(); - return gdalRegion; -} - } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h index 109de50f3b..8280b61ec3 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h @@ -40,7 +40,9 @@ #include #include + #include +#include class GDALDataset; class GDALRasterBand; @@ -73,7 +75,7 @@ public: // Public virtual function overloading virtual void reset() override; - virtual int maxChunkLevel() override; + virtual int maxChunkLevel() const override; virtual float noDataValueAsFloat() const override; virtual int rasterXSize() const override; virtual int rasterYSize() const override; @@ -101,19 +103,34 @@ private: // GDAL Helper methods GDALDataset* openGdalDataset(const std::string& filePath); - int calculateTileLevelDifference(int minimumPixelSize); - bool gdalHasOverviews() const; - int gdalOverview(const PixelRegion::PixelRange& baseRegionSize) const; - int gdalOverview(const TileIndex& tileIndex) const; - int gdalVirtualOverview(const TileIndex& tileIndex) const; - PixelRegion gdalPixelRegion(GDALRasterBand* rasterBand) const; + + /** + * Use as a helper function when determining the maximum tile level. This function + * returns the negated number of overviews requred to downscale the highest overview + * dataset so that it fits within minimumPixelSize pixels in the x-dimension. + */ + int calculateTileLevelDifference(int minimumPixelSize) const; // Member variables std::string _initDirectory; std::string _datasetFilePath; GDALDataset* _dataset; - GDALDataType _gdalType; + + struct GdalDatasetMetaDataCached { + int rasterCount; + float scale; + float offset; + int rasterXSize; + int rasterYSize; + float noDataValue; + std::array padfTransform; + + GDALDataType dataType; + + } _gdalDatasetMetaDataCached; + + mutable std::mutex _datasetLock; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp index bfb54df704..a2f9e000b6 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp @@ -68,21 +68,13 @@ RawTileDataReader::RawTileDataReader(const TileTextureInitData& initData, , _hasBeenInitialized(false) {} -void RawTileDataReader::ensureInitialized() { - if (!_hasBeenInitialized) { - initialize(); - _hasBeenInitialized = true; - } -} - -std::shared_ptr RawTileDataReader::defaultTileData() { +std::shared_ptr RawTileDataReader::defaultTileData() const { return std::make_shared(RawTile::createDefault(_initData)); } std::shared_ptr RawTileDataReader::readTileData(TileIndex tileIndex, - char* dataDestination, char* pboMappedDataDestination) + char* dataDestination, char* pboMappedDataDestination) const { - ensureInitialized(); IODescription io = getIODescription(tileIndex); RawTile::ReadError worstError = RawTile::ReadError::None; @@ -136,6 +128,15 @@ const PixelRegion::PixelRange RawTileDataReader::fullPixelSize() const { return glm::uvec2(geodeticToPixel(Geodetic2(90, 180))); } +PixelRegion RawTileDataReader::fullPixelRegion() const { + PixelRegion fullRegion; + fullRegion.start.x = 0; + fullRegion.start.y = 0; + fullRegion.numPixels.x = rasterXSize(); + fullRegion.numPixels.y = rasterYSize(); + return fullRegion; +} + std::array RawTileDataReader::getGeoTransform() const { std::array padfTransform; @@ -310,9 +311,8 @@ RawTile::ReadError RawTileDataReader::repeatedRasterRead( } std::shared_ptr RawTileDataReader::getTileMetaData( - std::shared_ptr rawTile, const PixelRegion& region) + std::shared_ptr rawTile, const PixelRegion& region) const { - ensureInitialized(); size_t bytesPerLine = _initData.bytesPerPixel() * region.numPixels.x; TileMetaData* preprocessData = new TileMetaData(); diff --git a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h index 58acdfdc16..4d0b5197e9 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h +++ b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h @@ -58,7 +58,7 @@ public: * which gets returned. */ std::shared_ptr readTileData(TileIndex tileIndex, - char* dataDestination, char* pboMappedDataDestination); + char* dataDestination, char* pboMappedDataDestination) const; TileDepthTransform getDepthTransform() const; const TileTextureInitData& tileTextureInitData() const; const PixelRegion::PixelRange fullPixelSize() const; @@ -67,7 +67,7 @@ public: * \returns the maximum chunk level available in the dataset. Should be a value * between 2 and 31. */ - virtual int maxChunkLevel() = 0; + virtual int maxChunkLevel() const = 0; /** * Reset the dataset to its initial state. This is the place to clear any cache used. @@ -78,11 +78,12 @@ public: virtual int rasterYSize() const = 0; virtual float depthOffset() const; virtual float depthScale() const; + PixelRegion fullPixelRegion() const; /** * Returns a single channeled empty RawTile of size 16 * 16 pixels. */ - std::shared_ptr defaultTileData(); + std::shared_ptr defaultTileData() const; /// Padding around all tiles to read to make sure edge blending works. const static PixelRegion padding; // same as the two above @@ -98,7 +99,7 @@ protected: /** * Call this in the constructor of the class extending RawTileDataReader */ - void ensureInitialized(); + //void ensureInitialized(); /** * The function returns a transform to map @@ -155,7 +156,7 @@ protected: int rasterBand, const IODescription& io, char* dst, int depth = 0) const; std::shared_ptr getTileMetaData( - std::shared_ptr result, const PixelRegion& region); + std::shared_ptr result, const PixelRegion& region) const; TileDepthTransform calculateTileDepthTransform(); RawTile::ReadError postProcessErrorCheck(std::shared_ptr ioResult) const; diff --git a/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.cpp index 19907da152..e0d4d72ac7 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.cpp @@ -50,14 +50,14 @@ SimpleRawTileDataReader::SimpleRawTileDataReader(const std::string& filePath, : RawTileDataReader(initData, preprocess) { _datasetFilePath = filePath; - ensureInitialized(); + initialize(); } void SimpleRawTileDataReader::reset() { initialize(); } -int SimpleRawTileDataReader::maxChunkLevel() { +int SimpleRawTileDataReader::maxChunkLevel() const { return 2; } diff --git a/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.h b/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.h index d0a8446d5f..0716dca804 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.h +++ b/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.h @@ -54,7 +54,7 @@ public: // Public virtual function overloading virtual void reset() override; - virtual int maxChunkLevel() override; + virtual int maxChunkLevel() const override; virtual float noDataValueAsFloat() const override; virtual int rasterXSize() const override; virtual int rasterYSize() const override; From ea44e7a26b8f6332db9e7d1f5a0042caa43cf039 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 7 Jun 2017 12:42:21 -0400 Subject: [PATCH 10/12] Fix billboard rendering for satellite trails Add necessary scene graph node for satellites into lodglobes/earth Update base files of satellite TLEs --- data/scene/globebrowsing.scene | 1 + data/scene/lodglobes/earth/earth.mod | 12 + data/scene/satellites/satellites.mod | 29 +- data/scene/satellites/tle/geo.txt | 1786 ++++++++++++------------ data/scene/satellites/tle/gps-ops.txt | 124 +- data/scene/satellites/tle/stations.txt | 355 +++-- 6 files changed, 1203 insertions(+), 1104 deletions(-) diff --git a/data/scene/globebrowsing.scene b/data/scene/globebrowsing.scene index 2de6f66138..1ae95684b4 100644 --- a/data/scene/globebrowsing.scene +++ b/data/scene/globebrowsing.scene @@ -95,6 +95,7 @@ return { "sun", "stars", "milkyway", + -- "satellites" } } diff --git a/data/scene/lodglobes/earth/earth.mod b/data/scene/lodglobes/earth/earth.mod index 6abf20c0d5..37a222bf58 100644 --- a/data/scene/lodglobes/earth/earth.mod +++ b/data/scene/lodglobes/earth/earth.mod @@ -13,6 +13,18 @@ return { }, }, }, + { + -- The default reference frame for Earth-orbiting satellites + Name = "EarthInertial", + Parent = "EarthBarycenter", + Transform = { + Rotation = { + Type = "SpiceRotation", + SourceFrame = "J2000", + DestinationFrame = "GALACTIC", + } + }, + }, -- EarthTrail module { Name = "EarthTrail", diff --git a/data/scene/satellites/satellites.mod b/data/scene/satellites/satellites.mod index 812c213a5c..427642b95a 100644 --- a/data/scene/satellites/satellites.mod +++ b/data/scene/satellites/satellites.mod @@ -1,4 +1,4 @@ -DOWNLOAD = true +DOWNLOAD = false function dirListing(dirname) f = io.popen('ls ' .. dirname) @@ -58,7 +58,7 @@ function getSat(title, file, lineNum) Parent = "EarthInertial", Renderable = { Type = "RenderablePlane", - Size = {3.0, 4.0}, + Size = 3e4, Origin = "Center", Body = "TLE", Billboard = true, @@ -103,31 +103,6 @@ function getSatTrail(title, file, lineNum, per, color) } end -function getTestPoint(parent, name, x, y, z) - return { - Name = name, - Parent = parent, - Renderable = { - Type = "RenderablePlane", - Size = {3.0, 4.0}, - Origin = "Center", - Body = "TLE", - Billboard = true, - Texture = "satB.png" - }, - Transform = { - Translation = { - Type = "StaticTranslation", - Position = {x, y, z}, - }, - Scale = { - Type = "StaticScale", - Scale = 1, - } - } - } -end - ------------------------------------------------------------- --Name, URL, and color scheme for each satellite group satelliteGroups = { diff --git a/data/scene/satellites/tle/geo.txt b/data/scene/satellites/tle/geo.txt index f454cdd1d4..131d1a11aa 100644 --- a/data/scene/satellites/tle/geo.txt +++ b/data/scene/satellites/tle/geo.txt @@ -1,1326 +1,1332 @@ TDRS 3 -1 19548U 88091B 17109.46103508 -.00000300 00000-0 00000-0 0 9992 -2 19548 14.4366 8.5664 0038366 314.4943 348.2278 1.00278758 91817 +1 19548U 88091B 17157.86807803 -.00000309 00000-0 00000-0 0 9997 +2 19548 14.4416 8.0727 0035139 315.3143 182.2791 1.00277792 92347 SKYNET 4C -1 20776U 90079A 17109.37676898 .00000127 00000-0 00000-0 0 9999 -2 20776 13.8022 16.7071 0004129 33.0118 326.9789 1.00271853 97371 +1 20776U 90079A 17157.24407692 .00000117 00000-0 00000-0 0 9991 +2 20776 13.8245 16.2209 0003137 48.2774 311.7180 1.00276680 97853 TDRS 5 -1 21639U 91054B 17109.79822090 .00000088 00000-0 00000-0 0 9991 -2 21639 14.3398 22.0348 0025712 348.0351 317.8695 1.00281320 94167 +1 21639U 91054B 17157.76236800 .00000078 00000-0 00000-0 0 9998 +2 21639 14.3705 21.5279 0024207 350.4285 350.3256 1.00280423 94648 TDRS 6 -1 22314U 93003B 17109.45807795 -.00000291 00000-0 00000-0 0 9993 -2 22314 13.8633 24.9549 0006813 311.7448 350.0794 1.00268039 88820 -INTELSAT 701 (IS-701) -1 22871U 93066A 17109.44518047 -.00000221 00000-0 00000-0 0 9991 -2 22871 4.0859 67.3063 0004065 323.4869 307.7041 1.00271708 85868 +1 22314U 93003B 17157.86825340 -.00000301 00000-0 00000-0 0 9999 +2 22314 13.8980 24.4494 0003763 305.2309 192.4426 1.00268641 89385 ASTRA 1D -1 23331U 94070A 17109.38111359 -.00000289 00000-0 00000-0 0 9991 -2 23331 7.4754 49.7042 0004041 326.3094 281.5525 1.00273534 82736 +1 23331U 94070A 17157.42011801 -.00000298 00000-0 00000-0 0 9990 +2 23331 7.5473 49.3635 0000659 296.5264 4.6759 1.00104533 83216 BRASILSAT B2 -1 23536U 95016A 17109.17233304 -.00000281 00000-0 00000-0 0 9993 -2 23536 7.0987 51.5887 0002352 353.2158 156.6954 1.00270982 80761 +1 23536U 95016A 17157.69941272 -.00000285 00000-0 00000-0 0 9997 +2 23536 7.1712 51.2584 0002332 20.9281 6.8855 1.00271709 81251 AMSC 1 -1 23553U 95019A 17108.82368405 -.00000116 00000-0 00000-0 0 9994 -2 23553 10.0105 40.4012 0004866 349.8728 10.0670 1.00272600 80621 +1 23553U 95019A 17156.69144898 -.00000124 00000-0 00000-0 0 9999 +2 23553 10.0698 39.9829 0003984 11.9967 347.9227 1.00271961 81090 TDRS 7 -1 23613U 95035B 17109.74146499 -.00000199 00000-0 00000-0 0 9999 -2 23613 14.9526 15.7382 0031518 358.3734 185.4077 1.00278526 79707 +1 23613U 95035B 17157.60700767 -.00000209 00000-0 00000-0 0 9993 +2 23613 14.9710 15.2291 0030718 2.0194 181.2233 1.00269402 80185 ECHOSTAR 1 -1 23754U 95073A 17109.43968494 -.00000248 00000-0 00000-0 0 9995 -2 23754 0.6886 90.3287 0002713 305.3278 253.1178 1.00272339 18868 +1 23754U 95073A 17157.49163003 -.00000246 00000-0 00000-0 0 9995 +2 23754 0.7924 90.2435 0002974 350.0571 274.5284 1.00272032 78375 INMARSAT 3-F1 -1 23839U 96020A 17109.85049412 .00000003 00000-0 00000-0 0 9996 -2 23839 3.8757 67.7545 0006005 321.1232 189.8994 1.00271328 77079 +1 23839U 96020A 17157.85035990 .00000002 00000-0 00000-0 0 9994 +2 23839 3.9663 67.5573 0005447 7.0278 191.4687 1.00272109 77250 ASTRA 1F -1 23842U 96021A 17109.86091057 .00000130 00000-0 00000-0 0 9995 -2 23842 0.0454 335.3223 0003840 58.0482 169.0272 1.00274247 18808 +1 23842U 96021A 17157.91317255 .00000135 00000-0 00000-0 0 9990 +2 23842 0.0562 314.1346 0004059 128.6019 185.7968 1.00272030 19280 MSAT M1 -1 23846U 96022A 17109.85707654 -.00000085 00000-0 00000-0 0 9996 -2 23846 7.6659 49.2344 0005400 338.8807 21.0525 1.00272402 76893 +1 23846U 96022A 17156.72760441 -.00000092 00000-0 00000-0 0 9995 +2 23846 7.7361 48.8942 0005104 25.5910 334.2903 1.00272898 77348 INMARSAT 3-F2 -1 24307U 96053A 17109.09942503 -.00000130 00000-0 00000-0 0 9994 -2 24307 2.5085 77.9756 0006616 293.5261 216.1694 1.00271468 75477 +1 24307U 96053A 17157.49688167 -.00000129 00000-0 00000-0 0 9992 +2 24307 2.6068 77.7716 0005484 340.3412 0.3761 1.00272172 75958 AMC-1 (GE-1) -1 24315U 96054A 17109.02073214 .00000052 00000-0 00000-0 0 9993 -2 24315 1.4453 85.2854 0002702 307.9108 52.4265 1.00272622 12778 +1 24315U 96054A 17156.88615406 .00000052 00000-0 00000-0 0 9994 +2 24315 1.5468 85.1195 0003085 352.0953 7.1338 1.00272423 13257 AFRICASAT-2 (MEASAT-2) -1 24653U 96063B 17109.62867817 -.00000229 00000-0 00000-0 0 9991 -2 24653 7.3977 50.1225 0006753 195.7505 336.3446 1.00271035 74912 -EUTELSAT 48A -1 24665U 96067A 17109.79528758 .00000112 00000-0 00000-0 0 9994 -2 24665 6.2644 55.4863 0005290 327.9777 159.1470 1.00272514 75142 +1 24653U 96063B 17157.54179772 -.00000234 00000-0 00000-0 0 9997 +2 24653 7.4699 49.7796 0006474 178.0401 10.3776 1.00272601 75398 INMARSAT 3-F3 -1 24674U 96070A 17109.55934831 .00000032 00000-0 00000-0 0 9996 -2 24674 3.3190 72.0293 0006158 317.0141 198.2475 1.00273297 74425 +1 24674U 96070A 17157.76269751 .00000032 00000-0 00000-0 0 9994 +2 24674 3.4130 71.8223 0005433 3.1247 273.0973 1.00274605 74907 AMC-2 (GE-2) -1 24713U 97002A 17109.43487562 -.00000215 00000-0 00000-0 0 9991 -2 24713 4.2292 66.2290 0005283 329.3197 243.8948 1.00271284 24778 +1 24713U 97002A 17157.30467139 -.00000217 00000-0 00000-0 0 9990 +2 24713 4.3187 66.0034 0005466 6.7557 206.9821 1.00273283 25250 INTELSAT 26 (IS-26) -1 24732U 97007A 17109.85049412 .00000001 00000-0 00000-0 0 9993 -2 24732 7.3728 50.4423 0005446 0.6341 167.4543 1.00272490 39195 +1 24732U 97007A 17157.92907338 -.00000004 00000-0 00000-0 0 9998 +2 24732 7.4468 50.1090 0005481 8.4977 235.6218 1.00274085 39676 GALAXY 25 (G-25) -1 24812U 97026A 17108.68375292 -.00000170 00000-0 00000-0 0 9999 -2 24812 0.0254 99.0059 0003618 294.8659 326.1560 1.00272434 72817 +1 24812U 97026A 17156.55276483 -.00000169 00000-0 00000-0 0 9998 +2 24812 0.0263 331.2615 0003489 101.7437 287.0330 1.00270031 73285 ABS-3 -1 24901U 97042A 17109.82795720 -.00000197 00000-0 00000-0 0 9994 -2 24901 4.7842 63.5836 0008401 318.8832 209.1740 1.00274176 71986 +1 24901U 97042A 17157.82985428 -.00000197 00000-0 00000-0 0 9993 +2 24901 4.8711 63.3290 0006867 355.5837 220.6103 1.00271955 72480 INTELSAT 5 (IS-5) -1 24916U 97046A 17109.18587367 -.00000146 00000-0 00000-0 0 9993 -2 24916 3.4334 71.3666 0003507 310.4218 49.5972 1.00272302 72073 +1 24916U 97046A 17157.05344110 -.00000149 00000-0 00000-0 0 9992 +2 24916 3.5265 71.1570 0003183 356.4821 3.1426 1.00272346 72550 AMC-3 (GE-3) -1 24936U 97050A 17109.43866123 -.00000267 00000-0 00000-0 0 9992 -2 24936 0.2562 91.5364 0002773 304.6917 257.4246 1.00272299 18885 +1 24936U 97050A 17157.39970170 -.00000264 00000-0 00000-0 0 9995 +2 24936 0.3597 92.2509 0003074 345.4247 249.2166 1.00272581 19365 NSS-5 -1 24957U 97053A 17109.86091057 .00000103 00000-0 00000-0 0 9999 -2 24957 3.7272 69.5661 0003844 325.1385 173.8467 1.00273806 71639 +1 24957U 97053A 17157.76527155 .00000103 00000-0 00000-0 0 9994 +2 24957 3.8209 69.3592 0003661 358.6132 153.3551 1.00271660 72116 ECHOSTAR 3 -1 25004U 97059A 17108.82026798 -.00000289 00000-0 00000-0 0 9990 -2 25004 2.0352 80.4323 0001581 345.7060 14.4861 1.00271741 71505 +1 25004U 97059A 17157.68394641 -.00000287 00000-0 00000-0 0 9991 +2 25004 2.1365 80.3085 0001609 11.9974 347.3946 1.00272496 71994 JCSAT-1B -1 25067U 97075A 17109.70661117 -.00000210 00000-0 00000-0 0 9999 -2 25067 5.4605 59.2656 0004387 299.9248 253.1557 1.00273307 73810 +1 25067U 97075A 17157.65122240 -.00000213 00000-0 00000-0 0 9998 +2 25067 5.5436 58.9740 0002484 352.1285 228.5799 1.00272836 71483 ASTRA 1G -1 25071U 97076A 17109.86091057 .00000101 00000-0 00000-0 0 9990 -2 25071 2.2044 78.5675 0003482 314.1769 176.4222 1.00270827 71015 +1 25071U 97076A 17157.76538498 .00000102 00000-0 00000-0 0 9998 +2 25071 2.3038 78.4519 0003655 354.3072 149.2269 1.00273075 71499 BRASILSAT B3 -1 25152U 98006A 17108.79091933 -.00000288 00000-0 00000-0 0 9995 -2 25152 3.9230 68.6320 0003061 319.4917 40.5071 1.00271783 9963 +1 25152U 98006A 17156.65845583 -.00000290 00000-0 00000-0 0 9994 +2 25152 4.0090 68.4273 0002828 3.0590 356.6200 1.00273130 10445 INMARSAT 3-F5 -1 25153U 98006B 17109.35905175 -.00000293 00000-0 00000-0 0 9997 -2 25153 2.4594 74.2634 0005018 316.2192 252.4390 1.00270718 70330 +1 25153U 98006B 17157.25743942 -.00000293 00000-0 00000-0 0 9991 +2 25153 2.5563 74.2286 0005365 0.4178 218.8480 1.00268538 70828 NSS-806 -1 25239U 98014A 17109.38817681 -.00000287 00000-0 00000-0 0 9991 -2 25239 0.0676 44.7475 0004496 346.2217 268.9453 1.00271303 70103 +1 25239U 98014A 17157.57688493 -.00000283 00000-0 00000-0 0 9998 +2 25239 0.0704 41.6431 0004502 32.6989 341.0322 1.00272485 14235 CHINASAT 5A (ZX 5A) -1 25354U 98033A 17109.93330977 -.00000360 00000-0 00000-0 0 9991 -2 25354 1.1195 87.4116 0002824 249.3502 333.0094 1.00271724 73697 +1 25354U 98033A 17157.64465316 -.00000358 00000-0 00000-0 0 9995 +2 25354 1.2212 87.1786 0001287 274.3863 251.2674 1.00268487 74179 THOR III -1 25358U 98035A 17109.59943801 -.00000046 00000-0 00000-0 0 9996 -2 25358 5.3275 59.4220 0002333 322.0900 37.8721 1.00273475 69301 +1 25358U 98035A 17156.46990006 -.00000052 00000-0 00000-0 0 9990 +2 25358 5.4063 59.1747 0001643 6.5467 353.2248 1.00271491 69779 INTELSAT 805 (IS-805) -1 25371U 98037A 17109.56476479 -.00000039 00000-0 00000-0 0 9994 -2 25371 0.0552 81.1481 0003018 313.2477 185.7800 1.00272687 69001 +1 25371U 98037A 17157.58191515 -.00000035 00000-0 00000-0 0 9990 +2 25371 0.0103 314.0624 0003659 127.6349 191.9694 1.00272663 69482 ASTRA 2A -1 25462U 98050A 17109.79707899 -.00000367 00000-0 00000-0 0 9992 -2 25462 0.0506 243.7651 0002414 147.3278 217.4480 1.00272536 12806 +1 25462U 98050A 17157.88659128 -.00000363 00000-0 00000-0 0 9992 +2 25462 0.0759 256.1314 0002007 177.7985 254.2102 1.00268909 13282 AFRISTAR -1 25515U 98063A 17109.79457863 .00000119 00000-0 00000-0 0 9992 -2 25515 3.1895 69.8428 0004202 324.1197 121.1622 1.00273351 67402 +1 25515U 98063A 17157.75189699 .00000119 00000-0 00000-0 0 9990 +2 25515 3.2821 69.7456 0003679 5.8761 111.3929 1.00270803 68062 JCSAT-4A -1 25630U 99006A 17109.84563219 -.00000163 00000-0 00000-0 0 9997 -2 25630 2.1756 80.2784 0001874 315.9107 198.3180 1.00271902 17060 +1 25630U 99006A 17157.82921876 -.00000331 00000-0 00000-0 0 9992 +2 25630 2.2754 80.0941 0000925 328.3183 270.6482 1.00579415 66939 SKYNET 4E -1 25639U 99009B 17108.01294515 .00000020 00000-0 00000-0 0 9998 -2 25639 10.0819 29.0659 0002679 356.8935 190.9802 1.00270583 17834 +1 25639U 99009B 17157.80109448 .00000014 00000-0 00000-0 0 9992 +2 25639 10.1255 28.6832 0002187 51.5487 109.5193 1.00270428 66956 ASIASAT 3S -1 25657U 99013A 17107.40683097 -.00000243 00000-0 00000-0 0 9990 -2 25657 2.3860 78.4929 0003383 306.5182 113.2092 1.00270446 66258 +1 25657U 99013A 17157.61576939 -.00000242 00000-0 00000-0 0 9993 +2 25657 2.4890 78.2975 0003096 342.3571 202.2375 1.00269091 66754 NIMIQ 1 -1 25740U 99027A 17109.52928144 -.00000207 00000-0 00000-0 0 9998 -2 25740 0.0148 262.6109 0006118 126.2716 282.9891 1.00271762 65567 +1 25740U 99027A 17157.39957437 -.00000203 00000-0 00000-0 0 9999 +2 25740 0.0106 324.8530 0006101 92.4300 255.0543 1.00273030 66134 ASTRA 1H -1 25785U 99033A 17109.79515799 .00000133 00000-0 00000-0 0 9998 -2 25785 3.7123 69.7226 0002879 318.8391 149.2716 1.00273831 17874 +1 25785U 99033A 17157.97189061 .00000133 00000-0 00000-0 0 9990 +2 25785 3.8060 69.5124 0002962 358.6213 220.7807 1.00270882 18351 TELKOM 1 -1 25880U 99042A 17109.82170495 -.00000353 00000-0 00000-0 0 9993 -2 25880 0.0400 110.4166 0001622 302.9461 198.6108 1.00272147 64810 +1 25880U 99042A 17157.87353010 -.00000349 00000-0 00000-0 0 9992 +2 25880 0.0476 125.4053 0001661 348.3920 204.1525 1.00275014 65320 ABS-7 -1 25894U 99046A 17109.76854753 -.00000370 00000-0 00000-0 0 9990 -2 25894 0.0100 221.8421 0002488 186.6286 192.3438 1.00269076 63594 +1 25894U 99046A 17157.75623596 -.00000367 00000-0 00000-0 0 9997 +2 25894 0.0142 11.5448 0002770 67.3211 204.8136 1.00266504 64071 ABS-6 -1 25924U 99053A 17108.98254232 -.00000127 00000-0 00000-0 0 9991 -2 25924 0.0384 81.9569 0002927 332.9838 305.0916 1.00273279 64323 +1 25924U 99053A 17156.85154310 -.00000126 00000-0 00000-0 0 9995 +2 25924 0.0384 323.6013 0002447 117.1377 279.2886 1.00273349 64811 TELSTAR 12 (ORION 2) -1 25949U 99059A 17109.52494125 -.00000070 00000-0 00000-0 0 9999 -2 25949 0.8111 88.8760 0003061 306.1548 252.5735 1.00272242 63981 +1 25949U 99059A 17157.76511053 -.00000066 00000-0 00000-0 0 9993 +2 25949 0.9151 88.8354 0003209 346.3667 346.3914 1.00272197 64461 AMC-4 (GE-4) -1 25954U 99060A 17108.61145333 -.00000281 00000-0 00000-0 0 9994 -2 25954 0.0649 79.9907 0002280 346.6647 293.3731 1.00272094 10188 +1 25954U 99060A 17156.48039619 -.00000280 00000-0 00000-0 0 9990 +2 25954 0.0442 284.7377 0002671 157.0802 278.2116 1.00270511 10661 GALAXY 11 (G-11) -1 26038U 99071A 17109.63923093 .00000129 00000-0 00000-0 0 9990 -2 26038 0.0026 2.5462 0001355 340.9142 139.5067 1.00270945 63542 +1 26038U 99071A 17157.91317255 .00000133 00000-0 00000-0 0 9996 +2 26038 0.0088 145.9068 0000374 257.2525 225.9702 1.00272198 64043 HISPASAT 1C -1 26071U 00007A 17109.29726701 -.00000220 00000-0 00000-0 0 9990 -2 26071 0.4421 88.4506 0009320 303.0136 199.4140 1.00272624 14096 +1 26071U 00007A 17157.52223545 .00000048 00000-0 00000-0 0 9994 +2 26071 0.5428 89.4925 0002589 72.6119 170.7654 0.99201181 14572 SUPERBIRD-B2 -1 26095U 00012A 17109.80052440 -.00000101 00000-0 00000-0 0 9999 -2 26095 0.2773 94.9481 0003255 289.2871 273.9855 1.00272081 62884 +1 26095U 00012A 17157.67454814 -.00000097 00000-0 00000-0 0 9992 +2 26095 0.3791 94.5663 0003041 339.8576 225.6408 1.00271692 63369 ASIASTAR -1 26107U 00016A 17109.78729904 -.00000340 00000-0 00000-0 0 9995 -2 26107 1.5529 81.9903 0004435 312.3735 202.1717 1.00272644 62385 +1 26107U 00016A 17157.86893387 -.00000337 00000-0 00000-0 0 9990 +2 26107 1.6532 81.9634 0004341 354.1170 237.1785 1.00269745 62868 EUTELSAT 16C -1 26243U 00019A 17109.10015684 .00000086 00000-0 00000-0 0 9994 -2 26243 4.1563 66.6099 0002776 317.1438 234.1657 1.00271651 62237 +1 26243U 00019A 17157.75174454 .00000086 00000-0 00000-0 0 9999 +2 26243 4.2466 66.3709 0002418 11.9963 102.0901 1.00273976 62686 EUTELSAT 80A -1 26369U 00028A 17109.84563219 -.00000149 00000-0 00000-0 0 9997 -2 26369 0.8925 84.9449 0005357 343.0840 165.0478 1.00272070 61896 +1 26369U 00028A 17157.85005696 .00000026 00000-0 00000-0 0 9994 +2 26369 0.9945 85.2151 0005047 330.7769 212.9123 1.00032976 62374 TDRS 8 -1 26388U 00034A 17109.33220883 -.00000229 00000-0 00000-0 0 9995 -2 26388 7.3965 56.3283 0005354 255.1959 104.7099 1.00265879 61633 +1 26388U 00034A 17157.19884633 -.00000238 00000-0 00000-0 0 9991 +2 26388 7.4759 55.9283 0003614 246.3223 113.4765 1.00270515 62106 ECHOSTAR 6 -1 26402U 00038A 17109.54389034 -.00000152 00000-0 00000-0 0 9998 -2 26402 4.0749 67.3876 0003545 322.0443 277.9953 1.00271890 61368 +1 26402U 00038A 17157.54494727 -.00000154 00000-0 00000-0 0 9999 +2 26402 4.1671 67.1693 0003849 10.8801 277.0633 1.00272694 61847 INTELSAT 9 (IS-9) -1 26451U 00043A 17109.47822243 -.00000276 00000-0 00000-0 0 9991 -2 26451 3.4188 71.5854 0002852 320.7192 304.5359 1.00271946 61292 +1 26451U 00043A 17157.57202302 -.00000265 00000-0 00000-0 0 9991 +2 26451 3.5142 71.3824 0003799 350.3295 358.0679 1.00365439 11073 BRASILSAT B4 -1 26469U 00046A 17108.91790864 -.00000176 00000-0 00000-0 0 9993 -2 26469 1.5387 85.3831 0003519 316.1537 44.1544 1.00272282 61413 +1 26469U 00046A 17156.78370957 -.00000176 00000-0 00000-0 0 9998 +2 26469 1.6370 85.2597 0003484 349.2296 10.0438 1.00271930 61899 NILESAT 102 -1 26470U 00046B 17109.84911682 -.00000065 00000-0 00000-0 0 9998 -2 26470 1.5586 83.8345 0004571 303.0626 119.9165 1.00272465 61099 +1 26470U 00046B 17157.54216150 -.00000064 00000-0 00000-0 0 9995 +2 26470 1.6601 83.7061 0003857 345.8061 13.7579 1.00272468 12139 ASTRA 2B -1 26494U 00054A 17109.79454052 .00000113 00000-0 00000-0 0 9993 -2 26494 2.0920 79.2060 0005340 324.6127 109.6767 1.00272153 13349 +1 26494U 00054A 17157.68035657 .00000067 00000-0 00000-0 0 9998 +2 26494 2.1910 79.0928 0002631 287.8567 148.5516 1.00093376 13823 AMC-7 (GE-7) -1 26495U 00054B 17108.79975778 .00000080 00000-0 00000-0 0 9999 -2 26495 0.0616 80.5828 0001259 259.2782 20.1388 1.00270838 60696 +1 26495U 00054B 17157.66591004 .00000083 00000-0 00000-0 0 9998 +2 26495 0.0425 70.3004 0000575 293.2921 356.4085 1.00272353 61199 NSS-11 (AAP-1) -1 26554U 00059A 17108.72090013 -.00000353 00000-0 00000-0 0 9997 -2 26554 0.0451 64.5425 0002377 356.1153 154.0906 1.00271371 7759 +1 26554U 00059A 17157.75422963 -.00000349 00000-0 00000-0 0 9992 +2 26554 0.0206 311.3634 0002835 132.7724 190.9234 1.00270805 8242 N-SAT-110 (JCSAT-110) -1 26559U 00060A 17109.92620640 -.00000360 00000-0 00000-0 0 9990 -2 26559 0.0423 72.2814 0001389 21.9396 197.4928 1.00271713 7732 +1 26559U 00060A 17157.96923611 -.00000355 00000-0 00000-0 0 9995 +2 26559 0.0511 101.0793 0001551 336.4429 277.0289 1.00272458 8215 AMC-6 (GE-6) -1 26580U 00067A 17109.32571233 -.00000281 00000-0 00000-0 0 9990 -2 26580 0.0453 59.9871 0001458 300.0146 257.8642 1.00272675 60422 +1 26580U 00067A 17157.36854942 -.00000206 00000-0 00000-0 0 9995 +2 26580 0.0431 293.8127 0000377 175.2322 198.9257 1.00016707 60911 INTELSAT 12 (IS-12) -1 26590U 00068A 17109.86091057 .00000129 00000-0 00000-0 0 9992 -2 26590 0.3603 93.4381 0001859 282.3212 187.2842 1.00271321 18173 +1 26590U 00068A 17157.75722942 .00000132 00000-0 00000-0 0 9991 +2 26590 0.4642 93.2981 0002778 18.8500 100.8023 1.00273874 18654 INTELSAT 1R (IS-1R) -1 26608U 00072A 17109.64888602 .00000123 00000-0 00000-0 0 9997 -2 26608 0.1985 89.5020 0002519 220.3285 342.2731 1.00001276 7770 +1 26608U 00072A 17157.82344980 -.00000051 00000-0 00000-0 0 9997 +2 26608 0.2962 92.8891 0001314 76.9935 193.6059 1.00082695 60592 ANIK F1 -1 26624U 00076A 17108.72312129 -.00000082 00000-0 00000-0 0 9998 -2 26624 0.0329 121.4486 0001707 320.4030 278.1724 1.00272679 9586 +1 26624U 00076A 17157.58929326 -.00000078 00000-0 00000-0 0 9994 +2 26624 0.0073 330.8252 0002626 129.0283 260.1762 1.00268795 60666 ASTRA 2D -1 26638U 00081A 17109.45244360 .00000043 00000-0 00000-0 0 9997 -2 26638 3.5382 70.2996 0001895 310.9025 49.1246 1.00269565 19363 +1 26638U 00081A 17157.31978469 .00000042 00000-0 00000-0 0 9998 +2 26638 3.6306 70.1028 0001749 3.1681 356.4654 1.00270542 19849 AMC-8 (GE-8) -1 26639U 00081B 17109.66575950 .00000096 00000-0 00000-0 0 9991 -2 26639 0.0560 75.8639 0002916 324.0708 268.6731 1.00272105 59802 +1 26639U 00081B 17157.50931538 .00000099 00000-0 00000-0 0 9998 +2 26639 0.0155 1.7174 0003007 70.9878 226.7467 1.00273654 60208 SKYNET 4F -1 26695U 01005B 17109.15862542 -.00000250 00000-0 00000-0 0 9993 -2 26695 8.8321 37.0552 0004216 348.6438 204.8395 1.00269486 59329 +1 26695U 01005B 17156.48174351 -.00000258 00000-0 00000-0 0 9993 +2 26695 8.8865 36.7282 0002854 21.9931 334.8059 1.00273913 59807 EUTELSAT 33C -1 26719U 01011A 17109.87063199 .00000147 00000-0 00000-0 0 9991 -2 26719 0.0686 12.8898 0005091 16.5455 165.2656 1.00275966 59005 +1 26719U 01011A 17157.91808519 .00000151 00000-0 00000-0 0 9997 +2 26719 0.0657 14.7416 0004077 45.4654 198.8809 1.00272805 59488 INTELSAT 10 (IS-10) -1 26766U 01019A 17109.86091057 .00000119 00000-0 00000-0 0 9993 -2 26766 1.3948 85.4036 0002391 289.9535 190.2135 1.00270276 12094 +1 26766U 01019A 17157.91226983 .00000122 00000-0 00000-0 0 9994 +2 26766 1.4974 85.2555 0002810 328.5020 217.6481 1.00273208 12572 INTELSAT 901 (IS-901) -1 26824U 01024A 17109.84336321 -.00000149 00000-0 00000-0 0 9992 -2 26824 0.0261 280.0596 0002831 114.8867 98.7920 1.00272393 58153 +1 26824U 01024A 17157.56229900 -.00000146 00000-0 00000-0 0 9995 +2 26824 0.0314 72.5832 0002605 339.3795 27.6129 1.00271212 58636 ASTRA 2C -1 26853U 01025A 17109.89842194 .00000038 00000-0 00000-0 0 9996 -2 26853 0.2757 90.5540 0003028 300.1366 201.2142 1.00271942 11518 +1 26853U 01025A 17157.85283747 .00000042 00000-0 00000-0 0 9993 +2 26853 0.3795 91.4600 0003533 340.7739 190.5107 1.00273957 11994 ARTEMIS -1 26863U 01029A 17108.74833679 -.00000369 00000-0 00000-0 0 9990 -2 26863 12.6705 33.6757 0002710 24.5441 181.1801 1.00267824 58844 +1 26863U 01029A 17157.90349637 -.00000377 00000-0 00000-0 0 9997 +2 26863 12.7220 33.1765 0002052 60.8791 249.7556 1.00272583 11082 INTELSAT 902 (IS-902) -1 26900U 01039A 17109.85049412 .00000024 00000-0 00000-0 0 9997 -2 26900 0.0207 123.4981 0002941 258.6277 194.1630 1.00271979 57225 +1 26900U 01039A 17157.85096675 .00000028 00000-0 00000-0 0 9997 +2 26900 0.0262 33.6893 0003013 55.7823 174.2913 1.00273188 57658 EUTELSAT 12 WEST B -1 26927U 01042A 17109.09950126 -.00000108 00000-0 00000-0 0 9993 -2 26927 0.0540 18.6027 0006151 4.9416 207.1825 1.00272329 56965 +1 26927U 01042A 17157.91924353 -.00000104 00000-0 00000-0 0 9996 +2 26927 0.0391 7.2969 0005667 56.4965 150.1242 1.00273270 57451 DIRECTV 4S -1 26985U 01052A 17109.59659368 -.00000121 00000-0 00000-0 0 9992 -2 26985 0.0173 196.8244 0002186 206.8425 277.8074 1.00271771 56441 +1 26985U 01052A 17157.53742727 -.00000117 00000-0 00000-0 0 9996 +2 26985 0.0233 331.2984 0002305 112.5189 263.5725 1.00269707 56932 INSAT-3C -1 27298U 02002A 17109.87176521 -.00000267 00000-0 00000-0 0 9993 -2 27298 0.5003 91.6589 0004933 233.5397 290.2973 1.00273754 55862 +1 27298U 02002A 17157.89595112 -.00000262 00000-0 00000-0 0 9994 +2 27298 0.6042 91.6269 0002103 228.4690 351.4248 1.00270722 56348 ECHOSTAR 7 -1 27378U 02006A 17109.71466358 -.00000008 00000-0 00000-0 0 9992 -2 27378 0.0548 74.8635 0001555 283.1864 348.4514 1.00270570 55514 +1 27378U 02006A 17157.50735625 -.00000005 00000-0 00000-0 0 9995 +2 27378 0.0111 338.1778 0001931 118.0619 222.7119 1.00271538 55998 INTELSAT 904 (IS-904) -1 27380U 02007A 17109.63923093 .00000127 00000-0 00000-0 0 9992 -2 27380 0.0404 99.7366 0003360 4.1943 19.2228 1.00279069 18224 +1 27380U 02007A 17157.75723111 .00000132 00000-0 00000-0 0 9993 +2 27380 0.0571 120.8959 0002880 308.6601 143.4987 1.00272687 18706 TDRS 9 -1 27389U 02011A 17109.32162528 -.00000104 00000-0 00000-0 0 9996 -2 27389 5.1301 79.8004 0020998 249.8573 341.4901 1.00273213 56894 +1 27389U 02011A 17157.72953012 -.00000105 00000-0 00000-0 0 9990 +2 27389 5.2291 79.2046 0017938 252.8065 173.8674 1.00272866 57374 JCSAT 2A -1 27399U 02015A 17109.87141731 -.00000315 00000-0 00000-0 0 9998 -2 27399 0.3548 92.8407 0000493 181.3625 23.6921 1.00270828 55072 +1 27399U 02015A 17157.82602378 -.00000311 00000-0 00000-0 0 9991 +2 27399 0.4587 92.8420 0001099 40.3381 195.6030 1.00268306 55559 ASTRA 3A -1 27400U 02015B 17108.74733222 -.00000286 00000-0 00000-0 0 9995 -2 27400 3.7011 69.0425 0002665 329.0947 30.9172 1.00268942 55178 +1 27400U 02015B 17156.61468224 -.00000288 00000-0 00000-0 0 9993 +2 27400 3.7937 68.8431 0003222 15.9485 343.7218 1.00274601 55655 INTELSAT 903 (IS-903) -1 27403U 02016A 17109.43050628 -.00000246 00000-0 00000-0 0 9994 -2 27403 0.0138 258.2337 0003167 139.5278 290.4450 1.00271614 55097 +1 27403U 02016A 17157.57202302 -.00000243 00000-0 00000-0 0 9997 +2 27403 0.0148 323.3270 0003052 105.3474 357.9124 1.00273140 12603 NSS-7 -1 27414U 02019A 17109.70994167 -.00000162 00000-0 00000-0 0 9991 -2 27414 1.7744 83.3135 0002842 313.9766 46.2757 1.00271193 55024 +1 27414U 02019A 17156.57859080 -.00000163 00000-0 00000-0 0 9993 +2 27414 1.8718 83.1197 0002435 355.0749 4.2885 1.00272047 55494 DIRECTV 5 (TEMPO 1) -1 27426U 02023A 17108.73086731 -.00000064 00000-0 00000-0 0 9991 -2 27426 0.0174 266.3382 0003496 130.1742 323.5161 1.00271176 54752 +1 27426U 02023A 17156.59985321 -.00000063 00000-0 00000-0 0 9990 +2 27426 0.0250 327.0495 0003596 106.1164 286.8736 1.00269966 55236 INTELSAT 905 (IS-905) -1 27438U 02027A 17109.84304013 -.00000192 00000-0 00000-0 0 9999 -2 27438 0.0135 247.4194 0002498 133.9617 105.7411 1.00271435 17830 +1 27438U 02027A 17157.56716090 -.00000189 00000-0 00000-0 0 9999 +2 27438 0.0156 297.3086 0003061 119.7567 17.7793 1.00272874 54890 EXPRESS-A4 -1 27441U 02029A 17109.27555153 -.00000250 00000-0 00000-0 0 9990 -2 27441 5.9632 56.8825 0002023 16.9727 18.2654 1.00267462 54427 +1 27441U 02029A 17157.83061253 -.00000254 00000-0 00000-0 0 9992 +2 27441 6.0451 56.5744 0004021 51.2124 231.9396 1.00266835 54901 GALAXY 3C (G-3C) -1 27445U 02030A 17108.68898528 -.00000159 00000-0 00000-0 0 9994 -2 27445 0.0191 284.8932 0001504 58.2763 16.8302 1.00271627 54401 +1 27445U 02030A 17155.56072771 -.00000160 00000-0 00000-0 0 9999 +2 27445 0.0146 313.9998 0002083 317.0344 88.9393 1.00268666 13494 EUTELSAT 5 WEST A -1 27460U 02035A 17109.43703532 -.00000051 00000-0 00000-0 0 9991 -2 27460 0.0485 30.4144 0005369 358.3253 331.2953 1.00271966 54081 +1 27460U 02035A 17157.30598495 -.00000048 00000-0 00000-0 0 9996 +2 27460 0.0407 354.0164 0005408 77.7738 288.2692 1.00271976 54561 N-STAR C -1 27461U 02035B 17109.75327161 -.00000314 00000-0 00000-0 0 9999 -2 27461 4.5246 65.1141 0003778 315.1078 234.9984 1.00271536 54116 -ECHOSTAR 8 -1 27501U 02039A 17109.28818986 -.00000250 00000-0 00000-0 0 9995 -2 27501 0.9663 88.6476 0003003 274.4750 231.3324 1.00272783 53720 +1 27461U 02035B 17157.67386207 -.00000317 00000-0 00000-0 0 9992 +2 27461 4.6131 64.8577 0004203 348.0196 220.9577 1.00269035 54595 EUTELSAT 36 WEST A -1 27508U 02040A 17107.52824913 -.00000253 00000-0 00000-0 0 9999 -2 27508 0.0788 36.9108 0006573 344.5112 338.6092 1.00271702 53633 +1 27508U 02040A 17157.39182088 -.00000249 00000-0 00000-0 0 9994 +2 27508 0.0671 16.5719 0004714 27.6473 315.8189 1.00274510 54130 METEOSAT-8 (MSG-1) -1 27509U 02040B 17109.89696630 .00000136 00000-0 00000-0 0 9994 -2 27509 4.7412 58.5517 0000716 163.2488 350.7710 1.00280418 53713 +1 27509U 02040B 17157.91560703 .00000134 00000-0 00000-0 0 9999 +2 27509 4.8249 58.4007 0000781 321.3004 247.0559 1.00282771 54194 INTELSAT 906 (IS-906) -1 27513U 02041A 17109.85049412 .00000006 00000-0 00000-0 0 9992 -2 27513 0.0246 261.5437 0002848 130.4092 186.4908 1.00271356 53426 +1 27513U 02041A 17157.85051046 .00000010 00000-0 00000-0 0 9996 +2 27513 0.0167 304.9366 0002695 145.8257 175.0220 1.00272562 53975 KODAMA (DRTS) -1 27516U 02042B 17108.79642807 -.00000244 00000-0 00000-0 0 9990 -2 27516 4.9371 62.3918 0003298 332.2488 189.8891 1.00269658 53490 +1 27516U 02042B 17157.92791715 -.00000245 00000-0 00000-0 0 9993 +2 27516 5.0249 62.1271 0003126 12.9916 245.2045 1.00267568 12844 KALPANA-1 (METSAT 1) -1 27525U 02043A 17109.37368610 -.00000081 00000-0 00000-0 0 9992 -2 27525 6.2545 55.6080 0013939 237.1150 122.7165 1.00273039 53516 +1 27525U 02043A 17157.24074489 -.00000087 00000-0 00000-0 0 9995 +2 27525 6.3332 55.3089 0012521 233.7089 125.9805 1.00272053 53999 HISPASAT 1D -1 27528U 02044A 17109.39356382 -.00000224 00000-0 00000-0 0 9990 -2 27528 0.0371 320.0927 0005078 59.4549 299.8001 1.00270661 53398 +1 27528U 02044A 17157.86991012 -.00000220 00000-0 00000-0 0 9996 +2 27528 0.0259 332.1791 0004154 85.5483 120.9071 1.00272546 9753 TDRS 10 -1 27566U 02055A 17109.07101571 .00000075 00000-0 00000-0 0 9990 -2 27566 4.9345 58.6619 0010010 245.5996 114.2712 1.00268874 52685 +1 27566U 02055A 17156.93899134 .00000071 00000-0 00000-0 0 9992 +2 27566 5.0166 58.4666 0007385 248.0779 111.5909 1.00270185 53166 NSS-6 -1 27603U 02057A 17109.87176521 -.00000279 00000-0 00000-0 0 9996 -2 27603 0.0413 67.8725 0001723 296.7346 252.3915 1.00273439 52556 +1 27603U 02057A 17156.77498163 -.00000277 00000-0 00000-0 0 9994 +2 27603 0.0473 102.4211 0001387 313.2719 212.6914 1.00271799 53021 NIMIQ 2 -1 27632U 02062A 17109.64448081 -.00000115 00000-0 00000-0 0 9991 -2 27632 1.8732 82.2184 0003990 251.5302 108.6754 0.99546813 52336 +1 27632U 02062A 17156.69497149 -.00000288 00000-0 00000-0 0 9998 +2 27632 1.9736 82.0863 0001443 250.4056 108.9664 1.00268898 11131 INTELSAT 907 (IS-907) -1 27683U 03007A 17109.49926753 -.00000210 00000-0 00000-0 0 9993 -2 27683 0.0063 240.7075 0003065 158.7584 320.5619 1.00271958 51896 +1 27683U 03007A 17157.36824828 -.00000207 00000-0 00000-0 0 9998 +2 27683 0.0167 299.5781 0002888 136.1041 284.3503 1.00272710 52377 GALAXY 12 (G-12) -1 27715U 03013B 17109.66402826 .00000050 00000-0 00000-0 0 9996 -2 27715 0.0478 86.1011 0001993 315.8430 276.0639 1.00273936 51455 +1 27715U 03013B 17157.47798205 .00000054 00000-0 00000-0 0 9991 +2 27715 0.0187 320.3459 0001910 124.4962 213.2990 1.00273091 19071 ASIASAT 4 -1 27718U 03014A 17109.27571116 -.00000368 00000-0 00000-0 0 9999 -2 27718 0.0556 98.2673 0000790 212.2328 118.4097 1.00269480 51370 +1 27718U 03014A 17154.76078257 -.00000373 00000-0 00000-0 0 9997 +2 27718 0.0554 107.4671 0000332 120.2394 60.6607 1.00269696 51826 HELLAS-SAT 2 -1 27811U 03020A 17109.79503602 .00000144 00000-0 00000-0 0 9993 -2 27811 0.0125 212.9725 0003974 178.8493 141.4613 1.00273626 9310 +1 27811U 03020A 17157.95948205 .00000148 00000-0 00000-0 0 9990 +2 27811 0.0173 15.2568 0004017 55.5793 209.0975 1.00271046 9793 AMC-9 (GE-12) -1 27820U 03024A 17109.46737024 -.00000224 00000-0 00000-0 0 9998 -2 27820 0.0218 293.7748 0002764 83.8388 275.3891 1.00271813 50833 +1 27820U 03024A 17157.36854942 -.00000221 00000-0 00000-0 0 9996 +2 27820 0.0149 345.1473 0002670 86.0434 233.4626 1.00271443 51310 THURAYA-2 -1 27825U 03026A 17109.79517323 .00000126 00000-0 00000-0 0 9999 -2 27825 4.8685 28.9069 0005038 348.5579 160.8904 1.00275241 50801 +1 27825U 03026A 17157.77479958 .00000124 00000-0 00000-0 0 9999 +2 27825 4.9108 29.1082 0004667 32.3379 156.8443 1.00274495 51289 OPTUS C1 -1 27831U 03028B 17109.78035437 -.00000155 00000-0 00000-0 0 9991 -2 27831 0.0507 133.4426 0002595 268.8651 242.7021 1.00272565 19517 +1 27831U 03028B 17157.64800564 -.00000152 00000-0 00000-0 0 9997 +2 27831 0.0147 142.7331 0003679 312.2794 189.5222 1.00269917 51256 ECHOSTAR 12 (RAINBOW 1) -1 27852U 03033A 17109.46075083 -.00000290 00000-0 00000-0 0 9996 -2 27852 0.0382 63.8611 0001223 318.1922 290.3816 1.00270465 50423 +1 27852U 03033A 17157.85925034 -.00000286 00000-0 00000-0 0 9997 +2 27852 0.0153 320.1155 0002459 153.4265 30.0486 1.00271393 50921 GALAXY 23 (G-23) -1 27854U 03034A 17109.64054391 .00000005 00000-0 00000-0 0 9991 -2 27854 0.0150 251.0578 0002912 134.7122 291.7534 1.00272107 50192 +1 27854U 03034A 17157.55834939 .00000009 00000-0 00000-0 0 9992 +2 27854 0.0078 50.3401 0002591 20.5670 264.2678 1.00266961 55470 EUTELSAT 33A -1 27948U 03043A 17109.79483020 .00000146 00000-0 00000-0 0 9992 -2 27948 2.2541 78.4922 0001717 242.0173 204.6018 1.00275799 11938 +1 27948U 03043A 17157.91808519 .00000148 00000-0 00000-0 0 9995 +2 27948 2.3530 78.3719 0002192 246.4604 292.0221 1.00272390 12410 GALAXY 13 (HORIZONS-1) -1 27954U 03044A 17109.48439302 .00000040 00000-0 00000-0 0 9993 -2 27954 0.0453 97.4231 0001056 288.3798 229.3282 1.00271259 49619 +1 27954U 03044A 17157.49490420 .00000044 00000-0 00000-0 0 9999 +2 27954 0.0095 68.2889 0001794 34.0552 203.9008 1.00269771 50093 ZHONGXING-20 -1 28082U 03052A 17109.86986843 -.00000331 00000-0 00000-0 0 9998 -2 28082 3.3906 71.5956 0004111 304.0462 248.9623 1.00274401 49211 +1 28082U 03052A 17157.86442207 -.00000331 00000-0 00000-0 0 9992 +2 28082 3.4896 71.3775 0002820 340.2019 258.3647 1.00271326 49698 YAMAL 202 -1 28089U 03053A 17109.86091057 .00000112 00000-0 00000-0 0 9996 -2 28089 0.0554 83.4076 0003529 305.2504 178.3485 1.00271369 49131 +1 28089U 03053A 17156.89999981 .00000113 00000-0 00000-0 0 9995 +2 28089 0.0645 108.1958 0003615 299.6727 219.6142 1.00274795 49602 EXPRESS-AM22 (SESAT 2) -1 28134U 03060A 17109.83425608 -.00000145 00000-0 00000-0 0 9992 -2 28134 0.3278 90.4268 0000687 5.5471 132.5702 1.00271889 48730 +1 28134U 03060A 17157.82012833 -.00000142 00000-0 00000-0 0 9993 +2 28134 0.4310 91.3126 0000677 12.5441 166.9011 1.00271968 49211 AMC-10 (GE-10) -1 28154U 04003A 17109.46557576 .00000080 00000-0 00000-0 0 9998 -2 28154 0.0231 283.7817 0002941 134.7830 181.7953 1.00273228 48388 +1 28154U 04003A 17157.68986111 .00000083 00000-0 00000-0 0 9999 +2 28154 0.0102 324.5364 0002911 113.5854 290.5135 1.00274282 48870 ABS-4 (MOBISAT-1) -1 28184U 04007A 17108.79562766 .00000033 00000-0 00000-0 0 9995 -2 28184 0.0252 265.3286 0001924 120.7856 168.3679 1.00270738 18783 +1 28184U 04007A 17157.85283747 .00000037 00000-0 00000-0 0 9999 +2 28184 0.0179 315.6427 0001657 131.2375 176.5646 1.00271252 19275 EUTELSAT 7A -1 28187U 04008A 17109.83313484 .00000040 00000-0 00000-0 0 9994 -2 28187 0.0698 23.2349 0003112 28.0538 103.7450 1.00272687 47843 +1 28187U 04008A 17157.64713779 .00000044 00000-0 00000-0 0 9991 +2 28187 0.0661 14.8212 0004472 83.1599 37.2438 1.00275037 48320 DIRECTV 7S -1 28238U 04016A 17109.70783875 -.00000007 00000-0 00000-0 0 9995 -2 28238 0.0349 29.0632 0003005 9.5876 305.0945 1.00272397 47521 +1 28238U 04016A 17157.55819626 -.00000004 00000-0 00000-0 0 9992 +2 28238 0.0157 340.2692 0003146 93.8117 262.9614 1.00273727 47995 AMC-11 (GE-11) -1 28252U 04017A 17109.46930970 .00000061 00000-0 00000-0 0 9994 -2 28252 0.0398 48.4822 0002797 354.9918 202.2254 1.00272474 47154 +1 28252U 04017A 17157.57680061 .00000064 00000-0 00000-0 0 9995 +2 28252 0.0180 353.1619 0002945 81.1891 257.4684 1.00274073 47636 INTELSAT 10-02 -1 28358U 04022A 17109.84357525 -.00000019 00000-0 00000-0 0 9992 -2 28358 0.0110 181.1909 0000091 89.7002 239.9407 1.00271548 47086 +1 28358U 04022A 17157.83869049 -.00000015 00000-0 00000-0 0 9999 +2 28358 0.0120 356.1950 0000295 58.0826 142.0919 1.00269757 47582 APSTAR 5 (TELSTAR 18) -1 28364U 04024A 17108.67767421 -.00000303 00000-0 00000-0 0 9997 -2 28364 0.0571 92.2449 0002968 301.6073 195.0706 1.00270267 47063 +1 28364U 04024A 17157.83092135 -.00000298 00000-0 00000-0 0 9995 +2 28364 0.0030 6.5684 0003143 80.0270 245.9630 1.00271874 47487 ANIK F2 -1 28378U 04027A 17109.75490392 -.00000058 00000-0 00000-0 0 9992 -2 28378 0.0327 10.2643 0000174 94.3803 264.0852 1.00272731 46816 +1 28378U 04027A 17157.51971437 -.00000055 00000-0 00000-0 0 9990 +2 28378 0.0287 34.3513 0000292 66.2633 230.5249 1.00273695 47284 AMAZONAS 1 -1 28393U 04031A 17109.09889142 -.00000253 00000-0 00000-0 0 9993 -2 28393 1.6288 83.9426 0004611 316.5274 166.3344 1.00270901 46528 +1 28393U 04031A 17157.57202302 -.00000251 00000-0 00000-0 0 9994 +2 28393 1.7315 83.7697 0004323 359.8041 341.2300 1.00271596 47001 AMC-15 -1 28446U 04041A 17109.53001451 -.00000096 00000-0 00000-0 0 9996 -2 28446 0.0163 82.5996 0002548 331.7430 239.2279 1.00270612 45849 +1 28446U 04041A 17157.35743792 -.00000094 00000-0 00000-0 0 9998 +2 28446 0.0306 43.6946 0002577 24.0323 210.8459 1.00270854 46323 AMC-16 -1 28472U 04048A 17109.28730701 -.00000214 00000-0 00000-0 0 9993 -2 28472 0.0471 59.9322 0002824 346.8967 179.1812 1.00272778 45211 +1 28472U 04048A 17157.39961249 -.00000211 00000-0 00000-0 0 9998 +2 28472 0.0300 46.8859 0002736 27.0149 239.9535 1.00272492 45742 NSS-10 (AMC-12) -1 28526U 05003A 17108.32271427 -.00000258 00000-0 00000-0 0 9992 -2 28526 0.0290 15.7760 0003009 25.7409 243.8406 1.00272548 44757 +1 28526U 05003A 17157.57202302 -.00000255 00000-0 00000-0 0 9996 +2 28526 0.0171 331.5816 0002986 103.2954 348.7724 1.00271963 20118 XTAR-EUR -1 28542U 05005A 17108.34551944 .00000143 00000-0 00000-0 0 9991 -2 28542 0.0391 71.8345 0003282 317.8171 330.3713 1.00276151 44626 +1 28542U 05005A 17156.21444778 .00000143 00000-0 00000-0 0 9996 +2 28542 0.0436 105.4196 0002521 319.0050 295.6000 1.00270784 45101 XM-3 (RHYTHM) -1 28626U 05008A 17109.28605345 -.00000213 00000-0 00000-0 0 9995 -2 28626 0.0166 47.5910 0000189 341.0688 196.7839 1.00268725 9095 +1 28626U 05008A 17157.39961249 -.00000210 00000-0 00000-0 0 9995 +2 28626 0.0068 215.5294 0000192 171.9039 286.3071 1.00266636 44993 INMARSAT 4-F1 -1 28628U 05009A 17109.05582249 -.00000267 00000-0 00000-0 0 9999 -2 28628 2.8685 11.1659 0003296 29.9529 329.8263 1.00272220 44126 +1 28628U 05009A 17156.92660775 -.00000269 00000-0 00000-0 0 9990 +2 28628 2.8757 11.8827 0003527 65.6031 294.1247 1.00272126 44606 APSTAR 6 -1 28638U 05012A 17109.93487365 -.00000327 00000-0 00000-0 0 9991 -2 28638 0.0499 68.4318 0002249 335.2848 275.0303 1.00269643 68860 +1 28638U 05012A 17157.83122773 -.00000322 00000-0 00000-0 0 9997 +2 28638 0.0306 58.4940 0002057 17.2640 252.9201 1.00272736 69343 SPACEWAY 1 -1 28644U 05015A 17109.62982047 -.00000110 00000-0 00000-0 0 9994 -2 28644 0.0049 159.3887 0000185 275.0996 257.2391 1.00272361 43965 +1 28644U 05015A 17157.53283144 -.00000106 00000-0 00000-0 0 9994 +2 28644 0.0476 154.0547 0000531 193.5024 356.4599 1.00266303 44440 DIRECTV 8 -1 28659U 05019A 17108.70523236 -.00000123 00000-0 00000-0 0 9997 -2 28659 0.0129 280.9460 0003657 119.7236 319.3625 1.00272462 43597 +1 28659U 05019A 17156.57419940 -.00000123 00000-0 00000-0 0 9991 +2 28659 0.0097 10.0881 0003284 61.1747 288.7721 1.00272405 44070 GALAXY 28 (G-28) -1 28702U 05022A 17109.42243941 -.00000193 00000-0 00000-0 0 9999 -2 28702 0.0122 204.0909 0002026 199.7705 226.9152 1.00268822 18564 +1 28702U 05022A 17156.36348095 -.00000193 00000-0 00000-0 0 9990 +2 28702 0.0123 38.9577 0002187 345.0013 271.8678 1.00272171 43748 EXPRESS-AM3 -1 28707U 05023A 17109.62966170 -.00000330 00000-0 00000-0 0 9996 -2 28707 0.0092 329.2575 0001659 83.3644 124.9591 1.00270309 43302 +1 28707U 05023A 17157.96047541 -.00000326 00000-0 00000-0 0 9993 +2 28707 0.0067 246.6538 0000998 196.3073 261.3603 1.00271254 43783 THAICOM 4 -1 28786U 05028A 17109.59563442 -.00000371 00000-0 00000-0 0 9994 -2 28786 0.0118 230.3243 0002092 165.6598 145.8354 1.00268640 18739 +1 28786U 05028A 17157.76759243 -.00000367 00000-0 00000-0 0 9997 +2 28786 0.0135 354.6117 0002419 79.0491 217.5158 1.00271590 43264 GALAXY 14 (G-14) -1 28790U 05030A 17109.48875712 .00000028 00000-0 00000-0 0 9994 -2 28790 0.0384 74.1639 0002401 315.5495 229.0270 1.00273948 42756 +1 28790U 05030A 17157.55541164 .00000032 00000-0 00000-0 0 9991 +2 28790 0.0190 327.0194 0002682 102.3421 260.7443 1.00273905 43230 ANIK F1R -1 28868U 05036A 17109.52684413 -.00000082 00000-0 00000-0 0 9998 -2 28868 0.0386 63.6774 0003129 327.7708 258.7292 1.00272492 42607 +1 28868U 05036A 17157.61521618 -.00000079 00000-0 00000-0 0 9994 +2 28868 0.0535 80.6010 0003176 336.5033 312.2768 1.00272802 13445 GALAXY 15 (G-15) -1 28884U 05041A 17109.46769616 .00000071 00000-0 00000-0 0 9991 -2 28884 0.0384 87.3342 0001713 311.3453 204.4300 1.00273785 42200 +1 28884U 05041A 17157.62737733 .00000074 00000-0 00000-0 0 9990 +2 28884 0.0095 323.7164 0001455 110.0613 274.2944 1.00274202 42555 SYRACUSE 3A -1 28885U 05041B 17109.86091057 .00000120 00000-0 00000-0 0 9998 -2 28885 0.0222 285.3830 0002879 108.2610 171.4361 1.00275192 42211 +1 28885U 05041B 17157.91226983 .00000125 00000-0 00000-0 0 9990 +2 28885 0.0123 47.9590 0003052 34.9277 188.0114 1.00271206 42698 INMARSAT 4-F2 -1 28899U 05044A 17109.27600366 .00000004 00000-0 00000-0 0 9991 -2 28899 2.5627 11.0679 0002772 32.6957 327.0524 1.00270578 41978 +1 28899U 05044A 17157.14672115 .00000004 00000-0 00000-0 0 9991 +2 28899 2.5707 11.7812 0002835 68.5546 291.1256 1.00271873 42451 TELKOM 2 -1 28902U 05046A 17109.76854753 -.00000371 00000-0 00000-0 0 9991 -2 28902 0.0276 142.9573 0000776 277.6646 182.0405 1.00269663 41690 +1 28902U 05046A 17157.64800564 -.00000143 00000-0 00000-0 0 9999 +2 28902 0.0827 108.2191 0002043 326.9180 210.4049 1.00271196 42171 SPACEWAY 2 -1 28903U 05046B 17109.53975024 -.00000134 00000-0 00000-0 0 9999 -2 28903 0.0333 75.6302 0000437 32.3955 195.0431 1.00271564 41944 +1 28903U 05046B 17157.53940951 -.00000132 00000-0 00000-0 0 9991 +2 28903 0.0462 140.7429 0000754 280.0859 289.4343 1.00279699 42429 INSAT-4A -1 28911U 05049A 17109.19304538 -.00000173 00000-0 00000-0 0 9992 -2 28911 0.0896 93.9505 0003716 237.1802 28.8541 1.00271991 12176 +1 28911U 05049A 17157.06201003 -.00000171 00000-0 00000-0 0 9992 +2 28911 0.0380 105.4216 0001734 235.8286 18.7432 1.00272070 42024 METEOSAT-9 (MSG-2) -1 28912U 05049B 17109.19149598 .00000055 00000-0 00000-0 0 9994 -2 28912 2.0885 70.7642 0000522 79.5257 135.4674 1.00268082 41526 +1 28912U 05049B 17157.96248359 .00000057 00000-0 00000-0 0 9999 +2 28912 2.1848 71.0339 0000745 329.3322 211.1678 1.00265631 41971 EUTELSAT 172A (GE-23) -1 28924U 05052A 17109.64414611 -.00000014 00000-0 00000-0 0 9998 -2 28924 0.0706 355.4632 0005866 37.6286 218.7303 1.00273847 18808 +1 28924U 05052A 17157.82344980 -.00000010 00000-0 00000-0 0 9998 +2 28924 0.0640 4.2410 0006025 69.7644 289.8344 1.00272333 19286 ECHOSTAR 10 -1 28935U 06003A 17109.52284194 -.00000064 00000-0 00000-0 0 9990 -2 28935 0.0546 73.5972 0001864 341.9720 230.2926 1.00273462 40937 +1 28935U 06003A 17157.52223405 -.00000060 00000-0 00000-0 0 9997 +2 28935 0.0128 334.6690 0001561 122.9496 235.2838 1.00272215 41441 HIMAWARI-7 (MTSAT-2) -1 28937U 06004A 17109.87357476 -.00000251 00000-0 00000-0 0 9993 -2 28937 0.0536 94.0981 0003570 289.3209 284.2189 1.00269818 40939 +1 28937U 06004A 17157.83045837 -.00000248 00000-0 00000-0 0 9993 +2 28937 0.0441 108.7166 0003613 332.5543 258.1068 1.00268894 41415 SPAINSAT -1 28945U 06007A 17108.50890032 -.00000224 00000-0 00000-0 0 9994 -2 28945 0.0281 235.8195 0002521 155.2004 328.9996 1.00271702 40674 +1 28945U 06007A 17157.37511961 -.00000221 00000-0 00000-0 0 9991 +2 28945 0.0293 238.9210 0003133 211.3907 269.7246 1.00272988 41167 EUTELSAT HOT BIRD 13E -1 28946U 06007B 17109.38717225 .00000079 00000-0 00000-0 0 9991 -2 28946 0.0589 259.6256 0003248 180.9284 279.4880 1.00272688 40755 +1 28946U 06007B 17157.25603244 .00000082 00000-0 00000-0 0 9999 +2 28946 0.0016 224.9414 0004732 246.4182 248.6911 1.00274880 41238 JCSAT-5A -1 29045U 06010A 17109.79755922 -.00000336 00000-0 00000-0 0 9994 -2 29045 0.0132 265.3814 0002096 155.2969 206.5745 1.00271513 40239 +1 29045U 06010A 17157.64299369 -.00000333 00000-0 00000-0 0 9996 +2 29045 0.0169 331.4853 0001801 104.7579 182.5102 1.00271734 40714 ASTRA 1KR -1 29055U 06012A 17109.87549389 .00000112 00000-0 00000-0 0 9995 -2 29055 0.0648 276.0152 0000832 45.1147 221.4152 1.00274823 12185 +1 29055U 06012A 17157.85991851 .00000115 00000-0 00000-0 0 9994 +2 29055 0.0465 282.5731 0001283 185.5859 116.0417 1.00270907 12662 GOES 13 -1 29155U 06018A 17108.63348614 -.00000258 00000-0 00000-0 0 9995 -2 29155 0.3062 272.8347 0005138 151.4577 295.7654 1.00279229 9835 +1 29155U 06018A 17157.49990045 -.00000253 00000-0 00000-0 0 9999 +2 29155 0.1971 273.2915 0005903 163.6851 283.0905 1.00263260 10321 EUTELSAT 113 WEST A -1 29162U 06020A 17108.73887038 -.00000045 00000-0 00000-0 0 9999 -2 29162 0.0192 277.4806 0002853 112.3865 330.1540 1.00272071 39910 +1 29162U 06020A 17156.60780462 -.00000044 00000-0 00000-0 0 9990 +2 29162 0.0229 128.7916 0002707 304.2820 286.9552 1.00271454 40391 THAICOM 5 -1 29163U 06020B 17109.91575226 -.00000130 00000-0 00000-0 0 9999 -2 29163 0.0113 266.6952 0003840 104.2002 245.4828 1.00272591 39954 +1 29163U 06020B 17157.93664823 -.00000125 00000-0 00000-0 0 9990 +2 29163 0.0397 277.1662 0002921 155.9102 238.1599 1.00271082 40439 GALAXY 16 (G-16) -1 29236U 06023A 17109.53974882 -.00000135 00000-0 00000-0 0 9997 -2 29236 0.0088 209.0266 0002818 192.6949 261.4131 1.00272563 39718 +1 29236U 06023A 17157.39925420 -.00000132 00000-0 00000-0 0 9995 +2 29236 0.0415 123.1487 0002843 321.6184 214.9466 1.00272656 40197 EUTELSAT HOT BIRD 13B -1 29270U 06032A 17109.87549389 .00000078 00000-0 00000-0 0 9997 -2 29270 0.0863 324.0839 0005219 54.6606 157.5753 1.00272770 13780 +1 29270U 06032A 17157.67673214 .00000083 00000-0 00000-0 0 9999 +2 29270 0.0640 13.7956 0004892 38.2230 99.8869 1.00275274 14264 JCSAT-3A -1 29272U 06033A 17109.79746014 -.00000354 00000-0 00000-0 0 9993 -2 29272 0.0178 233.9351 0001863 185.1999 204.0397 1.00268201 14196 +1 29272U 06033A 17157.90924543 -.00000349 00000-0 00000-0 0 9998 +2 29272 0.0158 340.2173 0002301 69.5341 301.0817 1.00271640 14671 SYRACUSE 3B -1 29273U 06033B 17109.85243352 -.00000052 00000-0 00000-0 0 9993 -2 29273 0.0016 117.1534 0004854 262.8406 129.8176 1.00272026 39177 +1 29273U 06033B 17157.79424205 -.00000048 00000-0 00000-0 0 9992 +2 29273 0.0116 334.5227 0004493 82.6200 118.9653 1.00273722 39657 KOREASAT 5 (MUGUNGWHA 5) -1 29349U 06034A 17109.79706375 -.00000367 00000-0 00000-0 0 9999 -2 29349 0.0171 262.2876 0001197 206.2811 139.5217 1.00270677 7778 +1 29349U 06034A 17157.88670208 -.00000362 00000-0 00000-0 0 9992 +2 29349 0.0198 52.2408 0001592 61.2599 214.2556 1.00271627 8253 ZHONGXING-22A -1 29398U 06038A 17109.94158009 -.00000324 00000-0 00000-0 0 9992 -2 29398 5.6881 58.1086 0002029 261.7195 329.1449 1.00272905 38866 +1 29398U 06038A 17156.94851480 -.00000327 00000-0 00000-0 0 9990 +2 29398 5.7706 57.8311 0001241 149.2261 130.6660 1.00268293 39337 DIRECTV 9S -1 29494U 06043A 17109.59659368 -.00000122 00000-0 00000-0 0 9996 -2 29494 0.0235 133.4313 0003478 263.5751 284.5543 1.00272093 38555 +1 29494U 06043A 17157.53742660 -.00000118 00000-0 00000-0 0 9996 +2 29494 0.0144 345.2743 0003696 90.6367 271.5991 1.00270006 18337 OPTUS D1 -1 29495U 06043B 17109.78035437 -.00000119 00000-0 00000-0 0 9999 -2 29495 0.0389 65.8650 0003495 327.4598 255.6741 1.00272455 38579 +1 29495U 06043B 17157.76302275 -.00000115 00000-0 00000-0 0 9993 +2 29495 0.0171 16.4417 0003644 55.5225 258.0832 1.00272516 39053 XM-4 (BLUES) -1 29520U 06049A 17109.73126757 -.00000031 00000-0 00000-0 0 9998 -2 29520 0.0175 50.0377 0000165 41.1512 264.8500 1.00272409 17931 +1 29520U 06049A 17157.57626399 -.00000028 00000-0 00000-0 0 9996 +2 29520 0.0294 135.2494 0000467 280.6183 291.5103 1.00277015 38924 BADR-4 -1 29526U 06051A 17109.10043128 .00000136 00000-0 00000-0 0 9993 -2 29526 0.0617 320.4353 0005022 40.9358 268.1979 1.00276660 38335 +1 29526U 06051A 17157.97290778 .00000140 00000-0 00000-0 0 9991 +2 29526 0.0475 335.9603 0003641 58.1927 237.6604 1.00269975 18249 FENGYUN 2D -1 29640U 06053A 17109.93315478 -.00000365 00000-0 10000-3 0 9992 -2 29640 4.3387 64.6675 0004916 340.2554 262.8725 1.00281669 38012 +1 29640U 06053A 17157.72187311 -.00000366 00000-0 10000-3 0 9996 +2 29640 4.4356 64.4357 0005259 316.6810 257.5736 1.00280861 38495 WILDBLUE-1 -1 29643U 06054A 17109.74856689 -.00000057 00000-0 00000-0 0 9993 -2 29643 0.0444 100.1325 0001842 303.9370 322.2794 1.00272752 38006 +1 29643U 06054A 17157.51971192 -.00000054 00000-0 00000-0 0 9995 +2 29643 0.0427 124.0490 0001177 301.0075 265.9807 1.00271293 38475 AMC-18 -1 29644U 06054B 17109.53001424 -.00000097 00000-0 00000-0 0 9994 -2 29644 0.0146 49.5256 0002597 345.3404 258.8092 1.00271942 38006 +1 29644U 06054B 17156.34682649 -.00000097 00000-0 00000-0 0 9999 +2 29644 0.0212 48.5605 0002690 21.6517 203.6505 1.00271544 38476 MEASAT-3 -1 29648U 06056A 17109.82485502 -.00000250 00000-0 00000-0 0 9996 -2 29648 0.0479 125.6704 0002875 328.1086 142.7705 1.00269997 16912 +1 29648U 06056A 17157.77607686 -.00000246 00000-0 00000-0 0 9997 +2 29648 0.0544 134.4165 0003237 323.0236 168.8382 1.00272457 17408 INSAT-4B -1 30793U 07007A 17109.87176521 -.00000266 00000-0 00000-0 0 9996 -2 30793 0.1032 95.6431 0006761 328.5772 191.2662 1.00270562 8662 +1 30793U 07007A 17157.78369844 -.00000262 00000-0 00000-0 0 9997 +2 30793 0.0520 278.1197 0008119 159.1606 193.7065 1.00270878 9141 SKYNET 5A -1 30794U 07007B 17109.87176521 -.00000279 00000-0 00000-0 0 9991 -2 30794 0.0701 1.1274 0003350 33.5560 222.4814 1.00269254 37159 +1 30794U 07007B 17157.86214683 -.00000276 00000-0 00000-0 0 9992 +2 30794 0.0669 9.2549 0003424 69.8600 221.9497 1.00271597 37586 ANIK F3 -1 31102U 07009A 17109.92227799 -.00000009 00000-0 00000-0 0 9998 -2 31102 0.0160 222.4812 0002235 174.9197 24.1145 1.00269555 13012 +1 31102U 07009A 17157.55819626 -.00000006 00000-0 00000-0 0 9993 +2 31102 0.0221 62.7142 0002439 5.1715 269.5064 1.00273137 13496 ASTRA 1L -1 31306U 07016A 17109.87549389 .00000112 00000-0 00000-0 0 9992 -2 31306 0.0802 300.7492 0003627 55.5715 186.2058 1.00274256 11533 +1 31306U 07016A 17157.85991851 .00000115 00000-0 00000-0 0 9991 +2 31306 0.0620 310.2522 0001942 67.5327 206.4174 1.00270848 36973 GALAXY 17 (G-17) -1 31307U 07016B 17109.53587587 -.00000182 00000-0 00000-0 0 9996 -2 31307 0.0392 33.9344 0003513 8.9980 266.8033 1.00270261 36525 +1 31307U 07016B 17157.75267660 -.00000178 00000-0 00000-0 0 9995 +2 31307 0.0199 19.2854 0003333 52.0696 3.9542 1.00271618 36899 ZHONGXING-6B -1 31800U 07031A 17109.79713234 -.00000370 00000-0 00000-0 0 9998 -2 31800 0.0131 249.1006 0002398 139.7626 221.7240 1.00270095 35894 +1 31800U 07031A 17157.60290969 -.00000367 00000-0 00000-0 0 9992 +2 31800 0.0230 52.6434 0002613 19.1105 156.0270 1.00270162 36405 DIRECTV 10 -1 31862U 07032A 17108.71065751 -.00000111 00000-0 00000-0 0 9995 -2 31862 0.0365 34.4633 0000151 39.8688 285.6743 1.00271941 12089 +1 31862U 07032A 17156.57961764 -.00000110 00000-0 00000-0 0 9990 +2 31862 0.0171 229.8134 0000365 192.5210 297.6683 1.00272418 12553 SPACEWAY 3 -1 32018U 07036A 17109.40753358 -.00000160 00000-0 00000-0 0 9991 -2 32018 0.0098 99.7378 0000110 334.5356 185.1857 1.00272613 35574 +1 32018U 07036A 17157.39936093 -.00000157 00000-0 00000-0 0 9997 +2 32018 0.0105 85.9695 0000327 288.7294 289.1154 1.00273225 36052 BSAT-3A -1 32019U 07036B 17109.11866778 -.00000359 00000-0 00000-0 0 9991 -2 32019 0.0456 154.5305 0000478 83.1873 122.2826 1.00272208 16950 +1 32019U 07036B 17156.98760919 -.00000357 00000-0 00000-0 0 9996 +2 32019 0.0533 228.9851 0001387 295.7273 195.2915 1.00273708 17432 INSAT-4CR -1 32050U 07037A 17109.86091057 .00000117 00000-0 00000-0 0 9990 -2 32050 0.0660 93.9132 0003220 286.0159 185.9821 1.00270887 17857 +1 32050U 07037A 17157.91226983 .00000121 00000-0 00000-0 0 9992 +2 32050 0.0621 273.6058 0003315 164.6304 193.5538 1.00268840 18336 OPTUS D2 -1 32252U 07044A 17109.87340333 -.00000192 00000-0 00000-0 0 9991 -2 32252 0.0147 192.5936 0003662 203.3350 278.6486 1.00270752 34895 +1 32252U 07044A 17157.83029597 -.00000187 00000-0 00000-0 0 9990 +2 32252 0.0170 311.7706 0003786 123.2105 271.3583 1.00272406 35376 INTELSAT 11 (IS-11) -1 32253U 07044B 17109.47116498 -.00000277 00000-0 00000-0 0 9995 -2 32253 0.0142 198.5042 0001905 211.1170 284.7663 1.00271114 34977 +1 32253U 07044B 17157.42131497 -.00000274 00000-0 00000-0 0 9996 +2 32253 0.0215 79.4921 0001089 18.7092 265.5013 1.00269309 35462 STAR ONE C1 -1 32293U 07056A 17108.60588995 -.00000285 00000-0 00000-0 0 9990 -2 32293 0.0361 68.8879 0002906 338.6367 312.5045 1.00271618 18230 +1 32293U 07056A 17156.47486952 -.00000284 00000-0 00000-0 0 9997 +2 32293 0.0179 339.0598 0002792 94.1440 286.8268 1.00271095 35033 SKYNET 5B -1 32294U 07056B 17109.87063199 .00000134 00000-0 00000-0 0 9997 -2 32294 0.0726 346.6530 0003739 49.7473 150.3091 1.00276152 34673 +1 32294U 07056B 17157.78452358 .00000137 00000-0 00000-0 0 9992 +2 32294 0.0666 355.6274 0003416 80.4168 126.8368 1.00271896 35155 ASTRA 4A (SIRIUS 4) -1 32299U 07057A 17109.95935472 .00000024 00000-0 00000-0 0 9992 -2 32299 0.0618 74.8891 0002823 318.7908 164.7363 1.00272121 18162 +1 32299U 07057A 17157.79354764 .00000028 00000-0 00000-0 0 9990 +2 32299 0.0158 4.3499 0003071 61.6161 119.9002 1.00271361 18644 HORIZONS-2 -1 32388U 07063B 17109.84563219 -.00000191 00000-0 00000-0 0 9998 -2 32388 0.0139 286.0592 0003273 110.1844 201.1581 1.00270534 34316 +1 32388U 07063B 17157.82951910 -.00000187 00000-0 00000-0 0 9993 +2 32388 0.0098 359.5424 0003256 74.6363 204.7150 1.00271755 34790 THURAYA-3 -1 32404U 08001A 17109.80549667 -.00000311 00000-0 00000-0 0 9991 -2 32404 4.0825 353.1399 0004631 32.5027 210.9089 1.00270104 33976 +1 32404U 08001A 17157.85732615 -.00000309 00000-0 00000-0 0 9993 +2 32404 4.0606 353.6630 0004915 73.1219 235.8036 1.00271427 34456 EXPRESS-AM33 -1 32478U 08003A 17109.84077001 -.00000289 00000-0 00000-0 0 9990 -2 32478 0.0152 301.6644 0001053 137.1186 168.4942 1.00270167 34076 +1 32478U 08003A 17157.75390184 -.00000285 00000-0 00000-0 0 9999 +2 32478 0.0086 238.5799 0001616 270.5402 114.1081 1.00270725 34543 THOR 5 -1 32487U 08006A 17109.84357525 -.00000017 00000-0 00000-0 0 9994 -2 32487 0.0100 224.3860 0002686 173.0011 113.6769 1.00272716 33631 +1 32487U 08006A 17157.83869049 -.00000013 00000-0 00000-0 0 9991 +2 32487 0.0156 281.8742 0002857 150.3466 124.4036 1.00274295 34240 KIZUNA (WINDS) -1 32500U 08007A 17109.80034125 -.00000267 00000-0 00000-0 0 9992 -2 32500 0.7105 90.5243 0002802 311.4971 237.1260 1.00273000 33354 +1 32500U 08007A 17157.89696484 -.00000263 00000-0 00000-0 0 9992 +2 32500 0.8125 90.3689 0002920 345.1458 285.8835 1.00271207 33832 AMC-14 -1 32708U 08011A 17109.00940753 .00000101 00000-0 00000-0 0 9998 -2 32708 19.0110 63.7353 0041194 353.4410 171.4592 1.00272819 34602 +1 32708U 08011A 17156.91785617 .00000083 00000-0 00000-0 0 9995 +2 32708 19.0978 63.0141 0041500 358.6629 181.1967 1.00270864 35021 DIRECTV 11 -1 32729U 08013A 17109.59358875 -.00000134 00000-0 00000-0 0 9992 -2 32729 0.0382 56.0864 0000304 59.8688 206.4364 1.00272124 12061 +1 32729U 08013A 17157.25083755 -.00000131 00000-0 00000-0 0 9997 +2 32729 0.0372 153.5491 0000269 220.5677 231.8543 1.00272501 12547 ICO G1 -1 32763U 08016A 17109.46311039 -.00000181 00000-0 00000-0 0 9992 -2 32763 3.8629 354.2733 0003193 34.8018 252.5437 1.00272162 33036 +1 32763U 08016A 17157.46018359 -.00000179 00000-0 00000-0 0 9991 +2 32763 3.8428 354.8787 0003081 84.0600 248.9372 1.00271214 33391 VINASAT-1 -1 32767U 08018A 17108.06029192 -.00000337 00000-0 00000-0 0 9992 -2 32767 0.0428 64.1353 0001962 353.4287 302.4590 1.00271670 33040 +1 32767U 08018A 17156.92650029 -.00000335 00000-0 00000-0 0 9997 +2 32767 0.0204 41.0751 0001934 39.4019 279.5445 1.00272775 33557 STAR ONE C2 -1 32768U 08018B 17108.61978712 -.00000273 00000-0 00000-0 0 9994 -2 32768 0.0454 131.1825 0003418 308.8962 279.9645 1.00271304 32997 +1 32768U 08018B 17156.48870814 -.00000272 00000-0 00000-0 0 9995 +2 32768 0.0671 122.9474 0002024 346.7193 250.3540 1.00274515 33473 TIANLIAN 1-01 -1 32779U 08019A 17109.94017743 -.00000145 00000-0 10000-3 0 9994 -2 32779 2.6814 76.3679 0035007 234.3891 316.0256 1.00272939 32926 +1 32779U 08019A 17157.82023682 -.00000144 00000-0 10000-3 0 9992 +2 32779 2.7809 76.1983 0032662 234.4128 320.1133 1.00274328 33403 AMOS-3 -1 32794U 08022A 17109.09970708 -.00000043 00000-0 00000-0 0 9993 -2 32794 0.0595 104.8299 0001689 273.7177 220.6565 1.00274012 32892 +1 32794U 08022A 17157.83869049 -.00000039 00000-0 00000-0 0 9998 +2 32794 0.0154 261.8990 0001577 150.5664 140.7638 1.00272098 49314 GALAXY 18 (G-18) -1 32951U 08024A 17108.76661383 .00000017 00000-0 00000-0 0 9999 -2 32951 0.0196 250.6568 0003081 141.7617 327.6053 1.00272266 12352 +1 32951U 08024A 17156.63537712 .00000018 00000-0 00000-0 0 9997 +2 32951 0.0151 336.3800 0002935 102.9117 280.7413 1.00270821 33015 CHINASAT 9 (ZX 9) -1 33051U 08028A 17109.93891748 -.00000256 00000-0 00000-0 0 9991 -2 33051 0.0035 93.5519 0004154 291.3009 253.5683 1.00270607 32462 +1 33051U 08028A 17155.32934455 -.00000258 00000-0 00000-0 0 9990 +2 33051 0.0161 341.0801 0003689 86.6287 35.9581 1.00268589 32928 SKYNET 5C -1 33055U 08030A 17109.84336321 -.00000147 00000-0 00000-0 0 9998 -2 33055 0.0642 16.5151 0003689 30.9862 86.4341 1.00272518 32426 +1 33055U 08030A 17157.56229900 -.00000144 00000-0 00000-0 0 9991 +2 33055 0.0609 351.9781 0004718 100.8819 346.9248 1.00271510 32833 TURKSAT 3A -1 33056U 08030B 17109.79511987 .00000138 00000-0 00000-0 0 9995 -2 33056 0.0739 86.4901 0004970 315.6520 134.1612 1.00271757 18814 +1 33056U 08030B 17157.91500177 .00000142 00000-0 00000-0 0 9996 +2 33056 0.0566 91.3709 0005689 343.1426 192.3863 1.00274806 19297 INTELSAT 25 (IS-25) -1 33153U 08034A 17109.51030431 -.00000232 00000-0 00000-0 0 9993 -2 33153 0.0221 260.1104 0002454 125.8941 334.0133 1.00272750 32096 +1 33153U 08034A 17157.37932809 -.00000229 00000-0 00000-0 0 9996 +2 33153 0.0166 338.1349 0002961 79.1305 302.7632 1.00269297 32570 BADR-6 -1 33154U 08034B 17109.87063199 .00000136 00000-0 00000-0 0 9992 -2 33154 0.0621 44.7690 0005842 358.1876 144.6091 1.00271980 32215 +1 33154U 08034B 17157.66748696 .00000140 00000-0 00000-0 0 9999 +2 33154 0.0743 51.2760 0005921 15.3876 94.8981 1.00275158 32698 ECHOSTAR 11 -1 33207U 08035A 17108.73053534 -.00000065 00000-0 00000-0 0 9990 -2 33207 0.0397 67.8246 0003497 338.4058 313.8032 1.00272857 32101 +1 33207U 08035A 17156.59952255 -.00000064 00000-0 00000-0 0 9994 +2 33207 0.0528 99.8600 0003197 341.5030 278.6723 1.00272504 32584 SUPERBIRD-C2 -1 33274U 08038A 17109.87357476 -.00000259 00000-0 00000-0 0 9990 -2 33274 0.0175 254.8108 0001102 148.1655 263.6446 1.00272781 31830 +1 33274U 08038A 17157.83045837 -.00000256 00000-0 00000-0 0 9991 +2 33274 0.0130 310.3152 0001601 133.2629 254.7403 1.00270812 72661 AMC-21 -1 33275U 08038B 17109.48875500 .00000028 00000-0 00000-0 0 9994 -2 33275 0.0597 72.0698 0002853 336.6617 210.0961 1.00272871 31949 +1 33275U 08038B 17157.55541164 .00000031 00000-0 00000-0 0 9995 +2 33275 0.0173 2.9638 0002983 87.0691 240.1617 1.00273272 32396 INMARSAT 4-F3 -1 33278U 08039A 17109.54169668 -.00000145 00000-0 00000-0 0 9997 -2 33278 3.0225 0.8885 0002543 31.1201 272.8375 1.00270930 13031 +1 33278U 08039A 17157.58629861 -.00000145 00000-0 00000-0 0 9990 +2 33278 3.0222 1.3769 0002696 75.6386 291.2543 1.00271476 32209 NIMIQ 4 -1 33373U 08044A 17109.46418286 -.00000228 00000-0 00000-0 0 9995 -2 33373 0.0127 253.3092 0002498 126.3359 273.2011 1.00272436 31282 +1 33373U 08044A 17157.36854942 -.00000225 00000-0 00000-0 0 9997 +2 33373 0.0106 46.0570 0002274 25.7256 233.8662 1.00271139 31909 GALAXY 19 (G-19) -1 33376U 08045A 17108.69456288 -.00000147 00000-0 00000-0 0 9997 -2 33376 0.0180 201.4039 0003192 201.2704 317.3551 1.00271627 31402 +1 33376U 08045A 17156.56351010 -.00000146 00000-0 00000-0 0 9992 +2 33376 0.0189 310.2271 0003369 124.8513 284.9581 1.00271945 31766 VENESAT-1 -1 33414U 08055A 17109.29742709 -.00000246 00000-0 00000-0 0 9994 -2 33414 0.0564 65.0437 0001550 335.6881 195.9200 1.00271731 31138 +1 33414U 08055A 17157.59285705 -.00000242 00000-0 00000-0 0 9994 +2 33414 0.0085 204.2447 0001484 265.7345 280.6349 1.00273402 31489 ASTRA 1M -1 33436U 08057A 17109.79453292 .00000111 00000-0 00000-0 0 9991 -2 33436 0.0161 246.8605 0003173 199.6942 66.7212 1.00271822 12206 +1 33436U 08057A 17156.96996942 .00000114 00000-0 00000-0 0 9999 +2 33436 0.0138 294.8713 0004901 170.0549 158.0159 1.00274166 31401 CIEL-2 -1 33453U 08063A 17109.66402826 .00000050 00000-0 00000-0 0 9992 -2 33453 0.0116 44.2125 0002959 349.6556 284.2771 1.00272823 30615 +1 33453U 08063A 17157.47798289 .00000053 00000-0 00000-0 0 9998 +2 33453 0.0098 325.2717 0003163 97.7131 235.3074 1.00272818 31091 EUTELSAT HOT BIRD 13C -1 33459U 08065A 17109.38720225 .00000079 00000-0 00000-0 0 9996 -2 33459 0.0561 323.4386 0005095 90.1267 306.4869 1.00272815 13838 +1 33459U 08065A 17157.25613886 .00000082 00000-0 00000-0 0 9993 +2 33459 0.0576 46.8414 0006473 34.2156 279.0166 1.00275065 14318 EUTELSAT 48D -1 33460U 08065B 17109.86091057 .00000116 00000-0 00000-0 0 9997 -2 33460 0.0572 41.5451 0001890 7.3274 157.2778 1.00272378 30485 +1 33460U 08065B 17157.14927659 .00000118 00000-0 00000-0 0 9999 +2 33460 0.0760 54.4942 0002013 19.4905 282.6043 1.00274429 31045 FENGYUN 2E -1 33463U 08066A 17109.82749177 -.00000213 00000-0 00000-0 0 9999 -2 33463 2.0739 66.6329 0003551 221.5686 305.0095 1.00271621 30542 +1 33463U 08066A 17157.75360454 -.00000198 00000-0 00000-0 0 9993 +2 33463 2.1632 66.9548 0003261 212.3566 333.3623 1.00259862 31022 EXPRESS-AM44 -1 33595U 09007A 17109.33478159 -.00000097 00000-0 00000-0 0 9996 -2 33595 0.0134 304.5978 0001027 164.3620 208.1833 1.00272382 30006 +1 33595U 09007A 17157.91924353 -.00000093 00000-0 00000-0 0 9991 +2 33595 0.0070 222.3990 0001170 247.4182 105.6063 1.00271553 30499 NSS-9 -1 33749U 09008A 17109.73882491 .00000064 00000-0 00000-0 0 9993 -2 33749 0.0358 28.5591 0002035 359.3335 269.1842 1.00273094 30017 +1 33749U 09008A 17157.76339559 .00000067 00000-0 00000-0 0 9994 +2 33749 0.0174 351.2485 0002402 76.2173 285.7820 1.00272814 30451 EUTELSAT 33E -1 33750U 09008B 17109.01307773 .00000147 00000-0 00000-0 0 9993 -2 33750 0.0135 26.4820 0001679 21.3926 197.2626 1.00274623 30042 +1 33750U 09008B 17157.91762347 .00000152 00000-0 00000-0 0 9993 +2 33750 0.0257 9.3758 0002718 102.9611 146.5826 1.00272786 30394 TELSTAR 11N -1 34111U 09009A 17109.45534944 -.00000259 00000-0 00000-0 0 9991 -2 34111 0.0131 205.2854 0002403 177.1310 311.6896 1.00268981 29866 +1 34111U 09009A 17157.57202302 -.00000255 00000-0 00000-0 0 9993 +2 34111 0.0025 13.2728 0002760 51.7493 358.5206 1.00272628 30354 EUTELSAT 10A -1 34710U 09016A 17109.70154076 .00000061 00000-0 00000-0 0 9996 -2 34710 0.0698 355.3875 0004856 30.8383 84.3356 1.00275764 7710 +1 34710U 09016A 17157.96249140 .00000064 00000-0 00000-0 0 9997 +2 34710 0.0633 3.3505 0004813 70.8917 177.7955 1.00271293 8197 SES-7 (PROTOSTAR 2) -1 34941U 09027A 17109.79693414 -.00000353 00000-0 00000-0 0 9992 -2 34941 0.0705 80.2056 0001202 221.3619 301.6514 1.00270190 29095 +1 34941U 09027A 17157.49923914 -.00000350 00000-0 00000-0 0 9990 +2 34941 0.0488 80.0440 0001143 201.2986 261.7544 1.00272726 29553 MEASAT-3A -1 35362U 09032A 17109.16953314 -.00000250 00000-0 00000-0 0 9991 -2 35362 0.0280 197.3379 0000312 225.1106 297.5598 1.00272517 28698 +1 35362U 09032A 17157.03850047 -.00000248 00000-0 00000-0 0 9996 +2 35362 0.0448 227.8773 0001048 273.5393 218.5906 1.00272701 29178 GOES 14 -1 35491U 09033A 17108.71406314 -.00000103 00000-0 00000-0 0 9995 -2 35491 0.1495 104.6482 0004650 130.2456 125.0674 1.00271916 28613 +1 35491U 09033A 17156.58341343 -.00000101 00000-0 00000-0 0 9991 +2 35491 0.2454 102.7014 0004603 117.0014 140.2619 1.00270799 29088 SIRIUS FM-5 -1 35493U 09034A 17109.52928144 -.00000208 00000-0 00000-0 0 9994 -2 35493 0.0135 239.3975 0000848 142.8224 289.9841 1.00268061 13195 +1 35493U 09034A 17157.39958199 -.00000205 00000-0 00000-0 0 9992 +2 35493 0.0100 316.6200 0001231 61.8476 294.2336 1.00271929 28903 TERRESTAR-1 -1 35496U 09035A 17109.68338181 -.00000066 00000-0 00000-0 0 9993 -2 35496 2.9409 343.2569 0002896 46.8937 312.8199 1.00272222 28637 +1 35496U 09035A 17156.55817255 -.00000066 00000-0 00000-0 0 9995 +2 35496 2.9032 344.2414 0002757 94.4467 265.4160 1.00271910 29109 ASIASAT 5 -1 35696U 09042A 17109.93537084 -.00000316 00000-0 00000-0 0 9992 -2 35696 0.0579 95.4909 0001526 265.5110 284.4445 1.00270557 28123 +1 35696U 09042A 17157.89006208 -.00000312 00000-0 00000-0 0 9995 +2 35696 0.0352 100.7177 0001776 295.7994 279.8860 1.00273901 28609 JCSAT-RA (JCSAT-12) -1 35755U 09044A 17109.06865655 -.00000354 00000-0 00000-0 0 9994 -2 35755 0.0679 62.3793 0001075 1.8255 295.8113 1.00271686 28070 +1 35755U 09044A 17156.93761316 -.00000352 00000-0 00000-0 0 9999 +2 35755 0.0661 62.5615 0001582 7.4265 290.0286 1.00272601 28551 OPTUS D3 -1 35756U 09044B 17109.68775817 -.00000156 00000-0 00000-0 0 9993 -2 35756 0.0198 30.5105 0004173 356.3031 224.7639 1.00269234 28084 +1 35756U 09044B 17157.54201878 -.00000151 00000-0 00000-0 0 9997 +2 35756 0.0273 351.7635 0004121 60.9845 193.5266 1.00274675 28565 PALAPA D -1 35812U 09046A 17109.11021490 -.00000366 00000-0 00000-0 0 9990 -2 35812 0.0127 110.2739 0002700 328.6549 281.1065 1.00270819 28135 +1 35812U 09046A 17156.97914051 -.00000365 00000-0 00000-0 0 9999 +2 35812 0.0136 18.9745 0002748 87.3136 253.7419 1.00272895 28616 NIMIQ 5 -1 35873U 09050A 17109.46471139 -.00000265 00000-0 00000-0 0 9997 -2 35873 0.0186 127.8859 0002202 272.6371 261.8144 1.00271105 27818 +1 35873U 09050A 17157.36854942 -.00000262 00000-0 00000-0 0 9993 +2 35873 0.0172 14.4735 0002299 59.0155 241.4463 1.00271352 28295 AMAZONAS 2 -1 35942U 09054A 17109.46075057 -.00000290 00000-0 00000-0 0 9995 -2 35942 0.0406 125.2718 0003417 314.6649 232.6780 1.00270146 27647 +1 35942U 09054A 17157.85448323 -.00000286 00000-0 00000-0 0 9996 +2 35942 0.0276 90.9532 0004533 11.8293 39.2946 1.00270624 28136 COMSATBW-1 -1 35943U 09054B 17109.85049412 .00000015 00000-0 00000-0 0 9999 -2 35943 0.0725 88.4800 0002890 319.0195 169.8273 1.00274343 27712 +1 35943U 09054B 17157.85096675 .00000020 00000-0 00000-0 0 9991 +2 35943 0.0503 88.9976 0002552 343.7982 191.9970 1.00271497 28244 NSS-12 -1 36032U 09058A 17109.26519408 .00000063 00000-0 00000-0 0 9998 -2 36032 0.0153 85.3786 0002693 310.2156 324.4289 1.00272724 27398 +1 36032U 09058A 17157.13414867 .00000065 00000-0 00000-0 0 9992 +2 36032 0.0414 65.0318 0002355 10.3984 284.5958 1.00272655 27882 THOR 6 -1 36033U 09058B 17109.84357525 -.00000018 00000-0 00000-0 0 9994 -2 36033 0.0338 116.9640 0002031 297.2204 96.7807 1.00272077 27428 +1 36033U 09058B 17157.83869049 -.00000014 00000-0 00000-0 0 9991 +2 36033 0.0452 132.8724 0002159 307.5934 116.0491 1.00273364 27976 INTELSAT 14 (IS-14) -1 36097U 09064A 17108.55049208 -.00000282 00000-0 00000-0 0 9997 -2 36097 0.0142 228.2092 0002443 161.3500 330.4546 1.00271068 27153 +1 36097U 09064A 17157.41670870 -.00000278 00000-0 00000-0 0 9996 +2 36097 0.0148 325.1446 0002797 106.8970 287.9895 1.00272855 27637 EUTELSAT 36B -1 36101U 09065A 17109.79495979 .00000147 00000-0 00000-0 0 9990 -2 36101 0.0706 354.6828 0004733 45.6029 129.9147 1.00275688 27183 +1 36101U 09065A 17157.91762347 .00000151 00000-0 00000-0 0 9998 +2 36101 0.0632 1.4658 0004225 73.3033 186.9720 1.00271862 27661 INTELSAT 15 (IS-15) -1 36106U 09067A 17109.84563219 -.00000193 00000-0 00000-0 0 9998 -2 36106 0.0229 65.0036 0002009 328.0303 204.6632 1.00267015 27050 +1 36106U 09067A 17157.82951986 -.00000190 00000-0 00000-0 0 9998 +2 36106 0.0098 1.9457 0002487 70.1153 207.1345 1.00272292 8240 DIRECTV 12 -1 36131U 09075A 17109.53266096 -.00000111 00000-0 00000-0 0 9994 -2 36131 0.0098 215.7537 0000482 195.2069 245.8201 1.00272300 13055 +1 36131U 09075A 17156.72800127 -.00000109 00000-0 00000-0 0 9993 +2 36131 0.0275 159.6681 0000566 199.0592 54.8869 1.00270150 27317 BEIDOU G1 -1 36287U 10001A 17109.80396529 -.00000294 00000-0 00000-0 0 9994 -2 36287 1.5014 356.3553 0001843 133.5478 147.5544 1.00266935 26624 +1 36287U 10001A 17157.89712527 -.00000288 00000-0 00000-0 0 9999 +2 36287 1.4884 359.4741 0002313 160.5357 198.5265 1.00272476 27107 RADUGA-1M 2 -1 36358U 10002A 17109.74146499 -.00000192 00000-0 00000-0 0 9993 -2 36358 0.0258 255.8745 0002954 181.3783 122.7018 1.00271726 26464 +1 36358U 10002A 17156.06102971 -.00000193 00000-0 00000-0 0 9998 +2 36358 0.0197 278.0107 0002278 180.8803 261.7570 1.00273357 26932 SDO -1 36395U 10005A 17109.59659368 -.00000050 00000-0 00000-0 0 9997 -2 36395 28.6969 141.4739 0000909 180.0516 359.3382 1.00274604 26517 +1 36395U 10005A 17154.53430946 -.00000039 00000-0 00000-0 0 9997 +2 36395 28.7501 140.6633 0000222 100.1228 102.0693 1.00272472 26930 INTELSAT 16 (IS-16) -1 36397U 10006A 17109.34395734 -.00000293 00000-0 00000-0 0 9996 -2 36397 0.0499 77.8533 0001720 325.7835 229.7205 1.00271029 26320 +1 36397U 10006A 17157.39494062 -.00000290 00000-0 00000-0 0 9995 +2 36397 0.0100 319.2844 0001807 116.2508 263.5401 1.00272891 26662 GOES 15 -1 36411U 10008A 17108.80111742 .00000082 00000-0 00000-0 0 9995 -2 36411 0.0845 107.5451 0002196 40.7905 211.6823 1.00271261 26135 +1 36411U 10008A 17157.66643394 .00000085 00000-0 00000-0 0 9999 +2 36411 0.1816 104.1057 0001663 47.8919 208.0117 1.00264667 26611 ECHOSTAR 14 -1 36499U 10010A 17109.71162832 -.00000008 00000-0 00000-0 0 9990 -2 36499 0.0132 237.5525 0002726 149.0214 318.7152 1.00272472 13035 +1 36499U 10010A 17157.55819626 -.00000004 00000-0 00000-0 0 9991 +2 36499 0.0147 313.2379 0002913 120.6589 263.3049 1.00272444 26468 SES-1 -1 36516U 10016A 17109.59659368 -.00000123 00000-0 00000-0 0 9995 -2 36516 0.0562 71.6275 0002616 328.5076 281.5327 1.00272043 25587 +1 36516U 10016A 17157.53742503 -.00000119 00000-0 00000-0 0 9991 +2 36516 0.0219 30.5483 0002873 37.3979 279.6608 1.00272382 25983 ASTRA 3B -1 36581U 10021A 17109.87063199 .00000128 00000-0 00000-0 0 9999 -2 36581 0.0480 20.8086 0003000 0.4031 163.8492 1.00271018 25338 +1 36581U 10021A 17157.75195799 .00000133 00000-0 00000-0 0 9997 +2 36581 0.0391 331.8898 0002753 112.5158 105.1380 1.00273632 25816 COMSATBW-2 -1 36582U 10021B 17109.87549389 .00000080 00000-0 00000-0 0 9997 -2 36582 0.0248 272.1949 0002509 141.3746 122.9332 1.00273454 25438 +1 36582U 10021B 17157.96011799 .00000085 00000-0 00000-0 0 9994 +2 36582 0.0552 288.8943 0002570 161.1769 164.3284 1.00276949 25918 BEIDOU G3 -1 36590U 10024A 17109.81804083 -.00000362 00000-0 00000-0 0 9992 -2 36590 1.5460 35.8006 0005170 317.5997 259.7029 1.00268954 25238 +1 36590U 10024A 17157.17118737 -.00000362 00000-0 00000-0 0 9998 +2 36590 1.3400 21.0961 0005900 326.7456 79.1070 1.00268923 25719 BADR-5 -1 36592U 10025A 17109.87063199 .00000136 00000-0 00000-0 0 9994 -2 36592 0.0084 199.0521 0001284 219.6189 128.8932 1.00271675 19672 +1 36592U 10025A 17157.71285259 .00000140 00000-0 00000-0 0 9998 +2 36592 0.0149 268.1660 0003147 207.7859 61.9736 1.00275049 25831 COMS 1 -1 36744U 10032A 17109.79746014 -.00000352 00000-0 00000-0 0 9997 -2 36744 0.0128 296.6078 0001143 114.8177 211.9829 1.00272096 17549 +1 36744U 10032A 17157.77345323 -.00000349 00000-0 00000-0 0 9992 +2 36744 0.0223 54.6123 0001126 17.2407 230.1570 1.00272611 18024 ARABSAT-5A -1 36745U 10032B 17109.01507715 .00000145 00000-0 00000-0 0 9995 -2 36745 0.0588 27.1817 0003181 358.4253 217.6208 1.00274332 25079 +1 36745U 10032B 17157.91808519 .00000149 00000-0 00000-0 0 9997 +2 36745 0.0516 7.4356 0002774 71.0605 178.0009 1.00270875 25588 ECHOSTAR 15 -1 36792U 10034A 17109.46845527 -.00000290 00000-0 00000-0 0 9996 -2 36792 0.0567 72.1387 0002685 341.0816 261.5451 1.00271876 24843 +1 36792U 10034A 17157.93114624 -.00000285 00000-0 00000-0 0 9992 +2 36792 0.0163 326.6210 0002811 120.7234 81.7356 1.00274228 25317 NILESAT 201 -1 36830U 10037A 17109.84516125 -.00000066 00000-0 00000-0 0 9994 -2 36830 0.0464 168.5990 0005942 238.0145 98.7804 1.00273128 24744 +1 36830U 10037A 17157.91924353 -.00000061 00000-0 00000-0 0 9996 +2 36830 0.0557 147.5290 0006449 289.2971 142.6059 1.00272093 25309 RASCOM-QAF 1R -1 36831U 10037B 17108.41786415 .00000010 00000-0 00000-0 0 9996 -2 36831 0.0201 102.7993 0004916 279.9705 337.2565 1.00272628 24753 +1 36831U 10037B 17157.28397349 .00000013 00000-0 00000-0 0 9992 +2 36831 0.0241 4.5323 0004147 67.0781 288.4347 1.00269772 25245 CHINASAT 6A (ZX 6A) -1 37150U 10042A 17109.93330977 -.00000362 00000-0 00000-0 0 9994 -2 37150 0.0339 148.1711 0000865 5.2443 155.8482 1.00269088 24354 +1 37150U 10042A 17156.38172375 -.00000362 00000-0 00000-0 0 9991 +2 37150 0.0303 76.0858 0002117 105.5893 334.7872 1.00270274 24823 QZS-1 (MICHIBIKI) -1 37158U 10045A 17106.42285458 -.00000167 00000-0 00000-0 0 9992 -2 37158 40.8146 160.2213 0750190 269.8852 60.8395 1.00298496 24136 +1 37158U 10045A 17157.90776417 -.00000101 00000-0 00000-0 0 9999 +2 37158 40.8420 159.4727 0752934 270.2097 289.7799 1.00282324 24689 XM-5 -1 37185U 10053A 17109.28730701 -.00000213 00000-0 00000-0 0 9996 -2 37185 0.0141 218.6640 0000712 157.1236 210.0100 1.00268489 23944 +1 37185U 10053A 17157.39960486 -.00000210 00000-0 00000-0 0 9993 +2 37185 0.0159 321.5041 0001950 37.8879 314.2652 1.00273149 24370 BSAT-3B -1 37207U 10056B 17109.82409681 -.00000359 00000-0 00000-0 0 9995 -2 37207 0.0457 359.1733 0003651 352.5047 262.9732 1.00270791 18714 +1 37207U 10056B 17157.73216803 -.00000355 00000-0 00000-0 0 9996 +2 37207 0.0458 328.4181 0002832 38.4537 261.9045 1.00271999 19195 BEIDOU G4 -1 37210U 10057A 17109.73863873 -.00000119 00000-0 00000-0 0 9991 -2 37210 0.9518 53.7889 0003556 171.8932 48.2646 1.00272575 23743 +1 37210U 10057A 17157.76302275 -.00000117 00000-0 00000-0 0 9999 +2 37210 0.7140 41.5129 0002592 174.3277 114.1286 1.00273985 24226 SKYTERRA 1 -1 37218U 10061A 17108.62239055 -.00000128 00000-0 00000-0 0 9990 -2 37218 3.2972 329.9464 0002278 140.2680 219.4488 1.00272470 23658 +1 37218U 10061A 17157.49089657 -.00000124 00000-0 00000-0 0 9996 +2 37218 3.2345 330.5505 0003926 156.4352 203.5108 1.00273487 24161 ZHONGXING-20A -1 37234U 10064A 17109.87157751 -.00000346 00000-0 00000-0 0 9993 -2 37234 0.0460 106.1696 0005375 277.6857 268.0576 1.00267735 23484 +1 37234U 10064A 17157.83107270 -.00000342 00000-0 00000-0 0 9999 +2 37234 0.0497 252.4998 0003318 154.1537 277.9389 1.00267000 23962 HYLAS 1 -1 37237U 10065A 17109.43476604 -.00000242 00000-0 00000-0 0 9995 -2 37237 0.0731 68.6326 0001460 328.0586 294.0799 1.00270893 23431 +1 37237U 10065A 17157.38521387 -.00000239 00000-0 00000-0 0 9997 +2 37237 0.0389 40.1805 0001814 38.8492 281.1460 1.00270886 23942 INTELSAT 17 (IS-17) -1 37238U 10065B 17108.93860541 -.00000011 00000-0 00000-0 0 9991 -2 37238 0.0223 237.4196 0002329 147.5520 226.1557 1.00274737 23367 +1 37238U 10065B 17157.89278181 -.00000006 00000-0 00000-0 0 9997 +2 37238 0.0101 291.2063 0002311 147.7385 203.9456 1.00272275 20368 EUTELSAT KA-SAT 9A -1 37258U 10069A 17108.40071294 .00000054 00000-0 00000-0 0 9994 -2 37258 0.0359 282.2401 0001368 168.1724 269.6075 1.00270842 10493 +1 37258U 10069A 17157.26711220 .00000057 00000-0 00000-0 0 9995 +2 37258 0.0333 291.8546 0002476 175.7444 252.4284 1.00278754 10981 HISPASAT 1E -1 37264U 10070A 17109.39356382 -.00000224 00000-0 00000-0 0 9996 -2 37264 0.0575 100.2730 0003575 319.1902 259.9345 1.00272529 19633 +1 37264U 10070A 17157.65195397 -.00000220 00000-0 00000-0 0 9991 +2 37264 0.0706 110.0648 0004979 347.7622 2.1245 1.00271641 20128 KOREASAT 6 -1 37265U 10070B 17109.76854753 -.00000370 00000-0 00000-0 0 9995 -2 37265 0.0087 207.2756 0001837 184.0850 209.3751 1.00271901 23232 -ELEKTRO-L 1 (GOMS 2) -1 37344U 11001A 17108.74003432 -.00000253 00000-0 00000-0 0 9995 -2 37344 2.3178 78.1764 0004346 284.5008 75.5986 1.00223056 22936 +1 37265U 10070B 17157.93007414 -.00000366 00000-0 00000-0 0 9996 +2 37265 0.0092 309.0212 0002028 105.8293 291.4938 1.00270400 23716 BEIDOU IGSO 3 -1 37384U 11013A 17109.80124025 -.00000143 00000-0 10000-3 0 9994 -2 37384 57.7566 73.5430 0027952 212.7482 331.4004 1.00278676 22136 +1 37384U 11013A 17157.95024447 -.00000219 00000-0 10000-3 0 9994 +2 37384 57.8138 73.0428 0026511 210.5075 74.5458 1.00264335 22616 INTELSAT NEW DAWN -1 37392U 11016A 17109.87063199 .00000147 00000-0 00000-0 0 9996 -2 37392 0.0130 188.6692 0000865 231.1277 134.6051 1.00274587 19758 +1 37392U 11016A 17157.91808519 .00000151 00000-0 00000-0 0 9992 +2 37392 0.0124 310.0296 0000824 63.2254 245.5350 1.00271368 20239 YAHSAT 1A -1 37393U 11016B 17109.90061142 .00000092 00000-0 00000-0 0 9996 -2 37393 0.0181 240.8846 0001741 153.6982 190.3197 1.00272051 8866 +1 37393U 11016B 17157.57855374 .00000096 00000-0 00000-0 0 9994 +2 37393 0.0088 304.6116 0002219 144.9465 66.3902 1.00271269 22492 TELSTAR 14R -1 37602U 11021A 17109.24567582 -.00000288 00000-0 00000-0 0 9999 -2 37602 0.0366 27.4091 0001608 347.0447 218.5197 1.00272198 22234 +1 37602U 11021A 17157.95317137 -.00000284 00000-0 00000-0 0 9995 +2 37602 0.0172 352.7963 0001552 49.4524 133.4413 1.00272534 22799 GSAT-8 -1 37605U 11022A 17109.86091057 .00000076 00000-0 00000-0 0 9994 -2 37605 0.1020 87.9553 0004486 216.8651 268.3149 1.00272462 19674 +1 37605U 11022A 17157.85329606 .00000080 00000-0 00000-0 0 9995 +2 37605 0.0441 274.3293 0003400 45.0355 298.2936 1.00273271 20151 ST-2 -1 37606U 11022B 17109.83913135 -.00000220 00000-0 00000-0 0 9994 -2 37606 0.0170 196.3808 0001828 221.1240 180.7207 1.00273015 21702 +1 37606U 11022B 17157.45981177 -.00000217 00000-0 00000-0 0 9992 +2 37606 0.0397 114.8699 0001056 289.8834 103.8397 1.00271415 22203 CHINASAT 10 (ZX 10) -1 37677U 11026A 17109.51775259 -.00000359 00000-0 00000-0 0 9997 -2 37677 0.0474 84.0307 0002648 126.3531 294.2764 1.00248803 21429 +1 37677U 11026A 17157.96923471 -.00000356 00000-0 00000-0 0 9997 +2 37677 0.0638 276.1553 0002479 222.3704 216.4311 1.00268996 21901 TIANLIAN 1-02 -1 37737U 11032A 17109.22132347 .00000022 00000-0 00000-0 0 9990 -2 37737 2.4701 77.6299 0006823 222.1705 164.0957 1.00273480 21179 +1 37737U 11032A 17157.76269751 .00000024 00000-0 00000-0 0 9994 +2 37737 2.5713 77.5385 0004133 224.3807 44.7881 1.00275324 21659 GSAT-12 -1 37746U 11034A 17109.87308744 -.00000174 00000-0 00000-0 0 9998 -2 37746 0.0499 103.0529 0006623 359.3848 143.0422 1.00271661 9951 +1 37746U 11034A 17157.90983847 -.00000169 00000-0 00000-0 0 9992 +2 37746 0.0175 312.6345 0007942 142.4166 210.9774 1.00271473 10424 SES-3 -1 37748U 11035A 17109.62982073 -.00000110 00000-0 00000-0 0 9997 -2 37748 0.0131 315.2486 0002598 50.3515 326.0524 1.00271835 21066 +1 37748U 11035A 17157.53283324 -.00000106 00000-0 00000-0 0 9998 +2 37748 0.0233 312.0806 0002815 86.6892 305.1847 1.00269738 21629 KAZSAT-2 -1 37749U 11035B 17108.82036674 -.00000207 00000-0 00000-0 0 9993 -2 37749 0.0276 298.8314 0001947 146.6449 143.5009 1.00271885 21015 +1 37749U 11035B 17157.54021977 -.00000202 00000-0 00000-0 0 9991 +2 37749 0.0336 243.8747 0001402 224.8646 67.3812 1.00269450 21500 ASTRA 1N -1 37775U 11041A 17109.79454052 .00000111 00000-0 00000-0 0 9993 -2 37775 0.0548 354.8739 0005564 50.1394 108.2864 1.00272289 10998 +1 37775U 11041A 17156.64834056 .00000113 00000-0 00000-0 0 9997 +2 37775 0.0509 21.2424 0005680 34.8032 90.8175 1.00275052 11463 BSAT-3C (JCSAT-110R) -1 37776U 11041B 17109.92647481 -.00000359 00000-0 00000-0 0 9994 -2 37776 0.0628 86.8751 0000719 41.7491 163.0887 1.00271027 16950 +1 37776U 11041B 17157.96923750 -.00000355 00000-0 00000-0 0 9993 +2 37776 0.0173 339.7994 0000221 150.8905 223.7644 1.00270349 17439 PAKSAT-1R -1 37779U 11042A 17109.63964149 .00000145 00000-0 00000-0 0 9991 -2 37779 0.0496 59.7647 0004277 323.8999 92.5225 1.00271125 20933 +1 37779U 11042A 17157.91606583 .00000150 00000-0 00000-0 0 9996 +2 37779 0.0561 124.7736 0003650 295.9957 202.4185 1.00274039 21413 CHINASAT 1A (ZX 1A) -1 37804U 11047A 17109.64563262 -.00000346 00000-0 00000-0 0 9991 -2 37804 0.0647 87.7233 0001187 300.6810 181.7995 1.00269866 20534 +1 37804U 11047A 17156.11357760 -.00000347 00000-0 00000-0 0 9990 +2 37804 0.0612 100.8674 0000325 277.4419 46.1710 1.00270138 21007 COSMOS 2473 -1 37806U 11048A 17109.33167506 -.00000116 00000-0 00000-0 0 9996 -2 37806 0.0611 102.8656 0003218 326.5672 244.0896 1.00272171 20519 +1 37806U 11048A 17156.33223026 -.00000116 00000-0 00000-0 0 9998 +2 37806 0.0617 100.9188 0004391 357.4588 261.6708 1.00272552 20998 SES-2 -1 37809U 11049A 17109.52928144 -.00000204 00000-0 00000-0 0 9992 -2 37809 0.0320 80.9550 0002347 303.1926 287.2002 1.00271215 20474 +1 37809U 11049A 17157.39955912 -.00000201 00000-0 00000-0 0 9990 +2 37809 0.0142 329.0445 0002694 87.8130 254.9818 1.00272084 20947 ARABSAT-5C -1 37810U 11049B 17109.87549389 .00000115 00000-0 00000-0 0 9992 -2 37810 0.0654 18.1795 0002915 5.7152 159.4168 1.00272348 20513 +1 37810U 11049B 17157.85991851 .00000119 00000-0 00000-0 0 9992 +2 37810 0.0615 358.9626 0002970 80.4993 145.5734 1.00273302 20844 EUTELSAT 7 WEST A -1 37816U 11051A 17109.44320334 -.00000068 00000-0 00000-0 0 9999 -2 37816 0.0856 50.0242 0001131 67.8455 242.1471 1.00273777 20366 +1 37816U 11051A 17157.31235323 -.00000066 00000-0 00000-0 0 9999 +2 37816 0.0591 3.6728 0004397 139.9932 216.3640 1.00271238 20904 QUETZSAT 1 -1 37826U 11054A 17109.43968457 -.00000250 00000-0 00000-0 0 9999 -2 37826 0.0316 302.4492 0002329 110.2871 236.2771 1.00270439 20543 +1 37826U 11054A 17157.59285705 -.00000246 00000-0 00000-0 0 9992 +2 37826 0.0168 345.0766 0003228 96.2390 310.2983 1.00272494 16853 INTELSAT 18 (IS-18) -1 37834U 11056A 17109.61446186 .00000044 00000-0 00000-0 0 9990 -2 37834 0.0165 251.9388 0002374 157.1755 199.9933 1.00271778 20303 +1 37834U 11056A 17157.76221866 .00000048 00000-0 00000-0 0 9999 +2 37834 0.0183 358.4864 0002192 77.2725 273.9864 1.00273099 20878 EUTELSAT 16A -1 37836U 11057A 17109.87549389 .00000095 00000-0 00000-0 0 9996 -2 37836 0.0688 11.3974 0004387 22.8398 145.0663 1.00272259 12455 +1 37836U 11057A 17157.75177503 .00000100 00000-0 00000-0 0 9998 +2 37836 0.0640 358.7853 0004559 80.3391 102.8677 1.00273992 20720 VIASAT-1 -1 37843U 11059A 17109.73399147 -.00000031 00000-0 00000-0 0 9997 -2 37843 0.0197 236.4052 0002479 157.4525 323.2884 1.00269890 13781 +1 37843U 11059A 17157.55657872 -.00000028 00000-0 00000-0 0 9998 +2 37843 0.0236 332.0258 0002788 98.6617 269.7295 1.00270478 21207 ASIASAT 7 -1 37933U 11069A 17109.78712543 -.00000343 00000-0 00000-0 0 9998 -2 37933 0.0096 259.7854 0001554 107.5606 229.5962 1.00273137 11317 +1 37933U 11069A 17157.96397713 -.00000338 00000-0 00000-0 0 9993 +2 37933 0.0339 90.0623 0001623 314.3435 303.6651 1.00269996 11791 LUCH 5A -1 37951U 11074B 17109.73848825 -.00000053 00000-0 00000-0 0 9990 -2 37951 1.5543 186.3003 0004116 188.6346 265.8699 1.00272821 19642 +1 37951U 11074B 17157.76286118 -.00000048 00000-0 00000-0 0 9991 +2 37951 1.5593 181.5961 0002924 232.2936 283.0553 1.00269984 20125 NIGCOMSAT 1R -1 38014U 11077A 17109.12702867 .00000136 00000-0 00000-0 0 9993 -2 38014 0.0440 63.2942 0000489 301.7407 290.5990 1.00271728 19478 +1 38014U 11077A 17157.73438644 .00000140 00000-0 00000-0 0 9997 +2 38014 0.0313 230.4947 0000634 180.2270 151.4601 1.00273119 19964 FENGYUN 2F -1 38049U 12002A 17109.76854753 -.00000364 00000-0 00000-0 0 9996 -2 38049 1.5975 78.0440 0002882 173.6427 344.9934 1.00280529 19346 +1 38049U 12002A 17157.96468103 -.00000362 00000-0 00000-0 0 9999 +2 38049 1.6969 78.1971 0003839 190.7806 85.9216 1.00278696 19824 SES-4 -1 38087U 12007A 17108.13199622 -.00000177 00000-0 00000-0 0 9992 -2 38087 0.0123 290.4055 0002279 98.2536 203.2582 1.00268262 18921 +1 38087U 12007A 17157.11470229 -.00000174 00000-0 00000-0 0 9996 +2 38087 0.0170 356.7705 0002200 91.8215 185.4172 1.00271589 19202 BEIDOU G5 -1 38091U 12008A 17109.53852497 .00000048 00000-0 00000-0 0 9995 -2 38091 2.1174 55.1503 0002755 242.4129 162.9155 1.00276830 18937 +1 38091U 12008A 17157.85253652 .00000051 00000-0 00000-0 0 9995 +2 38091 2.2012 56.2652 0002344 222.1259 342.6549 1.00271392 19415 INTELSAT 22 (IS-22) -1 38098U 12011A 17109.22329971 -.00000067 00000-0 00000-0 0 9990 -2 38098 0.0125 300.4427 0001919 88.3020 331.2659 1.00270814 18291 +1 38098U 12011A 17157.09228884 -.00000065 00000-0 00000-0 0 9997 +2 38098 0.0185 354.8786 0001888 85.1505 279.9922 1.00273219 18772 APSTAR 7 -1 38107U 12013A 17109.75336005 -.00000110 00000-0 00000-0 0 9996 -2 38107 0.0342 120.7564 0002548 256.6070 178.3835 1.00272029 18625 +1 38107U 12013A 17157.96725832 -.00000106 00000-0 00000-0 0 9997 +2 38107 0.0373 65.1972 0002380 6.2732 248.8047 1.00272749 19103 YAHSAT 1B -1 38245U 12016A 17109.29122739 .00000118 00000-0 00000-0 0 9995 -2 38245 0.0189 237.5950 0001815 158.4243 323.9982 1.00271381 12085 +1 38245U 12016A 17157.50535265 .00000121 00000-0 00000-0 0 9998 +2 38245 0.0196 306.8057 0001866 128.0132 49.8106 1.00274079 18857 JCSAT-13 -1 38331U 12023A 17109.07957790 -.00000365 00000-0 00000-0 0 9993 -2 38331 0.0122 223.7308 0001641 175.4996 320.7814 1.00269320 17986 +1 38331U 12023A 17156.94850367 -.00000363 00000-0 00000-0 0 9991 +2 38331 0.0110 308.1395 0002132 120.4353 291.4477 1.00272159 18467 VINASAT-2 -1 38332U 12023B 17109.79755161 -.00000337 00000-0 00000-0 0 9990 -2 38332 0.0089 224.0944 0002431 193.4078 209.5413 1.00270741 13117 +1 38332U 12023B 17157.91601519 -.00000333 00000-0 00000-0 0 9990 +2 38332 0.0132 25.7857 0001991 60.3401 270.9879 1.00271910 13596 NIMIQ 6 -1 38342U 12026A 17108.67826164 -.00000182 00000-0 00000-0 0 9990 -2 38342 0.0093 223.5817 0002838 174.8111 321.6274 1.00271706 16888 +1 38342U 12026A 17157.54443457 -.00000178 00000-0 00000-0 0 9995 +2 38342 0.0105 358.5601 0002789 64.2544 297.2147 1.00272560 18539 CHINASAT 2A (ZX 2A) -1 38352U 12028A 17109.80505128 -.00000302 00000-0 00000-0 0 9997 -2 38352 0.0679 91.1551 0004179 266.0557 238.9693 1.00272187 17836 +1 38352U 12028A 17157.85699163 -.00000297 00000-0 00000-0 0 9991 +2 38352 0.0494 237.5227 0003466 135.8783 288.8087 1.00268939 18572 INTELSAT 19 (IS-19) -1 38356U 12030A 17108.96319055 -.00000065 00000-0 00000-0 0 9998 -2 38356 0.0029 7.1052 0003031 24.6900 328.2230 1.00269853 17968 +1 38356U 12030A 17156.83216273 -.00000063 00000-0 00000-0 0 9993 +2 38356 0.0168 354.6506 0002633 79.7464 285.6317 1.00272104 17403 ECHOSTAR 17 -1 38551U 12035A 17108.72245865 -.00000083 00000-0 00000-0 0 9991 -2 38551 0.0201 228.1002 0001906 154.8912 337.0172 1.00270869 17518 +1 38551U 12035A 17157.58873433 -.00000080 00000-0 00000-0 0 9994 +2 38551 0.0233 332.4519 0001981 103.0033 284.5667 1.00270136 18016 METEOSAT-10 (MSG-3) -1 38552U 12035B 17109.42366536 -.00000013 00000-0 00000-0 0 9992 -2 38552 0.7872 51.1906 0000394 69.3907 239.4278 1.00276842 17341 +1 38552U 12035B 17157.29126091 -.00000010 00000-0 00000-0 0 9997 +2 38552 0.8697 351.3752 0002086 124.9845 243.6636 1.00265605 17823 SES-5 -1 38652U 12036A 17109.09993578 .00000026 00000-0 00000-0 0 9992 -2 38652 0.0310 261.9356 0001988 148.0310 198.3715 1.00273741 17518 +1 38652U 12036A 17157.75152347 .00000029 00000-0 00000-0 0 9992 +2 38652 0.0395 274.3756 0002074 160.0925 96.3891 1.00272923 18004 TIANLIAN 1-03 -1 38730U 12040A 17109.39372586 .00000064 00000-0 00000-0 0 9999 -2 38730 0.0348 243.4357 0002785 183.6680 292.9310 1.00274200 15176 +1 38730U 12040A 17157.26256946 .00000068 00000-0 00000-0 0 9993 +2 38730 0.1236 269.7366 0003508 194.5925 255.7104 1.00276653 17928 INTELSAT 20 (IS-20) -1 38740U 12043A 17108.23601258 -.00000033 00000-0 00000-0 0 9993 -2 38740 0.0252 136.2162 0000701 66.0360 157.7489 1.00272441 17216 +1 38740U 12043A 17157.10209497 -.00000031 00000-0 00000-0 0 9990 +2 38740 0.0074 355.5859 0000369 257.1739 107.2361 1.00270572 17706 HYLAS 2 -1 38741U 12043B 17109.33713261 .00000146 00000-0 00000-0 0 9998 -2 38741 0.0394 66.1517 0001949 338.2700 315.5991 1.00273334 17221 +1 38741U 12043B 17157.20607275 .00000148 00000-0 00000-0 0 9996 +2 38741 0.0225 332.1395 0002536 109.3849 278.5043 1.00270614 17705 INTELSAT 21 (IS-21) -1 38749U 12045A 17108.58645190 -.00000293 00000-0 00000-0 0 9993 -2 38749 0.0152 259.1644 0002045 139.5306 321.3243 1.00271023 17080 +1 38749U 12045A 17156.45544027 -.00000292 00000-0 00000-0 0 9998 +2 38749 0.0207 327.2182 0002224 103.5571 289.2487 1.00269618 17471 ASTRA 2F -1 38778U 12051A 17109.34491338 .00000141 00000-0 00000-0 0 9991 -2 38778 0.0526 229.5647 0000623 50.2926 80.1410 1.00271021 7621 +1 38778U 12051A 17157.21388270 .00000144 00000-0 00000-0 0 9993 +2 38778 0.0550 223.5384 0001024 294.3720 202.0940 1.00274747 17227 GSAT-10 -1 38779U 12051B 17109.19322503 -.00000173 00000-0 00000-0 0 9998 -2 38779 0.0675 96.6564 0002579 325.5687 297.8061 1.00270698 16574 +1 38779U 12051B 17157.06200223 -.00000172 00000-0 00000-0 0 9990 +2 38779 0.0600 108.0287 0003098 319.0622 292.9417 1.00272826 17225 INTELSAT 23 (IS-23) -1 38867U 12057A 17108.57264125 -.00000293 00000-0 00000-0 0 9991 -2 38867 0.0253 259.2573 0002088 147.0398 313.7248 1.00268747 16445 +1 38867U 12057A 17157.43886168 -.00000290 00000-0 00000-0 0 9994 +2 38867 0.0168 327.2962 0001873 101.8709 290.8530 1.00269890 17049 BEIDOU G6 -1 38953U 12059A 17109.94022429 -.00000183 00000-0 10000-3 0 9992 -2 38953 1.5354 80.0034 0003410 183.5982 7.1134 1.00274696 16500 +1 38953U 12059A 17157.96657905 -.00000180 00000-0 10000-3 0 9997 +2 38953 1.6354 80.0230 0003232 164.6746 82.8829 1.00271201 16981 LUCH 5B -1 38977U 12061A 17109.32845620 -.00000137 00000-0 00000-0 0 9994 -2 38977 3.4264 74.9099 0004071 303.8364 290.7467 1.00270606 16624 +1 38977U 12061A 17157.68524606 -.00000137 00000-0 00000-0 0 9994 +2 38977 3.5243 74.5915 0003594 334.5503 76.4936 1.00270463 17116 YAMAL 300K -1 38978U 12061B 17109.73882491 .00000062 00000-0 00000-0 0 9993 -2 38978 0.0334 64.1347 0000116 302.6522 290.1709 1.00269827 16325 +1 38978U 12061B 17157.76339559 .00000067 00000-0 00000-0 0 9996 +2 38978 0.0077 269.8177 0001550 295.7230 147.5796 1.00272474 16564 STAR ONE C3 -1 38991U 12062A 17109.27983056 -.00000257 00000-0 00000-0 0 9994 -2 38991 0.0491 79.1354 0002001 304.0560 210.1285 1.00271852 16222 +1 38991U 12062A 17157.71332171 -.00000253 00000-0 00000-0 0 9998 +2 38991 0.0734 91.7888 0001666 340.8503 4.4402 1.00270979 16702 EUTELSAT 21B -1 38992U 12062B 17109.36332927 .00000121 00000-0 00000-0 0 9999 -2 38992 0.0687 11.5802 0002286 27.7946 320.6471 1.00271786 16310 +1 38992U 12062B 17157.23219512 .00000124 00000-0 00000-0 0 9995 +2 38992 0.0675 19.6007 0002324 63.2598 277.1661 1.00274141 16791 ECHOSTAR 16 -1 39008U 12065A 17108.59617560 -.00000290 00000-0 00000-0 0 9992 -2 39008 0.0209 223.8197 0001669 166.1593 330.0305 1.00270268 16252 +1 39008U 12065A 17157.46241711 -.00000287 00000-0 00000-0 0 9999 +2 39008 0.0183 335.1454 0002154 98.7759 286.1030 1.00272183 16748 CHINASAT 12 (ZX 12) -1 39017U 12067A 17109.84077001 -.00000216 00000-0 00000-0 0 9991 -2 39017 0.0125 52.1679 0002902 344.5220 201.6274 1.00272419 16165 +1 39017U 12067A 17157.45137810 -.00000212 00000-0 00000-0 0 9992 +2 39017 0.0380 80.8874 0003130 347.3808 76.7743 1.00271328 16441 EUTELSAT 70B -1 39020U 12069A 17109.22781213 -.00000052 00000-0 00000-0 0 9994 -2 39020 0.0761 40.3174 0001704 359.9847 319.7156 1.00273572 16068 +1 39020U 12069A 17157.09675105 -.00000050 00000-0 00000-0 0 9992 +2 39020 0.0642 23.6083 0002690 84.5928 251.8281 1.00271618 16441 YAMAL 402 -1 39022U 12070A 17108.99755815 .00000077 00000-0 10000-3 0 9990 -2 39022 0.0104 185.9569 0002622 214.6557 220.6940 1.00272685 16043 +1 39022U 12070A 17156.83195538 .00000079 00000-0 10000-3 0 9998 +2 39022 0.0026 350.1820 0002673 86.6284 172.0224 1.00273066 16524 SKYNET 5D -1 39034U 12075A 17109.90061177 .00000091 00000-0 00000-0 0 9993 -2 39034 0.0721 4.8617 0003646 27.9290 192.3561 1.00271793 15974 +1 39034U 12075A 17157.95131024 .00000095 00000-0 00000-0 0 9994 +2 39034 0.0732 340.9460 0003806 99.6409 210.1949 1.00274362 16102 MEXSAT 3 -1 39035U 12075B 17109.74108741 -.00000034 00000-0 00000-0 0 9993 -2 39035 0.0327 143.1688 0001629 254.3807 322.4675 1.00272109 15627 +1 39035U 12075B 17156.61273742 -.00000033 00000-0 00000-0 0 9994 +2 39035 0.0056 236.9808 0001770 202.6099 280.4292 1.00271446 16102 TDRS 11 -1 39070U 13004A 17108.81217845 .00000081 00000-0 00000-0 0 9999 -2 39070 5.4717 328.7221 0010135 305.8529 53.8845 1.00265360 13147 +1 39070U 13004A 17157.67865594 .00000085 00000-0 00000-0 0 9991 +2 39070 5.4081 328.6812 0008105 303.3057 56.5753 1.00265821 13633 AMAZONAS 3 -1 39078U 13006A 17108.59469008 -.00000291 00000-0 00000-0 0 9998 -2 39078 0.0226 192.8297 0001208 189.3655 337.8146 1.00272840 11339 +1 39078U 13006A 17156.46368881 -.00000290 00000-0 00000-0 0 9993 +2 39078 0.0058 178.2682 0001754 277.6277 264.1241 1.00269298 11819 AZERSPACE 1 -1 39079U 13006B 17109.29572733 .00000125 00000-0 00000-0 0 9992 -2 39079 0.0380 59.2069 0002155 358.2504 302.5687 1.00272231 15388 +1 39079U 13006B 17156.16738929 .00000124 00000-0 00000-0 0 9990 +2 39079 0.0450 109.2747 0002427 335.6506 275.1008 1.00273612 15733 EUTELSAT 117 WEST A -1 39122U 13012A 17108.74938232 -.00000021 00000-0 00000-0 0 9993 -2 39122 0.0621 84.5471 0002723 307.7139 327.7605 1.00272703 14907 +1 39122U 13012A 17156.61823271 -.00000020 00000-0 00000-0 0 9997 +2 39122 0.0301 334.3523 0002356 95.1526 290.5205 1.00270899 15386 ANIK G1 -1 39127U 13014A 17108.72301666 -.00000082 00000-0 00000-0 0 9990 -2 39127 0.0141 251.0073 0001596 105.7194 3.2770 1.00272421 14706 +1 39127U 13014A 17157.58925234 -.00000079 00000-0 00000-0 0 9997 +2 39127 0.0122 300.7710 0001022 91.0215 328.2144 1.00272314 15190 CHINASAT 11 (ZX 11) -1 39157U 13020A 17109.82005012 -.00000299 00000-0 00000-0 0 9998 -2 39157 0.0110 209.0480 0002464 106.9430 285.3027 1.00269299 14607 +1 39157U 13020A 17157.88521376 -.00000296 00000-0 00000-0 0 9990 +2 39157 0.0216 297.5545 0002161 19.5915 355.0250 1.00272870 15084 EUTELSAT 7B -1 39163U 13022A 17108.40640327 .00000040 00000-0 00000-0 0 9997 -2 39163 0.0489 41.3036 0005001 330.3367 348.3758 1.00272149 14440 +1 39163U 13022A 17157.27263000 .00000043 00000-0 00000-0 0 9998 +2 39163 0.0500 34.9279 0004218 2.0841 323.0174 1.00274777 14935 SES-6 -1 39172U 13026A 17109.40461581 -.00000269 00000-0 00000-0 0 9999 -2 39172 0.0169 71.6556 0001814 346.6849 254.5218 1.00269637 14189 +1 39172U 13026A 17157.86072084 -.00000265 00000-0 00000-0 0 9994 +2 39172 0.0343 44.6534 0002271 33.2374 86.9252 1.00272899 14661 IRNSS-1A -1 39199U 13034A 17107.59747611 .00000118 00000-0 00000-0 0 9998 -2 39199 28.7210 116.0761 0021173 188.9070 171.0962 1.00271071 13809 +1 39199U 13034A 17157.45833099 .00000110 00000-0 00000-0 0 9996 +2 39199 28.8033 115.2188 0018966 189.2548 170.6083 1.00273932 14579 ALPHASAT -1 39215U 13038A 17109.43561126 .00000131 00000-0 00000-0 0 9996 -2 39215 1.6489 29.6730 0001563 5.9468 353.7801 1.00273935 10507 +1 39215U 13038A 17157.30226941 .00000131 00000-0 00000-0 0 9998 +2 39215 1.6886 29.2099 0002635 31.5775 327.7603 1.00270357 10987 INSAT-3D -1 39216U 13038B 17108.19845532 -.00000164 00000-0 00000-0 0 9992 -2 39216 0.1114 95.6066 0001281 289.2214 335.1824 1.00270427 13566 +1 39216U 13038B 17157.06441889 -.00000163 00000-0 00000-0 0 9998 +2 39216 0.0121 6.4352 0000691 34.8253 318.7445 1.00271459 14239 EUTELSAT 25B -1 39233U 13044A 17109.35241066 .00000135 00000-0 00000-0 0 9996 -2 39233 0.0548 38.0621 0001893 351.2735 330.6803 1.00269362 13091 +1 39233U 13044A 17157.22143286 .00000137 00000-0 00000-0 0 9992 +2 39233 0.0521 26.6700 0001824 46.4596 286.8905 1.00271878 13578 GSAT-7 -1 39234U 13044B 17109.21797557 -.00000086 00000-0 00000-0 0 9999 -2 39234 0.0905 98.9459 0002312 216.3847 44.6560 1.00272984 11819 +1 39234U 13044B 17157.08691953 -.00000084 00000-0 00000-0 0 9998 +2 39234 0.0182 263.6715 0000935 51.5189 44.8019 1.00273002 12284 AMOS-4 -1 39237U 13045A 17109.24289309 -.00000002 00000-0 00000-0 0 9995 -2 39237 0.0307 129.6945 0001970 232.1057 358.2058 1.00274519 13418 +1 39237U 13045A 17157.11192798 .00000001 00000-0 00000-0 0 9997 +2 39237 0.0546 115.1014 0000970 303.3385 301.5694 1.00273651 13899 ASTRA 2E -1 39285U 13056A 17109.34401615 .00000142 00000-0 00000-0 0 9991 -2 39285 0.0672 39.3149 0002281 347.3279 333.3742 1.00273719 12920 +1 39285U 13056A 17157.21313460 .00000144 00000-0 00000-0 0 9992 +2 39285 0.0570 13.9752 0002212 49.4873 296.5603 1.00271660 13402 SIRIUS FM-6 -1 39360U 13058A 17109.74482623 -.00000025 00000-0 00000-0 0 9990 -2 39360 0.0056 268.1075 0000804 306.6532 145.2396 1.00270730 12801 +1 39360U 13058A 17156.61640136 -.00000024 00000-0 00000-0 0 9992 +2 39360 0.0064 1.2561 0001302 214.3345 144.3998 1.00270910 13277 RADUGA-1M 3 -1 39375U 13062A 17109.89285655 -.00000048 00000-0 00000-0 0 9998 -2 39375 0.0057 227.8524 0002812 191.6803 180.0873 1.00273461 12589 +1 39375U 13062A 17153.54222145 -.00000055 00000-0 00000-0 0 9992 +2 39375 0.0111 85.9904 0003557 1.3292 69.0907 1.00272620 13021 SES-8 -1 39460U 13071A 17109.15996438 -.00000277 00000-0 00000-0 0 9994 -2 39460 0.0215 233.8425 0002700 181.3674 304.8155 1.00268173 12320 +1 39460U 13071A 17157.02889498 -.00000276 00000-0 00000-0 0 9999 +2 39460 0.0261 285.7228 0003217 152.2287 282.0846 1.00271753 11454 INMARSAT 5-F1 -1 39476U 13073A 17109.85049412 .00000019 00000-0 00000-0 0 9994 -2 39476 0.0141 212.3345 0000584 298.4402 66.1473 1.00270688 12386 +1 39476U 13073A 17157.78416375 .00000023 00000-0 00000-0 0 9990 +2 39476 0.0226 348.4229 0000042 157.5437 94.3041 1.00271057 12862 TKSAT-1 (TUPAC KATARI) -1 39481U 13075A 17109.52928144 -.00000203 00000-0 00000-0 0 9990 -2 39481 0.0117 242.6857 0002588 127.5037 300.9650 1.00271252 12048 +1 39481U 13075A 17157.39955912 -.00000199 00000-0 00000-0 0 9995 +2 39481 0.0262 80.8028 0002650 325.1093 265.7352 1.00268861 12778 EXPRESS-AM5 -1 39487U 13077A 17107.84678245 -.00000288 00000-0 00000-0 0 9998 -2 39487 0.0238 312.2169 0000702 25.0086 313.8487 1.00273362 12809 +1 39487U 13077A 17157.08737148 -.00000286 00000-0 00000-0 0 9995 +2 39487 0.0183 225.9272 0001087 152.4247 47.8212 1.00272613 13308 GSAT-14 -1 39498U 14001A 17109.21821508 -.00000086 00000-0 00000-0 0 9999 -2 39498 0.0256 161.8848 0004623 253.8490 304.3152 1.00272765 11909 +1 39498U 14001A 17157.08704643 -.00000083 00000-0 00000-0 0 9994 +2 39498 0.0121 359.3211 0005096 75.5744 285.1609 1.00269350 12386 THAICOM 6 -1 39500U 14002A 17109.91575337 -.00000130 00000-0 00000-0 0 9997 -2 39500 0.0622 121.4131 0002324 315.5938 179.3442 1.00273862 11907 +1 39500U 14002A 17157.93664877 -.00000125 00000-0 00000-0 0 9994 +2 39500 0.0699 124.7999 0003423 337.4406 209.0050 1.00271102 12387 TDRS 12 -1 39504U 14004A 17108.47280783 -.00000282 00000-0 00000-0 0 9999 -2 39504 6.0422 336.1678 0002694 28.4941 331.3755 1.00276390 10725 +1 39504U 14004A 17157.33909738 -.00000280 00000-0 00000-0 0 9994 +2 39504 5.9899 336.1128 0000870 62.9722 296.9805 1.00276997 11215 ABS-2 -1 39508U 14006A 17109.21554072 -.00000095 00000-0 00000-0 0 9995 -2 39508 0.0656 73.3977 0003400 312.5250 334.0996 1.00272187 11773 +1 39508U 14006A 17157.08454168 -.00000092 00000-0 00000-0 0 9995 +2 39508 0.0260 25.0067 0002927 56.4361 278.5904 1.00271774 12254 ATHENA-FIDUS -1 39509U 14006B 17109.31836167 .00000146 00000-0 00000-0 0 9991 -2 39509 0.0172 258.0824 0001436 153.6976 308.2329 1.00271121 11530 +1 39509U 14006B 17157.18733805 .00000148 00000-0 00000-0 0 9996 +2 39509 0.0240 56.4962 0001464 32.4149 271.1056 1.00273442 12002 TURKSAT 4A -1 39522U 14007A 17108.30939973 .00000137 00000-0 00000-0 0 9994 -2 39522 0.0482 271.6731 0002588 66.3946 21.9257 1.00273681 11445 +1 39522U 14007A 17157.17566243 .00000140 00000-0 00000-0 0 9993 +2 39522 0.0407 278.7972 0000805 116.4412 324.7670 1.00270948 11932 EXPRESS-AT1 -1 39612U 14010A 17109.86056334 .00000069 00000-0 00000-0 0 9995 -2 39612 0.0239 342.1001 0001390 119.8162 112.0397 1.00273860 11506 +1 39612U 14010A 17157.99154439 .00000074 00000-0 00000-0 0 9993 +2 39612 0.0243 210.4438 0000568 272.7509 185.3502 1.00273705 11983 EXPRESS-AT2 -1 39613U 14010B 17109.80396529 -.00000290 00000-0 00000-0 0 9990 -2 39613 0.0192 309.9020 0000507 163.1051 164.3590 1.00272134 11334 +1 39613U 14010B 17157.08877310 -.00000288 00000-0 00000-0 0 9992 +2 39613 0.0210 217.2465 0000533 238.6254 330.6118 1.00270915 11813 AMAZONAS 4A -1 39616U 14011A 17109.59198177 -.00000291 00000-0 00000-0 0 9990 -2 39616 0.0700 69.3908 0005338 327.2211 323.4301 1.00269976 11150 +1 39616U 14011A 17157.46096683 -.00000287 00000-0 00000-0 0 9993 +2 39616 0.0867 79.0306 0005518 343.3597 297.6664 1.00273138 11801 ASTRA 5B -1 39617U 14011B 17109.87063199 .00000146 00000-0 00000-0 0 9995 -2 39617 0.0620 306.2519 0003203 96.4430 150.3628 1.00272796 11131 +1 39617U 14011B 17157.91823566 .00000151 00000-0 00000-0 0 9991 +2 39617 0.0442 321.6428 0003825 122.9841 172.8998 1.00272907 11610 IRNSS-1B -1 39635U 14017A 17106.10098970 .00000066 00000-0 00000-0 0 9990 -2 39635 29.2031 295.8732 0018997 177.1399 182.8116 1.00276752 11225 +1 39635U 14017A 17156.95952933 .00000048 00000-0 00000-0 0 9996 +2 39635 29.1089 295.0821 0021490 179.1997 180.7604 1.00275528 11528 LUCH 5V -1 39727U 14023A 17109.93906795 -.00000281 00000-0 00000-0 0 9996 -2 39727 2.8199 299.0931 0002966 94.5519 247.3971 1.00271915528978 -KAZSAT 3 -1 39728U 14023B 17109.26104713 .00000052 00000-0 00000-0 0 9998 -2 39728 0.0143 251.6382 0001230 229.4791 238.8947 1.00270882 8902 +1 39727U 14023A 17157.96502630 -.00000273 00000-0 00000-0 0 9993 +2 39727 2.7255 299.0335 0002078 147.0891 251.5913 1.00273263529465 +KAZSAT-3 +1 39728U 14023B 17157.12992527 .00000054 00000-0 00000-0 0 9996 +2 39728 0.0095 359.2657 0000563 147.0049 213.7329 1.00271437 9383 EUTELSAT 3B -1 39773U 14030A 17109.95680470 .00000011 00000-0 00000-0 0 9996 -2 39773 0.0841 322.3770 0001701 75.8441 157.5548 1.00272325 10532 +1 39773U 14030A 17157.94471205 .00000016 00000-0 00000-0 0 9997 +2 39773 0.0590 5.2305 0002365 82.6403 150.8644 1.00273880 11019 ASIASAT 8 -1 40107U 14046A 17108.43659856 -.00000042 00000-0 00000-0 0 9997 -2 40107 0.0119 246.9864 0000325 121.2645 351.7496 1.00270279 68608 +1 40107U 14046A 17157.30284274 -.00000039 00000-0 00000-0 0 9991 +2 40107 0.0156 316.3110 0002166 118.5885 285.1248 1.00271407 69098 ASIASAT 6 -1 40141U 14052A 17109.94058306 -.00000371 00000-0 00000-0 0 9997 -2 40141 0.0162 237.3406 0000978 188.5950 240.8089 1.00271351 9512 +1 40141U 14052A 17157.93766262 -.00000366 00000-0 00000-0 0 9990 +2 40141 0.0178 58.3054 0000886 3.9150 290.7769 1.00271863 9998 OPTUS 10 -1 40146U 14054A 17108.96873335 -.00000082 00000-0 00000-0 0 9991 -2 40146 0.0733 334.7330 0001585 59.1047 326.1773 1.00274086 9486 +1 40146U 14054A 17156.83773548 -.00000081 00000-0 00000-0 0 9994 +2 40146 0.0340 82.9484 0001623 350.1925 286.8765 1.00271044 10053 MEASAT-3B -1 40147U 14054B 17109.16977926 -.00000249 00000-0 00000-0 0 9991 -2 40147 0.0139 31.0682 0002670 358.9432 330.0039 1.00270102 9369 +1 40147U 14054B 17157.03852819 -.00000248 00000-0 00000-0 0 9992 +2 40147 0.0238 357.1097 0002084 48.7697 314.1376 1.00269730 10103 LUCH (OLYMP) -1 40258U 14058A 17109.92803998 .00000060 00000-0 00000-0 0 9999 -2 40258 0.0075 179.7868 0000515 208.9661 163.4552 1.00272906 9396 +1 40258U 14058A 17157.78938271 .00000063 00000-0 00000-0 0 9992 +2 40258 0.0460 143.2667 0000810 265.0279 141.1304 1.00271236 9870 HIMAWARI-8 -1 40267U 14060A 17109.03337671 -.00000284 00000-0 00000-0 0 9993 -2 40267 0.0169 99.4949 0000850 348.4065 272.1083 1.00269924 9313 +1 40267U 14060A 17156.90236236 -.00000282 00000-0 00000-0 0 9994 +2 40267 0.0119 325.0622 0001214 124.4028 270.5486 1.00271594 9797 IRNSS-1C -1 40269U 14061A 17108.89275674 -.00000173 00000-0 00000-0 0 9990 -2 40269 3.1333 251.6716 0019082 9.6181 350.2659 1.00269076 9267 +1 40269U 14061A 17157.75544524 -.00000164 00000-0 00000-0 0 9992 +2 40269 3.0397 249.9431 0018690 6.2154 354.2400 1.00272682 9756 INTELSAT 30 (IS-30) -1 40271U 14062A 17109.40753358 -.00000158 00000-0 00000-0 0 9995 -2 40271 0.0126 211.5975 0001766 255.2120 152.5341 1.00268435 9214 +1 40271U 14062A 17156.40832028 -.00000159 00000-0 00000-0 0 9990 +2 40271 0.0114 8.1186 0001576 102.5867 195.2506 1.00272785 9687 ARSAT 1 -1 40272U 14062B 17109.43866049 -.00000268 00000-0 00000-0 0 9993 -2 40272 0.0110 235.2023 0001094 173.8657 244.7704 1.00270905 9064 +1 40272U 14062B 17157.39970265 -.00000265 00000-0 00000-0 0 9994 +2 40272 0.0314 136.5216 0001345 294.2969 256.2682 1.00272031 9818 EXPRESS-AM6 -1 40277U 14064A 17109.63283528 .00000089 00000-0 00000-0 0 9997 -2 40277 0.0221 327.4450 0000810 134.3775 26.9122 1.00271395 8043 +1 40277U 14064A 17157.95131343 .00000094 00000-0 00000-0 0 9998 +2 40277 0.0134 313.3619 0001000 156.2831 181.3635 1.00271307 8526 GSAT-16 -1 40332U 14078A 17109.27071338 .00000076 00000-0 00000-0 0 9994 -2 40332 0.0788 86.2534 0006291 346.8056 287.0151 1.00272192 8584 +1 40332U 14078A 17157.13958014 .00000078 00000-0 00000-0 0 9999 +2 40332 0.0783 272.6390 0007957 162.2825 285.1671 1.00272671 9190 DIRECTV 14 -1 40333U 14078B 17109.59358875 -.00000133 00000-0 00000-0 0 9999 -2 40333 0.0146 249.3051 0000286 129.3243 303.7125 1.00270870 8611 +1 40333U 14078B 17157.53940927 -.00000130 00000-0 00000-0 0 9998 +2 40333 0.0193 291.3592 0001426 68.8528 349.8871 1.00274125 9178 YAMAL 401 -1 40345U 14082A 17109.34233956 -.00000236 00000-0 00000-0 0 9996 -2 40345 0.0666 80.5801 0001445 8.0577 332.1630 1.00269966 8868 +1 40345U 14082A 17152.86438141 -.00000245 00000-0 00000-0 0 9994 +2 40345 0.0664 103.2093 0000168 299.4691 248.9586 1.00269334 9297 ASTRA 2G -1 40364U 14089A 17109.34497921 .00000141 00000-0 00000-0 0 9992 -2 40364 0.0153 357.1621 0004863 56.7436 306.1394 1.00272491 8421 +1 40364U 14089A 17157.21405344 .00000144 00000-0 00000-0 0 9992 +2 40364 0.0364 31.6860 0005116 29.5303 298.8354 1.00272096 8904 FENGYUN 2G -1 40367U 14090A 17109.43598381 -.00000335 00000-0 00000-0 0 9995 -2 40367 0.5568 261.4214 0002558 301.0266 266.4441 1.00260509 8495 +1 40367U 14090A 17157.97017683 -.00000331 00000-0 00000-0 0 9994 +2 40367 0.4550 257.2998 0003702 327.1910 124.6866 1.00261694 8979 INMARSAT 5-F2 -1 40384U 15005A 17109.35414264 -.00000293 00000-0 00000-0 0 9992 -2 40384 0.0206 237.1065 0000486 193.7680 209.2452 1.00270089 8127 +1 40384U 15005A 17157.57688493 -.00000290 00000-0 00000-0 0 9993 +2 40384 0.0216 336.1453 0000002 138.6792 293.0412 1.00270180 8618 ABS-3A -1 40424U 15010A 17108.43380787 -.00000034 00000-0 00000-0 0 9996 -2 40424 0.0115 243.8763 0001944 64.0974 52.0132 1.00273027 7859 +1 40424U 15010A 17156.30270265 -.00000034 00000-0 00000-0 0 9994 +2 40424 0.0166 334.1046 0001967 21.5779 4.3158 1.00270458 8336 EUTELSAT 115 WEST B -1 40425U 15010B 17108.74397819 -.00000033 00000-0 00000-0 0 9994 -2 40425 0.0023 66.7907 0000609 235.4939 57.7095 1.00270139 7853 +1 40425U 15010B 17156.61293761 -.00000032 00000-0 00000-0 0 9993 +2 40425 0.0060 158.5821 0000506 154.2196 47.1932 1.00268158 8366 EXPRESS-AM7 -1 40505U 15012A 17109.81855196 .00000142 00000-0 00000-0 0 9991 -2 40505 0.0007 199.1072 0002517 175.9892 167.6787 1.00272783 7816 +1 40505U 15012A 17157.74217898 .00000146 00000-0 00000-0 0 9991 +2 40505 0.0070 32.4634 0002254 29.6477 140.4119 1.00274561 8298 IRNSS-1D -1 40547U 15018A 17108.93580479 -.00000310 00000-0 00000-0 0 9992 -2 40547 29.1864 295.9627 0019702 179.0393 180.9184 1.00273644 7446 +1 40547U 15018A 17157.79985935 -.00000331 00000-0 00000-0 0 9999 +2 40547 29.0945 295.1992 0021169 178.4207 181.5447 1.00273872 7935 BEIDOU I1-S -1 40549U 15019A 17109.50198778 -.00000141 00000-0 00000-0 0 9998 -2 40549 54.4510 334.4397 0039145 181.6881 324.0406 1.00253900 7535 +1 40549U 15019A 17157.96031042 -.00000167 00000-0 00000-0 0 9999 +2 40549 54.4117 333.8858 0040189 185.8887 173.9188 1.00295772 8010 THOR 7 -1 40613U 15022A 17108.42761913 -.00000016 00000-0 00000-0 0 9992 -2 40613 0.0384 109.0718 0002651 284.7857 326.1639 1.00273293 7264 +1 40613U 15022A 17157.29387069 -.00000014 00000-0 00000-0 0 9995 +2 40613 0.0055 16.7658 0002798 58.2999 284.9653 1.00269452 7763 TURKMENALEM52E/MONACOSAT -1 40617U 15023A 17109.27900221 .00000095 00000-0 00000-0 0 9994 -2 40617 0.0069 271.1428 0003030 130.2756 318.6046 1.00269720 7293 +1 40617U 15023A 17157.14794716 .00000097 00000-0 00000-0 0 9995 +2 40617 0.0108 344.4284 0002771 86.6968 288.9050 1.00274348 7770 DIRECTV 15 -1 40663U 15026A 17108.71042695 -.00000111 00000-0 00000-0 0 9998 -2 40663 0.0196 120.0555 0000297 13.2497 226.7019 1.00270236 6979 +1 40663U 15026A 17156.57931752 -.00000110 00000-0 00000-0 0 9995 +2 40663 0.0400 105.4351 0000308 356.6694 257.8980 1.00270125 7468 SKY MEXICO-1 -1 40664U 15026B 17108.64406019 -.00000243 00000-0 00000-0 0 9991 -2 40664 0.0167 136.0530 0002150 262.9701 320.9971 1.00273348 6981 +1 40664U 15026B 17156.51304984 -.00000241 00000-0 00000-0 0 9996 +2 40664 0.0192 334.0846 0002191 94.4621 291.4767 1.00269981 7460 METEOSAT-11 (MSG-4) -1 40732U 15034A 17108.11510896 -.00000039 00000-0 00000-0 0 9990 -2 40732 1.9279 244.3808 0000871 108.3788 251.4878 1.00271839 6480 +1 40732U 15034A 17156.97556449 -.00000031 00000-0 00000-0 0 9993 +2 40732 1.8409 241.7802 0000480 251.7722 108.9386 1.00266938 6974 STAR ONE C4 -1 40733U 15034B 17108.61973130 -.00000273 00000-0 00000-0 0 9990 -2 40733 0.0518 50.5684 0003073 346.9583 322.4994 1.00270157 6486 +1 40733U 15034B 17156.48870247 -.00000272 00000-0 00000-0 0 9992 +2 40733 0.0645 72.8856 0002561 335.6664 311.4689 1.00273409 6966 INTELSAT 34 (IS-34) -1 40874U 15039A 17108.57945464 -.00000293 00000-0 00000-0 0 9997 -2 40874 0.0153 252.0193 0000803 313.8730 154.1083 1.00271237 6126 +1 40874U 15039A 17157.44569474 -.00000290 00000-0 00000-0 0 9997 +2 40874 0.0253 324.4014 0000673 42.2274 353.3721 1.00270149 6611 EUTELSAT 8 WEST B -1 40875U 15039B 17109.44529436 -.00000074 00000-0 00000-0 0 9999 -2 40875 0.0704 355.3737 0003352 21.2704 343.3722 1.00272004 6140 +1 40875U 15039B 17157.31420641 -.00000071 00000-0 00000-0 0 9993 +2 40875 0.0669 345.0647 0002924 77.3120 297.6536 1.00272288 6625 GSAT-6 -1 40880U 15041A 17109.19302429 -.00000172 00000-0 00000-0 0 9990 -2 40880 0.0261 183.0365 0007277 107.3728 69.5125 1.00268789 6081 +1 40880U 15041A 17157.06177879 -.00000171 00000-0 00000-0 0 9997 +2 40880 0.0248 283.2072 0005968 358.2972 78.4282 1.00271204 6581 INMARSAT 5-F3 -1 40882U 15042A 17108.92546331 .00000041 00000-0 00000-0 0 9999 -2 40882 0.0208 236.9687 0000953 249.1479 233.8922 1.00267404 6007 +1 40882U 15042A 17156.79441291 .00000043 00000-0 00000-0 0 9998 +2 40882 0.0217 333.5493 0000755 130.8034 255.6557 1.00268467 6498 TJS-1 -1 40892U 15046A 17109.73035331 -.00000165 00000-0 00000-0 0 9995 -2 40892 0.0820 276.5696 0007514 110.2171 239.0989 1.00272336 6006 +1 40892U 15046A 17157.67437281 -.00000160 00000-0 00000-0 0 9996 +2 40892 0.0390 94.0423 0001961 297.6627 261.4249 1.00274282 6487 EXPRESS-AM8 -1 40895U 15048A 17109.79632778 -.00000120 00000-0 00000-0 0 9995 -2 40895 0.0171 315.4830 0000930 145.1881 20.0907 1.00272184 5830 +1 40895U 15048A 17156.34083615 -.00000119 00000-0 00000-0 0 9996 +2 40895 0.0188 221.4276 0000582 228.7531 272.4900 1.00273368 6305 BEIDOU I2-S -1 40938U 15053A 17109.33759767 -.00000114 00000-0 00000-0 0 9990 -2 40938 54.2856 297.3332 0047489 171.5106 315.4929 1.00264459 5816 +1 40938U 15053A 17157.91354792 -.00000167 00000-0 00000-0 0 9994 +2 40938 54.2196 296.7873 0047087 172.5226 207.7175 1.00295744 6306 SKY MUSTER (NBN1A) -1 40940U 15054A 17109.03457499 -.00000287 00000-0 00000-0 0 9999 -2 40940 0.0177 248.5059 0001797 145.1389 326.3717 1.00270402 5743 +1 40940U 15054A 17156.90352899 -.00000286 00000-0 00000-0 0 9994 +2 40940 0.0244 321.8934 0002086 107.5619 290.5671 1.00269508 6225 ARSAT 2 -1 40941U 15054B 17108.65020886 -.00000233 00000-0 00000-0 0 9994 -2 40941 0.0146 240.4549 0001383 175.1351 304.4277 1.00270663 5778 +1 40941U 15054B 17156.51913242 -.00000232 00000-0 00000-0 0 9998 +2 40941 0.0430 126.2431 0001678 307.5160 286.2584 1.00272441 6259 MORELOS 3 -1 40946U 15056A 17108.65511739 -.00000058 00000-0 00000-0 0 9998 -2 40946 6.4994 329.8239 0001904 350.7732 9.0858 1.00271301 5734 +1 40946U 15056A 17156.52375644 -.00000058 00000-0 00000-0 0 9990 +2 40946 6.4382 329.6573 0001266 194.3751 165.5754 1.00273198 6211 APSTAR 9 -1 40982U 15059A 17109.02956332 -.00000274 00000-0 00000-0 0 9995 -2 40982 0.0146 174.3096 0000543 157.3652 28.3273 1.00272514 5616 +1 40982U 15059A 17156.89859662 -.00000273 00000-0 00000-0 0 9999 +2 40982 0.0437 132.3717 0000361 252.7207 334.9088 1.00271279 6097 TURKSAT 4B -1 40984U 15060A 17109.28455546 .00000106 00000-0 00000-0 0 9991 -2 40984 0.0141 240.2982 0001880 146.2651 333.4463 1.00272723 5579 +1 40984U 15060A 17157.15358557 .00000109 00000-0 00000-0 0 9997 +2 40984 0.0129 13.5932 0002306 57.1606 289.2712 1.00271214 6047 CHINASAT 2C (ZX 2C) -1 41021U 15063A 17109.81452186 -.00000332 00000-0 00000-0 0 9995 -2 41021 0.0096 299.9183 0003598 93.2700 211.5288 1.00269171 5461 +1 41021U 15063A 17157.96519169 -.00000328 00000-0 00000-0 0 9994 +2 41021 0.0135 187.6740 0002205 206.8564 311.9405 1.00272905 5949 GSAT-15 -1 41028U 15065A 17109.16405506 -.00000266 00000-0 00000-0 0 9992 -2 41028 0.0775 95.0431 0002136 304.3112 320.6664 1.00271474 5316 +1 41028U 15065A 17157.03303586 -.00000264 00000-0 00000-0 0 9994 +2 41028 0.0814 274.8255 0003106 130.7632 314.4368 1.00272144 5785 BADR-7 (ARABSAT-6B) -1 41029U 15065B 17108.35361110 .00000137 00000-0 00000-0 0 9991 -2 41029 0.0576 258.0240 0002310 352.7034 109.2520 1.00275353 5197 +1 41029U 15065B 17157.21998263 .00000139 00000-0 00000-0 0 9997 +2 41029 0.0441 258.8634 0002007 329.0067 132.1129 1.00271737 5685 LAOSAT 1 -1 41034U 15067A 17109.06709502 -.00000352 00000-0 00000-0 0 9999 -2 41034 0.0073 135.8570 0000526 91.2878 132.8508 1.00267321 5320 +1 41034U 15067A 17156.93622780 -.00000350 00000-0 00000-0 0 9997 +2 41034 0.0174 12.3004 0001327 146.2409 201.4638 1.00267265 5801 TELSTAR 12V -1 41036U 15068A 17108.46733881 -.00000127 00000-0 00000-0 0 9992 -2 41036 0.0205 234.5402 0002195 157.1075 328.3700 1.00272542 5074 +1 41036U 15068A 17157.33359668 -.00000124 00000-0 00000-0 0 9996 +2 41036 0.0227 64.3782 0002247 3.4888 292.1572 1.00272340 5555 CHINASAT 1C (ZX 1C) -1 41103U 15073A 17109.84563218 -.00000160 00000-0 00000-0 0 9998 -2 41103 0.0198 295.5873 0003254 27.4648 271.0110 1.00274317 5128 +1 41103U 15073A 17157.98537590 -.00000155 00000-0 00000-0 0 9994 +2 41103 0.0095 189.8426 0002402 127.5052 14.4726 1.00273936 5609 ELEKTRO-L 2 -1 41105U 15074A 17109.74146499 -.00000106 00000-0 00000-0 0 9998 -2 41105 0.0675 43.5062 0002143 13.6273 133.8389 1.00271793 4978 +1 41105U 15074A 17157.96725832 -.00000102 00000-0 00000-0 0 9995 +2 41105 0.0738 190.6773 0001945 246.5160 242.6717 1.00272238 5455 COSMOS 2513 -1 41121U 15075A 17104.80737361 -.00000150 00000-0 00000-0 0 9992 -2 41121 0.0614 89.3769 0003377 318.8997 165.7933 1.00272829 5009 +1 41121U 15075A 17157.45624638 -.00000143 00000-0 00000-0 0 9995 +2 41121 0.0997 101.1679 0001968 48.3364 350.0262 1.00270866 5534 EXPRESS-AMU1 -1 41191U 15082A 17109.79495979 .00000147 00000-0 00000-0 0 9991 -2 41191 0.0061 239.0346 0002242 134.0689 157.2840 1.00275812 4965 +1 41191U 15082A 17157.91591514 .00000151 00000-0 00000-0 0 9995 +2 41191 0.0024 331.7311 0002025 93.7745 195.8078 1.00271621 5448 GAOFEN 4 -1 41194U 15083A 17109.95158472 -.00000344 00000-0 00000-0 0 9997 -2 41194 0.0276 270.5707 0002482 288.3881 97.5910 1.00272587 4948 +1 41194U 15083A 17157.96397770 -.00000339 00000-0 00000-0 0 9991 +2 41194 0.0802 99.3310 0003190 117.4378 131.5242 1.00269785 5427 BELINTERSAT-1 -1 41238U 16001A 17109.86091057 .00000098 00000-0 10000-3 0 9991 -2 41238 0.0476 80.8418 0001400 321.8439 166.8973 1.00270521 4733 +1 41238U 16001A 17156.89909698 .00000100 00000-0 10000-3 0 9999 +2 41238 0.0412 131.9830 0001783 301.3605 196.3216 1.00272261 5193 IRNSS-1E -1 41241U 16003A 17109.43385342 -.00000261 00000-0 00000-0 0 9992 -2 41241 28.6899 115.7032 0019738 187.5177 172.4980 1.00269458 4649 +1 41241U 16003A 17151.92699686 -.00000279 00000-0 00000-0 0 9991 +2 41241 28.7592 114.9659 0019172 183.8467 36.2942 1.00270514 5077 INTELSAT 29E (IS-29E) -1 41308U 16004A 17108.56430669 -.00000290 00000-0 00000-0 0 9995 -2 41308 0.0112 234.0167 0001813 152.7944 333.2029 1.00271523 4603 +1 41308U 16004A 17157.43055619 -.00000287 00000-0 00000-0 0 9999 +2 41308 0.0402 124.8072 0002054 314.9781 280.2382 1.00272516 5118 EUTELSAT 9B -1 41310U 16005A 17108.40084250 .00000053 00000-0 00000-0 0 9999 -2 41310 0.0659 103.3328 0004200 242.3758 14.2841 1.00271734 4568 +1 41310U 16005A 17157.26699015 .00000057 00000-0 00000-0 0 9992 +2 41310 0.0496 126.1871 0001739 220.0825 13.7258 1.00274685 5054 SES-9 -1 41380U 16013A 17109.12304699 -.00000354 00000-0 00000-0 0 9992 -2 41380 0.0289 292.5928 0001503 120.3229 307.1031 1.00273492 3952 +1 41380U 16013A 17156.99199875 -.00000352 00000-0 00000-0 0 9995 +2 41380 0.0171 323.9761 0001871 110.6916 285.3528 1.00272955 4681 EUTELSAT 65 WEST A -1 41382U 16014A 17108.60646641 -.00000284 00000-0 00000-0 0 9995 -2 41382 0.0535 1.4670 0001810 42.9219 315.6301 1.00269437 4092 +1 41382U 16014A 17156.47536617 -.00000284 00000-0 00000-0 0 9994 +2 41382 0.0464 4.2061 0001803 67.6657 288.1467 1.00273478 4491 IRNSS-1F -1 41384U 16015A 17108.07655739 .00000144 00000-0 00000-0 0 9991 -2 41384 4.2823 266.5566 0021021 174.5290 185.3144 1.00268992 4132 +1 41384U 16015A 17156.94054837 .00000154 00000-0 00000-0 0 9993 +2 41384 4.1802 265.3994 0022688 181.7070 178.5192 1.00276072 4625 BEIDOU IGSO 6 -1 41434U 16021A 17109.93294973 -.00000104 00000-0 10000-3 0 9990 -2 41434 55.4678 73.0379 0027418 186.2336 20.1519 1.00282535 3943 +1 41434U 16021A 17157.65734022 -.00000177 00000-0 10000-3 0 9996 +2 41434 55.5278 72.5149 0026618 183.6472 331.4539 1.00272722 4423 IRNSS-1G -1 41469U 16027A 17109.80548166 -.00000350 00000-0 00000-0 0 9995 -2 41469 4.3521 267.8276 0001662 81.9772 277.8583 1.00272940 3657 +1 41469U 16027A 17157.67271219 -.00000337 00000-0 00000-0 0 9990 +2 41469 4.2514 266.7228 0000811 126.7626 233.4852 1.00276255 4138 JCSAT 2B -1 41471U 16028A 17108.99641659 -.00000174 00000-0 00000-0 0 9993 -2 41471 0.0152 212.5195 0001316 207.3801 300.1134 1.00267815 3537 +1 41471U 16028A 17156.86540709 -.00000172 00000-0 00000-0 0 9994 +2 41471 0.0206 344.0388 0001744 97.0403 278.9406 1.00271311 4046 THAICOM 8 -1 41552U 16031A 17109.20564832 -.00000130 00000-0 00000-0 0 9991 -2 41552 0.0609 49.6106 0005206 346.5402 323.8895 1.00271880 3184 +1 41552U 16031A 17156.07731655 -.00000130 00000-0 00000-0 0 9997 +2 41552 0.0755 54.9061 0004450 354.2584 310.8724 1.00271674 3708 INTELSAT 31 (IS-31) -1 41581U 16035A 17108.68905406 -.00000159 00000-0 00000-0 0 9995 -2 41581 0.0165 235.0901 0001521 329.6450 155.2623 1.00270775 3153 +1 41581U 16035A 17156.55797754 -.00000158 00000-0 00000-0 0 9998 +2 41581 0.0263 266.5979 0001050 350.7469 102.6424 1.00272562 3621 BEIDOU G7 -1 41586U 16037A 17108.89666898 -.00000258 00000-0 00000-0 0 9994 -2 41586 1.3357 315.3485 0001413 293.0668 66.1289 1.00271303 3245 -ABS-2A -1 41588U 16038A 17109.21603041 -.00000092 00000-0 00000-0 0 9991 -2 41588 0.0140 203.8626 0001635 106.8769 49.2463 1.00271507 3174 +1 41586U 16037A 17157.77149967 -.00000255 00000-0 00000-0 0 9995 +2 41586 1.2548 317.4376 0001449 263.9468 96.1170 1.00267179 3733 +ABS-2A (MONGOLSAT-1) +1 41588U 16038A 17157.08504291 -.00000090 00000-0 00000-0 0 9994 +2 41588 0.0175 352.9121 0002063 11.1873 355.9023 1.00271473 3652 EUTELSAT 117 WEST B -1 41589U 16038B 17108.74976076 -.00000020 00000-0 00000-0 0 9991 -2 41589 0.0020 62.9880 0000589 245.6426 51.3642 1.00271393 3151 +1 41589U 16038B 17156.61871427 -.00000019 00000-0 00000-0 0 9992 +2 41589 0.0011 150.6444 0000191 117.9652 91.3882 1.00273023 3638 BRISAT -1 41591U 16039A 17108.00901951 -.00000206 00000-0 00000-0 0 9990 -2 41591 0.0233 244.8899 0002135 138.2883 336.8314 1.00268925 3080 +1 41591U 16039A 17156.87509979 -.00000203 00000-0 00000-0 0 9999 +2 41591 0.0197 323.0587 0002303 109.2375 287.7287 1.00271878 3561 ECHOSTAR 18 -1 41592U 16039B 17108.59571440 -.00000290 00000-0 00000-0 0 9994 -2 41592 0.0362 83.3856 0002203 301.1179 335.5116 1.00272705 3085 +1 41592U 16039B 17156.46482146 -.00000290 00000-0 00000-0 0 9997 +2 41592 0.0186 349.3730 0002661 75.4375 295.2171 1.00272715 3558 TIANTONG-1 1 -1 41725U 16048A 17109.98839853 -.00000331 00000-0 00000-0 0 9997 -2 41725 4.6664 325.2502 0005147 47.8490 292.4837 1.00273060 2720 +1 41725U 16048A 17157.96535390 -.00000323 00000-0 00000-0 0 9998 +2 41725 4.6001 325.3222 0003197 61.0390 318.1514 1.00268250 3213 JCSAT-16 -1 41729U 16050A 17108.97413394 -.00000101 00000-0 00000-0 0 9995 -2 41729 0.0214 233.9840 0001950 164.1830 321.8468 1.00269925 2524 +1 41729U 16050A 17156.84308590 -.00000099 00000-0 00000-0 0 9991 +2 41729 0.0182 4.5057 0001977 77.2034 278.3128 1.00270643 3001 INTELSAT 36 (IS-36) -1 41747U 16053A 17107.23874362 -.00000034 00000-0 00000-0 0 9997 -2 41747 0.0400 57.8421 0002632 315.5832 346.5849 1.00272866 2403 +1 41747U 16053A 17157.10224625 -.00000031 00000-0 00000-0 0 9996 +2 41747 0.0351 68.1148 0003188 305.6980 346.1959 1.00271935 2921 INTELSAT 33E (IS-33E) -1 41748U 16053B 17109.25689042 .00000040 00000-0 00000-0 0 9997 -2 41748 0.0077 283.4605 0001942 115.4537 321.1050 1.00272322 2665 +1 41748U 16053B 17157.12580693 .00000042 00000-0 00000-0 0 9990 +2 41748 0.0280 53.2312 0001987 42.9356 263.8558 1.00273968 3158 INSAT-3DR -1 41752U 16054A 17109.21783586 -.00000086 00000-0 00000-0 0 9998 -2 41752 0.0502 110.6593 0006977 172.6235 76.6448 1.00273404 2275 +1 41752U 16054A 17157.08690279 -.00000083 00000-0 00000-0 0 9999 +2 41752 0.0492 273.0204 0005898 5.9511 80.9615 1.00272237 2752 GSAT-18 -1 41793U 16060A 17109.21832816 -.00000086 00000-0 00000-0 0 9991 -2 41793 0.0681 103.5668 0007141 344.5396 271.9804 1.00272774 1997 +1 41793U 16060A 17157.08728701 -.00000083 00000-0 00000-0 0 9993 +2 41793 0.0522 125.5807 0008392 321.2972 273.2183 1.00272754 2478 SKY MUSTER 2 -1 41794U 16060B 17109.02193438 -.00000253 00000-0 00000-0 0 9997 -2 41794 0.0161 252.1229 0001560 142.4845 325.4077 1.00271260 1983 +1 41794U 16060B 17156.89088062 -.00000251 00000-0 00000-0 0 9998 +2 41794 0.0159 317.9919 0001850 114.8702 287.1579 1.00271100 2461 HIMAWARI-9 -1 41836U 16064A 17109.03310503 -.00000284 00000-0 00000-0 0 9997 -2 41836 0.0162 231.3963 0000976 186.6913 301.9219 1.00268372 1641 +1 41836U 16064A 17156.90204452 -.00000281 00000-0 00000-0 0 9997 +2 41836 0.0132 44.4867 0001500 36.3302 279.1996 1.00273071 2125 SHIJIAN-17 (SJ-17) -1 41838U 16065A 17109.80052440 -.00000093 00000-0 00000-0 0 9996 -2 41838 0.0565 66.4860 0008876 31.5156 201.2680 1.00267898 1687 +1 41838U 16065A 17157.62437860 -.00000315 00000-0 00000-0 0 9999 +2 41838 0.1537 86.2147 0001778 18.5593 154.3135 1.00090507 2167 GOES 16 -1 41866U 16071A 17108.67373753 -.00000190 00000-0 00000-0 0 9999 -2 41866 0.0014 223.2961 0001987 178.7937 317.9255 1.00269109 1555 +1 41866U 16071A 17156.54258151 -.00000188 00000-0 00000-0 0 9999 +2 41866 0.0014 287.1718 0000772 114.4348 318.3993 1.00261476 2035 TIANLIAN 1-04 -1 41869U 16072A 17107.14392972 -.00000118 00000-0 00000-0 0 9998 -2 41869 2.7838 290.2877 0005754 125.0979 278.8535 1.00271227 1749 +1 41869U 16072A 17157.90505278 -.00000111 00000-0 00000-0 0 9995 +2 41869 2.6784 289.9420 0007110 146.7236 221.6497 1.00272396 2259 FENGYUN 4A -1 41882U 16077A 17109.58103998 -.00000307 00000-0 00000-0 0 9996 -2 41882 0.1297 268.7524 0002994 226.4283 21.1594 1.00263665 1438 +1 41882U 16077A 17157.97017885 -.00000334 00000-0 00000-0 0 9991 +2 41882 0.0320 250.4568 0009426 195.4519 263.5833 1.00269626 1918 ECHOSTAR 19 -1 41893U 16079A 17108.69476273 -.00000146 00000-0 00000-0 0 9991 -2 41893 0.0187 226.6808 0001485 182.5815 310.7505 1.00268526 1173 +1 41893U 16079A 17156.56377543 -.00000146 00000-0 00000-0 0 9990 +2 41893 0.0231 328.6797 0001923 102.3709 288.9703 1.00273918 1663 STAR ONE D1 -1 41904U 16082B 17108.65855044 -.00000219 00000-0 00000-0 0 9992 -2 41904 0.0245 111.6291 0002451 293.1443 315.2510 1.00272670 1227 +1 41904U 16082B 17156.52745717 -.00000218 00000-0 00000-0 0 9995 +2 41904 0.0372 91.4069 0002354 350.9388 277.6800 1.00271924 1716 TJS-2 -1 41911U 17001A 17109.50654808 -.00000351 00000-0 00000-0 0 9999 -2 41911 0.7999 280.0638 0002553 167.2440 50.2427 1.00265878 1185 +1 41911U 17001A 17157.96319302 -.00000345 00000-0 00000-0 0 9992 +2 41911 0.6987 279.6145 0001076 207.3678 222.8143 1.00267197 1667 HISPASAT 36W-1 -1 41942U 17006A 17108.49778271 -.00000201 00000-0 00000-0 0 9990 -2 41942 0.0307 126.3547 0002775 260.8299 332.8345 1.00273657 972 +1 41942U 17006A 17156.39406066 -.00000251 00000-0 00000-0 0 9997 +2 41942 0.0574 107.7778 0001097 335.2546 276.9788 1.00272717 1454 TELKOM 3S -1 41944U 17007A 17109.09603879 -.00000371 00000-0 00000-0 0 9999 -2 41944 0.0531 73.1774 0000708 6.1870 280.6486 1.00271256 669 +1 41944U 17007A 17156.96517789 -.00000369 00000-0 00000-0 0 9998 +2 41944 0.0196 325.4121 0002604 119.1288 275.4888 1.00269877 1070 INTELSAT 32E (IS-32E) -1 41945U 17007B 17108.54534578 -.00000277 00000-0 00000-0 0 9993 -2 41945 0.0211 232.4659 0000439 284.8357 202.7003 1.00268694 698 +1 41945U 17007B 17157.41157112 -.00000274 00000-0 00000-0 0 9995 +2 41945 0.0179 8.1546 0000641 349.1981 2.6473 1.00270850 1176 +ECHOSTAR 23 +1 42070U 17014A 17157.41643175 -.00000278 00000-0 00000-0 0 9996 +2 42070 0.0216 331.8718 0002115 103.7733 284.3784 1.00270214 887 +SES-10 +1 42432U 17017A 17157.47759086 -.00000277 00000-0 00000-0 0 9995 +2 42432 0.0328 338.8066 0002019 110.1376 271.0789 1.00269446 719 +CHINASAT 16 (SJ-13) +1 42662U 17018A 17156.98568600 -.00000359 00000-0 00000-0 0 9997 +2 42662 0.1082 97.0396 0003514 129.1950 133.7356 1.00271270 667 +KOREASAT 7 +1 42691U 17023A 17157.60290750 -.00000367 00000-0 00000-0 0 9992 +2 42691 0.0077 349.1222 0000873 76.8932 162.0996 1.00270811 377 +SGDC +1 42692U 17023B 17157.42566131 -.00000256 00000-0 00000-0 0 9999 +2 42692 0.0526 44.5619 0000855 34.5487 254.8001 1.00271224 375 +GSAT-9 +1 42695U 17024A 17156.71022076 -.00000294 00000-0 00000-0 0 9991 +2 42695 0.0413 178.9945 0003863 260.0872 168.2197 1.00273618 354 \ No newline at end of file diff --git a/data/scene/satellites/tle/gps-ops.txt b/data/scene/satellites/tle/gps-ops.txt index 5a498425e9..75e18e3533 100644 --- a/data/scene/satellites/tle/gps-ops.txt +++ b/data/scene/satellites/tle/gps-ops.txt @@ -1,93 +1,93 @@ GPS BIIR-2 (PRN 13) -1 24876U 97035A 17109.73375644 -.00000012 00000-0 00000-0 0 9992 -2 24876 55.5643 229.4105 0036557 106.5416 253.8548 2.00562036144850 +1 24876U 97035A 17157.59786847 .00000019 00000-0 00000-0 0 9996 +2 24876 55.5513 227.5274 0034589 106.0906 254.3641 2.00561883145810 GPS BIIR-3 (PRN 11) -1 25933U 99055A 17109.65740979 .00000008 00000-0 00000-0 0 9993 -2 25933 51.5943 80.2017 0164482 93.5980 140.6974 2.00559092128473 +1 25933U 99055A 17157.81823278 -.00000081 00000-0 00000-0 0 9990 +2 25933 51.6254 78.0928 0166095 94.4525 354.0300 2.00558378129440 GPS BIIR-4 (PRN 20) -1 26360U 00025A 17109.81822694 .00000034 00000-0 00000-0 0 9999 -2 26360 53.1062 157.3245 0041561 90.8273 1.8392 2.00564454124177 +1 26360U 00025A 17157.82515987 .00000060 00000-0 00000-0 0 9996 +2 26360 53.1170 155.3222 0040993 91.9775 104.3666 2.00561532125131 GPS BIIR-5 (PRN 28) -1 26407U 00040A 17109.72770267 -.00000058 00000-0 00000-0 0 9993 -2 26407 56.6488 347.4270 0199991 270.0939 38.2665 2.00567294122845 +1 26407U 00040A 17157.93926722 -.00000076 00000-0 00000-0 0 9998 +2 26407 56.6372 345.5470 0199158 270.1220 289.7792 2.00567008123812 GPS BIIR-6 (PRN 14) -1 26605U 00071A 17109.91594260 -.00000014 00000-0 00000-0 0 9997 -2 26605 55.1353 227.1576 0091621 248.1584 104.4436 2.00567152120445 +1 26605U 00071A 17157.87543271 .00000026 00000-0 00000-0 0 9993 +2 26605 55.1227 225.2520 0093903 248.3083 174.0281 2.00565489121414 GPS BIIR-7 (PRN 18) -1 26690U 01004A 17109.78566808 .00000030 00000-0 00000-0 0 9997 -2 26690 53.0287 160.2705 0181728 256.2994 113.2448 2.00553627118851 +1 26690U 01004A 17157.89507387 .00000063 00000-0 00000-0 0 9995 +2 26690 53.0389 158.2602 0183394 256.9116 288.9071 2.00570451119814 GPS BIIR-8 (PRN 16) -1 27663U 03005A 17109.59259250 -.00000059 00000-0 00000-0 0 9992 -2 27663 56.7184 347.1682 0092496 23.4683 306.5317 2.00563261104201 +1 27663U 03005A 17157.94951778 -.00000076 00000-0 00000-0 0 9997 +2 27663 56.7061 345.2850 0092504 24.7076 300.8478 2.00560319105174 GPS BIIR-9 (PRN 21) -1 27704U 03010A 17109.45896894 .00000044 00000-0 00000-0 0 9993 -2 27704 53.8252 100.6579 0242330 263.6172 289.5204 2.00560332102998 +1 27704U 03010A 17157.88465515 -.00000050 00000-0 00000-0 0 9993 +2 27704 53.8528 98.6489 0242249 264.5394 334.3334 2.00563816103977 GPS BIIR-10 (PRN 22) -1 28129U 03058A 17108.92540211 .00000021 00000-0 00000-0 0 9992 -2 28129 52.9154 160.3028 0078030 259.1988 99.9936 2.00579000 97688 +1 28129U 03058A 17157.28858587 .00000066 00000-0 00000-0 0 9992 +2 28129 52.9268 158.2762 0077488 261.4987 97.6433 2.00547197 98653 GPS BIIR-11 (PRN 19) -1 28190U 04009A 17109.78405102 -.00000044 00000-0 00000-0 0 9997 -2 28190 55.9742 48.2291 0100656 53.7277 206.5104 2.00565372 95887 +1 28190U 04009A 17157.67197517 -.00000090 00000-0 00000-0 0 9997 +2 28190 55.9984 46.3329 0100885 55.9552 221.8691 2.00564644 96849 GPS BIIR-12 (PRN 23) -1 28361U 04023A 17109.67197838 -.00000016 00000-0 00000-0 0 9994 -2 28361 54.1189 222.3390 0116919 218.8962 232.5879 2.00552789 93943 +1 28361U 04023A 17157.86272955 .00000033 00000-0 00000-0 0 9990 +2 28361 54.1085 220.3751 0119012 220.1274 106.1343 2.00555923 94908 GPS BIIR-13 (PRN 02) -1 28474U 04045A 17109.80139524 .00000047 00000-0 00000-0 0 9999 -2 28474 54.2062 100.0906 0169972 246.2805 298.8317 2.00552002 91333 +1 28474U 04045A 17157.74251056 -.00000050 00000-0 00000-0 0 9995 +2 28474 54.2321 98.1213 0170418 247.2038 351.6925 2.00548722 92298 GPS BIIRM-1 (PRN 17) -1 28874U 05038A 17109.78616237 -.00000048 00000-0 00000-0 0 9996 -2 28874 56.1319 45.4826 0118701 254.3506 28.1379 2.00570959 84737 +1 28874U 05038A 17157.68738399 -.00000090 00000-0 00000-0 0 9999 +2 28874 56.1546 43.5924 0118451 254.5136 55.9262 2.00568186 85694 GPS BIIRM-2 (PRN 31) -1 29486U 06042A 17109.84481250 .00000007 00000-0 00000-0 0 9998 -2 29486 55.4369 284.6203 0085225 343.6385 263.4212 2.00562325 77337 +1 29486U 06042A 17157.89402977 -.00000073 00000-0 00000-0 0 9999 +2 29486 55.4047 282.7005 0084721 343.9526 36.5660 2.00559154 78309 GPS BIIRM-3 (PRN 12) -1 29601U 06052A 17109.44438112 -.00000058 00000-0 00000-0 0 9990 -2 29601 56.6911 346.0938 0064836 46.5746 314.0087 2.00578841 76304 +1 29601U 06052A 17157.30711204 -.00000075 00000-0 00000-0 0 9993 +2 29601 56.6791 344.2294 0064809 49.4604 311.1238 2.00552294 77266 GPS BIIRM-4 (PRN 15) -1 32260U 07047A 17109.76747141 -.00000018 00000-0 00000-0 0 9996 -2 32260 53.2450 218.7351 0089867 32.0784 328.4730 2.00550702 69758 +1 32260U 07047A 17157.13563594 .00000032 00000-0 00000-0 0 9993 +2 32260 53.2348 216.7628 0090280 32.1796 328.4497 2.00547487 70695 GPS BIIRM-5 (PRN 29) -1 32384U 07062A 17109.82767948 -.00000047 00000-0 00000-0 0 9996 -2 32384 56.1949 46.0590 0007162 349.1522 190.7070 2.00567498 68450 +1 32384U 07062A 17156.21822177 -.00000098 00000-0 00000-0 0 9993 +2 32384 56.2180 44.2317 0006335 4.0971 192.7823 2.00570259 69404 GPS BIIRM-6 (PRN 07) -1 32711U 08012A 17109.17017566 .00000005 00000-0 00000-0 0 9991 -2 32711 55.1649 284.0298 0104617 211.6174 147.7414 2.00555102 66640 +1 32711U 08012A 17157.53427379 -.00000075 00000-0 00000-0 0 9999 +2 32711 55.1332 282.0856 0107470 212.2063 147.1234 2.00556288 67631 GPS BIIRM-8 (PRN 05) -1 35752U 09043A 17109.80875753 .00000030 00000-0 00000-0 0 9992 -2 35752 54.2447 161.8840 0048052 28.4418 96.4367 2.00557153 56266 +1 35752U 09043A 17157.70219478 .00000069 00000-0 00000-0 0 9992 +2 35752 54.2537 159.9422 0048788 28.4210 116.6992 2.00553334 57229 GPS BIIF-1 (PRN 25) -1 36585U 10022A 17109.45861331 -.00000056 00000-0 00000-0 0 9993 -2 36585 56.0008 342.9525 0062857 43.8593 292.2361 2.00572192 50488 +1 36585U 10022A 17157.89436302 -.00000078 00000-0 00000-0 0 9994 +2 36585 55.9864 341.0322 0063534 45.4099 345.2901 2.00574808 51467 GPS BIIF-2 (PRN 01) -1 37753U 11036A 17109.65756309 .00000053 00000-0 00000-0 0 9993 -2 37753 55.4143 103.1083 0063799 28.9219 177.7211 2.00561953 42171 +1 37753U 11036A 17157.85963422 -.00000044 00000-0 00000-0 0 9995 +2 37753 55.4395 101.1871 0066031 30.2070 60.5198 2.00562311 43146 GPS BIIF-3 (PRN 24) -1 38833U 12053A 17109.36112639 .00000003 00000-0 00000-0 0 9998 -2 38833 54.1932 280.9976 0055446 25.7503 334.5131 2.00560911 33233 +1 38833U 12053A 17157.72375300 -.00000072 00000-0 00000-0 0 9994 +2 38833 54.1611 279.0056 0055661 25.8719 334.3965 2.00561617 33411 GPS BIIF-4 (PRN 27) -1 39166U 13023A 17109.71335229 -.00000054 00000-0 00000-0 0 9994 -2 39166 55.8396 42.5193 0046353 15.5591 344.5802 2.00565270 28782 +1 39166U 13023A 17157.07836358 -.00000093 00000-0 00000-0 0 9998 +2 39166 55.8615 40.6350 0047704 18.0209 342.1899 2.00565151 29728 GPS BIIF-5 (PRN 30) -1 39533U 14008A 17109.71803235 .00000003 00000-0 00000-0 0 9996 -2 39533 54.3474 286.2694 0026612 180.2094 179.7840 2.00561576 22608 +1 39533U 14008A 17157.58173524 -.00000078 00000-0 00000-0 0 9998 +2 39533 54.3154 284.3055 0028684 182.6529 177.3191 2.00563830 23567 GPS BIIF-6 (PRN 06) -1 39741U 14026A 17109.49522789 .00000051 00000-0 00000-0 0 9997 -2 39741 55.4016 102.6345 0010242 287.2500 72.6522 2.00565694 21432 +1 39741U 14026A 17157.35873360 -.00000044 00000-0 00000-0 0 9992 +2 39741 55.4261 100.7272 0009830 291.4939 68.3647 2.00562339 22395 GPS BIIF-7 (PRN 09) -1 40105U 14045A 17109.58870938 -.00000015 00000-0 00000-0 0 9997 -2 40105 54.6417 222.2176 0006094 114.5172 245.5503 2.00565991 19002 +1 40105U 14045A 17157.45126217 .00000031 00000-0 00000-0 0 9997 +2 40105 54.6318 220.2927 0005069 122.1672 237.9622 2.00569715 19965 GPS BIIF-8 (PRN 03) -1 40294U 14068A 17109.45908091 .00000027 00000-0 00000-0 0 9991 -2 40294 54.9913 162.8335 0006001 343.2122 16.8409 2.00553719 18104 +1 40294U 14068A 17157.32446828 .00000074 00000-0 00000-0 0 9997 +2 40294 55.0008 160.9300 0007263 345.6258 14.3805 2.00557500 19060 GPS BIIF-9 (PRN 26) -1 40534U 15013A 17109.59579211 -.00000056 00000-0 00000-0 0 9995 -2 40534 54.9576 342.1019 0018236 356.2473 3.7829 2.00562102 14725 +1 40534U 15013A 17157.46020623 -.00000081 00000-0 00000-0 0 9990 +2 40534 54.9417 340.1560 0018129 358.6255 1.3832 2.00559260 16117 GPS BIIF-10 (PRN 08) -1 40730U 15033A 17109.25722952 -.00000055 00000-0 00000-0 0 9999 -2 40730 55.3741 42.2354 0027546 314.4917 45.2822 2.00570200 12905 +1 40730U 15033A 17157.11983367 -.00000094 00000-0 00000-0 0 9999 +2 40730 55.3960 40.3091 0027177 318.4074 41.4282 2.00567662 13865 GPS BIIF-11 (PRN 10) -1 41019U 15062A 17109.31059499 .00000026 00000-0 00000-0 0 9995 -2 41019 55.0013 162.6249 0025268 204.7841 155.1668 2.00563458 10725 +1 41019U 15062A 17157.67265313 .00000072 00000-0 00000-0 0 9992 +2 41019 55.0103 160.7038 0026458 206.0557 153.8364 2.00563621 11698 GPS BIIF-12 (PRN 32) -1 41328U 16007A 17109.39652641 -.00000014 00000-0 00000-0 0 9992 -2 41328 54.8999 222.3973 0011692 216.7815 143.1423 2.00558460 8782 +1 41328U 16007A 17157.76013989 .00000034 00000-0 00000-0 0 9993 +2 41328 54.8890 220.4662 0013935 220.3704 139.6078 2.00556828 9756 diff --git a/data/scene/satellites/tle/stations.txt b/data/scene/satellites/tle/stations.txt index 0f0506fc87..fdab931a9d 100644 --- a/data/scene/satellites/tle/stations.txt +++ b/data/scene/satellites/tle/stations.txt @@ -1,180 +1,285 @@ ISS (ZARYA) -1 25544U 98067A 17109.92096824 .00002787 00000-0 49344-4 0 9990 -2 25544 51.6434 328.7262 0007243 75.4107 32.5712 15.54131334 52697 +1 25544U 98067A 17157.94655197 .00002630 00000-0 47191-4 0 9994 +2 25544 51.6418 89.3693 0004703 241.3496 157.2990 15.53992000 60168 TIANGONG 1 -1 37820U 11053A 17109.70783838 .00019763 00000-0 12539-3 0 9991 -2 37820 42.7590 197.4071 0018147 19.0253 112.4332 15.75889937318739 +1 37820U 11053A 17157.70967876 .00020914 00000-0 11813-3 0 9994 +2 37820 42.7593 264.1306 0019426 359.5204 148.5490 15.78435713326314 AGGIESAT 4 -1 41313U 98067HP 17109.81227259 .00031142 00000-0 24561-3 0 9998 -2 41313 51.6371 301.8896 0003500 267.9298 92.1299 15.71127246 69747 +1 41313U 98067HP 17157.16086447 .00018711 00000-0 13577-3 0 9993 +2 41313 51.6375 59.3234 0004723 101.9367 258.2161 15.73442509 77199 BEVO 2 -1 41314U 98067HQ 17109.68429905 .00156013 20027-4 50373-3 0 9996 -2 41314 51.6235 283.2567 0005515 275.3685 84.6691 15.90548487 69787 -MINXSS -1 41474U 98067HU 17109.73827802 .00306018 48569-4 71516-3 0 9992 -2 41474 51.6472 293.8859 0006892 279.9569 80.0662 15.96438057 53089 -STMSAT-1 -1 41476U 98067HW 17109.88070258 .02335240 11870-4 10986-2 0 9994 -2 41476 51.6204 288.5305 0012717 288.4489 71.5067 16.20615210 53079 +1 41314U 98067HQ 17157.88632967 .00703414 31345-3 45291-3 0 9995 +2 41314 51.6177 25.8163 0007485 251.9715 108.0487 16.16778687 77482 NODES 2 -1 41477U 98067HX 17109.78732856 .00065132 00000-0 42046-3 0 9993 -2 41477 51.6317 305.4154 0003507 222.8310 137.2416 15.75484120 52843 +1 41477U 98067HX 17157.90383726 .00052219 00000-0 26238-3 0 9995 +2 41477 51.6294 56.6595 0003371 94.5932 265.5455 15.81168393 60445 NODES 1 -1 41478U 98067HY 17109.81327838 .00066571 00000-0 43583-3 0 9993 -2 41478 51.6337 305.5905 0003334 219.7891 140.2864 15.75153441 52848 +1 41478U 98067HY 17157.81578248 .00053127 00000-0 27329-3 0 9992 +2 41478 51.6327 57.5946 0003116 94.0560 266.0798 15.80650524 60427 FLOCK 2E'-1 -1 41479U 98067HZ 17109.82905449 .00029193 00000-0 27831-3 0 9992 -2 41479 51.6365 313.2731 0001172 62.9361 297.1754 15.66532776 52708 +1 41479U 98067HZ 17157.82937824 .00017516 00000-0 15561-3 0 9990 +2 41479 51.6361 69.0720 0001235 132.9379 227.1721 15.68631858 60232 FLOCK 2E'-3 -1 41480U 98067JA 17109.78977551 .00023981 00000-0 22881-3 0 9991 -2 41480 51.6367 313.0301 0001516 116.2427 243.8724 15.66630662 52697 +1 41480U 98067JA 17157.85350922 .00015886 00000-0 14210-3 0 9991 +2 41480 51.6360 68.5033 0000732 66.0320 294.0753 15.68548906 60237 FLOCK 2E'-2 -1 41481U 98067JB 17109.83105879 .00025245 00000-0 23401-3 0 9998 -2 41481 51.6355 311.7758 0001181 45.0304 315.0788 15.67316853 52705 +1 41481U 98067JB 17157.93598542 .00014396 00000-0 12524-3 0 9994 +2 41481 51.6345 66.7643 0001590 141.5719 218.5391 15.69326443 60254 FLOCK 2E'-4 -1 41482U 98067JC 17109.79676564 .00028405 00000-0 24875-3 0 9995 -2 41482 51.6352 311.5368 0001631 168.7346 191.3688 15.68647594 52701 +1 41482U 98067JC 17157.79065223 .00022341 00000-0 17773-3 0 9994 +2 41482 51.6345 66.5289 0001496 79.7829 280.3337 15.71128503 60244 FLOCK 2E-1 -1 41483U 98067ID 17109.65478592 .00019453 00000-0 19150-3 0 9995 -2 41483 51.6381 314.4039 0002624 157.9400 202.1709 15.65994639 52522 +1 41483U 98067ID 17157.29569450 .00013969 00000-0 13019-3 0 9996 +2 41483 51.6375 72.3135 0002141 32.0954 328.0172 15.67656718 59998 FLOCK 2E-2 -1 41484U 98067JE 17109.82139276 .00023265 00000-0 21668-3 0 9991 -2 41484 51.6388 312.5323 0002244 167.0663 193.0391 15.67251790 52561 +1 41484U 98067JE 17157.23012824 .00019455 00000-0 16890-3 0 9995 +2 41484 51.6385 71.1428 0002213 46.7114 313.4067 15.69112127 60000 FLOCK 2E-3 -1 41486U 98067JG 17109.83030932 .00019642 00000-0 19928-3 0 9993 -2 41486 51.6376 314.8200 0002650 199.1890 160.9006 15.65226077 52551 +1 41486U 98067JG 17157.94249624 .00012046 00000-0 11618-3 0 9997 +2 41486 51.6371 70.6259 0002649 64.7641 295.3629 15.66964173 60095 FLOCK 2E-4 -1 41487U 98067JH 17109.84556035 .00021562 00000-0 21013-3 0 9994 -2 41487 51.6376 313.3996 0002901 202.4468 157.6401 15.66171142 52573 +1 41487U 98067JH 17157.79997702 .00013956 00000-0 12913-3 0 9998 +2 41487 51.6373 69.6496 0003643 57.6827 302.4521 15.67836732 60092 FLOCK 2E-6 -1 41563U 98067JM 17109.78874028 .00018524 00000-0 19029-3 0 9995 -2 41563 51.6372 315.2682 0001335 51.8098 308.3017 15.64958450 50616 +1 41563U 98067JM 17157.84789515 .00010970 00000-0 10867-3 0 9999 +2 41563 51.6366 71.4681 0001397 138.8569 221.2533 15.66405325 58148 FLOCK 2E-5 -1 41564U 98067JN 17109.79523798 .00018624 00000-0 19210-3 0 9995 -2 41564 51.6372 315.3186 0001291 58.7101 301.4020 15.64849440 50604 +1 41564U 98067JN 17157.85787038 .00011762 00000-0 11662-3 0 9993 +2 41564 51.6367 71.5423 0001207 135.2529 224.8564 15.66295284 58135 FLOCK 2E-7 -1 41565U 98067JP 17109.77087667 .00027808 00000-0 25811-3 0 9992 -2 41565 51.6365 312.8853 0002940 243.9307 116.1387 15.67223362 50539 +1 41565U 98067JP 17157.81556449 .00017448 00000-0 15131-3 0 9992 +2 41565 51.6360 68.2287 0004609 80.6839 279.4679 15.69221451 58070 FLOCK 2E-8 -1 41566U 98067JQ 17109.80005150 .00089692 00000-0 42658-3 0 9991 -2 41566 51.6335 301.7154 0005913 241.2167 118.8242 15.82123501 50671 +1 41566U 98067JQ 17157.91086070 .00121698 16725-4 36063-3 0 9997 +2 41566 51.6286 49.8665 0004713 142.6928 217.4407 15.92335896 58310 FLOCK 2E'-5 -1 41567U 98067JR 17109.82240982 .00018645 00000-0 19803-3 0 9994 -2 41567 51.6378 316.2578 0003052 269.9747 90.0898 15.64101875 50468 +1 41567U 98067JR 17157.78191446 .00011191 00000-0 11495-3 0 9990 +2 41567 51.6378 73.2981 0004907 93.3825 266.7732 15.65457253 57979 FLOCK 2E'-6 -1 41568U 98067JS 17109.73365885 .00019933 00000-0 19922-3 0 9998 -2 41568 51.6366 314.8878 0002651 264.8215 95.2478 15.65593919 50502 +1 41568U 98067JS 17157.77145550 .00014626 00000-0 13869-3 0 9998 +2 41568 51.6364 70.9405 0004513 92.1048 268.0465 15.67174872 58038 FLOCK 2E'-8 -1 41569U 98067JT 17109.81323064 .00028772 00000-0 26479-3 0 9997 -2 41569 51.6363 312.4223 0001607 185.1389 174.9591 15.67417153 50424 +1 41569U 98067JT 17157.91417765 .00016441 00000-0 14148-3 0 9993 +2 41569 51.6361 67.3905 0002434 64.2282 295.8966 15.69467197 57974 FLOCK 2E'-7 -1 41570U 98067JU 17109.84953955 .00031567 00000-0 26673-3 0 9992 -2 41570 51.6369 310.4309 0002960 184.1959 175.9014 15.69458790 50470 +1 41570U 98067JU 17157.81477341 .00022161 00000-0 16934-3 0 9991 +2 41570 51.6364 65.2376 0002923 51.8320 308.2941 15.72094779 58010 FLOCK 2E-9 -1 41571U 98067JV 17109.82645424 .00028760 00000-0 26059-3 0 9999 -2 41571 51.6370 311.7739 0002674 242.4455 117.6270 15.67801154 50410 +1 41571U 98067JV 17157.85234832 .00017668 00000-0 14924-3 0 9995 +2 41571 51.6366 66.9928 0004309 82.3948 277.7538 15.69854026 57958 FLOCK 2E-10 -1 41572U 98067JW 17109.81540411 .00024857 00000-0 23657-3 0 9993 -2 41572 51.6371 313.2010 0003003 248.3230 111.7447 15.66668690 50397 +1 41572U 98067JW 17157.81407914 .00017118 00000-0 15232-3 0 9998 +2 41572 51.6364 68.9926 0004709 84.5269 275.6265 15.68604804 57928 FLOCK 2E-12 -1 41573U 98067JX 17109.77960367 .00027556 00000-0 25527-3 0 9992 -2 41573 51.6367 312.9551 0002571 267.1560 92.9142 15.67278525 50390 +1 41573U 98067JX 17157.94759666 .00016648 00000-0 14342-3 0 9995 +2 41573 51.6359 67.6218 0004148 94.9148 265.2323 15.69425430 57951 FLOCK 2E-11 -1 41574U 98067JY 17109.78226357 .00026708 00000-0 24509-3 0 9995 -2 41574 51.6353 312.1863 0003298 269.1599 90.9019 15.67528751 50407 +1 41574U 98067JY 17157.94425949 .00017277 00000-0 14780-3 0 9995 +2 41574 51.6347 66.8056 0005101 97.8056 262.3520 15.69560822 57963 FLOCK 2E'-9 -1 41575U 98067JZ 17109.81056748 .00029764 00000-0 26509-3 0 9992 -2 41575 51.6348 311.6084 0002751 288.6496 71.4202 15.68204720 50402 +1 41575U 98067JZ 17157.81983142 .00020007 00000-0 16391-3 0 9991 +2 41575 51.6346 66.7030 0004859 109.2903 250.8620 15.70492303 57943 FLOCK 2E'-10 -1 41576U 98067KA 17109.77269490 .00030074 00000-0 27691-3 0 9997 -2 41576 51.6376 312.9270 0002762 288.6796 71.3901 15.67378357 50288 +1 41576U 98067KA 17157.81080505 .00018690 00000-0 16006-3 0 9991 +2 41576 51.6368 68.2311 0004669 108.5169 251.6336 15.69470167 57824 FLOCK 2E'-11 -1 41577U 98067KB 17109.79101284 .00023668 00000-0 22296-3 0 9993 -2 41577 51.6378 313.0548 0003312 262.9815 97.0805 15.66954445 50106 +1 41577U 98067KB 17157.84387094 .00016884 00000-0 14804-3 0 9995 +2 41577 51.6373 68.4600 0005029 90.7988 269.3585 15.68978391 57649 FLOCK 2E'-12 -1 41578U 98067KC 17109.83071225 .00028915 00000-0 26144-3 0 9996 -2 41578 51.6355 312.5190 0003879 246.8376 113.2211 15.67846378 50119 +1 41578U 98067KC 17157.85229234 .00021128 00000-0 17555-3 0 9991 +2 41578 51.6350 67.7005 0005424 83.6803 276.4812 15.70108031 57654 FLOCK 2E'-13 -1 41761U 98067KH 17109.80002983 .00014655 00000-0 18690-3 0 9995 -2 41761 51.6392 324.4021 0007265 49.8199 310.3429 15.59526131 33795 +1 41761U 98067KH 17157.84121992 .00007650 00000-0 96912-4 0 9995 +2 41761 51.6386 82.7486 0005694 217.4113 142.6484 15.60558941 41297 FLOCK 2E'-14 -1 41762U 98067KJ 17109.85521685 .00012951 00000-0 16504-3 0 9995 -2 41762 51.6404 324.0354 0007100 50.3983 309.7636 15.59672213 33808 +1 41762U 98067KJ 17157.95581036 .00008251 00000-0 10337-3 0 9991 +2 41762 51.6398 82.0348 0005588 217.7092 142.3510 15.60728191 41318 FLOCK 2E'-16 -1 41763U 98067KK 17109.84145497 .00015760 00000-0 19696-3 0 9994 -2 41763 51.6404 323.9389 0006632 60.9401 299.2256 15.59999189 33766 +1 41763U 98067KK 17157.86607714 .00009474 00000-0 11591-3 0 9995 +2 41763 51.6398 82.1815 0004711 229.1912 130.8674 15.61149602 41266 FLOCK 2E'-15 -1 41764U 98067KL 17109.87177553 .00013668 00000-0 17536-3 0 9992 -2 41764 51.6402 324.1424 0006951 56.4927 303.6730 15.59436947 33760 +1 41764U 98067KL 17157.85165937 .00007422 00000-0 94554-4 0 9993 +2 41764 51.6395 82.8349 0005200 225.0806 134.9766 15.60465657 41250 TIANGONG-2 -1 41765U 16057A 17109.88457597 .00006208 00000-0 76612-4 0 9995 -2 41765 42.7849 342.3366 0007020 274.6731 154.6477 15.60877974 33874 +1 41765U 16057A 17157.80446253 .00002148 00000-0 29064-4 0 9995 +2 41765 42.7836 56.6308 0011038 266.5003 156.2729 15.61250586 41363 FLOCK 2E'-18 -1 41769U 98067KM 17109.85904600 .00012974 00000-0 16652-3 0 9993 -2 41769 51.6402 324.0512 0006179 77.3335 282.8349 15.59486030 33761 +1 41769U 98067KM 17157.90167314 .00007746 00000-0 98248-4 0 9998 +2 41769 51.6397 82.4126 0004132 251.5664 108.4880 15.60508848 41269 FLOCK 2E'-17 -1 41776U 98067KN 17109.85282571 .00010304 00000-0 13324-3 0 9995 -2 41776 51.6411 324.0213 0006338 78.3972 281.7732 15.59560942 33750 +1 41776U 98067KN 17157.95839727 .00007735 00000-0 97973-4 0 9997 +2 41776 51.6407 82.0579 0004483 252.8988 107.1514 15.60548603 41262 FLOCK 2E'-19 -1 41777U 98067KP 17109.85740966 .00015381 00000-0 18245-3 0 9990 -2 41777 51.6392 322.5300 0005414 79.0163 281.1440 15.61402073 33734 +1 41777U 98067KP 17157.25856684 .00014123 00000-0 15879-3 0 9995 +2 41777 51.6383 83.3506 0003434 249.6465 110.4161 15.62884005 41142 FLOCK 2E'-20 -1 41782U 98067KQ 17109.83324911 .00018487 00000-0 22266-3 0 9990 -2 41782 51.6405 323.1334 0005543 75.7821 284.3788 15.60844608 33593 -SOYUZ-MS 02 -1 41820U 16063A 17099.31803792 .00003510 00000-0 60428-4 0 9993 -2 41820 51.6436 21.5790 0006756 40.2971 107.7536 15.54046698 51040 +1 41782U 98067KQ 17157.95631435 .00009933 00000-0 11651-3 0 9990 +2 41782 51.6397 80.5325 0003339 246.9810 113.0833 15.62193473 41113 BANXING-2 -1 41834U 16057H 17109.90404225 .00010491 00000-0 10102-3 0 9995 -2 41834 42.7856 340.6951 0007273 205.2685 229.1726 15.66598364 27965 -SOYUZ-MS 03 -1 41864U 16070A 17108.56623476 .00002987 00000-0 52374-4 0 9994 -2 41864 51.6439 335.4785 0007166 70.0921 13.3272 15.54123193 23600 +1 41834U 16057H 17157.77057558 .00008103 00000-0 75609-4 0 9997 +2 41834 42.7847 52.6919 0007283 184.5004 279.8030 15.67673228 35473 STARS-C -1 41895U 98067KR 17109.79899468 .00030018 00000-0 38671-3 0 9995 -2 41895 51.6404 327.3984 0005536 106.1447 254.0155 15.58751599 18878 +1 41895U 98067KR 17157.84313134 .00019979 00000-0 23763-3 0 9994 +2 41895 51.6388 85.7683 0002910 282.4174 77.6493 15.61123932 26374 TANCREDO-1 -1 41931U 98067KT 17109.86190081 .00052089 00000-0 58691-3 0 9995 -2 41931 51.6395 326.3112 0006129 69.5695 290.5957 15.61995558 14461 +1 41931U 98067KT 17157.96072007 .00039094 00000-0 36943-3 0 9993 +2 41931 51.6375 82.7854 0004077 216.5790 143.4928 15.66595418 21991 ITF-2 -1 41932U 98067KU 17109.85588580 .00016634 00000-0 22758-3 0 9991 -2 41932 51.6413 327.7805 0006108 60.3108 299.8492 15.57538630 14445 +1 41932U 98067KU 17157.88784681 .00010759 00000-0 14197-3 0 9997 +2 41932 51.6410 86.8287 0004551 222.4119 137.6522 15.58968825 21931 WASEDA-SAT3 -1 41933U 98067KV 17109.84844175 .00021108 00000-0 28355-3 0 9997 -2 41933 51.6407 327.7291 0005970 62.7540 297.4060 15.57848382 14443 -EGG -1 41934U 98067KW 17109.82873718 .00359689 00000-0 22549-2 0 9997 -2 41934 51.6334 324.5691 0004769 232.7194 127.3371 15.75166791 14578 +1 41933U 98067KV 17157.86766680 .00012735 00000-0 16372-3 0 9998 +2 41933 51.6393 86.6847 0004401 224.8923 135.1714 15.59470034 21932 AOBA-VELOX 3 -1 41935U 98067KX 17109.85496819 .00018693 00000-0 25356-3 0 9991 -2 41935 51.6411 327.7732 0005547 65.6383 294.5187 15.57678773 14541 +1 41935U 98067KX 17157.81606468 .00011476 00000-0 14944-3 0 9996 +2 41935 51.6407 87.0963 0003886 226.1035 133.9638 15.59246212 22020 TUPOD -1 41936U 98067KY 17109.76502401 .00076370 00000-0 79702-3 0 9997 -2 41936 51.6390 326.4192 0004334 84.8776 275.2714 15.63809782 13933 +1 41936U 98067KY 17157.83506049 .00063704 00000-0 50159-3 0 9992 +2 41936 51.6364 81.9421 0002677 193.2921 166.8006 15.70842192 21474 OSNSAT -1 41939U 98067KZ 17109.84725302 .00038473 00000-0 46963-3 0 9991 -2 41939 51.6399 326.9674 0006966 65.0500 295.1216 15.60039674 13811 +1 41939U 98067KZ 17157.84088402 .00022114 00000-0 24411-3 0 9996 +2 41939 51.6393 84.9970 0004937 223.7956 136.2648 15.62981464 21312 PROGRESS-MS 05 -1 42056U 17010A 17108.56623476 .00002987 00000-0 52374-4 0 9993 -2 42056 51.6439 335.4785 0007166 70.0921 13.3272 15.54123193 8629 +1 42056U 17010A 17157.62806167 .00002380 00000-0 43406-4 0 9997 +2 42056 51.6419 90.9570 0004682 239.7339 175.9756 15.53988626 60112 LEMUR-2-REDFERN-GOES -1 42059U 98067LA 17109.86490573 .00020711 00000-0 29467-3 0 9992 -2 42059 51.6413 328.5872 0009106 82.8311 277.3716 15.56286742 6922 +1 42059U 98067LA 17157.87023427 .00010532 00000-0 14537-3 0 9998 +2 42059 51.6398 88.2022 0006952 257.0236 102.9980 15.57773986 14409 TECHEDSAT 5 -1 42066U 98067LB 17109.86435488 .00105210 00000-0 11946-2 0 9994 -2 42066 51.6390 327.8308 0003545 127.5897 232.5420 15.61508635 6667 +1 42066U 98067LB 17157.88081783 .00130272 00000-0 92629-3 0 9998 +2 42066 51.6337 83.7399 0002362 159.2104 200.8991 15.72955201 14190 LEMUR-2-TRUTNA -1 42067U 98067LC 17109.85891074 .00025317 00000-0 35271-3 0 9998 -2 42067 51.6412 328.5475 0008572 83.5926 276.6041 15.56728774 6755 +1 42067U 98067LC 17157.83820430 .00021776 00000-0 27852-3 0 9998 +2 42067 51.6394 87.9877 0006160 253.1659 106.8658 15.59134351 14230 LEMUR-2-AUSTINTACIOUS -1 42068U 98067LD 17109.86578689 .00018494 00000-0 26447-3 0 9997 -2 42068 51.6410 328.5924 0008622 83.6075 276.5898 15.56237023 6857 +1 42068U 98067LD 17157.86892448 .00014740 00000-0 19909-3 0 9997 +2 42068 51.6396 88.1920 0006243 256.1891 103.8407 15.57991820 14338 LEMUR-2-TRUTNAHD -1 42069U 98067LE 17109.86629258 .00021052 00000-0 29958-3 0 9991 -2 42069 51.6412 328.5961 0008488 82.8885 277.3071 15.56276065 6908 +1 42069U 98067LE 17157.80477585 .00011342 00000-0 15525-3 0 9998 +2 42069 51.6404 88.5168 0006281 253.3949 106.6354 15.57911149 14374 ISS DEB -1 42434U 98067LF 17109.82210271 .00056714 00000-0 79599-3 0 9993 -2 42434 51.6406 329.0485 0005861 67.1845 292.9765 15.56154397 3068 +1 42434U 98067LF 17157.20389631 .00040897 00000-0 48519-3 0 9998 +2 42434 51.6377 91.2421 0003699 204.1460 155.9360 15.60776006 10458 CYGNUS OA-7 -1 42681U 17019A 17109.46972691 -.00000487 00000-0 00000-0 0 9991 -2 42681 51.6511 331.0240 0010106 169.9930 268.8149 15.53958196 134 +1 42681U 17019A 17157.83399044 .00001407 00000-0 30326-4 0 9990 +2 42681 51.6394 89.9608 0004737 238.3552 236.4249 15.52253009 7650 +SOYUZ-MS 04 +1 42682U 17020A 17157.62806167 .00002380 00000-0 43406-4 0 9993 +2 42682 51.6419 90.9570 0004682 239.7339 175.9756 15.53988626 60117 +TIANZHOU 1 +1 42684U 17021A 17153.14877196 .00078565 00000-0 89444-3 0 9998 +2 42684 42.7826 84.4016 0010794 236.6582 266.9899 15.61251018 6668 +ISS DEB +1 42697U 98067LG 17157.84861892 .00037507 00000-0 52116-3 0 9995 +2 42697 51.6412 89.5469 0003850 241.7810 118.2802 15.56620141 5063 +SOMP2 +1 42700U 98067LH 17157.85852898 .00010448 00000-0 15717-3 0 9998 +2 42700 51.6402 89.6186 0005697 289.6047 70.4329 15.55441951 3338 +HAVELSAT +1 42701U 98067LJ 17157.85877506 .00009249 00000-0 14019-3 0 9993 +2 42701 51.6404 89.6204 0005687 290.2093 69.8287 15.55398233 3328 +COLUMBIA +1 42702U 98067LK 17157.85640689 .00019375 00000-0 28110-3 0 9992 +2 42702 51.6402 89.6049 0005582 283.5939 76.4431 15.55829187 3256 +SGSAT +1 42703U 98067LL 17157.85837147 .00016082 00000-0 23650-3 0 9996 +2 42703 51.6399 89.6179 0001779 215.0092 145.0783 15.55619060 3249 +CXBN-2 +1 42704U 98067LM 17157.86087475 .00009857 00000-0 14967-3 0 9992 +2 42704 51.6403 89.6346 0001531 217.8699 142.2185 15.55266596 3259 +ICECUBE +1 42705U 98067LN 17157.86139170 .00012469 00000-0 18766-3 0 9997 +2 42705 51.6404 89.6388 0001477 225.7849 134.3021 15.55229909 3316 +PHOENIX +1 42706U 98067LP 17157.85919097 .00010424 00000-0 15699-3 0 9992 +2 42706 51.6405 89.6243 0000606 264.1635 95.9287 15.55419085 3245 +X-CUBESAT +1 42707U 98067LQ 17157.85942325 .00010489 00000-0 15798-3 0 9994 +2 42707 51.6402 89.6253 0000714 261.3522 98.7388 15.55408199 3234 +QBEE50-LTU-OC +1 42708U 98067LR 17157.85976115 .00010073 00000-0 15218-3 0 9995 +2 42708 51.6403 89.6273 0000806 257.2200 102.8701 15.55374747 3199 +ALTAIR PATHFINDER +1 42711U 98067LS 17157.86492244 .00006899 00000-0 10825-3 0 9996 +2 42711 51.6401 89.6607 0004088 214.3267 145.7460 15.54917330 2901 +SHARC +1 42712U 98067LT 17157.86348986 .00006919 00000-0 10815-3 0 9992 +2 42712 51.6404 89.6521 0001998 212.8804 147.2063 15.55020563 3144 +ZA-AEROSAT +1 42713U 98067LU 17157.86235707 .00008829 00000-0 13523-3 0 9990 +2 42713 51.6402 89.6446 0001922 199.0347 161.0573 15.55180619 2906 +LINK +1 42714U 98067LV 17157.86266135 .00009504 00000-0 14497-3 0 9992 +2 42714 51.6401 89.6466 0002117 206.7176 153.3706 15.55190802 3011 +CSUNSAT 1 +1 42715U 98067LW 17157.86415953 .00009161 00000-0 14070-3 0 9993 +2 42715 51.6400 89.6561 0004236 203.1814 156.8987 15.55050192 2904 +UPSAT +1 42716U 98067LX 17157.86094233 .00011468 00000-0 17226-3 0 9997 +2 42716 51.6402 89.6352 0004008 295.0779 64.9796 15.55373568 3039 +SPACECUBE +1 42717U 98067LY 17157.86170034 .00009917 00000-0 15049-3 0 9999 +2 42717 51.6403 89.6401 0003993 293.5006 66.5565 15.55272760 2273 +HOOPOE +1 42718U 98067LZ 17157.86153836 .00010781 00000-0 16274-3 0 9993 +2 42718 51.6403 89.6391 0003987 292.5690 67.4879 15.55311723 2274 +UNSW-ECO +1 42721U 98067MA 17157.80343503 .00013771 00000-0 20735-3 0 9992 +2 42721 51.6403 89.9999 0007120 268.2498 91.7677 15.55097441 1963 +NJUST-1 +1 42722U 98067MB 17157.25292095 .00001440 00000-0 28291-4 0 9997 +2 42722 51.6402 92.7556 0007027 267.2164 245.0421 15.54901758 1874 +CHALLENGER +1 42723U 98067MC 17157.80404552 .00011009 00000-0 16798-3 0 9992 +2 42723 51.6404 90.0040 0006958 268.5782 91.4412 15.54978044 1941 +DUTHSAT +1 42724U 98067MD 17157.80428604 .00013264 00000-0 20078-3 0 9998 +2 42724 51.6404 90.0056 0006075 271.4432 88.5863 15.54994883 1861 +LILACSAT-1 +1 42725U 98067ME 17157.80476334 .00008530 00000-0 13233-3 0 9997 +2 42725 51.6404 90.0092 0006008 272.8653 87.1650 15.54873181 1864 +NSIGHT-1 +1 42726U 98067MF 17157.86942714 .00006534 00000-0 10336-3 0 9997 +2 42726 51.6405 89.6907 0005990 273.7292 86.3014 15.54792750 1882 +SNUSAT-1 +1 42727U 98067MG 17157.86945727 .00009989 00000-0 15371-3 0 9996 +2 42727 51.6398 89.6902 0007575 228.4973 131.5369 15.54864564 1848 +QBITO +1 42728U 98067MH 17155.94045484 .00010441 00000-0 16007-3 0 9997 +2 42728 51.6397 99.3085 0003029 277.2248 82.8398 15.54926471 1380 +AALTO-2 +1 42729U 98067MJ 17155.81189444 .00010269 00000-0 15754-3 0 9995 +2 42729 51.6399 99.9497 0003050 275.8476 84.2168 15.54929551 1379 +SUSAT +1 42730U 98067MK 17157.80448090 .00010291 00000-0 15784-3 0 9991 +2 42730 51.6404 90.0078 0003110 281.5326 78.5315 15.54933074 1678 +I-INSPIRE II +1 42731U 98067ML 17156.13327249 .00009265 00000-0 14256-3 0 9991 +2 42731 51.6393 98.3448 0007164 207.3399 152.7216 15.54972835 1467 +POLYITAN-2-SAU +1 42732U 98067MM 17155.94043987 .00010678 00000-0 16312-3 0 9999 +2 42732 51.6392 99.3069 0007216 206.4771 153.5852 15.54981238 1438 +SNUSAT-1B +1 42733U 98067MN 17157.80452231 .00009513 00000-0 14625-3 0 9994 +2 42733 51.6398 90.0067 0007034 214.9107 145.1423 15.54959154 1721 +EXALTA-1 +1 42734U 98067MP 17156.39039283 .00009453 00000-0 14516-3 0 9998 +2 42734 51.6396 97.0623 0008589 235.9084 124.1092 15.54988337 1452 +AOXIANG-1 +1 42735U 98067MQ 17157.80450021 .00008356 00000-0 12927-3 0 9998 +2 42735 51.6402 90.0072 0007677 265.5134 94.4980 15.54971752 3094 +BEEAGLESAT +1 42736U 98067MR 17155.94091570 .00008525 00000-0 13203-3 0 9998 +2 42736 51.6398 99.3106 0007570 257.5066 102.5078 15.54911642 1499 +ATLANTIS +1 42737U 98067MS 17157.73973140 .00018727 00000-0 27851-3 0 9999 +2 42737 51.6395 90.3231 0007506 257.5958 102.4193 15.55165668 1662 +DRAGON CRS-11 +1 42744U 17030A 17157.37842914 .00002356 00000-0 43046-4 0 9998 +2 42744 51.6419 92.2016 0004681 238.9005 219.3491 15.53987082 60075 +FALCON 9 DEB +1 42745U 17030B 17156.27917736 -.00003619 11440-4 00000-0 0 9999 +2 42745 51.6486 97.5083 0103286 51.0958 103.4391 16.01768424 228 +FALCON 9 DEB +1 42746U 17030C 17156.87548135 -.00561144 11417-4 -52194-3 0 9990 +2 42746 51.6257 94.2528 0099282 55.6445 305.5405 16.01548785 322 From 1e0240b47a2b53d121b0c446e8ccde9a28bfda8e Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 7 Jun 2017 17:14:12 -0400 Subject: [PATCH 11/12] Update Ghoul repository --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index b76cbabe61..16af15c4ee 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit b76cbabe61baf05b1105e9dccdae0e7e5f8c4405 +Subproject commit 16af15c4ee8f860542fc59050739d600c2a3c895 From 9a7eba16bd828216ce578e35d546ec62df3fbc47 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 8 Jun 2017 00:07:51 -0400 Subject: [PATCH 12/12] Remove warnings Update Ghoul repository Fix spelling mistake in openspace.cfg --- apps/OpenSpace/main.cpp | 8 ++++++- ext/ghoul | 2 +- include/openspace/network/messagestructures.h | 2 +- include/openspace/util/timeline.h | 2 +- .../rendering/renderablefieldlines.cpp | 2 +- .../globebrowsing/geometry/geodeticpatch.cpp | 2 +- modules/globebrowsing/tile/pixelregion.cpp | 15 +++++-------- .../newhorizons/rendering/renderablefov.cpp | 10 +-------- modules/onscreengui/src/gui.cpp | 3 ++- modules/onscreengui/src/guiiswacomponent.cpp | 4 ++-- .../rendering/renderabletoyvolume.cpp | 4 ++-- openspace.cfg | 2 +- src/documentation/documentation.cpp | 5 +++-- src/documentation/documentationengine.cpp | 1 + src/documentation/documentationgenerator.cpp | 1 + src/engine/downloadmanager.cpp | 22 ++++++++++--------- src/engine/logfactory.cpp | 4 +++- src/engine/openspaceengine.cpp | 4 ++-- src/engine/wrapper/sgctwindowwrapper.cpp | 1 + src/network/parallelconnection.cpp | 6 ++--- src/rendering/renderable.cpp | 8 ++++--- src/scene/scene_lua.inl | 6 +++-- src/util/keys.cpp | 2 +- src/util/spicemanager.cpp | 8 ++++--- 24 files changed, 66 insertions(+), 58 deletions(-) diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index ec55894de0..d816e22ed1 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -42,10 +42,16 @@ #include #include -#include #include #include +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable : 4091) +#include +#pragma warning (pop) +#endif // _MSC_VER + #endif // WIN32 #ifdef OPENVR_SUPPORT diff --git a/ext/ghoul b/ext/ghoul index 16af15c4ee..b362a77feb 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 16af15c4ee8f860542fc59050739d600c2a3c895 +Subproject commit b362a77feb81c751519386d42615ba04e0c92d1c diff --git a/include/openspace/network/messagestructures.h b/include/openspace/network/messagestructures.h index ee2ffc71a9..b3943d7fed 100644 --- a/include/openspace/network/messagestructures.h +++ b/include/openspace/network/messagestructures.h @@ -66,7 +66,7 @@ struct CameraKeyframe { // Follow focus node rotation? buffer.insert(buffer.end(), reinterpret_cast(&_followNodeRotation), reinterpret_cast(&_followNodeRotation) + sizeof(_followNodeRotation)); - int nodeNameLength = _focusNode.size(); + int nodeNameLength = static_cast(_focusNode.size()); // Add focus node buffer.insert(buffer.end(), reinterpret_cast(&nodeNameLength), reinterpret_cast(&nodeNameLength) + sizeof(nodeNameLength)); diff --git a/include/openspace/util/timeline.h b/include/openspace/util/timeline.h index 794aecf96a..9c96f0b582 100644 --- a/include/openspace/util/timeline.h +++ b/include/openspace/util/timeline.h @@ -91,6 +91,6 @@ bool compareKeyframeTimeWithTime(const KeyframeBase& a, double b); } // namespace openspace -#include ; +#include #endif // __OPENSPACE_CORE___TIMELINE___H__ diff --git a/modules/fieldlines/rendering/renderablefieldlines.cpp b/modules/fieldlines/rendering/renderablefieldlines.cpp index 9a61c48b46..a6dc9e6f52 100644 --- a/modules/fieldlines/rendering/renderablefieldlines.cpp +++ b/modules/fieldlines/rendering/renderablefieldlines.cpp @@ -325,7 +325,7 @@ void RenderableFieldlines::loadSeedPoints() { loadSeedPointsFromTable(); break; default: - ghoul_assert(false, "Missing case label"); + throw ghoul::MissingCaseException(); } } diff --git a/modules/globebrowsing/geometry/geodeticpatch.cpp b/modules/globebrowsing/geometry/geodeticpatch.cpp index f1e04122ab..72f515d91b 100644 --- a/modules/globebrowsing/geometry/geodeticpatch.cpp +++ b/modules/globebrowsing/geometry/geodeticpatch.cpp @@ -92,7 +92,7 @@ Geodetic2 GeodeticPatch::getCorner(Quad q) const { case NORTH_EAST: return Geodetic2(maxLat(), maxLon());// northEastCorner(); case SOUTH_WEST: return Geodetic2(minLat(), minLon());// southWestCorner(); case SOUTH_EAST: return Geodetic2(minLat(), maxLon());// southEastCorner(); - default: ghoul_assert(false, "Missing case label"); + default: throw ghoul::MissingCaseException(); } } diff --git a/modules/globebrowsing/tile/pixelregion.cpp b/modules/globebrowsing/tile/pixelregion.cpp index b24d7b263d..4375afd19a 100644 --- a/modules/globebrowsing/tile/pixelregion.cpp +++ b/modules/globebrowsing/tile/pixelregion.cpp @@ -240,16 +240,11 @@ int PixelRegion::area() const { int PixelRegion::edge(Side side) const { switch (side) { - case Side::LEFT: - return start.x; - case Side::TOP: - return start.y; - case Side::RIGHT: - return start.x + numPixels.x; - case Side::BOTTOM: - return start.y + numPixels.y; - default: - ghoul_assert(false, "Missing case label"); + case Side::LEFT: return start.x; + case Side::TOP: return start.y; + case Side::RIGHT: return start.x + numPixels.x; + case Side::BOTTOM: return start.y + numPixels.y; + default: throw ghoul::MissingCaseException(); } } diff --git a/modules/newhorizons/rendering/renderablefov.cpp b/modules/newhorizons/rendering/renderablefov.cpp index 33d7e51270..6e1f64d90a 100644 --- a/modules/newhorizons/rendering/renderablefov.cpp +++ b/modules/newhorizons/rendering/renderablefov.cpp @@ -653,19 +653,11 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string& break; } case ThisIntersect: - { - break; - } case NextIntersect: - { - break; - } case BothIntersect: - { break; - } default: - ghoul_assert(false, "Missing case label"); + throw ghoul::MissingCaseException(); } } } diff --git a/modules/onscreengui/src/gui.cpp b/modules/onscreengui/src/gui.cpp index c3e520fa33..5f91a7bfd6 100644 --- a/modules/onscreengui/src/gui.cpp +++ b/modules/onscreengui/src/gui.cpp @@ -364,7 +364,8 @@ void GUI::initializeGL() { _fontTexture->setDataOwnership(ghoul::opengl::Texture::TakeOwnership::No); _fontTexture->uploadTexture(); GLuint id = *_fontTexture; - ImGui::GetIO().Fonts->TexID = reinterpret_cast(id); + uint64_t tmp = id; + ImGui::GetIO().Fonts->TexID = reinterpret_cast(tmp); glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); diff --git a/modules/onscreengui/src/guiiswacomponent.cpp b/modules/onscreengui/src/guiiswacomponent.cpp index b0a36ebb91..35e29c7a1d 100644 --- a/modules/onscreengui/src/guiiswacomponent.cpp +++ b/modules/onscreengui/src/guiiswacomponent.cpp @@ -38,7 +38,7 @@ namespace { using json = nlohmann::json; - const ImVec2 size = ImVec2(350, 500); + const ImVec2 WindowSize = ImVec2(350, 500); } // namespace namespace openspace { @@ -59,7 +59,7 @@ void GuiIswaComponent::render() { bool e = _isEnabled; - ImGui::Begin("ISWA", &e, size, 0.5f); + ImGui::Begin("ISWA", &e, WindowSize, 0.5f); _isEnabled = e; diff --git a/modules/toyvolume/rendering/renderabletoyvolume.cpp b/modules/toyvolume/rendering/renderabletoyvolume.cpp index e5df97b9cf..8086a47ac5 100644 --- a/modules/toyvolume/rendering/renderabletoyvolume.cpp +++ b/modules/toyvolume/rendering/renderabletoyvolume.cpp @@ -41,8 +41,8 @@ RenderableToyVolume::RenderableToyVolume(const ghoul::Dictionary& dictionary) , _stepSize("stepSize", "Step Size", 0.02, 0.01, 1) , _scaling("scaling", "Scaling", glm::vec3(1.0, 1.0, 1.0), glm::vec3(0.0), glm::vec3(10.0)) , _translation("translation", "Translation", glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0), glm::vec3(10.0)) - , _rotation("rotation", "Euler rotation", glm::vec3(0.0, 0.0, 0.0), glm::vec3(0), glm::vec3(6.28)) - , _color("color", "Color", glm::vec4(1.0, 0.0, 0.0, 0.1), glm::vec4(0.0), glm::vec4(1.0)) { + , _rotation("rotation", "Euler rotation", glm::vec3(0.f, 0.f, 0.f), glm::vec3(0), glm::vec3(6.28f)) + , _color("color", "Color", glm::vec4(1.f, 0.f, 0.f, 0.1f), glm::vec4(0.f), glm::vec4(1.f)) { float scalingExponent, stepSize; glm::vec3 scaling, translation, rotation; diff --git a/openspace.cfg b/openspace.cfg index 4736a0e50e..75326922e7 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -79,7 +79,7 @@ return { -- OnScreenTextScaling = "framebuffer", -- PerSceneCache = true, -- DisableRenderingOnMaster = true, - KeyDisableSceneOnMaster = true, + -- DisableSceneOnMaster = true, DownloadRequestURL = "http://data.openspaceproject.com/request.cgi", RenderingMethod = "Framebuffer", OpenGLDebugContext = { diff --git a/src/documentation/documentation.cpp b/src/documentation/documentation.cpp index bef1b621d4..e82cea9388 100644 --- a/src/documentation/documentation.cpp +++ b/src/documentation/documentation.cpp @@ -80,7 +80,8 @@ std::string to_string(openspace::documentation::TestResult::Offense::Reason reas case openspace::documentation::TestResult::Offense::Reason::WrongType: return "Wrong type"; default: - ghoul_assert(false, "Missing case label"); + throw ghoul::MissingCaseException(); + } } @@ -89,7 +90,7 @@ std::string to_string(openspace::documentation::TestResult::Warning::Reason reas case openspace::documentation::TestResult::Warning::Reason::Deprecated: return "Deprecated"; default: - ghoul_assert(false, "Missing case label"); + throw ghoul::MissingCaseException(); } } diff --git a/src/documentation/documentationengine.cpp b/src/documentation/documentationengine.cpp index 92f48e26ae..4f862869fc 100644 --- a/src/documentation/documentationengine.cpp +++ b/src/documentation/documentationengine.cpp @@ -298,6 +298,7 @@ std::string DocumentationEngine::generateJson() const { void DocumentationEngine::addDocumentation(Documentation doc) { for (const DocumentationEntry& e : doc.entries) { + (void)e; // Unused variable in Release mode ghoul_assert( e.documentation.find('"') == std::string::npos, "Documentation cannot contain \" character" diff --git a/src/documentation/documentationgenerator.cpp b/src/documentation/documentationgenerator.cpp index ac27f90b67..3f11f02563 100644 --- a/src/documentation/documentationgenerator.cpp +++ b/src/documentation/documentationgenerator.cpp @@ -52,6 +52,7 @@ DocumentationGenerator::DocumentationGenerator(std::string name, ghoul_precondition(!_name.empty(), "name must not be empty"); ghoul_precondition(!_jsonName.empty(), "jsonName must not be empty"); for (const HandlebarTemplate& t : _handlebarTemplates) { + (void)t; // Unused variable in Release mode ghoul_precondition(!t.name.empty(), "name must not be empty"); ghoul_precondition(!t.filename.empty(), "filename must not be empty"); } diff --git a/src/engine/downloadmanager.cpp b/src/engine/downloadmanager.cpp index 51ab4e8580..d1e205788a 100644 --- a/src/engine/downloadmanager.cpp +++ b/src/engine/downloadmanager.cpp @@ -169,19 +169,21 @@ std::shared_ptr DownloadManager::downloadFile( #ifdef WIN32 FILE* fp; errno_t error = fopen_s(&fp, file.path().c_str(), "wb"); - ghoul_assert( - error == 0, - "Could not open/create file:" + file.path() + ". Errno: " + std::to_string(errno) - ); + if (error != 0) { + LERROR( + "Could not open/create file:" + file.path() + + ". Errno: " + std::to_string(errno) + ); + } #else FILE* fp = fopen(file.path().c_str(), "wb"); // write binary #endif // WIN32 - ghoul_assert( - fp != nullptr, - "Could not open/create file:" + file.path() + ". Errno: " + std::to_string(errno) - ); - - //LDEBUG("Start downloading file: '" << url << "' into file '" << file.path() << "'"); + if (!fp) { + LERROR( + "Could not open/create file:" + file.path() + + ". Errno: " + std::to_string(errno) + ); + } auto downloadFunction = [url, failOnError, diff --git a/src/engine/logfactory.cpp b/src/engine/logfactory.cpp index cddfd946b2..01366f9c21 100644 --- a/src/engine/logfactory.cpp +++ b/src/engine/logfactory.cpp @@ -212,7 +212,9 @@ std::unique_ptr createLog(const ghoul::Dictionary& dictiona ); } } - ghoul_assert(false, "Missing case in the documentation for LogFactory"); + else { + throw ghoul::MissingCaseException(); + } } } // namespace openspace diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index b92582582a..81318c1d5a 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -953,7 +953,7 @@ void OpenSpaceEngine::initializeGL() { LDEBUGC(category, std::string(message)); break; default: - ghoul_assert(false, "Missing case label"); + throw ghoul::MissingCaseException(); } }; ghoul::opengl::debug::setDebugCallback(callback); @@ -1308,7 +1308,7 @@ void OpenSpaceEngine::registerModuleCallback(OpenSpaceEngine::CallbackOption opt _moduleCallbacks.postDraw.push_back(std::move(function)); break; default: - ghoul_assert(false, "Missing case label"); + throw ghoul::MissingCaseException(); } } diff --git a/src/engine/wrapper/sgctwindowwrapper.cpp b/src/engine/wrapper/sgctwindowwrapper.cpp index 2ea95e707a..8d04c9aa98 100644 --- a/src/engine/wrapper/sgctwindowwrapper.cpp +++ b/src/engine/wrapper/sgctwindowwrapper.cpp @@ -158,6 +158,7 @@ int SGCTWindowWrapper::currentNumberOfAaSamples() const { bool SGCTWindowWrapper::isRegularRendering() const { sgct::SGCTWindow* w = sgct::Engine::instance()->getCurrentWindowPtr(); std::size_t nViewports = w->getNumberOfViewports(); + (void)nViewports; // Unused in Release mode ghoul_assert(nViewports > 0, "At least one viewport must exist at this time"); sgct_core::Viewport* vp = w->getViewport(0); sgct_core::NonLinearProjection* nlp = vp->getNonLinearProjectionPtr(); diff --git a/src/network/parallelconnection.cpp b/src/network/parallelconnection.cpp index 0a73c4eb12..85db183e4f 100644 --- a/src/network/parallelconnection.cpp +++ b/src/network/parallelconnection.cpp @@ -94,9 +94,9 @@ ParallelConnection::ParallelConnection() , _address("address", "Address", "localhost") , _name("name", "Connection name", "Anonymous") , _bufferTime("bufferTime", "Buffer Time", 1, 0.5, 10) - , _timeKeyframeInterval("timeKeyframeInterval", "Time keyframe interval", 0.1, 0, 1) - , _cameraKeyframeInterval("cameraKeyframeInterval", "Camera Keyframe interval", 0.1, 0, 1) - , _timeTolerance("timeTolerance", "Time tolerance", 1, 0.5, 5) + , _timeKeyframeInterval("timeKeyframeInterval", "Time keyframe interval", 0.1f, 0.f, 1.f) + , _cameraKeyframeInterval("cameraKeyframeInterval", "Camera Keyframe interval", 0.1f, 0.f, 1.f) + , _timeTolerance("timeTolerance", "Time tolerance", 1.f, 0.5f, 5.f) , _lastTimeKeyframeTimestamp(0) , _lastCameraKeyframeTimestamp(0) , _clientSocket(INVALID_SOCKET) diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 231bbcbb0f..b8b926a5fa 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -70,9 +70,11 @@ std::unique_ptr Renderable::createFromDictionary( const ghoul::Dictionary& dictionary) { // The name is passed down from the SceneGraphNode - std::string name; - bool success = dictionary.getValue(SceneGraphNode::KeyName, name); - ghoul_assert(success, "The SceneGraphNode did not set the 'name' key"); + ghoul_assert( + dictionary.hasKeyAndValue(SceneGraphNode::KeyName), + "The SceneGraphNode did not set the 'name' key" + ); + std::string name = dictionary.value(SceneGraphNode::KeyName); documentation::testSpecificationAndThrow(Documentation(), dictionary, "Renderable"); diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 31554ac1af..ee86083384 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -179,7 +179,9 @@ int property_setValueSingle(lua_State* L) { for (properties::Property* prop : allProperties()) { std::string propFullId = prop->fullyQualifiedIdentifier(); //Look for a match in the uri with the group name (first term) removed - int propMatchLength = propFullId.length() - pathRemainderToMatch.length(); + int propMatchLength = + static_cast(propFullId.length()) - + static_cast(pathRemainderToMatch.length()); if (propMatchLength >= 0) { std::string thisPropMatchId = propFullId.substr(propMatchLength); @@ -289,7 +291,7 @@ int property_setValueRegex(lua_State* L) { } catch (const std::regex_error& e) { LERRORC("property_setValueRegex", "Malformed regular expression: '" - << regex << "'"); + << regex << "':" << e.what()); } return 0; diff --git a/src/util/keys.cpp b/src/util/keys.cpp index 056bd85bd9..ab02ed8bc4 100644 --- a/src/util/keys.cpp +++ b/src/util/keys.cpp @@ -129,7 +129,7 @@ std::string to_string(openspace::Key key) { return p.first; } } - ghoul_assert(false, "Missing key in KeyMapping"); + throw ghoul::MissingCaseException(); } std::string to_string(openspace::KeyModifier mod) { diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index 05fb0cc8f2..d73edaec64 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -75,7 +75,8 @@ namespace { case openspace::SpiceManager::FieldOfViewMethod::Point: return "POINT"; default: - ghoul_assert(false, "Missing case label"); + throw ghoul::MissingCaseException(); + } } @@ -86,7 +87,8 @@ namespace { case openspace::SpiceManager::TerminatorType::Penumbral: return "PENUMBRAL"; default: - ghoul_assert(false, "Missing case label"); + throw ghoul::MissingCaseException(); + } } } @@ -148,7 +150,7 @@ SpiceManager::AberrationCorrection::operator const char*() const { case Type::ConvergedNewtonianStellar: return (direction == Direction::Reception) ? "CN+S" : "XCN+S"; default: - ghoul_assert(false, "Missing case label"); + throw ghoul::MissingCaseException(); } }