diff --git a/common/device-model.cpp b/common/device-model.cpp index 3b9e3d35b5a..134e87ae68b 100644 --- a/common/device-model.cpp +++ b/common/device-model.cpp @@ -22,7 +22,7 @@ #include "device-model.h" using namespace rs400; -using namespace nlohmann; +using rsutils::json; using namespace rs2::sw_update; namespace rs2 diff --git a/common/device-model.h b/common/device-model.h index bd7f0f69c62..20e434ea36c 100644 --- a/common/device-model.h +++ b/common/device-model.h @@ -1,12 +1,11 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2023 Intel Corporation. All Rights Reserved. - #pragma once #include #include "notifications.h" #include "realsense-ui-advanced-mode.h" -#include +#include #include "sw-update/dev-updates-profile.h" #include #include "updates-model.h" @@ -426,7 +425,7 @@ namespace rs2 const std::string& error_message); void load_viewer_configurations(const std::string& json_str); - void save_viewer_configurations(std::ofstream& outfile, nlohmann::json& j); + void save_viewer_configurations(std::ofstream& outfile, rsutils::json& j); void handle_online_sw_update( std::shared_ptr< notifications_model > nm, std::shared_ptr< sw_update::dev_updates_profile::update_profile > update_profile, diff --git a/common/rs-config.cpp b/common/rs-config.cpp index ad443c0038a..81443816c2a 100644 --- a/common/rs-config.cpp +++ b/common/rs-config.cpp @@ -8,7 +8,7 @@ #include #include -using json = nlohmann::json; +using json = rsutils::json; using namespace rs2; @@ -31,7 +31,7 @@ void config_file::remove(const char* key) void config_file::reset() { - _j = nlohmann::json::object(); + _j = json::object(); save(); } @@ -40,7 +40,7 @@ std::string config_file::get(const char* key, const char* def) const auto it = _j.find(key); if (it != _j.end() && it->is_string()) { - return rsutils::json::string_ref( *it ); + return it->string_ref(); } return get_default(key, def); } @@ -105,7 +105,7 @@ void config_file::save() } config_file::config_file() - : _j( nlohmann::json::object() ) + : _j( rsutils::json::object() ) { } diff --git a/common/rs-config.h b/common/rs-config.h index 9165e032395..9bf4e96cc84 100644 --- a/common/rs-config.h +++ b/common/rs-config.h @@ -2,7 +2,7 @@ // Copyright(c) 2017 Intel Corporation. All Rights Reserved. #pragma once -#include +#include #include #include @@ -94,6 +94,6 @@ namespace rs2 std::map _defaults; std::string _filename; - nlohmann::json _j; + rsutils::json _j; }; } \ No newline at end of file diff --git a/common/subdevice-model.h b/common/subdevice-model.h index a22f2420200..9713bd73b30 100644 --- a/common/subdevice-model.h +++ b/common/subdevice-model.h @@ -18,7 +18,6 @@ #include #include -#include #include "objects-in-frame.h" #include "processing-block-model.h" diff --git a/common/sw-update/versions-db-manager.cpp b/common/sw-update/versions-db-manager.cpp index 7de2473a507..514f4c25806 100644 --- a/common/sw-update/versions-db-manager.cpp +++ b/common/sw-update/versions-db-manager.cpp @@ -2,7 +2,7 @@ // Copyright(c) 2020 Intel Corporation. All Rights Reserved. #include "versions-db-manager.h" -#include +#include #include #include #include @@ -16,7 +16,7 @@ namespace rs2 namespace sw_update { - using json = nlohmann::json; + using json = rsutils::json; using namespace http; query_status_type versions_db_manager::query_versions(const std::string &device_name, component_part_type component, const update_policy_type policy, version& out_version) diff --git a/src/context.cpp b/src/context.cpp index a7549fe6173..db857670703 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -19,47 +19,34 @@ #include #include #include -using json = nlohmann::json; - -#include +#include +using json = rsutils::json; namespace librealsense { - static nlohmann::json load_settings( nlohmann::json const & context_settings ) + static rsutils::json load_settings( rsutils::json const & context_settings ) { // Allow ignoring of any other settings, global or not! - if( ! rsutils::json::get( context_settings, "inherit", true ) ) + if( ! context_settings.nested( "inherit" ).default_value( true ) ) return context_settings; - nlohmann::json config; - - // Load the realsense configuration file settings - std::ifstream f( rsutils::os::get_special_folder( rsutils::os::special_folder::app_data ) + RS2_CONFIG_FILENAME ); - if( f.good() ) - { - try - { - config = nlohmann::json::parse( f ); - } - catch( std::exception const & e ) - { - throw std::runtime_error( "failed to load configuration file: " + std::string( e.what() ) ); - } - } + auto const filename = rsutils::os::get_special_folder( rsutils::os::special_folder::app_data ) + RS2_CONFIG_FILENAME; + auto config = rsutils::json_config::load_from_file( filename ); - config = rsutils::json::load_settings( config, "context", "config-file" ); + // Take only the 'context' part of it + config = rsutils::json_config::load_settings( config, "context", "config-file" ); // Patch the given context settings into the configuration - rsutils::json::patch( config, context_settings, "context settings" ); + config.override( context_settings, "context settings" ); return config; } context::context( json const & settings ) : _settings( load_settings( settings ) ) // global | application | local - , _device_mask( rsutils::json::get< unsigned >( _settings, "device-mask", RS2_PRODUCT_LINE_ANY ) ) + , _device_mask( _settings.nested( "device-mask" ).default_value< unsigned >( RS2_PRODUCT_LINE_ANY ) ) { static bool version_logged = false; if( ! version_logged ) @@ -191,7 +178,7 @@ namespace librealsense { std::shared_ptr< processing_block_interface > context::create_pp_block( std::string const & name, - nlohmann::json const & settings ) + rsutils::json const & settings ) { return rscore_pp_block_factory().create_pp_block( name, settings ); } diff --git a/src/context.h b/src/context.h index 8e0159e508e..807bcea842a 100644 --- a/src/context.h +++ b/src/context.h @@ -1,10 +1,9 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2015 Intel Corporation. All Rights Reserved. - #pragma once #include -#include +#include #include #include @@ -18,12 +17,12 @@ namespace librealsense class context { - context( nlohmann::json const & ); // private! use make() + context( rsutils::json const & ); // private! use make() void create_factories( std::shared_ptr< context > const & sptr ); public: - static std::shared_ptr< context > make( nlohmann::json const & ); + static std::shared_ptr< context > make( rsutils::json const & ); static std::shared_ptr< context > make( char const * json_settings ); ~context(); @@ -61,12 +60,12 @@ namespace librealsense void add_device( std::shared_ptr< device_info > const & ); void remove_device( std::shared_ptr< device_info > const & ); - const nlohmann::json & get_settings() const { return _settings; } + const rsutils::json & get_settings() const { return _settings; } // Create processing blocks given a name and settings. // std::shared_ptr< processing_block_interface > create_pp_block( std::string const & name, - nlohmann::json const & settings ); + rsutils::json const & settings ); private: void invoke_devices_changed_callbacks( std::vector< std::shared_ptr< device_info > > const & devices_removed, @@ -78,7 +77,7 @@ namespace librealsense std::vector< std::shared_ptr< device_info > > const & /*added*/ > _devices_changed; - nlohmann::json _settings; // Save operation settings + rsutils::json _settings; // Save operation settings unsigned const _device_mask; std::vector< std::shared_ptr< device_factory > > _factories; diff --git a/src/core/pp-block-factory.h b/src/core/pp-block-factory.h index 85a76f6273a..d41845b2681 100644 --- a/src/core/pp-block-factory.h +++ b/src/core/pp-block-factory.h @@ -2,7 +2,7 @@ // Copyright(c) 2023 Intel Corporation. All Rights Reserved. #pragma once -#include +#include #include @@ -30,7 +30,7 @@ class pp_block_factory // The name is case-insensitive. // virtual std::shared_ptr< processing_block_interface > create_pp_block( std::string const & name, - nlohmann::json const & settings ) + rsutils::json const & settings ) = 0; }; diff --git a/src/dds/rs-dds-depth-sensor-proxy.cpp b/src/dds/rs-dds-depth-sensor-proxy.cpp index 3417229e157..8992cf5e6f2 100644 --- a/src/dds/rs-dds-depth-sensor-proxy.cpp +++ b/src/dds/rs-dds-depth-sensor-proxy.cpp @@ -38,15 +38,15 @@ void dds_depth_sensor_proxy::add_no_metadata( frame * const f, streaming_impl & } -void dds_depth_sensor_proxy::add_frame_metadata( frame * const f, nlohmann::json const & dds_md, streaming_impl & streaming ) +void dds_depth_sensor_proxy::add_frame_metadata( frame * const f, rsutils::json const & dds_md, streaming_impl & streaming ) { - if( auto du = rsutils::json::nested( dds_md, metadata_header_key, depth_units_key ) ) + if( auto du = dds_md.nested( metadata_header_key, depth_units_key ) ) { try { - f->additional_data.depth_units = rsutils::json::value< float >( du ); + f->additional_data.depth_units = du.get< float >(); } - catch( nlohmann::json::exception const & ) + catch( rsutils::json::exception const & ) { f->additional_data.depth_units = get_depth_scale(); } diff --git a/src/dds/rs-dds-depth-sensor-proxy.h b/src/dds/rs-dds-depth-sensor-proxy.h index 3b72b296d86..a00822fc312 100644 --- a/src/dds/rs-dds-depth-sensor-proxy.h +++ b/src/dds/rs-dds-depth-sensor-proxy.h @@ -1,6 +1,5 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2023 Intel Corporation. All Rights Reserved. - #pragma once #include "rs-dds-sensor-proxy.h" @@ -29,7 +28,7 @@ class dds_depth_sensor_proxy protected: void add_no_metadata( frame *, streaming_impl & ) override; - void add_frame_metadata( frame *, nlohmann::json const & md, streaming_impl & ) override; + void add_frame_metadata( frame *, rsutils::json const & md, streaming_impl & ) override; }; diff --git a/src/dds/rs-dds-device-proxy.cpp b/src/dds/rs-dds-device-proxy.cpp index 049165561fb..2698ab73f71 100644 --- a/src/dds/rs-dds-device-proxy.cpp +++ b/src/dds/rs-dds-device-proxy.cpp @@ -127,19 +127,19 @@ dds_device_proxy::dds_device_proxy( std::shared_ptr< const device_info > const & auto & j = dev->device_info().to_json(); std::string str; - if( rsutils::json::get_ex( j, "serial", &str ) ) + if( j.nested( "serial" ).get_ex( str ) ) { register_info( RS2_CAMERA_INFO_SERIAL_NUMBER, str ); - rsutils::json::get_ex( j, "fw-update-id", &str ); // if fails, str will be the serial + j.nested( "fw-update-id" ).get_ex( str ); // if fails, str will be the serial register_info( RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID, str ); } - else if( rsutils::json::get_ex( j, "fw-update-id", &str ) ) + else if( j.nested( "fw-update-id" ).get_ex( str ) ) register_info( RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID, str ); - if( rsutils::json::get_ex( j, "fw-version", &str ) ) + if( j.nested( "fw-version" ).get_ex( str ) ) register_info( RS2_CAMERA_INFO_FIRMWARE_VERSION, str ); - if( rsutils::json::get_ex( j, "product-line", &str ) ) + if( j.nested( "product-line" ).get_ex( str ) ) register_info( RS2_CAMERA_INFO_PRODUCT_LINE, str ); - register_info( RS2_CAMERA_INFO_CAMERA_LOCKED, rsutils::json::get( j, "locked", true ) ? "YES" : "NO" ); + register_info( RS2_CAMERA_INFO_CAMERA_LOCKED, j.nested( "locked" ).default_value( true ) ? "YES" : "NO" ); // Assumes dds_device initialization finished struct sensor_info @@ -296,9 +296,9 @@ dds_device_proxy::dds_device_proxy( std::shared_ptr< const device_info > const & if( _dds_dev->supports_metadata() ) { _metadata_subscription = _dds_dev->on_metadata_available( - [this]( std::shared_ptr< const nlohmann::json > const & dds_md ) + [this]( std::shared_ptr< const rsutils::json > const & dds_md ) { - std::string const & stream_name = rsutils::json::nested( *dds_md, stream_name_key ).string_ref(); + std::string const & stream_name = dds_md->nested( stream_name_key ).string_ref(); auto it = _stream_name_to_owning_sensor.find( stream_name ); if( it != _stream_name_to_owning_sensor.end() ) it->second->handle_new_metadata( stream_name, dds_md ); @@ -354,9 +354,9 @@ dds_device_proxy::dds_device_proxy( std::shared_ptr< const device_info > const & // Depth & IR matched by frame-number, time-stamp-matched to color. // Motion streams will not get synced. rs2_matchers matcher = RS2_MATCHER_DLR_C; - if( auto matcher_j = rsutils::json::nested( _dds_dev->participant()->settings(), "device", "matcher" ) ) + if( auto matcher_j = _dds_dev->participant()->settings().nested( "device", "matcher" ) ) { - if( ! matcher_j->is_string() || ! try_parse( matcher_j.string_ref(), matcher ) ) + if( ! matcher_j.is_string() || ! try_parse( matcher_j.string_ref(), matcher ) ) LOG_WARNING( "Invalid 'device/matcher' value " << matcher_j ); } set_matcher_type( matcher ); @@ -506,8 +506,8 @@ void dds_device_proxy::tag_profiles( stream_profiles profiles ) const void dds_device_proxy::hardware_reset() { - nlohmann::json control = nlohmann::json::object( { { "id", "hw-reset" } } ); - nlohmann::json reply; + rsutils::json control = rsutils::json::object( { { "id", "hw-reset" } } ); + rsutils::json reply; _dds_dev->send_control( control, &reply ); } @@ -516,11 +516,11 @@ std::vector< uint8_t > dds_device_proxy::send_receive_raw_data( const std::vecto { // debug_interface function auto hexdata = rsutils::string::hexarray::to_string( input ); - nlohmann::json control = nlohmann::json::object( { { "id", "hwm" }, { "data", hexdata } } ); - nlohmann::json reply; + rsutils::json control = rsutils::json::object( { { "id", "hwm" }, { "data", hexdata } } ); + rsutils::json reply; _dds_dev->send_control( control, &reply ); rsutils::string::hexarray data; - if( ! rsutils::json::get_ex( reply, "data", &data ) ) + if( ! reply.nested( "data" ).get_ex( data ) ) throw std::runtime_error( "Failed HWM: missing 'data' in reply" ); return data.detach(); } @@ -536,17 +536,17 @@ std::vector< uint8_t > dds_device_proxy::build_command( uint32_t opcode, { // debug_interface function rsutils::string::hexarray hexdata( std::vector< uint8_t >( data, data + dataLength ) ); - nlohmann::json control = nlohmann::json::object( { { "id", "hwm" }, - { "data", hexdata }, - { "opcode", opcode }, - { "param1", param1 }, - { "param2", param2 }, - { "param3", param3 }, - { "param4", param4 }, - { "build-command", true } } ); - nlohmann::json reply; + rsutils::json control = rsutils::json::object( { { "id", "hwm" }, + { "data", hexdata }, + { "opcode", opcode }, + { "param1", param1 }, + { "param2", param2 }, + { "param3", param3 }, + { "param4", param4 }, + { "build-command", true } } ); + rsutils::json reply; _dds_dev->send_control( control, &reply ); - if( ! rsutils::json::get_ex( reply, "data", &hexdata ) ) + if( ! reply.nested( "data" ).get_ex( hexdata ) ) throw std::runtime_error( "Failed HWM: missing 'data' in reply" ); return hexdata.detach(); } diff --git a/src/dds/rs-dds-sensor-proxy.cpp b/src/dds/rs-dds-sensor-proxy.cpp index cc686bba674..35abf678340 100644 --- a/src/dds/rs-dds-sensor-proxy.cpp +++ b/src/dds/rs-dds-sensor-proxy.cpp @@ -338,7 +338,7 @@ void dds_sensor_proxy::handle_motion_data( realdds::topics::imu_msg && imu, void dds_sensor_proxy::handle_new_metadata( std::string const & stream_name, - std::shared_ptr< const nlohmann::json > const & dds_md ) + std::shared_ptr< const rsutils::json > const & dds_md ) { if( ! _md_enabled ) return; @@ -346,8 +346,8 @@ void dds_sensor_proxy::handle_new_metadata( std::string const & stream_name, auto it = _streaming_by_name.find( stream_name ); if( it != _streaming_by_name.end() ) { - if( auto timestamp = rsutils::json::nested( *dds_md, metadata_header_key, timestamp_key ) ) - it->second.syncer.enqueue_metadata( timestamp.value< realdds::dds_nsec >(), dds_md ); + if( auto timestamp = dds_md->nested( metadata_header_key, timestamp_key ) ) + it->second.syncer.enqueue_metadata( timestamp.get< realdds::dds_nsec >(), dds_md ); else throw std::runtime_error( "missing metadata header/timestamp" ); } @@ -366,17 +366,17 @@ void dds_sensor_proxy::add_no_metadata( frame * const f, streaming_impl & stream void dds_sensor_proxy::add_frame_metadata( frame * const f, - nlohmann::json const & dds_md, + rsutils::json const & dds_md, streaming_impl & streaming ) { - nlohmann::json const & md_header = rsutils::json::nested( dds_md, metadata_header_key ); - nlohmann::json const & md = rsutils::json::nested( dds_md, metadata_key ); + auto md_header = dds_md.nested( metadata_header_key ); + auto md = dds_md.nested( metadata_key ); // A frame number is "optional". If the server supplies it, we try to use it for the simple fact that, // otherwise, we have no way of detecting drops without some advanced heuristic tracking the FPS and // timestamps. If not supplied, we use an increasing counter. // Note that if we have no metadata, we have no frame-numbers! So we need a way of generating them - if( rsutils::json::get_ex( md_header, frame_number_key, &f->additional_data.frame_number ) ) + if( md_header.nested( frame_number_key ).get_ex( f->additional_data.frame_number ) ) { f->additional_data.last_frame_number = streaming.last_frame_number.exchange( f->additional_data.frame_number ); if( f->additional_data.frame_number != f->additional_data.last_frame_number + 1 @@ -396,7 +396,7 @@ void dds_sensor_proxy::add_frame_metadata( frame * const f, // purposes, so we ignore here. The domain is optional, and really only rs-dds-adapter communicates it // because the source is librealsense... f->additional_data.timestamp; - rsutils::json::get_ex( md_header, timestamp_domain_key, &f->additional_data.timestamp_domain ); + md_header.nested( timestamp_domain_key ).get_ex( f->additional_data.timestamp_domain ); if( ! md.empty() ) { @@ -408,13 +408,10 @@ void dds_sensor_proxy::add_frame_metadata( frame * const f, std::string const & keystr = librealsense::get_string( key ); try { - if( auto value = rsutils::json::nested( md, keystr ) ) - { - if( value->is_number_integer() ) - metadata[key] = { true, rsutils::json::get< rs2_metadata_type >( md, keystr ) }; - } + if( auto value_j = md.nested( keystr, &rsutils::json::is_number_integer ) ) + metadata[key] = { true, value_j.get< rs2_metadata_type >() }; } - catch( nlohmann::json::exception const & ) + catch( rsutils::json::exception const & ) { // The metadata key doesn't exist or the value isn't the right type... we ignore it! // (all metadata is not there when we create the frame, so no need to erase) @@ -440,7 +437,7 @@ void dds_sensor_proxy::start( rs2_frame_callback_sptr callback ) auto & streaming = _streaming_by_name[dds_stream->name()]; streaming.syncer.on_frame_release( frame_releaser ); streaming.syncer.on_frame_ready( - [this, &streaming]( syncer_type::frame_holder && fh, std::shared_ptr< const nlohmann::json > const & md ) + [this, &streaming]( syncer_type::frame_holder && fh, std::shared_ptr< const rsutils::json > const & md ) { if( _is_streaming ) // stop was not called { diff --git a/src/dds/rs-dds-sensor-proxy.h b/src/dds/rs-dds-sensor-proxy.h index e336077669d..ba4d76208e4 100644 --- a/src/dds/rs-dds-sensor-proxy.h +++ b/src/dds/rs-dds-sensor-proxy.h @@ -10,7 +10,7 @@ #include -#include +#include #include #include @@ -96,10 +96,10 @@ class dds_sensor_proxy : public software_sensor const std::shared_ptr< stream_profile_interface > &, streaming_impl & ); void handle_new_metadata( std::string const & stream_name, - std::shared_ptr< const nlohmann::json > const & metadata ); + std::shared_ptr< const rsutils::json > const & metadata ); virtual void add_no_metadata( frame *, streaming_impl & ); - virtual void add_frame_metadata( frame *, nlohmann::json const & metadata, streaming_impl & ); + virtual void add_frame_metadata( frame *, rsutils::json const & metadata, streaming_impl & ); friend class dds_device_proxy; // Currently calls handle_new_metadata }; diff --git a/src/dds/rsdds-device-factory.cpp b/src/dds/rsdds-device-factory.cpp index dead02a37c8..6c52989ebcd 100644 --- a/src/dds/rsdds-device-factory.cpp +++ b/src/dds/rsdds-device-factory.cpp @@ -83,12 +83,12 @@ static std::mutex domain_context_by_id_mutex; rsdds_device_factory::rsdds_device_factory( std::shared_ptr< context > const & ctx, callback && cb ) : super( ctx ) { - rsutils::json::nested dds_settings( ctx->get_settings(), std::string( "dds", 3 ) ); + auto dds_settings = ctx->get_settings().nested( std::string( "dds", 3 ) ); if( ! dds_settings.exists() - || dds_settings->is_object() && dds_settings.find( std::string( "enabled", 7 ) ).default_value( true ) ) + || dds_settings.is_object() && dds_settings.nested( std::string( "enabled", 7 ) ).default_value( true ) ) { - auto domain_id = dds_settings.find( std::string( "domain", 6 ) ).default_value< realdds::dds_domain_id >( 0 ); - auto participant_name_j = dds_settings.find( std::string( "participant", 11 ) ); + auto domain_id = dds_settings.nested( std::string( "domain", 6 ) ).default_value< realdds::dds_domain_id >( 0 ); + auto participant_name_j = dds_settings.nested( std::string( "participant", 11 ) ); auto participant_name = participant_name_j.default_value( rsutils::os::executable_name() ); std::lock_guard< std::mutex > lock( domain_context_by_id_mutex ); @@ -145,7 +145,7 @@ std::vector< std::shared_ptr< device_info > > rsdds_device_factory::query_device return true; } std::string product_line; - if( rsutils::json::get_ex( dev->device_info().to_json(), "product-line", &product_line ) ) + if( dev->device_info().to_json().nested( "product-line" ).get_ex( product_line ) ) { if( product_line == "D400" ) { diff --git a/src/device.cpp b/src/device.cpp index 33c4d3c8b9c..a9dd9bb48a4 100644 --- a/src/device.cpp +++ b/src/device.cpp @@ -204,7 +204,7 @@ format_conversion device::get_format_conversion() const return format_conversion::full; std::string const format_conversion( "format-conversion", 17 ); std::string const full( "full", 4 ); - auto const value = rsutils::json::get( context->get_settings(), format_conversion, full ); + auto const value = context->get_settings().nested( format_conversion ).default_value( full ); if( value == full ) return format_conversion::full; if( value == "basic" ) diff --git a/src/ds/advanced_mode/json_loader.hpp b/src/ds/advanced_mode/json_loader.hpp index a927ae9ac1d..dcf7ee932dc 100644 --- a/src/ds/advanced_mode/json_loader.hpp +++ b/src/ds/advanced_mode/json_loader.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include "types.h" #include "presets.h" @@ -23,7 +23,7 @@ namespace librealsense { - using json = nlohmann::json; + using json = rsutils::json; template struct param_group @@ -498,7 +498,7 @@ namespace librealsense { try { - if (value.type() != nlohmann::basic_json<>::value_t::string) + if( ! value.is_string() ) { float val = value; std::stringstream ss; diff --git a/src/ds/d400/d400-auto-calibration.cpp b/src/ds/d400/d400-auto-calibration.cpp index 9629bd6d979..61096a96fb1 100644 --- a/src/ds/d400/d400-auto-calibration.cpp +++ b/src/ds/d400/d400-auto-calibration.cpp @@ -2,7 +2,7 @@ // Copyright(c) 2016 Intel Corporation. All Rights Reserved. #include -#include +#include #include "d400-device.h" #include "d400-private.h" #include "d400-thermal-monitor.h" @@ -203,13 +203,11 @@ namespace librealsense std::map auto_calibrated::parse_json(std::string json_content) { - using json = nlohmann::json; - - auto j = json::parse(json_content); + auto j = rsutils::json::parse(json_content); std::map values; - for (json::iterator it = j.begin(); it != j.end(); ++it) + for (auto it = j.begin(); it != j.end(); ++it) { values[it.key()] = it.value(); } diff --git a/src/ds/d400/d400-device.cpp b/src/ds/d400/d400-device.cpp index bdf64596969..103088496d3 100644 --- a/src/ds/d400/d400-device.cpp +++ b/src/ds/d400/d400-device.cpp @@ -36,7 +36,6 @@ #include "d400-thermal-monitor.h" #include #include -#include #include #include diff --git a/src/ds/d500/d500-device.cpp b/src/ds/d500/d500-device.cpp index 7a071114838..e182d46967d 100644 --- a/src/ds/d500/d500-device.cpp +++ b/src/ds/d500/d500-device.cpp @@ -37,7 +37,6 @@ #include #include -#include #include #include diff --git a/src/rs.cpp b/src/rs.cpp index 55137a83354..d0916f72fcb 100644 --- a/src/rs.cpp +++ b/src/rs.cpp @@ -191,7 +191,7 @@ rs2_context* rs2_create_context(int api_version, rs2_error** error) BEGIN_API_CA { verify_version_compatibility(api_version); - nlohmann::json settings; + rsutils::json settings; return new rs2_context{ context::make( settings ) }; } HANDLE_EXCEPTIONS_AND_RETURN(nullptr, api_version) @@ -2699,7 +2699,7 @@ NOARGS_HANDLE_EXCEPTIONS_AND_RETURN(0) rs2_device* rs2_create_software_device(rs2_error** error) BEGIN_API_CALL { // We're not given a context... - auto ctx = context::make( nlohmann::json::object( { { "dds", false } } ) ); + auto ctx = context::make( rsutils::json::object( { { "dds", false } } ) ); auto dev_info = std::make_shared< software_device_info >( ctx ); auto dev = std::make_shared< software_device >( dev_info ); dev_info->set_device( dev ); diff --git a/src/rscore-pp-block-factory.cpp b/src/rscore-pp-block-factory.cpp index df830fd1b0c..679bcf63e06 100644 --- a/src/rscore-pp-block-factory.cpp +++ b/src/rscore-pp-block-factory.cpp @@ -20,7 +20,7 @@ namespace librealsense { std::shared_ptr< processing_block_interface > -rscore_pp_block_factory::create_pp_block( std::string const & name, nlohmann::json const & settings ) +rscore_pp_block_factory::create_pp_block( std::string const & name, rsutils::json const & settings ) { // These filters do not accept settings (nor are settings recorded in ros_writer) (void *)&settings; diff --git a/src/rscore-pp-block-factory.h b/src/rscore-pp-block-factory.h index 4671d54ea24..58bc2819487 100644 --- a/src/rscore-pp-block-factory.h +++ b/src/rscore-pp-block-factory.h @@ -12,7 +12,7 @@ class rscore_pp_block_factory : public pp_block_factory { public: std::shared_ptr< processing_block_interface > create_pp_block( std::string const & name, - nlohmann::json const & settings ) override; + rsutils::json const & settings ) override; }; diff --git a/src/sensor.cpp b/src/sensor.cpp index 37342131b0b..d4e52bf0d6a 100644 --- a/src/sensor.cpp +++ b/src/sensor.cpp @@ -401,10 +401,10 @@ void log_callback_end( uint32_t fps, , _raw_sensor( raw_sensor ) , _options_watcher( _raw_sensor ) { - nlohmann::json const & settings = device->get_context()->get_settings(); - if( auto interval_j = rsutils::json::nested( settings, std::string( "options-update-interval", 23 ) ) ) + rsutils::json const & settings = device->get_context()->get_settings(); + if( auto interval_j = settings.nested( std::string( "options-update-interval", 23 ) ) ) { - auto interval = interval_j.value< uint32_t >(); // NOTE: can throw! + auto interval = interval_j.get< uint32_t >(); // NOTE: can throw! _options_watcher.set_update_interval( std::chrono::milliseconds( interval ) ); } diff --git a/src/serialized-utilities.h b/src/serialized-utilities.h index 55d04fccf2f..20130cfaa96 100644 --- a/src/serialized-utilities.h +++ b/src/serialized-utilities.h @@ -1,11 +1,11 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once + #include #include #include -#include +#include namespace librealsense @@ -14,7 +14,7 @@ namespace librealsense namespace serialized_utilities { - using json = nlohmann::json; + using json = rsutils::json; struct device_info { diff --git a/third-party/realdds/include/realdds/dds-device-server.h b/third-party/realdds/include/realdds/dds-device-server.h index 8f3bcdfd09a..b5f130e5398 100644 --- a/third-party/realdds/include/realdds/dds-device-server.h +++ b/third-party/realdds/include/realdds/dds-device-server.h @@ -1,6 +1,5 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once #include @@ -8,7 +7,7 @@ #include #include -#include +#include #include #include @@ -86,7 +85,7 @@ class dds_device_server std::map< std::string, std::shared_ptr< dds_stream_server > > const & streams() const { return _stream_name_to_server; } void publish_notification( topics::flexible_msg && ); - void publish_metadata( nlohmann::json && ); + void publish_metadata( rsutils::json && ); bool has_metadata_readers() const; @@ -95,17 +94,17 @@ class dds_device_server void on_set_option( set_option_callback callback ) { _set_option_callback = std::move( callback ); } void on_query_option( query_option_callback callback ) { _query_option_callback = std::move( callback ); } - typedef std::function< bool( std::string const &, nlohmann::json const &, nlohmann::json & ) > control_callback; + typedef std::function< bool( std::string const &, rsutils::json const &, rsutils::json & ) > control_callback; void on_control( control_callback callback ) { _control_callback = std::move( callback ); } private: void on_control_message_received(); void handle_control_message( std::string const & id, - nlohmann::json const & control_message, - nlohmann::json & reply ); + rsutils::json const & control_message, + rsutils::json & reply ); - void handle_set_option( const nlohmann::json & msg, nlohmann::json & reply ); - void handle_query_option( const nlohmann::json & msg, nlohmann::json & reply ); + void handle_set_option( const rsutils::json & msg, rsutils::json & reply ); + void handle_query_option( const rsutils::json & msg, rsutils::json & reply ); std::shared_ptr< dds_option > find_option( const std::string & option_name, const std::string & stream_name ) const; std::shared_ptr< dds_publisher > _publisher; diff --git a/third-party/realdds/include/realdds/dds-device.h b/third-party/realdds/include/realdds/dds-device.h index 6e5118491d9..5ad15344406 100644 --- a/third-party/realdds/include/realdds/dds-device.h +++ b/third-party/realdds/include/realdds/dds-device.h @@ -1,6 +1,5 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once #include "dds-defines.h" @@ -8,7 +7,7 @@ #include "dds-stream.h" #include -#include +#include #include #include #include @@ -50,7 +49,7 @@ class dds_device // Utility function for checking replies: // If 'p_explanation' is nullptr, will throw if the reply status is not 'ok'. // Otherise will return a false if not 'ok', and the explanation will be filled out. - static bool check_reply( nlohmann::json const & reply, std::string * p_explanation = nullptr ); + static bool check_reply( rsutils::json const & reply, std::string * p_explanation = nullptr ); //----------- below this line, a device must be running! @@ -64,22 +63,22 @@ class dds_device void set_option_value( const std::shared_ptr< dds_option > & option, float new_value ); float query_option_value( const std::shared_ptr< dds_option > & option ); - void send_control( topics::flexible_msg &&, nlohmann::json * reply = nullptr ); + void send_control( topics::flexible_msg &&, rsutils::json * reply = nullptr ); bool has_extrinsics() const; std::shared_ptr< extrinsics > get_extrinsics( std::string const & from, std::string const & to ) const; bool supports_metadata() const; - typedef std::function< void( std::shared_ptr< const nlohmann::json > const & md ) > on_metadata_available_callback; + typedef std::function< void( std::shared_ptr< const rsutils::json > const & md ) > on_metadata_available_callback; rsutils::subscription on_metadata_available( on_metadata_available_callback && ); typedef std::function< void( - dds_nsec timestamp, char type, std::string const & text, nlohmann::json const & data ) > + dds_nsec timestamp, char type, std::string const & text, rsutils::json const & data ) > on_device_log_callback; rsutils::subscription on_device_log( on_device_log_callback && cb ); - typedef std::function< void( std::string const & id, nlohmann::json const & ) > on_notification_callback; + typedef std::function< void( std::string const & id, rsutils::json const & ) > on_notification_callback; rsutils::subscription on_notification( on_notification_callback && ); private: diff --git a/third-party/realdds/include/realdds/dds-metadata-syncer.h b/third-party/realdds/include/realdds/dds-metadata-syncer.h index 1142e24bfd6..40734e0c9a4 100644 --- a/third-party/realdds/include/realdds/dds-metadata-syncer.h +++ b/third-party/realdds/include/realdds/dds-metadata-syncer.h @@ -1,9 +1,8 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2023 Intel Corporation. All Rights Reserved. - #pragma once -#include +#include #include #include @@ -54,7 +53,7 @@ class dds_metadata_syncer typedef std::unique_ptr< frame_type, on_frame_release_callback > frame_holder; // Metadata is intended to be JSON - typedef std::shared_ptr< const nlohmann::json > metadata_type; + typedef std::shared_ptr< const rsutils::json > metadata_type; // So our main callback gets this generic frame and metadata: typedef std::function< void( frame_holder &&, metadata_type const & metadata ) > on_frame_ready_callback; diff --git a/third-party/realdds/include/realdds/dds-option.h b/third-party/realdds/include/realdds/dds-option.h index b1d492dd304..8c621626e4d 100644 --- a/third-party/realdds/include/realdds/dds-option.h +++ b/third-party/realdds/include/realdds/dds-option.h @@ -1,10 +1,8 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once - -#include +#include #include #include @@ -31,7 +29,7 @@ class dds_option dds_option_range _range; std::string _description; - dds_option( nlohmann::json const & ); + dds_option( rsutils::json const & ); friend class dds_stream_base; std::weak_ptr< dds_stream_base > _stream; @@ -49,8 +47,8 @@ class dds_option const dds_option_range & get_range() const { return _range; } const std::string & get_description() const { return _description; } - nlohmann::json to_json() const; - static std::shared_ptr< dds_option > from_json( nlohmann::json const & j ); + rsutils::json to_json() const; + static std::shared_ptr< dds_option > from_json( rsutils::json const & j ); }; typedef std::vector< std::shared_ptr< dds_option > > dds_options; diff --git a/third-party/realdds/include/realdds/dds-participant.h b/third-party/realdds/include/realdds/dds-participant.h index 13dabc82d5b..d2c23707274 100644 --- a/third-party/realdds/include/realdds/dds-participant.h +++ b/third-party/realdds/include/realdds/dds-participant.h @@ -1,12 +1,10 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once #include "dds-defines.h" -#include - +#include #include #include #include @@ -52,7 +50,7 @@ class dds_participant struct listener_impl; - nlohmann::json _settings; + rsutils::json _settings; public: dds_participant() = default; @@ -64,7 +62,7 @@ class dds_participant // // The domain ID may be -1: in this case the settings "domain" is queried and a default of 0 is used // - void init( dds_domain_id, std::string const & participant_name, nlohmann::json const & settings ); + void init( dds_domain_id, std::string const & participant_name, rsutils::json const & settings ); bool is_valid() const { return ( nullptr != _participant ); } bool operator!() const { return ! is_valid(); } @@ -72,7 +70,7 @@ class dds_participant eprosima::fastdds::dds::DomainParticipant * get() const { return _participant; } eprosima::fastdds::dds::DomainParticipant * operator->() const { return get(); } - nlohmann::json const & settings() const { return _settings; } + rsutils::json const & settings() const { return _settings; } // RTPS 8.2.4.2 "Every Participant has GUID , where the constant ENTITYID_PARTICIPANT // is a special value defined by the RTPS protocol. Its actual value depends on the PSM." diff --git a/third-party/realdds/include/realdds/dds-serialization.h b/third-party/realdds/include/realdds/dds-serialization.h index b1416288ce0..c4d75fcfc49 100644 --- a/third-party/realdds/include/realdds/dds-serialization.h +++ b/third-party/realdds/include/realdds/dds-serialization.h @@ -4,7 +4,7 @@ #include -#include +#include #include @@ -28,14 +28,17 @@ class DomainParticipantQos; namespace eprosima { namespace fastrtps { + // Allow j["key"] = qos.lease_duration; -void to_json( nlohmann::json &, Duration_t const & ); +void to_json( rsutils::json &, Duration_t const & ); // Allow j.get< eprosima::fastrtps::Duration_t >(); -void from_json( nlohmann::json const &, Duration_t & ); +void from_json( rsutils::json const &, Duration_t & ); + namespace rtps { std::ostream & operator<<( std::ostream &, class WriterProxyData const & ); std::ostream & operator<<( std::ostream &, class ReaderProxyData const & ); } // namespace rtps + } // namespace fastrtps } // namespace eprosima @@ -57,7 +60,7 @@ eprosima::fastrtps::rtps::MemoryManagementPolicy_t history_memory_policy_from_st // "kind": "reliable" // } // -void override_reliability_qos_from_json( eprosima::fastdds::dds::ReliabilityQosPolicy & qos, nlohmann::json const & ); +void override_reliability_qos_from_json( eprosima::fastdds::dds::ReliabilityQosPolicy & qos, rsutils::json const & ); // Override QoS durability from a JSON source. // The JSON can be a simple string indicating simple durability kind: @@ -67,7 +70,7 @@ void override_reliability_qos_from_json( eprosima::fastdds::dds::ReliabilityQosP // "kind": "persistent" // } // -void override_durability_qos_from_json( eprosima::fastdds::dds::DurabilityQosPolicy & qos, nlohmann::json const & ); +void override_durability_qos_from_json( eprosima::fastdds::dds::DurabilityQosPolicy & qos, rsutils::json const & ); // Override QoS history from a JSON source. // The JSON can be a simple unsigned integer indicating simple history depth: @@ -78,7 +81,7 @@ void override_durability_qos_from_json( eprosima::fastdds::dds::DurabilityQosPol // "depth": 20 // } // -void override_history_qos_from_json( eprosima::fastdds::dds::HistoryQosPolicy & qos, nlohmann::json const & ); +void override_history_qos_from_json( eprosima::fastdds::dds::HistoryQosPolicy & qos, rsutils::json const & ); // Override QoS liveliness from a JSON source. @@ -89,14 +92,14 @@ void override_history_qos_from_json( eprosima::fastdds::dds::HistoryQosPolicy & // "announcement-period": 3 // seconds // } // -void override_liveliness_qos_from_json( eprosima::fastdds::dds::LivelinessQosPolicy & qos, nlohmann::json const & ); +void override_liveliness_qos_from_json( eprosima::fastdds::dds::LivelinessQosPolicy & qos, rsutils::json const & ); // Override QoS data-sharing from a JSON source. // The JSON can be a simple boolean indicating off or automatic mode: // "data-sharing": true // <-- the JSON is the true value // -void override_data_sharing_qos_from_json( eprosima::fastdds::dds::DataSharingQosPolicy & qos, nlohmann::json const & ); +void override_data_sharing_qos_from_json( eprosima::fastdds::dds::DataSharingQosPolicy & qos, rsutils::json const & ); // Override QoS endpoint from a JSON source. // The JSON is an object: @@ -104,7 +107,7 @@ void override_data_sharing_qos_from_json( eprosima::fastdds::dds::DataSharingQos // "history-memory-policy": "preallocated-with-realloc" // } // -void override_endpoint_qos_from_json( eprosima::fastdds::dds::RTPSEndpointQos & qos, nlohmann::json const & ); +void override_endpoint_qos_from_json( eprosima::fastdds::dds::RTPSEndpointQos & qos, rsutils::json const & ); // Override participant QoS from a JSON source. @@ -114,7 +117,7 @@ void override_endpoint_qos_from_json( eprosima::fastdds::dds::RTPSEndpointQos & // "lease-duration": 10, // seconds // } // -void override_participant_qos_from_json( eprosima::fastdds::dds::DomainParticipantQos & qos, nlohmann::json const & ); +void override_participant_qos_from_json( eprosima::fastdds::dds::DomainParticipantQos & qos, rsutils::json const & ); } // namespace realdds diff --git a/third-party/realdds/include/realdds/dds-stream-profile.h b/third-party/realdds/include/realdds/dds-stream-profile.h index e9f07faa8bd..a6e20a6d517 100644 --- a/third-party/realdds/include/realdds/dds-stream-profile.h +++ b/third-party/realdds/include/realdds/dds-stream-profile.h @@ -1,10 +1,8 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once - -#include +#include #include #include @@ -76,7 +74,7 @@ class dds_stream_profile : _frequency( frequency ) { } - dds_stream_profile( nlohmann::json const &, int & index ); + dds_stream_profile( rsutils::json const &, int & index ); public: std::shared_ptr< dds_stream_base > stream() const { return _stream.lock(); } @@ -90,13 +88,13 @@ class dds_stream_profile virtual std::string details_to_string() const; // Serialization to a JSON array representation - virtual nlohmann::json to_json() const; + virtual rsutils::json to_json() const; // Build a profile from a json array object, e.g.: // auto profile = dds_stream_profile::from_json< dds_video_stream_profile >( j ); // This is the reverse of to_json() which returns a json array template< class final_stream_profile > - static std::shared_ptr< final_stream_profile > from_json( nlohmann::json const & j ) + static std::shared_ptr< final_stream_profile > from_json( rsutils::json const & j ) { int it = 0; auto profile = std::make_shared< final_stream_profile >( j, it ); @@ -105,7 +103,7 @@ class dds_stream_profile } private: - static void verify_end_of_json( nlohmann::json const &, int index ); + static void verify_end_of_json( rsutils::json const &, int index ); }; @@ -131,7 +129,7 @@ class dds_video_stream_profile : public dds_stream_profile , _encoding( encoding ) { } - dds_video_stream_profile( nlohmann::json const &, int & index ); + dds_video_stream_profile( rsutils::json const &, int & index ); uint16_t width() const { return _width; } uint16_t height() const { return _height; } @@ -139,7 +137,7 @@ class dds_video_stream_profile : public dds_stream_profile std::string details_to_string() const override; - nlohmann::json to_json() const override; + rsutils::json to_json() const override; }; @@ -152,7 +150,7 @@ class dds_motion_stream_profile : public dds_stream_profile : super( frequency ) { } - dds_motion_stream_profile( nlohmann::json const & j, int & index ) + dds_motion_stream_profile( rsutils::json const & j, int & index ) : super( j, index ) { } diff --git a/third-party/realdds/include/realdds/dds-topic-reader.h b/third-party/realdds/include/realdds/dds-topic-reader.h index cf8563052da..fe375bbef52 100644 --- a/third-party/realdds/include/realdds/dds-topic-reader.h +++ b/third-party/realdds/include/realdds/dds-topic-reader.h @@ -1,12 +1,11 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once #include #include -#include +#include #include #include @@ -76,7 +75,7 @@ class dds_topic_reader : public eprosima::fastdds::dds::DataReaderListener = eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS ); // default is transient local // Override default values with JSON contents - void override_from_json( nlohmann::json const & ); + void override_from_json( rsutils::json const & ); }; // The callbacks should be set before we actually create the underlying DDS objects, so the reader does not diff --git a/third-party/realdds/include/realdds/dds-topic-writer.h b/third-party/realdds/include/realdds/dds-topic-writer.h index c43daa07318..bb6e6b13d38 100644 --- a/third-party/realdds/include/realdds/dds-topic-writer.h +++ b/third-party/realdds/include/realdds/dds-topic-writer.h @@ -7,7 +7,7 @@ #include #include "dds-defines.h" -#include +#include #include #include @@ -75,7 +75,7 @@ class dds_topic_writer : protected eprosima::fastdds::dds::DataWriterListener = eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS ); // default is transient local // Override default values with JSON contents - void override_from_json( nlohmann::json const & ); + void override_from_json( rsutils::json const & ); }; // The callbacks should be set before we actually create the underlying DDS objects, so the writer does not diff --git a/third-party/realdds/include/realdds/dds-trinsics.h b/third-party/realdds/include/realdds/dds-trinsics.h index edb390d5a2e..15a58b03f10 100644 --- a/third-party/realdds/include/realdds/dds-trinsics.h +++ b/third-party/realdds/include/realdds/dds-trinsics.h @@ -1,9 +1,8 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2023 Intel Corporation. All Rights Reserved. - #pragma once -#include +#include #include #include @@ -33,8 +32,8 @@ struct video_intrinsics return width < rhs.width || ( width == rhs.width && height < rhs.height ); } - nlohmann::json to_json() const; - static video_intrinsics from_json( nlohmann::json const & j ); + rsutils::json to_json() const; + static video_intrinsics from_json( rsutils::json const & j ); }; // Internal properties of a motion stream. @@ -45,8 +44,8 @@ struct motion_intrinsics std::array< float, 3 > noise_variances = { 0 }; std::array< float, 3 > bias_variances = { 0 }; - nlohmann::json to_json() const; - static motion_intrinsics from_json( nlohmann::json const & j ); + rsutils::json to_json() const; + static motion_intrinsics from_json( rsutils::json const & j ); }; @@ -56,8 +55,8 @@ struct extrinsics std::array< float, 9 > rotation = { 0 }; // Column-major 3x3 rotation matrix std::array< float, 3 > translation = { 0 }; // Three-element translation vector, in meters - nlohmann::json to_json() const; - static extrinsics from_json( nlohmann::json const & j ); + rsutils::json to_json() const; + static extrinsics from_json( rsutils::json const & j ); }; diff --git a/third-party/realdds/include/realdds/topics/device-info-msg.h b/third-party/realdds/include/realdds/topics/device-info-msg.h index 87c343e242e..9208bcf72de 100644 --- a/third-party/realdds/include/realdds/topics/device-info-msg.h +++ b/third-party/realdds/include/realdds/topics/device-info-msg.h @@ -2,8 +2,7 @@ // Copyright(c) 2022 Intel Corporation. All Rights Reserved. #pragma once -#include - +#include #include namespace realdds { @@ -11,7 +10,7 @@ namespace topics { class device_info { - nlohmann::json _json; + rsutils::json _json; public: //std::string serial; @@ -27,8 +26,8 @@ class device_info std::string const & serial_number() const; void set_serial_number( std::string const & ); - nlohmann::json const & to_json() const; - static device_info from_json( nlohmann::json const & ); + rsutils::json const & to_json() const; + static device_info from_json( rsutils::json const & ); // Substring of information already stored in the device-info that can be used to print the device 'name'. // (mostly for use with debug messages) diff --git a/third-party/realdds/include/realdds/topics/flexible-msg.h b/third-party/realdds/include/realdds/topics/flexible-msg.h index 7088c02b3e9..72f3a8e80d6 100644 --- a/third-party/realdds/include/realdds/topics/flexible-msg.h +++ b/third-party/realdds/include/realdds/topics/flexible-msg.h @@ -1,18 +1,15 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once - #include "flexible/flexible.h" #include +#include #include #include #include -#include - namespace eprosima { namespace fastdds { @@ -82,10 +79,10 @@ class flexible_msg flexible_msg() = default; flexible_msg( raw::flexible && ); - flexible_msg( nlohmann::json const &, uint32_t version = 0 ); - flexible_msg( data_format format, nlohmann::json const &, uint32_t version = 0 ); + flexible_msg( rsutils::json const &, uint32_t version = 0 ); + flexible_msg( data_format format, rsutils::json const &, uint32_t version = 0 ); - nlohmann::json json_data() const; + rsutils::json json_data() const; // Get the custom data with casting to the desired type // Syntax: auto stream_info = msg.custom_data< STREAM_INFO >(); diff --git a/third-party/realdds/include/realdds/topics/flexible/flexible-writer.h b/third-party/realdds/include/realdds/topics/flexible/flexible-writer.h index 0cdd049d86e..1f8f5d849e4 100644 --- a/third-party/realdds/include/realdds/topics/flexible/flexible-writer.h +++ b/third-party/realdds/include/realdds/topics/flexible/flexible-writer.h @@ -1,13 +1,10 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once - #include -#include - +#include #include #include #include @@ -49,7 +46,7 @@ class flexible_writer void wait_for_readers( int n_readers, std::chrono::seconds timeout = std::chrono::seconds( 3 ) ); - void write( nlohmann::json && json ); + void write( rsutils::json && json ); private: void on_publication_matched( eprosima::fastdds::dds::PublicationMatchedStatus const & status ); diff --git a/third-party/realdds/py/pyrealdds.cpp b/third-party/realdds/py/pyrealdds.cpp index cab2ec5a0b1..d526ac5541f 100644 --- a/third-party/realdds/py/pyrealdds.cpp +++ b/third-party/realdds/py/pyrealdds.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -75,42 +76,30 @@ std::string script_name() } -nlohmann::json load_rs_settings( nlohmann::json const & local_settings ) +rsutils::json load_rs_settings( rsutils::json const & local_settings ) { - nlohmann::json config; - // Load the realsense configuration file settings - std::ifstream f( rsutils::os::get_special_folder( rsutils::os::special_folder::app_data ) + "realsense-config.json" ); - if( f.good() ) - { - try - { - config = nlohmann::json::parse( f ); - } - catch( std::exception const & e ) - { - throw std::runtime_error( "failed to load configuration file: " + std::string( e.what() ) ); - } - } + std::string const filename = rsutils::os::get_special_folder( rsutils::os::special_folder::app_data ) + "realsense-config.json"; + auto config = rsutils::json_config::load_from_file( filename ); // Load "python"-specific settings - auto settings = rsutils::json::load_app_settings( config, "python", "context", "config-file" ); + rsutils::json settings = rsutils::json_config::load_app_settings( config, "python", "context", "config-file" ); // Take the "dds" settings only - settings = rsutils::json::nested( settings, "dds" ); + settings = settings.nested( "dds" ); // Patch any script-specific settings // NOTE: this is also accessed by pyrealsense2, where a "context" hierarchy is still used auto script = script_name(); - if( auto script_settings = rsutils::json::nested( config, script, "context", "dds" ) ) - rsutils::json::patch( settings, script_settings, "config-file/" + script + "/context" ); + if( auto script_settings = config.nested( script, "context", "dds" ) ) + settings.override( script_settings, "config-file/" + script + "/context" ); // We should always have DDS enabled if( settings.is_object() ) settings.erase( "enabled" ); // Patch the given local settings into the configuration - rsutils::json::patch( settings, local_settings, "local settings" ); + settings.override( local_settings, "local settings" ); return settings; } @@ -201,7 +190,7 @@ PYBIND11_MODULE(NAME, m) { ( char const * topic_name, eprosima::fastrtps::types::DynamicType_ptr dyn_type ), callback( topic_name, dyn_type->get_name() ); ) ); - m.def( "load_rs_settings", &load_rs_settings, "local-settings"_a = nlohmann::json::object() ); + m.def( "load_rs_settings", &load_rs_settings, "local-settings"_a = rsutils::json::object() ); m.def( "script_name", &script_name ); py::class_< dds_participant, @@ -210,10 +199,10 @@ PYBIND11_MODULE(NAME, m) { participant( m, "participant" ); participant.def( py::init<>() ) .def( "init", - []( dds_participant & self, nlohmann::json const & local_settings, realdds::dds_domain_id domain_id ) + []( dds_participant & self, rsutils::json const & local_settings, realdds::dds_domain_id domain_id ) { self.init( domain_id, script_name(), local_settings ); }, - "local-settings"_a = nlohmann::json::object(), "domain-id"_a = -1 ) - .def( "init", &dds_participant::init, "domain-id"_a, "participant-name"_a, "local-settings"_a = nlohmann::json::object() ) + "local-settings"_a = rsutils::json::object(), "domain-id"_a = -1 ) + .def( "init", &dds_participant::init, "domain-id"_a, "participant-name"_a, "local-settings"_a = rsutils::json::object() ) .def( "is_valid", &dds_participant::is_valid ) .def( "guid", &dds_participant::guid ) .def( "create_guid", &dds_participant::create_guid ) @@ -469,7 +458,7 @@ PYBIND11_MODULE(NAME, m) { "json"_a, "version"_a = 0 ) .def( py::init( []( std::string const & json_string ) { - return flexible_msg( flexible_msg::data_format::JSON, nlohmann::json::parse( json_string ) ); + return flexible_msg( flexible_msg::data_format::JSON, rsutils::json::parse( json_string ) ); } ) ) .def_static( "create_topic", static_cast< flexible_msg_create_topic * >( &flexible_msg::create_topic ) ) .def_readwrite( "data_format", &flexible_msg::_data_format ) @@ -777,10 +766,10 @@ PYBIND11_MODULE(NAME, m) { // def callback( json ): // print( json['value'] ) # calls __getitem__ // json['value'] = { 'more': True } # calls __setitem__ - struct json_ref { nlohmann::json & j; }; + struct json_ref { rsutils::json & j; }; py::class_< json_ref, std::shared_ptr< json_ref > >( m, "json_ref" ) .def( "__getitem__", []( json_ref const & jr, std::string const & key ) { return jr.j.at( key ); } ) - .def( "__setitem__", []( json_ref & jr, std::string const & key, nlohmann::json const & value ) { jr.j[key] = value; } ); + .def( "__setitem__", []( json_ref & jr, std::string const & key, rsutils::json const & value ) { jr.j[key] = value; } ); using realdds::dds_device_server; py::class_< dds_device_server, std::shared_ptr< dds_device_server > >( m, "device_server" ) @@ -797,14 +786,14 @@ PYBIND11_MODULE(NAME, m) { } ) .def( "publish_notification", - []( dds_device_server & self, nlohmann::json const & j ) { self.publish_notification( j ); }, + []( dds_device_server & self, rsutils::json const & j ) { self.publish_notification( j ); }, py::call_guard< py::gil_scoped_release >() ) .def( "publish_metadata", &dds_device_server::publish_metadata, py::call_guard< py::gil_scoped_release >() ) .def( "broadcast", &dds_device_server::broadcast ) .def( FN_FWD_R( dds_device_server, on_control, false, (dds_device_server &, std::string const &, py::object &&, json_ref &&), - ( std::string const & id, nlohmann::json const & control, nlohmann::json & reply ), + ( std::string const & id, rsutils::json const & control, rsutils::json & reply ), return callback( self, id, json_to_py( control ), json_ref{ reply } ); ) ); using realdds::dds_stream; @@ -894,21 +883,21 @@ PYBIND11_MODULE(NAME, m) { []( dds_device & self, std::function< void( dds_device &, py::object && ) > callback ) { return std::make_shared< subscription >( self.on_metadata_available( - [&self, callback]( std::shared_ptr< const nlohmann::json > const & pj ) + [&self, callback]( std::shared_ptr< const rsutils::json > const & pj ) { FN_FWD_CALL( dds_device, "on_metadata_available", callback( self, json_to_py( *pj ) ); ) } ) ); } ) .def( "on_device_log", []( dds_device & self, std::function< void( dds_device &, dds_nsec, char, std::string const &, py::object && ) > callback ) { return std::make_shared< subscription >( self.on_device_log( - [&self, callback]( dds_nsec timestamp, char type, std::string const & text, nlohmann::json const & data ) + [&self, callback]( dds_nsec timestamp, char type, std::string const & text, rsutils::json const & data ) { FN_FWD_CALL( dds_device, "on_device_log", callback( self, timestamp, type, text, json_to_py( data ) ); ) } ) ); } ) .def( "on_notification", []( dds_device & self, std::function< void( dds_device &, std::string const &, py::object && ) > callback ) { return std::make_shared< subscription >( self.on_notification( - [&self, callback]( std::string const & id, nlohmann::json const & data ) + [&self, callback]( std::string const & id, rsutils::json const & data ) { FN_FWD_CALL( dds_device, "on_notification", callback( self, id, json_to_py( data ) ); ) } ) ); } ) .def( "n_streams", &dds_device::number_of_streams ) @@ -929,9 +918,9 @@ PYBIND11_MODULE(NAME, m) { .def( "query_option_value", &dds_device::query_option_value ) .def( "send_control", - []( dds_device & self, nlohmann::json const & j, bool wait_for_reply ) + []( dds_device & self, rsutils::json const & j, bool wait_for_reply ) { - nlohmann::json reply; + rsutils::json reply; self.send_control( j, wait_for_reply ? &reply : nullptr ); return reply; }, @@ -1041,18 +1030,18 @@ PYBIND11_MODULE(NAME, m) { .def( py::init<>() ) .def( FN_FWD( dds_metadata_syncer, on_frame_ready, - ( dds_metadata_syncer::frame_type, nlohmann::json const & ), - ( dds_metadata_syncer::frame_holder && fh, std::shared_ptr< const nlohmann::json > const & metadata ), - callback( self.get_frame( fh ), metadata ? *metadata : nlohmann::json() ); ) ) + ( dds_metadata_syncer::frame_type, rsutils::json const & ), + ( dds_metadata_syncer::frame_holder && fh, std::shared_ptr< const rsutils::json > const & metadata ), + callback( self.get_frame( fh ), metadata ? *metadata : rsutils::json() ); ) ) .def( FN_FWD( dds_metadata_syncer, on_metadata_dropped, - ( dds_metadata_syncer::key_type, nlohmann::json const & ), - ( dds_metadata_syncer::key_type key, std::shared_ptr< const nlohmann::json > const & metadata ), - callback( key, metadata ? *metadata : nlohmann::json() ); ) ) + ( dds_metadata_syncer::key_type, rsutils::json const & ), + ( dds_metadata_syncer::key_type key, std::shared_ptr< const rsutils::json > const & metadata ), + callback( key, metadata ? *metadata : rsutils::json() ); ) ) .def( "enqueue_frame", &dds_metadata_syncer::enqueue_frame ) .def( "enqueue_metadata", - []( dds_metadata_syncer & self, dds_metadata_syncer::key_type key, nlohmann::json const & j ) - { self.enqueue_metadata( key, std::make_shared< const nlohmann::json >( j ) ); } ); + []( dds_metadata_syncer & self, dds_metadata_syncer::key_type key, rsutils::json const & j ) + { self.enqueue_metadata( key, std::make_shared< const rsutils::json >( j ) ); } ); metadata_syncer.attr( "max_frame_queue_size" ) = dds_metadata_syncer::max_frame_queue_size; metadata_syncer.attr( "max_md_queue_size" ) = dds_metadata_syncer::max_md_queue_size; } diff --git a/third-party/realdds/src/dds-device-impl.cpp b/third-party/realdds/src/dds-device-impl.cpp index 47d376efd08..fe1bcf6a9ec 100644 --- a/third-party/realdds/src/dds-device-impl.cpp +++ b/third-party/realdds/src/dds-device-impl.cpp @@ -47,12 +47,12 @@ static std::string const id_hwm( "hwm", 3 ); namespace { -nlohmann::json device_settings( std::shared_ptr< realdds::dds_participant > const & participant ) +rsutils::json device_settings( std::shared_ptr< realdds::dds_participant > const & participant ) { - nlohmann::json settings = rsutils::json::nested( participant->settings(), "device" ); - if( settings.is_null() ) + auto settings = participant->settings().nested( "device" ); + if( ! settings ) // Nothing there: default is empty object - return nlohmann::json::object(); + return rsutils::json::object(); if( ! settings.is_object() ) // Device settings, if they exist, must be an object! DDS_THROW( runtime_error, "participant 'device' settings must be an object: " << settings ); @@ -95,8 +95,8 @@ void dds_device::impl::set_state( state_t new_state ) { if( _metadata_reader ) { - nlohmann::json md_settings = rsutils::json::nested( _device_settings, "metadata" ); - if( ! md_settings.is_null() && ! md_settings.is_object() ) // not found is null + auto md_settings = _device_settings.nested( "metadata" ); + if( md_settings.exists() && ! md_settings.is_object() ) { LOG_DEBUG( "[" << debug_name() << "] ... metadata is available but device/metadata is disabled" ); _metadata_reader.reset(); @@ -137,7 +137,7 @@ dds_device::impl::impl( std::shared_ptr< dds_participant > const & participant, , _subscriber( std::make_shared< dds_subscriber >( participant ) ) , _device_settings( device_settings( participant ) ) , _reply_timeout_ms( - rsutils::json::nested( _device_settings, "control", "reply-timeout-ms" ).default_value< size_t >( 2000 ) ) + _device_settings.nested( "control", "reply-timeout-ms" ).default_value< size_t >( 2000 ) ) { create_notifications_reader(); create_control_writer(); @@ -172,13 +172,13 @@ void dds_device::impl::wait_until_ready( size_t timeout_ms ) } -void dds_device::impl::handle_notification( nlohmann::json const & j, +void dds_device::impl::handle_notification( rsutils::json const & j, eprosima::fastdds::dds::SampleInfo const & sample ) { try { // First handle the notification - auto id = rsutils::json::get< std::string >( j, id_key ); + auto id = j.at( id_key ).get< std::string >(); auto it = _notification_handlers.find( id ); if( it != _notification_handlers.end() ) ( this->*( it->second ) )( j, sample ); @@ -196,18 +196,17 @@ void dds_device::impl::handle_notification( nlohmann::json const & j, try { // Check if this is a reply - maybe someone's waiting on it... - auto sampleit = j.find( sample_key ); - if( sampleit != j.end() ) + if( auto sample = j.nested( sample_key ) ) { - nlohmann::json const & sample = *sampleit; // [".", ] + // [".", ] if( sample.size() == 2 && sample.is_array() ) { // We have to be the ones who sent the control! - auto const reply_guid = guid_from_string( rsutils::json::get< std::string >( sample, 0 ) ); + auto const reply_guid = guid_from_string( sample[0].get< std::string >() ); auto const control_guid = _control_writer->get()->guid(); if( reply_guid == control_guid ) { - auto const sequence_number = rsutils::json::get< uint64_t >( sample, 1 ); + auto const sequence_number = sample[1].get< uint64_t >(); std::unique_lock< std::mutex > lock( _replies_mutex ); auto replyit = _replies.find( sequence_number ); if( replyit != _replies.end() ) @@ -235,7 +234,7 @@ void dds_device::impl::handle_notification( nlohmann::json const & j, } -void dds_device::impl::on_option_value( nlohmann::json const & j, eprosima::fastdds::dds::SampleInfo const & ) +void dds_device::impl::on_option_value( rsutils::json const & j, eprosima::fastdds::dds::SampleInfo const & ) { if( ! is_ready() ) return; @@ -247,13 +246,13 @@ void dds_device::impl::on_option_value( nlohmann::json const & j, eprosima::fast dds_device::check_reply( j ); // We need the original control request as part of the reply, otherwise we can't know what option this is for - rsutils::json::nested control( j, control_key ); + auto control = j.nested( control_key ); if( ! control.is_object() ) throw std::runtime_error( "missing control object" ); // Find the relevant (stream) options to update dds_options const * options = &_options; - std::string const & stream_name = control.find( stream_name_key ).string_ref_or_empty(); // default = empty = device option + std::string const & stream_name = control.nested( stream_name_key ).string_ref_or_empty(); // default = empty = device option if( ! stream_name.empty() ) { auto stream_it = _streams.find( stream_name ); @@ -277,40 +276,40 @@ void dds_device::impl::on_option_value( nlohmann::json const & j, eprosima::fast LOG_DEBUG( "[" << debug_name() << "] option '" << option_name << "': not found" ); }; - rsutils::json::nested value_j( j, value_key ); + auto value_j = j.nested( value_key ); if( ! value_j.exists() ) { // Use case: // Bulk query without ANY option names supplied, { "option-name": [] } // There is no 'value' key; instead, the server returns option-value pairs in 'option-values': - rsutils::json::nested option_values( j, option_values_key ); + auto option_values = j.nested( option_values_key ); if( ! option_values.is_object() ) throw std::runtime_error( "missing value or option-values" ); - for( auto it = option_values->begin(); it != option_values->end(); ++it ) + for( auto it = option_values.begin(); it != option_values.end(); ++it ) update_option( it.key(), it.value().get< float >() ); return; } - auto option_name_j = control.find( option_name_key ); + auto option_name_j = control.nested( option_name_key ); if( ! option_name_j.exists() ) throw std::runtime_error( "missing option-name" ); - if( value_j->is_array() ) + if( value_j.is_array() ) { // Use case: // Bulk query, but specific option names were given, { "option-name": ["opt1", ...] } // The 'option-name' should be an array of options for which values are returned // The 'value' should be a similarly-sized array - if( ! option_name_j->is_array() ) + if( ! option_name_j.is_array() ) throw std::runtime_error( "'option-name' does not match 'value' array type" ); - if( value_j->size() != option_name_j->size() ) + if( value_j.size() != option_name_j.size() ) throw std::runtime_error( "'option-name' does not match 'value' array size" ); - auto size = value_j->size(); + auto size = value_j.size(); for( auto x = 0; x < size; ++x ) { - auto const & option_name = rsutils::json::string_ref( option_name_j->at( x ) ); - auto const new_value = rsutils::json::value< float >( value_j->at( x ) ); + auto const & option_name = option_name_j[x].string_ref(); + auto const new_value = value_j[x].get< float >(); update_option( option_name, new_value ); } return; @@ -320,27 +319,27 @@ void dds_device::impl::on_option_value( nlohmann::json const & j, eprosima::fast // Simple single-option value update, { "option-name": "opt1" } // 'option-name' should be a string // A single 'value' is returned - if( ! option_name_j->is_string() ) + if( ! option_name_j.is_string() ) throw std::runtime_error( "option-name is not a string" ); auto & option_name = option_name_j.string_ref(); - update_option( option_name, rsutils::json::value< float >( value_j ) ); + update_option( option_name, value_j.get< float >() ); } -void dds_device::impl::on_known_notification( nlohmann::json const & j, eprosima::fastdds::dds::SampleInfo const & ) +void dds_device::impl::on_known_notification( rsutils::json const & j, eprosima::fastdds::dds::SampleInfo const & ) { // This is a known notification, but we don't want to do anything for it } -void dds_device::impl::on_log( nlohmann::json const & j, eprosima::fastdds::dds::SampleInfo const & ) +void dds_device::impl::on_log( rsutils::json const & j, eprosima::fastdds::dds::SampleInfo const & ) { // This is the notification for "log" (see docs/notifications.md#Logging) // - `entries` is an array containing 1 or more log entries - auto it = j.find( entries_key ); - if( it == j.end() ) + auto entries = j.nested( entries_key ); + if( ! entries ) throw std::runtime_error( "log entries not found" ); - if( ! it->is_array() ) + if( ! entries.is_array() ) throw std::runtime_error( "log entries not an array" ); // Each log entry is a JSON array of `[timestamp, type, text, data]` containing: // - `timestamp`: when the event occurred @@ -348,7 +347,7 @@ void dds_device::impl::on_log( nlohmann::json const & j, eprosima::fastdds::dds: // - `text`: any text that needs output // - `data`: optional; an object containing any pertinent information about the event size_t x = 0; - for( auto & entry : *it ) + for( auto & entry : entries ) { try { @@ -356,13 +355,13 @@ void dds_device::impl::on_log( nlohmann::json const & j, eprosima::fastdds::dds: throw std::runtime_error( "not an array" ); if( entry.size() < 3 || entry.size() > 4 ) throw std::runtime_error( "bad array length" ); - auto timestamp = rsutils::json::get< dds_nsec >( entry, 0 ); - auto const & stype = rsutils::json::string_ref( entry[1] ); + auto timestamp = entry[0].get< dds_nsec >(); + auto const & stype = entry[1].string_ref(); if( stype.length() != 1 || ! strchr( "EWID", stype[0] ) ) throw std::runtime_error( "type not one of 'EWID'" ); char const type = stype[0]; - auto const & text = rsutils::json::string_ref( entry[2] ); - nlohmann::json const & data = entry.size() > 3 ? entry[3] : rsutils::json::null_json; + auto const & text = entry[2].string_ref(); + auto const & data = entry.size() > 3 ? entry[3] : rsutils::null_json; if( ! _on_device_log.raise( timestamp, type, text, data ) ) LOG_DEBUG( "[" << debug_name() << "][" << timestamp << "][" << type << "] " << text @@ -382,24 +381,24 @@ void dds_device::impl::open( const dds_stream_profiles & profiles ) if( profiles.empty() ) DDS_THROW( runtime_error, "must provide at least one profile" ); - auto stream_profiles = nlohmann::json(); + rsutils::json stream_profiles; for( auto & profile : profiles ) { auto stream = profile->stream(); if( ! stream ) DDS_THROW( runtime_error, "profile " << profile->to_string() << " is not part of any stream" ); - if( stream_profiles.find( stream->name() ) != stream_profiles.end() ) + if( stream_profiles.nested( stream->name() ) ) DDS_THROW( runtime_error, "more than one profile found for stream '" << stream->name() << "'" ); stream_profiles[stream->name()] = profile->to_json(); } - nlohmann::json j = { + rsutils::json j = { { id_key, id_open_streams }, { "stream-profiles", stream_profiles }, }; - nlohmann::json reply; + rsutils::json reply; write_control_message( j, &reply ); } @@ -409,7 +408,7 @@ void dds_device::impl::set_option_value( const std::shared_ptr< dds_option > & o if( ! option ) DDS_THROW( runtime_error, "must provide an option to set" ); - nlohmann::json j = nlohmann::json::object({ + rsutils::json j = rsutils::json::object({ { id_key, id_set_option }, { option_name_key, option->get_name() }, { value_key, new_value } @@ -417,7 +416,7 @@ void dds_device::impl::set_option_value( const std::shared_ptr< dds_option > & o if( auto stream = option->stream() ) j[stream_name_key] = stream->name(); - nlohmann::json reply; + rsutils::json reply; write_control_message( j, &reply ); //option->set_value( new_value ); } @@ -428,21 +427,21 @@ float dds_device::impl::query_option_value( const std::shared_ptr< dds_option > if( !option ) DDS_THROW( runtime_error, "must provide an option to query" ); - nlohmann::json j = nlohmann::json::object({ + rsutils::json j = rsutils::json::object({ { id_key, id_query_option }, { option_name_key, option->get_name() } }); if( auto stream = option->stream() ) j[stream_name_key] = stream->name(); - nlohmann::json reply; + rsutils::json reply; write_control_message( j, &reply ); - return rsutils::json::get< float >( reply, value_key ); + return reply.at( value_key ).get< float >(); } -void dds_device::impl::write_control_message( topics::flexible_msg && msg, nlohmann::json * reply ) +void dds_device::impl::write_control_message( topics::flexible_msg && msg, rsutils::json * reply ) { assert( _control_writer != nullptr ); auto this_sequence_number = std::move( msg ).write_to( *_control_writer ); @@ -486,7 +485,7 @@ void dds_device::impl::create_notifications_reader() //On discovery writer sends a burst of messages, if history is too small we might loose some of them //(even if reliable). Setting depth to cover known use-cases plus some spare rqos.history().depth = 24; - rqos.override_from_json( rsutils::json::nested( _device_settings, "notification" ) ); + rqos.override_from_json( _device_settings.nested( "notification" ) ); _notifications_reader->on_data_available( [&]() @@ -530,7 +529,7 @@ void dds_device::impl::create_metadata_reader() { try { - auto sptr = std::make_shared< const nlohmann::json >( message.json_data() ); + auto sptr = std::make_shared< const rsutils::json >( message.json_data() ); _on_metadata_available.raise( sptr ); } catch( std::exception const & e ) @@ -553,12 +552,12 @@ void dds_device::impl::create_control_writer() _control_writer = std::make_shared< dds_topic_writer >( topic ); dds_topic_writer::qos wqos( eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS ); wqos.history().depth = 10; // default is 1 - wqos.override_from_json( rsutils::json::nested( _device_settings, "control" ) ); + wqos.override_from_json( _device_settings.nested( "control" ) ); _control_writer->run( wqos ); } -void dds_device::impl::on_device_header( nlohmann::json const & j, eprosima::fastdds::dds::SampleInfo const & sample ) +void dds_device::impl::on_device_header( rsutils::json const & j, eprosima::fastdds::dds::SampleInfo const & sample ) { if( _state != state_t::WAIT_FOR_DEVICE_HEADER ) return; @@ -567,17 +566,17 @@ void dds_device::impl::on_device_header( nlohmann::json const & j, eprosima::fas // with a server. eprosima::fastrtps::rtps::iHandle2GUID( _server_guid, sample.publication_handle ); - _n_streams_expected = rsutils::json::get< size_t >( j, "n-streams" ); + _n_streams_expected = j.at( "n-streams" ).get< size_t >(); LOG_DEBUG( "[" << debug_name() << "] ... " << id_device_header << ": " << _n_streams_expected << " streams expected" ); - if( rsutils::json::has( j, "extrinsics" ) ) + if( auto extrinsics_j = j.nested( "extrinsics" ) ) { - for( auto & ex : j["extrinsics"] ) + for( auto & ex : extrinsics_j ) { - std::string from_name = rsutils::json::get< std::string >( ex, 0 ); - std::string to_name = rsutils::json::get< std::string >( ex, 1 ); + std::string const & from_name = ex[0].string_ref(); + std::string const & to_name = ex[1].string_ref(); LOG_DEBUG( "[" << debug_name() << "] ... got extrinsics from " << from_name << " to " << to_name ); - extrinsics extr = extrinsics::from_json( rsutils::json::get< nlohmann::json >( ex, 2 ) ); + extrinsics extr = extrinsics::from_json( ex[2] ); _extrinsics_map[std::make_pair( from_name, to_name )] = std::make_shared< extrinsics >( extr ); } } @@ -586,16 +585,16 @@ void dds_device::impl::on_device_header( nlohmann::json const & j, eprosima::fas } -void dds_device::impl::on_device_options( nlohmann::json const & j, eprosima::fastdds::dds::SampleInfo const & sample ) +void dds_device::impl::on_device_options( rsutils::json const & j, eprosima::fastdds::dds::SampleInfo const & sample ) { if( _state != state_t::WAIT_FOR_DEVICE_OPTIONS ) return; - if( rsutils::json::has( j, "options" ) ) + if( auto options_j = j.nested( "options" ) ) { - LOG_DEBUG( "[" << debug_name() << "] ... " << id_device_options << ": " << j["options"].size() << " options received" ); + LOG_DEBUG( "[" << debug_name() << "] ... " << id_device_options << ": " << options_j.size() << " options received" ); - for( auto & option_json : j["options"] ) + for( auto & option_json : options_j ) { auto option = dds_option::from_json( option_json ); _options.push_back( option ); @@ -609,22 +608,22 @@ void dds_device::impl::on_device_options( nlohmann::json const & j, eprosima::fa } -void dds_device::impl::on_stream_header( nlohmann::json const & j, eprosima::fastdds::dds::SampleInfo const & sample ) +void dds_device::impl::on_stream_header( rsutils::json const & j, eprosima::fastdds::dds::SampleInfo const & sample ) { if( _state != state_t::WAIT_FOR_STREAM_HEADER ) return; if( _streams.size() >= _n_streams_expected ) DDS_THROW( runtime_error, "more streams than expected (" << _n_streams_expected << ") received" ); - auto stream_type = rsutils::json::get< std::string >( j, "type" ); - auto stream_name = rsutils::json::get< std::string >( j, "name" ); + auto & stream_type = j.at( "type" ).string_ref(); + auto & stream_name = j.at( "name" ).string_ref(); auto & stream = _streams[stream_name]; if( stream ) DDS_THROW( runtime_error, "stream '" << stream_name << "' already exists" ); - auto sensor_name = rsutils::json::get< std::string >( j, "sensor-name" ); - size_t default_profile_index = rsutils::json::get< size_t >( j, "default-profile-index" ); + auto & sensor_name = j.at( "sensor-name" ).string_ref(); + size_t default_profile_index = j.at( "default-profile-index" ).get< size_t >(); dds_stream_profiles profiles; #define TYPE2STREAM( S, P ) \ @@ -645,7 +644,7 @@ void dds_device::impl::on_stream_header( nlohmann::json const & j, eprosima::fas #undef TYPE2STREAM - if( rsutils::json::get< bool >( j, "metadata-enabled" ) ) + if( j.at( "metadata-enabled" ).get< bool >() ) { create_metadata_reader(); stream->enable_metadata(); // Call before init_profiles @@ -670,22 +669,21 @@ void dds_device::impl::on_stream_header( nlohmann::json const & j, eprosima::fas } -void dds_device::impl::on_stream_options( nlohmann::json const & j, eprosima::fastdds::dds::SampleInfo const & sample ) +void dds_device::impl::on_stream_options( rsutils::json const & j, eprosima::fastdds::dds::SampleInfo const & sample ) { if( _state != state_t::WAIT_FOR_STREAM_OPTIONS ) return; - auto stream_it = _streams.find( rsutils::json::get< std::string >( j, "stream-name" ) ); + auto & stream_name = j.at( "stream-name" ).string_ref(); + auto stream_it = _streams.find( stream_name ); if( stream_it == _streams.end() ) DDS_THROW( runtime_error, - std::string( "Received stream options for stream '" ) - + rsutils::json::get< std::string >( j, "stream-name" ) - + "' whose header was not received yet" ); + "Received stream options for stream '" << stream_name << "' whose header was not received yet" ); - if( rsutils::json::has( j, "options" ) ) + if( auto options_j = j.nested( "options" ) ) { dds_options options; - for( auto & option : j["options"] ) + for( auto & option : options_j ) { options.push_back( dds_option::from_json( option ) ); } @@ -693,10 +691,8 @@ void dds_device::impl::on_stream_options( nlohmann::json const & j, eprosima::fa stream_it->second->init_options( options ); } - auto intit = j.find( "intrinsics" ); - if( intit != j.end() ) + if( auto j_int = j.nested( "intrinsics" ) ) { - nlohmann::json const & j_int = *intit; if( auto video_stream = std::dynamic_pointer_cast< dds_video_stream >( stream_it->second ) ) { std::set< video_intrinsics > intrinsics; @@ -706,15 +702,15 @@ void dds_device::impl::on_stream_options( nlohmann::json const & j, eprosima::fa } else if( auto motion_stream = std::dynamic_pointer_cast< dds_motion_stream >( stream_it->second ) ) { - motion_stream->set_accel_intrinsics( motion_intrinsics::from_json( j_int["accel"] ) ); - motion_stream->set_gyro_intrinsics( motion_intrinsics::from_json( j_int["gyro"] ) ); + motion_stream->set_accel_intrinsics( motion_intrinsics::from_json( j_int.at( "accel" ) ) ); + motion_stream->set_gyro_intrinsics( motion_intrinsics::from_json( j_int.at( "gyro" ) ) ); } } - if( rsutils::json::has( j, "recommended-filters" ) ) + if( auto filters_j = j.nested( "recommended-filters" ) ) { std::vector< std::string > filter_names; - for( auto & filter : j["recommended-filters"] ) + for( auto & filter : filters_j ) { filter_names.push_back( filter ); } diff --git a/third-party/realdds/src/dds-device-impl.h b/third-party/realdds/src/dds-device-impl.h index 3839e8cff97..a87862e7043 100644 --- a/third-party/realdds/src/dds-device-impl.h +++ b/third-party/realdds/src/dds-device-impl.h @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -51,7 +51,7 @@ class dds_device::impl public: topics::device_info const _info; - nlohmann::json const _device_settings; + rsutils::json const _device_settings; dds_guid _server_guid; std::shared_ptr< dds_participant > const _participant; std::shared_ptr< dds_subscriber > _subscriber; @@ -60,7 +60,7 @@ class dds_device::impl std::mutex _replies_mutex; std::condition_variable _replies_cv; - std::map< dds_sequence_number, nlohmann::json > _replies; + std::map< dds_sequence_number, rsutils::json > _replies; size_t _reply_timeout_ms; std::shared_ptr< dds_topic_reader > _notifications_reader; @@ -82,12 +82,12 @@ class dds_device::impl void open( const dds_stream_profiles & profiles ); - void write_control_message( topics::flexible_msg &&, nlohmann::json * reply = nullptr ); + void write_control_message( topics::flexible_msg &&, rsutils::json * reply = nullptr ); void set_option_value( const std::shared_ptr< dds_option > & option, float new_value ); float query_option_value( const std::shared_ptr< dds_option > & option ); - using on_metadata_available_signal = rsutils::signal< std::shared_ptr< const nlohmann::json > const & >; + using on_metadata_available_signal = rsutils::signal< std::shared_ptr< const rsutils::json > const & >; using on_metadata_available_callback = on_metadata_available_signal::callback; rsutils::subscription on_metadata_available( on_metadata_available_callback && cb ) { @@ -97,14 +97,14 @@ class dds_device::impl using on_device_log_signal = rsutils::signal< dds_nsec, // timestamp char, // type std::string const &, // text - nlohmann::json const & >; // data + rsutils::json const & >; // data using on_device_log_callback = on_device_log_signal::callback; rsutils::subscription on_device_log( on_device_log_callback && cb ) { return _on_device_log.subscribe( std::move( cb ) ); } - using on_notification_signal = rsutils::signal< std::string const &, nlohmann::json const & >; + using on_notification_signal = rsutils::signal< std::string const &, rsutils::json const & >; using on_notification_callback = on_notification_signal::callback; rsutils::subscription on_notification( on_notification_callback && cb ) { @@ -117,20 +117,20 @@ class dds_device::impl void create_control_writer(); // notification handlers - void on_option_value( nlohmann::json const &, eprosima::fastdds::dds::SampleInfo const & ); - void on_known_notification( nlohmann::json const &, eprosima::fastdds::dds::SampleInfo const & ); - void on_log( nlohmann::json const &, eprosima::fastdds::dds::SampleInfo const & ); - void on_device_header( nlohmann::json const &, eprosima::fastdds::dds::SampleInfo const & ); - void on_device_options( nlohmann::json const &, eprosima::fastdds::dds::SampleInfo const & ); - void on_stream_header( nlohmann::json const &, eprosima::fastdds::dds::SampleInfo const & ); - void on_stream_options( nlohmann::json const &, eprosima::fastdds::dds::SampleInfo const & ); + void on_option_value( rsutils::json const &, eprosima::fastdds::dds::SampleInfo const & ); + void on_known_notification( rsutils::json const &, eprosima::fastdds::dds::SampleInfo const & ); + void on_log( rsutils::json const &, eprosima::fastdds::dds::SampleInfo const & ); + void on_device_header( rsutils::json const &, eprosima::fastdds::dds::SampleInfo const & ); + void on_device_options( rsutils::json const &, eprosima::fastdds::dds::SampleInfo const & ); + void on_stream_header( rsutils::json const &, eprosima::fastdds::dds::SampleInfo const & ); + void on_stream_options( rsutils::json const &, eprosima::fastdds::dds::SampleInfo const & ); typedef std::map< std::string, - void ( dds_device::impl::* )( nlohmann::json const &, + void ( dds_device::impl::* )( rsutils::json const &, eprosima::fastdds::dds::SampleInfo const & ) > notification_handlers; static notification_handlers const _notification_handlers; - void handle_notification( nlohmann::json const &, eprosima::fastdds::dds::SampleInfo const & ); + void handle_notification( rsutils::json const &, eprosima::fastdds::dds::SampleInfo const & ); on_metadata_available_signal _on_metadata_available; on_device_log_signal _on_device_log; diff --git a/third-party/realdds/src/dds-device-server.cpp b/third-party/realdds/src/dds-device-server.cpp index 9f2853c0d73..5b577038b73 100644 --- a/third-party/realdds/src/dds-device-server.cpp +++ b/third-party/realdds/src/dds-device-server.cpp @@ -24,7 +24,7 @@ #include #include -using nlohmann::json; +using rsutils::json; using rsutils::string::slice; using rsutils::string::shorten_json_string; @@ -91,7 +91,7 @@ static void on_discovery_device_header( size_t const n_streams, //LOG_DEBUG( "-----> CBOR size = " << json::to_cbor( device_header.json_data() ).size() ); notifications.add_discovery_notification( std::move( device_header ) ); - auto device_options = nlohmann::json::array(); + auto device_options = rsutils::json::array(); for( auto & opt : options ) device_options.push_back( std::move( opt->to_json() ) ); topics::flexible_msg device_options_message( json { @@ -108,7 +108,7 @@ static void on_discovery_device_header( size_t const n_streams, static void on_discovery_stream_header( std::shared_ptr< dds_stream_server > const & stream, dds_notification_server & notifications ) { - auto profiles = nlohmann::json::array(); + auto profiles = rsutils::json::array(); for( auto & sp : stream->profiles() ) profiles.push_back( std::move( sp->to_json() ) ); topics::flexible_msg stream_header_message( json{ @@ -125,35 +125,35 @@ static void on_discovery_stream_header( std::shared_ptr< dds_stream_server > con //LOG_DEBUG( "-----> CBOR size = " << json::to_cbor( stream_header_message.json_data() ).size() ); notifications.add_discovery_notification( std::move( stream_header_message ) ); - auto stream_options = nlohmann::json::array(); + auto stream_options = rsutils::json::array(); for( auto & opt : stream->options() ) stream_options.push_back( std::move( opt->to_json() ) ); - nlohmann::json intrinsics; + rsutils::json intrinsics; if( auto video_stream = std::dynamic_pointer_cast< dds_video_stream_server >( stream ) ) { - intrinsics = nlohmann::json::array(); + intrinsics = rsutils::json::array(); for( auto & intr : video_stream->get_intrinsics() ) intrinsics.push_back( intr.to_json() ); } else if( auto motion_stream = std::dynamic_pointer_cast< dds_motion_stream_server >( stream ) ) { - intrinsics = nlohmann::json::object( { + intrinsics = rsutils::json::object( { { "accel", motion_stream->get_accel_intrinsics().to_json() }, { "gyro", motion_stream->get_gyro_intrinsics().to_json() } } ); } - auto stream_filters = nlohmann::json::array(); + auto stream_filters = rsutils::json::array(); for( auto & filter : stream->recommended_filters() ) stream_filters.push_back( filter ); - topics::flexible_msg stream_options_message( json { + topics::flexible_msg stream_options_message( json::object( { { id_key, "stream-options" }, { "stream-name", stream->name() }, - { "options" , std::move( stream_options ) }, - { "intrinsics" , intrinsics }, + { "options", std::move( stream_options ) }, + { "intrinsics", intrinsics }, { "recommended-filters", std::move( stream_filters ) }, - } ); + } ) ); json_string = slice( stream_options_message.custom_data< char const >(), stream_options_message._data.size() ); LOG_DEBUG( "-----> JSON = " << shorten_json_string( json_string, 300 ) << " size " << json_string.length() ); //LOG_DEBUG( "-----> CBOR size = " << json::to_cbor( stream_options_message.json_data() ).size() ); @@ -206,8 +206,7 @@ void dds_device_server::init( std::vector< std::shared_ptr< dds_stream_server > _metadata_writer = std::make_shared< dds_topic_writer >( topic, _publisher ); dds_topic_writer::qos wqos( eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS ); wqos.history().depth = 10; // default is 1 - wqos.override_from_json( - rsutils::json::nested( _subscriber->get_participant()->settings(), "device", "metadata" ) ); + wqos.override_from_json( _subscriber->get_participant()->settings().nested( "device", "metadata" ) ); _metadata_writer->run( wqos ); } } @@ -221,7 +220,7 @@ void dds_device_server::init( std::vector< std::shared_ptr< dds_stream_server > _control_reader->on_data_available( [&]() { on_control_message_received(); } ); dds_topic_reader::qos rqos( RELIABLE_RELIABILITY_QOS ); - rqos.override_from_json( rsutils::json::nested( _subscriber->get_participant()->settings(), "device", "control" ) ); + rqos.override_from_json( _subscriber->get_participant()->settings().nested( "device", "control" ) ); _control_reader->run( rqos ); } catch( std::exception const & ) @@ -250,7 +249,7 @@ void dds_device_server::publish_notification( topics::flexible_msg && notificati } -void dds_device_server::publish_metadata( nlohmann::json && md ) +void dds_device_server::publish_metadata( rsutils::json && md ) { if( ! _metadata_writer ) DDS_THROW( runtime_error, "device '" + _topic_root + "' has no stream with enabled metadata" ); @@ -281,14 +280,16 @@ void dds_device_server::on_control_message_received() _control_dispatcher.invoke( [j = data.json_data(), sample = info, this]( dispatcher::cancellable_timer ) { - json reply; - reply[sample_key] = json::array( { + auto sample_j = json::array( { rsutils::string::from( realdds::print_raw_guid( sample.sample_identity.writer_guid() ) ), sample.sample_identity.sequence_number().to64long(), } ); + LOG_DEBUG( "<----- control " << sample_j << ": " << j ); + json reply; + reply[sample_key] = std::move( sample_j ); try { - std::string id = rsutils::json::get< std::string >( j, id_key ); + std::string const & id = j.at( id_key ).string_ref(); reply[id_key] = id; reply[control_key] = j; handle_control_message( id, j, reply ); @@ -298,9 +299,9 @@ void dds_device_server::on_control_message_received() reply[status_key] = "error"; reply[explanation_key] = e.what(); } + LOG_DEBUG( "-----> reply " << reply ); try { - LOG_DEBUG( "-----> reply " << reply ); publish_notification( reply ); } catch( ... ) @@ -313,11 +314,9 @@ void dds_device_server::on_control_message_received() void dds_device_server::handle_control_message( std::string const & id, - nlohmann::json const & j, - nlohmann::json & reply ) + rsutils::json const & j, + rsutils::json & reply ) { - LOG_DEBUG( "<----- control " << j ); - if( id.compare( id_set_option ) == 0 ) { handle_set_option( j, reply ); @@ -328,21 +327,21 @@ void dds_device_server::handle_control_message( std::string const & id, } else if( ! _control_callback || ! _control_callback( id, j, reply ) ) { - DDS_THROW( runtime_error, "invalid control '" + id + "'" ); + DDS_THROW( runtime_error, "invalid control" ); } } -void dds_device_server::handle_set_option( const nlohmann::json & j, nlohmann::json & reply ) +void dds_device_server::handle_set_option( const rsutils::json & j, rsutils::json & reply ) { - auto option_name = rsutils::json::get< std::string >( j, option_name_key ); + auto & option_name = j.at( option_name_key ).string_ref(); std::string stream_name; // default is empty, for a device option - rsutils::json::get_ex( j, stream_name_key, &stream_name ); + j.nested( stream_name_key ).get_ex( stream_name ); std::shared_ptr< dds_option > opt = find_option( option_name, stream_name ); if( opt ) { - float value = rsutils::json::get< float >( j, value_key ); + float value = j.at( value_key ).get< float >(); if( _set_option_callback ) _set_option_callback( opt, value ); //Handle setting option outside realdds opt->set_value( value ); //Update option object. Do second to check if _set_option_callback did not throw @@ -354,15 +353,15 @@ void dds_device_server::handle_set_option( const nlohmann::json & j, nlohmann::j stream_name = "device"; else stream_name = "'" + stream_name + "'"; - DDS_THROW( runtime_error, stream_name + " option '" + option_name + "' not found" ); + DDS_THROW( runtime_error, stream_name << " option '" << option_name << "' not found" ); } } -void dds_device_server::handle_query_option( const nlohmann::json & j, nlohmann::json & reply ) +void dds_device_server::handle_query_option( const rsutils::json & j, rsutils::json & reply ) { std::string stream_name; // default is empty, for a device option - rsutils::json::get_ex( j, stream_name_key, &stream_name ); + j.nested( stream_name_key ).get_ex( stream_name ); auto query_option = [&]( std::shared_ptr< dds_option > const & option ) { @@ -379,9 +378,9 @@ void dds_device_server::handle_query_option( const nlohmann::json & j, nlohmann: } return value; }; - auto query_option_j = [&]( rsutils::json::nested const & j ) + auto query_option_j = [&]( rsutils::json const & j ) { - if( ! j->is_string() ) + if( ! j.is_string() ) DDS_THROW( runtime_error, "option name should be a string; got " << j ); std::string const & option_name = j.string_ref(); std::shared_ptr< dds_option > option = find_option( option_name, stream_name ); @@ -395,13 +394,13 @@ void dds_device_server::handle_query_option( const nlohmann::json & j, nlohmann: DDS_THROW( runtime_error, stream_name + " option '" + option_name + "' not found" ); }; - rsutils::json::nested option_name( j, option_name_key ); + auto option_name = j.nested( option_name_key ); if( option_name.is_array() ) { - if( option_name->empty() ) + if( option_name.empty() ) { // Query all options and return in option:value object - nlohmann::json & option_values = reply[option_values_key] = nlohmann::json::object(); + rsutils::json & option_values = reply[option_values_key] = rsutils::json::object(); if( stream_name.empty() ) { for( auto const & option : _options ) @@ -419,9 +418,9 @@ void dds_device_server::handle_query_option( const nlohmann::json & j, nlohmann: } else { - nlohmann::json & value = reply[value_key]; - for( auto x = 0; x < option_name->size(); ++x ) - value.push_back( query_option_j( option_name->at( x ) ) ); + rsutils::json & value = reply[value_key]; + for( auto x = 0; x < option_name.size(); ++x ) + value.push_back( query_option_j( option_name.at( x ) ) ); } } else diff --git a/third-party/realdds/src/dds-device-watcher.cpp b/third-party/realdds/src/dds-device-watcher.cpp index 9fef65c9a18..1fa669d2141 100644 --- a/third-party/realdds/src/dds-device-watcher.cpp +++ b/third-party/realdds/src/dds-device-watcher.cpp @@ -51,7 +51,7 @@ dds_device_watcher::dds_device_watcher( std::shared_ptr< dds_participant > const } auto j = msg.json_data(); - if( j.find( "stopping" ) != j.end() ) + if( j.nested( "stopping" ) ) { // This device is stopping for whatever reason (e.g., HW reset); remove it LOG_DEBUG( "DDS device (from " << _participant->print( guid ) << ") is stopping" ); diff --git a/third-party/realdds/src/dds-device.cpp b/third-party/realdds/src/dds-device.cpp index bf5dcc2d9ea..98ecc21cfa6 100644 --- a/third-party/realdds/src/dds-device.cpp +++ b/third-party/realdds/src/dds-device.cpp @@ -94,7 +94,7 @@ float dds_device::query_option_value( const std::shared_ptr< dds_option > & opti return _impl->query_option_value( option ); } -void dds_device::send_control( topics::flexible_msg && msg, nlohmann::json * reply ) +void dds_device::send_control( topics::flexible_msg && msg, rsutils::json * reply ) { _impl->write_control_message( std::move( msg ), reply ); } @@ -141,29 +141,29 @@ static std::string const explanation_key( "explanation", 11 ); static std::string const id_key( "id", 2 ); -bool dds_device::check_reply( nlohmann::json const & reply, std::string * p_explanation ) +bool dds_device::check_reply( rsutils::json const & reply, std::string * p_explanation ) { - auto status_j = rsutils::json::nested( reply, status_key ); + auto status_j = reply.nested( status_key ); if( ! status_j ) return true; std::ostringstream os; - if( ! status_j->is_string() ) + if( ! status_j.is_string() ) os << "bad status " << status_j; else if( status_j.string_ref() == status_ok ) return true; else { os << "["; - if( auto id = rsutils::json::nested( reply, id_key ) ) + if( auto id = reply.nested( id_key ) ) { - if( id->is_string() ) + if( id.is_string() ) os << "\"" << id.string_ref() << "\" "; } os << status_j.string_ref() << "]"; - if( auto explanation_j = rsutils::json::nested( reply, explanation_key ) ) + if( auto explanation_j = reply.nested( explanation_key ) ) { os << ' '; - if( ! explanation_j->is_string() || explanation_j.string_ref().empty() ) + if( explanation_j.string_ref_or_empty().empty() ) os << "bad explanation " << explanation_j; else os << explanation_j.string_ref(); diff --git a/third-party/realdds/src/dds-notification-server.cpp b/third-party/realdds/src/dds-notification-server.cpp index 583b678a084..baa4084e420 100644 --- a/third-party/realdds/src/dds-notification-server.cpp +++ b/third-party/realdds/src/dds-notification-server.cpp @@ -91,7 +91,7 @@ dds_notification_server::dds_notification_server( std::shared_ptr< dds_publisher // If history is too small writer will not be able to re-transmit needed samples. // Setting history to cover known use-cases plus some spare wqos.history().depth = 24; - wqos.override_from_json( rsutils::json::nested( publisher->get_participant()->settings(), "device", "notification" ) ); + wqos.override_from_json( publisher->get_participant()->settings().nested( "device", "notification" ) ); _writer->run( wqos ); } diff --git a/third-party/realdds/src/dds-option.cpp b/third-party/realdds/src/dds-option.cpp index d4b756990ff..0a8ca29efbf 100644 --- a/third-party/realdds/src/dds-option.cpp +++ b/third-party/realdds/src/dds-option.cpp @@ -5,7 +5,6 @@ #include #include -using nlohmann::json; namespace realdds { @@ -20,42 +19,42 @@ dds_option::dds_option( const std::string & name, dds_option_range const & range } -dds_option::dds_option( nlohmann::json const & j ) +dds_option::dds_option( rsutils::json const & j ) { int index = 0; - _name = rsutils::json::get< std::string >( j, index++ ); - _value = rsutils::json::get< float >( j, index++ ); - _range.min = rsutils::json::get< float >( j, index++ ); - _range.max = rsutils::json::get< float >( j, index++ ); - _range.step = rsutils::json::get< float >( j, index++ ); - _range.default_value = rsutils::json::get< float >( j, index++ ); - _description = rsutils::json::get< std::string >( j, index++ ); + _name = j[index++].string_ref(); + _value = j[index++].get< float >(); + _range.min = j[index++].get< float >(); + _range.max = j[index++].get< float >(); + _range.step = j[index++].get< float >(); + _range.default_value = j[index++].get< float >(); + _description = j[index++].string_ref(); if( index != j.size() ) - DDS_THROW( runtime_error, "expected end of json at index " + std::to_string( index ) ); + DDS_THROW( runtime_error, "expected end of json at index " << index ); } void dds_option::init_stream( std::shared_ptr< dds_stream_base > const & stream ) { if( _stream.lock() ) - DDS_THROW( runtime_error, "option '" + get_name() + "' already has a stream" ); + DDS_THROW( runtime_error, "option '" << get_name() << "' already has a stream" ); if( ! stream ) DDS_THROW( runtime_error, "null stream" ); _stream = stream; } -/* static */ std::shared_ptr< dds_option > dds_option::from_json( nlohmann::json const & j ) +/*static*/ std::shared_ptr< dds_option > dds_option::from_json( rsutils::json const & j ) { return std::shared_ptr< dds_option >( new dds_option( j ) ); } -nlohmann::json dds_option::to_json() const +rsutils::json dds_option::to_json() const { - return json::array( { _name, _value, _range.min, _range.max, _range.step, _range.default_value, _description } ); + return rsutils::json::array( { _name, _value, _range.min, _range.max, _range.step, _range.default_value, _description } ); } } // namespace realdds diff --git a/third-party/realdds/src/dds-participant.cpp b/third-party/realdds/src/dds-participant.cpp index 6347d1d1b66..5412f17fc3b 100644 --- a/third-party/realdds/src/dds-participant.cpp +++ b/third-party/realdds/src/dds-participant.cpp @@ -186,7 +186,7 @@ struct dds_participant::listener_impl : public eprosima::fastdds::dds::DomainPar }; -void dds_participant::init( dds_domain_id domain_id, std::string const & participant_name, nlohmann::json const & settings ) +void dds_participant::init( dds_domain_id domain_id, std::string const & participant_name, rsutils::json const & settings ) { if( is_valid() ) { @@ -198,8 +198,7 @@ void dds_participant::init( dds_domain_id domain_id, std::string const & partici if( domain_id == -1 ) { // Get it from settings and default to 0 - if( ! rsutils::json::get_ex( settings, "domain", &domain_id ) ) - domain_id = 0; + domain_id = settings.nested( "domain" ).default_value( 0 ); } _domain_listener = std::make_shared< listener_impl >( *this ); @@ -245,7 +244,7 @@ void dds_participant::init( dds_domain_id domain_id, std::string const & partici if( settings.is_object() ) _settings = settings; else if( settings.is_null() ) - _settings = nlohmann::json::object(); + _settings = rsutils::json::object(); else DDS_THROW( runtime_error, "provided settings are invalid: " << settings ); diff --git a/third-party/realdds/src/dds-serialization.cpp b/third-party/realdds/src/dds-serialization.cpp index 7792d495cb6..ac4ff1a79df 100644 --- a/third-party/realdds/src/dds-serialization.cpp +++ b/third-party/realdds/src/dds-serialization.cpp @@ -118,7 +118,7 @@ namespace fastrtps { // Allow j["key"] = qos.lease_duration; -void to_json( nlohmann::json & j, Duration_t const & duration ) +void to_json( rsutils::json & j, Duration_t const & duration ) { if( duration == c_TimeInfinite ) j = "infinite"; @@ -130,17 +130,17 @@ void to_json( nlohmann::json & j, Duration_t const & duration ) // Allow j.get< eprosima::fastrtps::Duration_t >(); -void from_json( nlohmann::json const & j, Duration_t & duration ) +void from_json( rsutils::json const & j, Duration_t & duration ) { if( j.is_string() ) { - auto & s = rsutils::json::string_ref( j ); + auto & s = j.string_ref(); if( rsutils::string::nocase_equal( s, "infinite" ) ) duration = c_TimeInfinite; else if( rsutils::string::nocase_equal( s, "invalid" ) ) duration = c_TimeInvalid; else - throw nlohmann::json::type_error::create( 317, "unknown duration value '" + s + "'", &j ); + throw rsutils::json::type_error::create( 317, "unknown duration value '" + s + "'", &j ); } else duration = realdds::dds_time( j.get< double >() ); @@ -244,151 +244,139 @@ eprosima::fastrtps::rtps::MemoryManagementPolicy_t history_memory_policy_from_st } -void override_reliability_qos_from_json( eprosima::fastdds::dds::ReliabilityQosPolicy & qos, nlohmann::json const & j ) +void override_reliability_qos_from_json( eprosima::fastdds::dds::ReliabilityQosPolicy & qos, rsutils::json const & j ) { - if( j.is_null() ) - return; if( j.is_string() ) - qos.kind = reliability_kind_from_string( rsutils::json::string_ref( j ) ); + qos.kind = reliability_kind_from_string( j.string_ref() ); else if( j.is_object() ) { - std::string kind_str; - if( rsutils::json::get_ex( j, "kind", &kind_str ) ) - qos.kind = reliability_kind_from_string( kind_str ); + if( auto kind_j = j.nested( "kind", &rsutils::json::is_string ) ) + qos.kind = reliability_kind_from_string( kind_j.string_ref() ); } } -void override_durability_qos_from_json( eprosima::fastdds::dds::DurabilityQosPolicy & qos, nlohmann::json const & j ) +void override_durability_qos_from_json( eprosima::fastdds::dds::DurabilityQosPolicy & qos, rsutils::json const & j ) { - if( j.is_null() ) - return; if( j.is_string() ) - qos.kind = durability_kind_from_string( j.get_ref< const nlohmann::json::string_t & >() ); + qos.kind = durability_kind_from_string( j.get_ref< const rsutils::json::string_t & >() ); else if( j.is_object() ) { - std::string kind_str; - if( rsutils::json::get_ex( j, "kind", &kind_str ) ) - qos.kind = durability_kind_from_string( kind_str ); + if( auto kind_j = j.nested( "kind", &rsutils::json::is_string ) ) + qos.kind = durability_kind_from_string( kind_j.string_ref() ); } } -void override_history_qos_from_json( eprosima::fastdds::dds::HistoryQosPolicy & qos, nlohmann::json const & j ) +void override_history_qos_from_json( eprosima::fastdds::dds::HistoryQosPolicy & qos, rsutils::json const & j ) { - if( j.is_null() ) - return; if( j.is_number_unsigned() ) - qos.depth = rsutils::json::value< int32_t >( j ); + qos.depth = j.get< int32_t >(); else if( j.is_object() ) { - std::string kind_str; - if( rsutils::json::get_ex( j, "kind", &kind_str ) ) - qos.kind = history_kind_from_string( kind_str ); - rsutils::json::get_ex( j, "depth", &qos.depth ); + if( auto kind_j = j.nested( "kind", &rsutils::json::is_string ) ) + qos.kind = history_kind_from_string( kind_j.string_ref() ); + j.nested( "depth" ).get_ex( qos.depth ); } } -void override_liveliness_qos_from_json( eprosima::fastdds::dds::LivelinessQosPolicy & qos, nlohmann::json const & j ) +void override_liveliness_qos_from_json( eprosima::fastdds::dds::LivelinessQosPolicy & qos, rsutils::json const & j ) { if( j.is_object() ) { - if( auto kind = rsutils::json::nested( j, "kind" ) ) + if( auto kind = j.nested( "kind" ) ) { - if( kind->is_string() ) - qos.kind = liveliness_kind_from_string( rsutils::json::string_ref( kind ) ); + if( kind.is_string() ) + qos.kind = liveliness_kind_from_string( kind.string_ref() ); else DDS_THROW( runtime_error, "liveliness kind not a string: " << kind ); } - if( auto lease = rsutils::json::nested( j, "lease-duration" ) ) + if( auto lease = j.nested( "lease-duration" ) ) { - if( lease->is_null() ) + if( lease.is_null() ) qos.lease_duration = eprosima::fastdds::dds::LivelinessQosPolicy().lease_duration; else - lease->get_to( qos.lease_duration ); + lease.get_to( qos.lease_duration ); } - if( auto announce = rsutils::json::nested( j, "announcement-period" ) ) + if( auto announce = j.nested( "announcement-period" ) ) { - if( announce->is_null() ) + if( announce.is_null() ) qos.announcement_period = eprosima::fastdds::dds::LivelinessQosPolicy().announcement_period; else - announce->get_to( qos.announcement_period ); + announce.get_to( qos.announcement_period ); } } } -void override_data_sharing_qos_from_json( eprosima::fastdds::dds::DataSharingQosPolicy & qos, nlohmann::json const & j ) +void override_data_sharing_qos_from_json( eprosima::fastdds::dds::DataSharingQosPolicy & qos, rsutils::json const & j ) { if( j.is_boolean() ) { - if( rsutils::json::value< bool >( j ) ) + if( j.get< bool >() ) qos.automatic(); else qos.off(); } - else if( ! j.is_null() ) + else if( j.exists() ) { DDS_THROW( runtime_error, "data-sharing must be a boolean (off/automatic); got " << j ); } } -void override_endpoint_qos_from_json( eprosima::fastdds::dds::RTPSEndpointQos & qos, nlohmann::json const & j ) +void override_endpoint_qos_from_json( eprosima::fastdds::dds::RTPSEndpointQos & qos, rsutils::json const & j ) { - if( j.is_null() ) - return; if( j.is_object() ) { - std::string policy_str; - if( rsutils::json::get_ex( j, "history-memory-policy", &policy_str ) ) - qos.history_memory_policy = history_memory_policy_from_string( policy_str ); + if( auto policy_j = j.nested( "history-memory-policy", &rsutils::json::is_string ) ) + qos.history_memory_policy = history_memory_policy_from_string( policy_j.string_ref() ); } } -static bool parse_ip_list( nlohmann::json const & j, std::string const & key, std::vector< std::string > * output ) +static bool parse_ip_list( rsutils::json const & j, std::string const & key, std::vector< std::string > * output ) { - if( auto whitelist_j = rsutils::json::nested( j, key ) ) + if( auto whitelist_j = j.nested( key ) ) { - if( ! whitelist_j->is_array() ) + if( ! whitelist_j.is_array() ) return false; - for( auto & ip : whitelist_j.get() ) + for( auto & ip : whitelist_j ) { if( ! ip.is_string() ) return false; if( output ) - output->push_back( rsutils::json::string_ref( ip ) ); + output->push_back( ip.string_ref() ); } } return true; } -static void override_udp_settings( eprosima::fastdds::rtps::UDPTransportDescriptor & udp, nlohmann::json const & j ) +static void override_udp_settings( eprosima::fastdds::rtps::UDPTransportDescriptor & udp, rsutils::json const & j ) { - rsutils::json::get_ex( j, "send-buffer-size", &udp.sendBufferSize ); - rsutils::json::get_ex( j, "receive-buffer-size", &udp.receiveBufferSize ); + j.nested( "send-buffer-size" ).get_ex( udp.sendBufferSize ); + j.nested( "receive-buffer-size" ).get_ex( udp.receiveBufferSize ); if( ! parse_ip_list( j, "whitelist", &udp.interfaceWhiteList ) ) LOG_WARNING( "invalid UDP whitelist in settings" ); } -void override_participant_qos_from_json( eprosima::fastdds::dds::DomainParticipantQos & qos, nlohmann::json const & j ) +void override_participant_qos_from_json( eprosima::fastdds::dds::DomainParticipantQos & qos, rsutils::json const & j ) { if( ! j.is_object() ) return; - rsutils::json::get_ex( j, "participant-id", &qos.wire_protocol().participant_id ); - rsutils::json::get_ex( j, "lease-duration", &qos.wire_protocol().builtin.discovery_config.leaseDuration ); + j.nested( "participant-id" ).get_ex( qos.wire_protocol().participant_id ); + j.nested( "lease-duration" ).get_ex( qos.wire_protocol().builtin.discovery_config.leaseDuration ); - rsutils::json::get_ex( j, "use-builtin-transports", &qos.transport().use_builtin_transports ); - if( auto udp_j = rsutils::json::nested( j, "udp" ) ) + j.nested( "use-builtin-transports" ).get_ex( qos.transport().use_builtin_transports ); + if( auto udp_j = j.nested( "udp" ) ) { for( auto t : qos.transport().user_transports ) - if( auto udp_t = std::dynamic_pointer_cast(t) ) + if( auto udp_t = std::dynamic_pointer_cast< eprosima::fastdds::rtps::UDPTransportDescriptor >( t ) ) { override_udp_settings( *udp_t, udp_j ); break; diff --git a/third-party/realdds/src/dds-stream-profile.cpp b/third-party/realdds/src/dds-stream-profile.cpp index 663f43e0d71..235a57d5e5a 100644 --- a/third-party/realdds/src/dds-stream-profile.cpp +++ b/third-party/realdds/src/dds-stream-profile.cpp @@ -6,8 +6,6 @@ #include #include -using nlohmann::json; - #include @@ -137,15 +135,15 @@ dds_video_encoding dds_video_encoding::from_rs2( int rs2_format ) } -dds_stream_profile::dds_stream_profile( json const & j, int & it ) - : _frequency( rsutils::json::get< int16_t >( j, it++ ) ) +dds_stream_profile::dds_stream_profile( rsutils::json const & j, int & it ) + : _frequency( j[it++].get< int16_t >() ) { // NOTE: the order of construction is the order of declaration -- therefore the to_json() function // should use the same ordering! } -/* static */ void dds_stream_profile::verify_end_of_json( nlohmann::json const & j, int index ) +/* static */ void dds_stream_profile::verify_end_of_json( rsutils::json const & j, int index ) { if( index != j.size() ) DDS_THROW( runtime_error, "expected end of json at index " + std::to_string( index ) ); @@ -189,23 +187,23 @@ void dds_stream_profile::init_stream( std::weak_ptr< dds_stream_base > const & s } -json dds_stream_profile::to_json() const +rsutils::json dds_stream_profile::to_json() const { // NOTE: same ordering as construction! - return json::array( { frequency() } ); + return rsutils::json::array( { frequency() } ); } -dds_video_stream_profile::dds_video_stream_profile( nlohmann::json const & j, int & index ) +dds_video_stream_profile::dds_video_stream_profile( rsutils::json const & j, int & index ) : super( j, index ) - , _encoding( rsutils::json::get< std::string >( j, index++ ) ) + , _encoding( j[index++].get< std::string >() ) { - _width = rsutils::json::get< int16_t >( j, index++ ); - _height = rsutils::json::get< int16_t >( j, index++ ); + _width = j[index++].get< int16_t >(); + _height = j[index++].get< int16_t >(); } -json dds_video_stream_profile::to_json() const +rsutils::json dds_video_stream_profile::to_json() const { auto profile = super::to_json(); profile += encoding().to_string(); diff --git a/third-party/realdds/src/dds-stream-sensor-bridge.cpp b/third-party/realdds/src/dds-stream-sensor-bridge.cpp index 2ee2420f403..e3a835604db 100644 --- a/third-party/realdds/src/dds-stream-sensor-bridge.cpp +++ b/third-party/realdds/src/dds-stream-sensor-bridge.cpp @@ -12,8 +12,6 @@ #include #include -using nlohmann::json; - namespace realdds { diff --git a/third-party/realdds/src/dds-topic-reader.cpp b/third-party/realdds/src/dds-topic-reader.cpp index 29690990fd6..09294ad7f7e 100644 --- a/third-party/realdds/src/dds-topic-reader.cpp +++ b/third-party/realdds/src/dds-topic-reader.cpp @@ -87,19 +87,16 @@ dds_topic_reader::qos::qos( eprosima::fastdds::dds::ReliabilityQosPolicyKind rel } -void dds_topic_reader::qos::override_from_json( nlohmann::json const & qos_settings ) +void dds_topic_reader::qos::override_from_json( rsutils::json const & qos_settings ) { // Default values should be set before we're called: // All we do here is override those - if specified! - if( qos_settings.is_null() ) - return; - - override_reliability_qos_from_json( reliability(), rsutils::json::nested( qos_settings, "reliability" ) ); - override_durability_qos_from_json( durability(), rsutils::json::nested( qos_settings, "durability" ) ); - override_history_qos_from_json( history(), rsutils::json::nested( qos_settings, "history" ) ); - override_liveliness_qos_from_json( liveliness(), rsutils::json::nested( qos_settings, "liveliness" ) ); - override_data_sharing_qos_from_json( data_sharing(), rsutils::json::nested( qos_settings, "data-sharing" ) ); - override_endpoint_qos_from_json( endpoint(), rsutils::json::nested( qos_settings, "endpoint" ) ); + override_reliability_qos_from_json( reliability(), qos_settings.nested( "reliability" ) ); + override_durability_qos_from_json( durability(), qos_settings.nested( "durability" ) ); + override_history_qos_from_json( history(), qos_settings.nested( "history" ) ); + override_liveliness_qos_from_json( liveliness(), qos_settings.nested( "liveliness" ) ); + override_data_sharing_qos_from_json( data_sharing(), qos_settings.nested( "data-sharing" ) ); + override_endpoint_qos_from_json( endpoint(), qos_settings.nested( "endpoint" ) ); } diff --git a/third-party/realdds/src/dds-topic-writer.cpp b/third-party/realdds/src/dds-topic-writer.cpp index f18d0445c7b..72ced8853e5 100644 --- a/third-party/realdds/src/dds-topic-writer.cpp +++ b/third-party/realdds/src/dds-topic-writer.cpp @@ -87,19 +87,16 @@ dds_topic_writer::qos::qos( eprosima::fastdds::dds::ReliabilityQosPolicyKind rel } -void dds_topic_writer::qos::override_from_json( nlohmann::json const & qos_settings ) +void dds_topic_writer::qos::override_from_json( rsutils::json const & qos_settings ) { // Default values should be set before we're called: // All we do here is override those - if specified! - if( qos_settings.is_null() ) - return; - - override_reliability_qos_from_json( reliability(), rsutils::json::nested( qos_settings, "reliability" ) ); - override_durability_qos_from_json( durability(), rsutils::json::nested( qos_settings, "durability" ) ); - override_history_qos_from_json( history(), rsutils::json::nested( qos_settings, "history" ) ); - override_liveliness_qos_from_json( liveliness(), rsutils::json::nested( qos_settings, "liveliness" ) ); - override_data_sharing_qos_from_json( data_sharing(), rsutils::json::nested( qos_settings, "data-sharing" ) ); - override_endpoint_qos_from_json( endpoint(), rsutils::json::nested( qos_settings, "endpoint" ) ); + override_reliability_qos_from_json( reliability(), qos_settings.nested( "reliability" ) ); + override_durability_qos_from_json( durability(), qos_settings.nested( "durability" ) ); + override_history_qos_from_json( history(), qos_settings.nested( "history" ) ); + override_liveliness_qos_from_json( liveliness(), qos_settings.nested( "liveliness" ) ); + override_data_sharing_qos_from_json( data_sharing(), qos_settings.nested( "data-sharing" ) ); + override_endpoint_qos_from_json( endpoint(), qos_settings.nested( "endpoint" ) ); } diff --git a/third-party/realdds/src/dds-trinsics.cpp b/third-party/realdds/src/dds-trinsics.cpp index cc2b2bef95e..e9ff1d16528 100644 --- a/third-party/realdds/src/dds-trinsics.cpp +++ b/third-party/realdds/src/dds-trinsics.cpp @@ -10,31 +10,31 @@ namespace realdds { -nlohmann::json video_intrinsics::to_json() const +rsutils::json video_intrinsics::to_json() const { - return nlohmann::json::array( { + return rsutils::json::array( { width, height, principal_point_x, principal_point_y, focal_lenght_x, focal_lenght_y, distortion_model, distortion_coeffs[0], distortion_coeffs[1], distortion_coeffs[2], distortion_coeffs[3], distortion_coeffs[4] } ); } -/* static */ video_intrinsics video_intrinsics::from_json( nlohmann::json const & j ) +/* static */ video_intrinsics video_intrinsics::from_json( rsutils::json const & j ) { video_intrinsics ret; int index = 0; - ret.width = rsutils::json::get< int >( j, index++ ); - ret.height = rsutils::json::get< int >( j, index++ ); - ret.principal_point_x = rsutils::json::get< float >( j, index++ ); - ret.principal_point_y = rsutils::json::get< float >( j, index++ ); - ret.focal_lenght_x = rsutils::json::get< float >( j, index++ ); - ret.focal_lenght_y = rsutils::json::get< float >( j, index++ ); - ret.distortion_model = rsutils::json::get< int >( j, index++ ); - ret.distortion_coeffs[0] = rsutils::json::get< float >( j, index++ ); - ret.distortion_coeffs[1] = rsutils::json::get< float >( j, index++ ); - ret.distortion_coeffs[2] = rsutils::json::get< float >( j, index++ ); - ret.distortion_coeffs[3] = rsutils::json::get< float >( j, index++ ); - ret.distortion_coeffs[4] = rsutils::json::get< float >( j, index++ ); + ret.width = j[index++].get< int >(); + ret.height = j[index++].get< int >(); + ret.principal_point_x = j[index++].get< float >(); + ret.principal_point_y = j[index++].get< float >(); + ret.focal_lenght_x = j[index++].get< float >(); + ret.focal_lenght_y = j[index++].get< float >(); + ret.distortion_model = j[index++].get< int >(); + ret.distortion_coeffs[0] = j[index++].get< float >(); + ret.distortion_coeffs[1] = j[index++].get< float >(); + ret.distortion_coeffs[2] = j[index++].get< float >(); + ret.distortion_coeffs[3] = j[index++].get< float >(); + ret.distortion_coeffs[4] = j[index++].get< float >(); if( index != j.size() ) DDS_THROW( runtime_error, "expected end of json at index " + std::to_string( index ) ); @@ -42,9 +42,9 @@ nlohmann::json video_intrinsics::to_json() const return ret; } -nlohmann::json motion_intrinsics::to_json() const +rsutils::json motion_intrinsics::to_json() const { - return nlohmann::json::array( { + return rsutils::json::array( { data[0][0], data[0][1], data[0][2], data[0][3], data[1][0], data[1][1], data[1][2], data[1][3], data[2][0], data[2][1], data[2][2], data[2][3], @@ -53,29 +53,29 @@ nlohmann::json motion_intrinsics::to_json() const } ); } -/* static */ motion_intrinsics motion_intrinsics::from_json( nlohmann::json const & j ) +/* static */ motion_intrinsics motion_intrinsics::from_json( rsutils::json const & j ) { motion_intrinsics ret; int index = 0; - ret.data[0][0] = rsutils::json::get< float >( j, index++ ); - ret.data[0][1] = rsutils::json::get< float >( j, index++ ); - ret.data[0][2] = rsutils::json::get< float >( j, index++ ); - ret.data[0][3] = rsutils::json::get< float >( j, index++ ); - ret.data[1][0] = rsutils::json::get< float >( j, index++ ); - ret.data[1][1] = rsutils::json::get< float >( j, index++ ); - ret.data[1][2] = rsutils::json::get< float >( j, index++ ); - ret.data[1][3] = rsutils::json::get< float >( j, index++ ); - ret.data[2][0] = rsutils::json::get< float >( j, index++ ); - ret.data[2][1] = rsutils::json::get< float >( j, index++ ); - ret.data[2][2] = rsutils::json::get< float >( j, index++ ); - ret.data[2][3] = rsutils::json::get< float >( j, index++ ); - ret.noise_variances[0] = rsutils::json::get< float >( j, index++ ); - ret.noise_variances[1] = rsutils::json::get< float >( j, index++ ); - ret.noise_variances[2] = rsutils::json::get< float >( j, index++ ); - ret.bias_variances[0] = rsutils::json::get< float >( j, index++ ); - ret.bias_variances[1] = rsutils::json::get< float >( j, index++ ); - ret.bias_variances[2] = rsutils::json::get< float >( j, index++ ); + ret.data[0][0] = j[index++].get< float >(); + ret.data[0][1] = j[index++].get< float >(); + ret.data[0][2] = j[index++].get< float >(); + ret.data[0][3] = j[index++].get< float >(); + ret.data[1][0] = j[index++].get< float >(); + ret.data[1][1] = j[index++].get< float >(); + ret.data[1][2] = j[index++].get< float >(); + ret.data[1][3] = j[index++].get< float >(); + ret.data[2][0] = j[index++].get< float >(); + ret.data[2][1] = j[index++].get< float >(); + ret.data[2][2] = j[index++].get< float >(); + ret.data[2][3] = j[index++].get< float >(); + ret.noise_variances[0] = j[index++].get< float >(); + ret.noise_variances[1] = j[index++].get< float >(); + ret.noise_variances[2] = j[index++].get< float >(); + ret.bias_variances[0] = j[index++].get< float >(); + ret.bias_variances[1] = j[index++].get< float >(); + ret.bias_variances[2] = j[index++].get< float >(); if( index != j.size() ) DDS_THROW( runtime_error, "expected end of json at index " + std::to_string( index ) ); @@ -83,9 +83,9 @@ nlohmann::json motion_intrinsics::to_json() const return ret; } -nlohmann::json extrinsics::to_json() const +rsutils::json extrinsics::to_json() const { - return nlohmann::json::array( { + return rsutils::json::array( { rotation[0], rotation[1], rotation[2], rotation[3], rotation[4], rotation[5], rotation[6], rotation[7], rotation[8], @@ -93,23 +93,23 @@ nlohmann::json extrinsics::to_json() const } ); } -/* static */ extrinsics extrinsics::from_json( nlohmann::json const & j ) +/* static */ extrinsics extrinsics::from_json( rsutils::json const & j ) { extrinsics ret; int index = 0; - ret.rotation[0] = rsutils::json::get< float >( j, index++ ); - ret.rotation[1] = rsutils::json::get< float >( j, index++ ); - ret.rotation[2] = rsutils::json::get< float >( j, index++ ); - ret.rotation[3] = rsutils::json::get< float >( j, index++ ); - ret.rotation[4] = rsutils::json::get< float >( j, index++ ); - ret.rotation[5] = rsutils::json::get< float >( j, index++ ); - ret.rotation[6] = rsutils::json::get< float >( j, index++ ); - ret.rotation[7] = rsutils::json::get< float >( j, index++ ); - ret.rotation[8] = rsutils::json::get< float >( j, index++ ); - ret.translation[0] = rsutils::json::get< float >( j, index++ ); - ret.translation[1] = rsutils::json::get< float >( j, index++ ); - ret.translation[2] = rsutils::json::get< float >( j, index++ ); + ret.rotation[0] = j[index++].get< float >(); + ret.rotation[1] = j[index++].get< float >(); + ret.rotation[2] = j[index++].get< float >(); + ret.rotation[3] = j[index++].get< float >(); + ret.rotation[4] = j[index++].get< float >(); + ret.rotation[5] = j[index++].get< float >(); + ret.rotation[6] = j[index++].get< float >(); + ret.rotation[7] = j[index++].get< float >(); + ret.rotation[8] = j[index++].get< float >(); + ret.translation[0] = j[index++].get< float >(); + ret.translation[1] = j[index++].get< float >(); + ret.translation[2] = j[index++].get< float >(); if( index != j.size() ) DDS_THROW( runtime_error, "expected end of json at index " + std::to_string( index ) ); diff --git a/third-party/realdds/src/topics/device-info-msg.cpp b/third-party/realdds/src/topics/device-info-msg.cpp index 93d033f43c5..141559b52db 100644 --- a/third-party/realdds/src/topics/device-info-msg.cpp +++ b/third-party/realdds/src/topics/device-info-msg.cpp @@ -5,7 +5,6 @@ #include #include -#include #include namespace realdds { @@ -17,7 +16,7 @@ static std::string topic_root_key( "topic-root", 10 ); static std::string serial_number_key( "serial", 6 ); -/* static */ device_info device_info::from_json( nlohmann::json const & j ) +/* static */ device_info device_info::from_json( rsutils::json const & j ) { device_info ret; ret._json = j; @@ -32,7 +31,7 @@ static std::string serial_number_key( "serial", 6 ); } -nlohmann::json const & device_info::to_json() const +rsutils::json const & device_info::to_json() const { return _json; } @@ -40,7 +39,7 @@ nlohmann::json const & device_info::to_json() const std::string const & device_info::name() const { - return rsutils::json::nested( _json, name_key ).string_ref_or_empty(); + return _json.nested( name_key ).string_ref_or_empty(); } void device_info::set_name( std::string const & v ) @@ -51,7 +50,7 @@ void device_info::set_name( std::string const & v ) std::string const & device_info::topic_root() const { - return rsutils::json::nested( _json, topic_root_key ).string_ref_or_empty(); + return _json.nested( topic_root_key ).string_ref_or_empty(); } void device_info::set_topic_root( std::string const & v ) @@ -62,7 +61,7 @@ void device_info::set_topic_root( std::string const & v ) std::string const & device_info::serial_number() const { - return rsutils::json::nested( _json, serial_number_key ).string_ref_or_empty(); + return _json.nested( serial_number_key ).string_ref_or_empty(); } void device_info::set_serial_number( std::string const & v ) diff --git a/third-party/realdds/src/topics/flexible-msg.cpp b/third-party/realdds/src/topics/flexible-msg.cpp index e08e77b41eb..d0f8572c271 100644 --- a/third-party/realdds/src/topics/flexible-msg.cpp +++ b/third-party/realdds/src/topics/flexible-msg.cpp @@ -13,8 +13,7 @@ #include #include -#include -using nlohmann::json; +#include namespace realdds { @@ -29,7 +28,7 @@ flexible_msg::flexible_msg( raw::flexible && main ) } -flexible_msg::flexible_msg( json const & j, uint32_t version ) +flexible_msg::flexible_msg( rsutils::json const & j, uint32_t version ) : _data_format( data_format::JSON ) , _version( version ) { @@ -39,13 +38,13 @@ flexible_msg::flexible_msg( json const & j, uint32_t version ) } -flexible_msg::flexible_msg( data_format format, json const & j, uint32_t version ) +flexible_msg::flexible_msg( data_format format, rsutils::json const & j, uint32_t version ) : _data_format( format ) , _version( version ) { if( data_format::CBOR == format ) { - _data = std::move( json::to_cbor( j ) ); + _data = std::move( rsutils::json::to_cbor( j ) ); } else if( data_format::JSON == format ) { @@ -101,17 +100,17 @@ flexible_msg::take_next( dds_topic_reader & reader, flexible_msg * output, epros } -json flexible_msg::json_data() const +rsutils::json flexible_msg::json_data() const { if( _data_format == data_format::JSON ) { char const * begin = (char const *)_data.data(); char const * end = begin + _data.size(); - return json::parse( begin, end ); + return rsutils::json::parse( begin, end ); } if( _data_format == data_format::CBOR ) { - return json::from_cbor( _data.begin(), _data.end() ); + return rsutils::json::from_cbor( _data.begin(), _data.end() ); } DDS_THROW( runtime_error, "non-json flexible data is still unsupported" ); } diff --git a/third-party/realdds/src/topics/flexible-reader.cpp b/third-party/realdds/src/topics/flexible-reader.cpp index aa0550f77c7..5e001072424 100644 --- a/third-party/realdds/src/topics/flexible-reader.cpp +++ b/third-party/realdds/src/topics/flexible-reader.cpp @@ -10,7 +10,7 @@ #include -#include +#include namespace realdds { diff --git a/third-party/realdds/src/topics/flexible-writer.cpp b/third-party/realdds/src/topics/flexible-writer.cpp index 5a8b8645ac8..ad6eefb558a 100644 --- a/third-party/realdds/src/topics/flexible-writer.cpp +++ b/third-party/realdds/src/topics/flexible-writer.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include namespace realdds { @@ -46,7 +46,7 @@ void flexible_writer::wait_for_readers( int n_readers, std::chrono::seconds time } -void flexible_writer::write( nlohmann::json && json ) +void flexible_writer::write( rsutils::json && json ) { std::string json_string = json.dump(); flexible_msg msg( std::move( json ) ); diff --git a/third-party/rsutils/include/rsutils/json-config.h b/third-party/rsutils/include/rsutils/json-config.h new file mode 100644 index 00000000000..31e8d84940a --- /dev/null +++ b/third-party/rsutils/include/rsutils/json-config.h @@ -0,0 +1,29 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. +#pragma once + +#include + + +namespace rsutils { +namespace json_config { + + +// Load the contents of a file into a JSON object. +json load_from_file( std::string const & filename ); + +// Recursively patches existing 'j' with contents of 'overrides', which must be a JSON object +void override( json_ref overrides, std::string const & what = {} ); + +// Loads configuration settings from 'global' content +json load_app_settings( json const & global, + std::string const & application, + json_key const & subkey, + std::string const & error_context ); + +// Same as above, but automatically takes the application name from the executable-name +json load_settings( json const & global, json_key const & subkey, std::string const & error_context ); + + +} // namespace json_config +} // namespace rsutils diff --git a/third-party/rsutils/include/rsutils/json-fwd.h b/third-party/rsutils/include/rsutils/json-fwd.h new file mode 100644 index 00000000000..ba3dff1ec0a --- /dev/null +++ b/third-party/rsutils/include/rsutils/json-fwd.h @@ -0,0 +1,76 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. +#pragma once + +#include + + +namespace rsutils { + + +using json_key = std::string; // default of basic_json + + +class json_ref; // Our 'nested' json const reference wrapper +class json_base; // The 'json' base class + + +// We use a custom base class to inject our own functionality into every 'json' object: +// json <- nlohmann::basic_json<...> <- json_base +// +// NOTE: everything here is templated or forward-declared: neither 'json' nor 'json_ref' are defined yet, and 'json' +// can't even be referred to because there's a circular dependency (it derives from json_base). +// +// This class defines new functionality that the basic 'json' doesn't have that we want (like nested()), but the actual +// implementations are always in 'json_ref'! +// +// WARNING: we cannot override already-existing 'json' functions! In fact, it's the other way around: 'json' functions +// will override ours, so, for example, if we defined find() it would not be usable. +// +class json_base +{ + // Since we know how we're derived from, we can get the json, or the reference to it, from this: + inline json_ref _ref() const; + +public: + inline bool exists() const; + + template< class T > inline T default_value( T const & default_value ) const; + + template< class T > inline bool get_ex( T & value ) const; + + inline json_ref default_object() const; + inline json_ref default_string() const; + + inline std::string const & string_ref() const; + inline std::string const & string_ref_or_empty() const; + + template< typename... Rest > inline json_ref nested( Rest... rest ) const; + + // Recursively patches with contents of 'overrides', which must be a JSON object + void override( json_ref overrides, std::string const & what = {} ); + +}; + + +using json = nlohmann::basic_json< std::map, // all template arguments are defaults + std::vector, + json_key, + bool, + std::int64_t, + std::uint64_t, + double, + std::allocator, + nlohmann::adl_serializer, + std::vector< std::uint8_t >, + json_base >; // except custom base class! + + +// We can't put these inside json, unfortunately... +extern json const null_json; // default json state +extern json const missing_json; // i.e., not there: exists() will be 'false' +extern json const empty_json_string; +extern json const empty_json_object; + + +} // namespace rsutils diff --git a/third-party/rsutils/include/rsutils/json.h b/third-party/rsutils/include/rsutils/json.h index d072a435dcc..7ee5108b546 100644 --- a/third-party/rsutils/include/rsutils/json.h +++ b/third-party/rsutils/include/rsutils/json.h @@ -2,260 +2,228 @@ // Copyright(c) 2022 Intel Corporation. All Rights Reserved. #pragma once +#include "json-fwd.h" #include -#include namespace rsutils { -namespace json { -extern nlohmann::json const null_json; -extern nlohmann::json const empty_json_string; -extern nlohmann::json const empty_json_object; - - -// Returns true if the json has a certain key. -// Does not check the value at all, so it could be any type or null. -inline bool has( nlohmann::json const & j, std::string const & key ) +template< typename... Rest > +json_ref _nested_json( json const & j ); +template< typename... Rest > +json_ref _nested_json( json const & j, bool ( json::*is_fn )() const ); +template< typename... Rest > +json_ref _nested_json( json const & j, json_key const & inner, Rest... rest ); +template< typename... Rest > +json_ref _nested_json( json const & j, json::size_type index, Rest... rest ); + + +// A copyable reference to a read-only NON-OWNED json. +// I.e., this is for temporary use and is only valid as long as the original json object is alive! +// +// As this is a read-only reference, no non-const functionality is exposed here. +// +// This is used as the result of any 'nested' searches inside another JSON. As such, it is also used to communicate +// 'not-found' via the exists() call, so we're castable to bool. +// +// We also use this together with json_base to supply json functionality before json is defined. +// +class json_ref { - auto it = j.find( key ); - if( it == j.end() ) - return false; - return true; -} + json const & _j; +public: + constexpr json_ref() : _j( missing_json ) {} + constexpr json_ref( json const & j ) : _j( j ) {} -// Returns true if the json has a certain key and its value is not null. -// Does not check the value type. -inline bool has_value( nlohmann::json const & j, std::string const & key ) -{ - auto it = j.find( key ); - if( it == j.end() || it->is_null() ) - return false; - return true; -} - + template< typename... Rest > + json_ref( json const & j, Rest... rest ) + : _j( _nested_json( j, std::forward< Rest >( rest )... ) ) + {} -// Get the JSON as a value (copy involved); it must exist -template < class T > -T value( nlohmann::json const & j ) -{ - return j.get< T >(); -} -// Get the JSON as a value, or a default if not there (copy involved) -template < class T > -T value( nlohmann::json const & j, T const & default_value ) -{ - if( j.is_null() ) - return default_value; - return j.get< T >(); -} -// Get a JSON string by reference (zero copy); it must be a string or it'll throw -inline std::string const & string_ref( nlohmann::json const & j ) -{ - return j.get_ref< const nlohmann::json::string_t & >(); -} + // A json value can be null, so we use the internal 'discarded' flag to denote a non-existent one + bool exists() const noexcept { return ! _j.is_discarded(); } + operator bool() const noexcept { return exists(); } + + constexpr json const & get_json() const noexcept { return _j; } + constexpr operator json const &() const noexcept { return get_json(); } + + bool is_null() const noexcept { return _j.is_null(); } + bool is_array() const noexcept { return _j.is_array(); } + bool is_object() const noexcept { return _j.is_object(); } + bool is_string() const noexcept { return _j.is_string(); } + bool is_boolean() const noexcept { return _j.is_boolean(); } + bool is_number() const noexcept { return _j.is_number(); } + bool is_number_float() const noexcept { return _j.is_number_float(); } + bool is_number_integer() const noexcept { return _j.is_number_integer(); } + bool is_number_unsigned() const noexcept { return _j.is_number_unsigned(); } + bool is_primitive() const noexcept { return _j.is_primitive(); } + bool is_structured() const noexcept { return _j.is_structured(); } + + bool empty() const noexcept { return _j.empty(); } + json::size_type size() const noexcept { return _j.size(); } + json::const_iterator begin() const noexcept { return _j.begin(); } + json::const_iterator end() const noexcept { return _j.end(); } + + std::string dump( const int indent = -1 ) const { return _j.dump( indent ); } + + // Allow easy read-only lookup of nested json hierarchies: + // j["one"]["two"]["three"] // undefined; will throw/assert if a hierarchy isn't there + // But: + // j.nested( "one", "two", "three" ) // will not throw; does not copy! + // The result is either a null JSON object or a valid one. The boolean operator can be used as an easy check: + // if( auto inside = j.nested( "one", "two" ) ) + // { ... } + // + template< typename... Rest > + inline json_ref nested( Rest... rest ) const + { + return _nested_json( _j, std::forward< Rest >( rest )... ); + } + template< class Key > inline json::const_reference at( Key key ) const { return _j.at( std::forward< Key >( key ) ); } + template< class Key > inline json::const_reference operator[]( Key key ) const { return _j.operator[]( key ); } + template< class T > inline T get() const { return _j.get< T >(); } + template< class T > inline void get_to( T & value ) const { _j.get_to( value ); } -// If there, gets the value at the given key and returns true; otherwise false. -// Turns json exceptions into runtime errors with additional info. -template< class T > -bool get_ex( nlohmann::json const & j, std::string const & key, T * pv ) -{ - auto it = j.find( key ); - if( it == j.end() || it->is_null() ) - return false; - try + // If there, gets the value at the given key and returns true; otherwise false + template< class T > + bool get_ex( T & value ) const { - // This will throw for type mismatches, etc. - it->get_to( *pv ); + if( ! exists() ) + return false; + _j.get_to( value ); + return true; } - catch( nlohmann::json::exception & e ) + + // Get the JSON as a value, or a default if not there (throws if wrong type) + template< class T > + T default_value( T const & default_value ) const { - throw std::runtime_error( "[while getting '" + key + "']" + e.what() ); + return exists() ? _j.get< T >() : default_value; } - return true; -} + // Get the object, with a default being an empty one; does not throw + inline json const & default_object() const noexcept { return is_object() ? _j : empty_json_object; } -// If there, returns the value at the given key; otherwise returns a default value. -template < class T > -T get( nlohmann::json const & j, std::string const & key, T const & default_value ) -{ - if( ! j.is_object() ) - return default_value; - return j.value( key, default_value ); -} + // Get the string object, with a default being an empty one; does not throw + inline json const & default_string() const noexcept { return is_string() ? _j : empty_json_string; } + // Get a JSON string by reference (zero copy); it must be a string or it'll throw + inline std::string const & string_ref() const { return _j.get_ref< const json::string_t & >(); } -// If there, returns the value at the given key; otherwise throws! -// Turns json exceptions into runtime errors with additional info. -template < class T > -T get( nlohmann::json const & j, std::string const & key ) -{ - // This will throw for type mismatches, etc. - // Does not check for existence: will throw, too! - return j.at(key).get< T >(); -} + // Get a JSON string by reference (zero copy); does not throw + inline std::string const & string_ref_or_empty() const { return default_string().get_ref< const json::string_t & >(); } +}; -// If there, returns the value at the given index (in an array); otherwise throws! -// Turns json exceptions into runtime errors with additional info. -template < class T > -T get( nlohmann::json const & j, int index ) +inline std::ostream & operator<<( std::ostream & os, json_ref const & j ) { - // This will throw for type mismatches, etc. - // Does not check for existence: will throw, too! - return j.at( index ).get< T >(); + return operator<<( os, static_cast< json const & >( j ) ); } -// If there, returns the value at the given iterator; otherwise throws! -// Turns json exceptions into runtime errors with additional info. -template < class T > -T get( nlohmann::json const & j, nlohmann::json::const_iterator const & it ) +template< typename... Rest > +json_ref _nested_json( json const & j ) { - if( it == j.end() ) - throw std::runtime_error( "unexpected end of json" ); - // This will throw for type mismatches, etc. - // Does not check for existence: will throw, too! - return it->get< T >(); + // j.nested() + return j; } - - template< typename... Rest > -nlohmann::json const & _nested( nlohmann::json const & j ) +json_ref _nested_json( json const & j, bool ( json::*is_fn )() const ) { + // j.nested( &json::is_string ) + if( ! ( j.*is_fn )() ) + return missing_json; return j; } template< typename... Rest > -nlohmann::json const & _nested( nlohmann::json const & j, std::string const & inner, Rest... rest ) +json_ref _nested_json( json const & j, json_key const & inner, Rest... rest ) { + // j.nested( "key", ... ) auto it = j.find( inner ); if( it == j.end() ) - return null_json; - return _nested( *it, std::forward< Rest >( rest )... ); + return missing_json; + return _nested_json( *it, std::forward< Rest >( rest )... ); } - - -// Allow easy read-only lookup of nested json hierarchies: -// j["one"]["two"]["three"] // undefined; will throw/assert if a hierarchy isn't there -// But: -// nested( j, "one", "two", "three" ) // will not throw; does not copy! -// The result is either a null JSON object or a valid one. The boolean operator can be used as an easy check: -// if( auto inside = nested( j, "one", "two" ) ) -// { ... } -// -class nested +template< typename... Rest > +json_ref _nested_json( json const & j, json::size_type index, Rest... rest ) { - nlohmann::json const & _j; - -public: - nested() : _j( null_json ) {} + // j.nested( index, ... ) + if( ! j.is_array() ) + return missing_json; + if( index >= j.size() ) + return missing_json; + return _nested_json( j[index], std::forward< Rest >( rest )... ); +} - template< typename... Rest > - nested( nlohmann::json const & j, Rest... rest ) - : _j( _nested( j, std::forward< Rest >( rest )... ) ) - {} - nlohmann::json const * operator->() const { return &_j; } +// Since we know how we're derived from, we can get the json, or the reference to it, from this: +// json <- nlohmann::basic_json<...> <- json_base +inline json_ref json_base::_ref() const +{ + return static_cast< json const & >( *this ); +} - bool exists() const { return ! _j.is_null(); } - operator bool() const { return exists(); } - nlohmann::json const & get() const { return _j; } - operator nlohmann::json const & () const { return get(); } +// Returns false if the object wasn't found +inline bool json_base::exists() const +{ + return _ref().exists(); +} - bool is_array() const { return _j.is_array(); } - bool is_object() const { return _j.is_object(); } - bool is_string() const { return _j.is_string(); } +// Get the JSON as a value, or a default if not there (throws if wrong type) +template< class T > +inline T json_base::default_value( T const & default_value ) const +{ + return _ref().default_value( default_value ); +} - // Dig deeper - template< typename... Rest > - inline nested find( Rest... rest ) const - { - return nested( _j, std::forward< Rest >( rest )... ); - } - inline nested operator[]( std::string const & key ) const { return find( key ); } +// If there, gets the value at the given key and returns true; otherwise false +template< class T > +inline bool json_base::get_ex( T & value ) const +{ + return _ref().get_ex( value ); +} - // Get the JSON as a value - template< class T > T value() const { return json::value< T >( get() ); } - // Get the JSON as a value, or a default if not there (throws if wrong type) - template < class T > T default_value( T const & default_value ) const { return json::value< T >( get(), default_value ); } - // Get the object, with a default being an empty one; does not throw - nlohmann::json const & default_object() const { return is_object() ? _j : empty_json_object; } - // Get the object, with a default being an empty one; does not throw - nlohmann::json const & default_string() const { return is_string() ? _j : empty_json_string; } - // Get a JSON string by reference (zero copy); it must be a string or it'll throw - inline std::string const & string_ref() const { return json::string_ref( get() ); } - // Get a JSON string by reference (zero copy); does not throw - inline std::string const & string_ref_or_empty() const { return json::string_ref( default_string() ); } -}; +// Get the object, with a default being an empty one; does not throw +inline json_ref json_base::default_object() const +{ + return _ref().default_object(); +} +// Get the string object, with a default being an empty one; does not throw +inline json_ref json_base::default_string() const +{ + return _ref().default_string(); +} -// Recursively patches existing 'j' with contents of 'patches', which must be a JSON object. -// A 'null' value inside erases previous contents. Any other value overrides. -// See: https://json.nlohmann.me/api/basic_json/merge_patch/ -// Example below, for load_app_settings. -// Use 'what' to denote what it is we're patching in, if a failure happens. The std::runtime_error will populate with -// it. -// -void patch( nlohmann::json & j, nlohmann::json const & patches, std::string const & what = {} ); - - -// Loads configuration settings from 'global' content. -// E.g., a configuration file may contain: -// { -// "context": { -// "dds": { -// "enabled": false, -// "domain" : 5 -// } -// }, -// ... -// } -// This function will load a specific key 'context' inside and return it. The result will be a disabling of dds: -// Besides this "global" key, application-specific settings can override the global settings, e.g.: -// { -// "context": { -// "dds": { -// "enabled": false, -// "domain" : 5 -// } -// }, -// "realsense-viewer": { -// "context": { -// "dds": { "enabled": null } -// } -// }, -// ... -// } -// If the current application is 'realsense-viewer', then the global 'context' settings will be patched with the -// application-specific 'context' and returned: -// { -// "dds": { -// "domain" : 5 -// } -// } -// See rules for patching in patch(). -// The 'application' is usually any single-word executable name (without extension). -// The 'subkey' is mandatory. -// The 'error_context' is used for error reporting, to show what failed. Like application, it should be a single word -// that can be used to denote hierarchy within the global json. -// -nlohmann::json load_app_settings( nlohmann::json const & global, - std::string const & application, - std::string const & subkey, - std::string const & error_context ); +// Get a JSON string by reference (zero copy); it must be a string or it'll throw +inline std::string const & json_base::string_ref() const +{ + return _ref().string_ref(); +} +// Get a JSON string by reference (zero copy); does not throw +inline std::string const & json_base::string_ref_or_empty() const +{ + return default_string().string_ref(); +} -// Same as above, but automatically takes the application name from the executable-name. +// Allow easy read-only lookup of nested json hierarchies: +// j["one"]["two"]["three"] // undefined; will throw/assert if a hierarchy isn't there +// But: +// j.nested( "one", "two", "three" ) // will not throw; does not copy! +// The result is either a null JSON object or a valid one. The boolean operator can be used as an easy check: +// if( auto inside = j.nested( "one", "two" ) ) +// { ... } // -nlohmann::json load_settings( nlohmann::json const & global, - std::string const & subkey, - std::string const & error_context ); +template< typename... Rest > +inline json_ref json_base::nested( Rest... rest ) const +{ + return _ref().nested( std::forward< Rest >( rest )... ); +} -} // namespace json } // namespace rsutils diff --git a/third-party/rsutils/include/rsutils/py/pybind11.h b/third-party/rsutils/include/rsutils/py/pybind11.h index 31d840488a1..acc196d3697 100644 --- a/third-party/rsutils/include/rsutils/py/pybind11.h +++ b/third-party/rsutils/include/rsutils/py/pybind11.h @@ -32,6 +32,42 @@ constexpr auto json_to_py = pyjson::from_json; constexpr auto py_to_json = pyjson::to_json; +// pybind11 caster specifically for rsutils::json +// This is a copy of the code for nlohmann, in pybind11_json.hpp above +#include +namespace pybind11 { +namespace detail { + +template<> +struct type_caster< rsutils::json > +{ +public: + PYBIND11_TYPE_CASTER( rsutils::json, _( "json" ) ); + + bool load( handle src, bool ) + { + try + { + value = pyjson::to_json( src ); + return true; + } + catch( ... ) + { + return false; + } + } + + static handle cast( rsutils::json src, return_value_policy /* policy */, handle /* parent */ ) + { + object obj = pyjson::from_json( src ); + return obj.release(); + } +}; + +} // namespace detail +} // namespace pybind11 + + namespace py = pybind11; using namespace pybind11::literals; diff --git a/third-party/rsutils/include/rsutils/string/hexarray.h b/third-party/rsutils/include/rsutils/string/hexarray.h index 9a5f45dc3c7..aa70d8fe98f 100644 --- a/third-party/rsutils/include/rsutils/string/hexarray.h +++ b/third-party/rsutils/include/rsutils/string/hexarray.h @@ -1,9 +1,8 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2023 Intel Corporation. All Rights Reserved. - #pragma once -#include +#include #include #include @@ -37,7 +36,7 @@ class hexarray private: bytes _bytes; - friend void from_json( nlohmann::json const &, hexarray & ); + friend void from_json( rsutils::json const &, hexarray & ); public: hexarray() = default; @@ -72,9 +71,9 @@ inline std::ostream & operator<<( std::ostream & os, hexarray const & hexa ) // Allow j["key"] = hexarray( bytes ); -void to_json( nlohmann::json &, const hexarray & ); +void to_json( rsutils::json &, const hexarray & ); // Allow j.get< hexarray >(); -void from_json( nlohmann::json const &, hexarray & ); +void from_json( rsutils::json const &, hexarray & ); // See https://github.com/nlohmann/json#arbitrary-types-conversions diff --git a/third-party/rsutils/py/pyrsutils.cpp b/third-party/rsutils/py/pyrsutils.cpp index 7d0ce2c5147..3b29223eead 100644 --- a/third-party/rsutils/py/pyrsutils.cpp +++ b/third-party/rsutils/py/pyrsutils.cpp @@ -40,7 +40,7 @@ PYBIND11_MODULE(NAME, m) { py::arg( "max-length" ) = 96 ); m.def( "shorten_json_string", - []( nlohmann::json const & j, size_t max_length ) + []( rsutils::json const & j, size_t max_length ) { return rsutils::string::shorten_json_string( j.dump(), max_length ).to_string(); }, py::arg( "json" ), py::arg( "max-length" ) = 96 ); diff --git a/third-party/rsutils/src/hexarray.cpp b/third-party/rsutils/src/hexarray.cpp index 85f584426fd..46e208348be 100644 --- a/third-party/rsutils/src/hexarray.cpp +++ b/third-party/rsutils/src/hexarray.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include namespace rsutils { @@ -25,32 +25,32 @@ namespace string { } -void to_json( nlohmann::json & j, const hexarray & hexa ) +void to_json( rsutils::json & j, const hexarray & hexa ) { j = hexa.to_string(); } -void from_json( nlohmann::json const & j, hexarray & hexa ) +void from_json( rsutils::json const & j, hexarray & hexa ) { if( j.is_array() ) { hexa._bytes.resize( j.size() ); std::transform( j.begin(), j.end(), std::begin( hexa._bytes ), - []( nlohmann::json const & elem ) + []( rsutils::json const & elem ) { if( ! elem.is_number_unsigned() ) - throw nlohmann::json::type_error::create( 302, "array value not an unsigned integer", &elem ); + throw rsutils::json::type_error::create( 302, "array value not an unsigned integer", &elem ); auto v = elem.template get< uint64_t >(); if( v > 255 ) - throw nlohmann::json::out_of_range::create( 401, "array value out of range", &elem ); + throw rsutils::json::out_of_range::create( 401, "array value out of range", &elem ); return uint8_t( v ); } ); } else if( j.is_string() ) hexa = hexarray::from_string( j.get< std::string >() ); else - throw nlohmann::json::type_error::create( 317, "hexarray should be a string", &j ); + throw rsutils::json::type_error::create( 317, "hexarray should be a string", &j ); } diff --git a/third-party/rsutils/src/json.cpp b/third-party/rsutils/src/json.cpp index 5b55788bf24..617af45befe 100644 --- a/third-party/rsutils/src/json.cpp +++ b/third-party/rsutils/src/json.cpp @@ -2,18 +2,32 @@ // Copyright(c) 2023 Intel Corporation. All Rights Reserved. #include +#include #include +#include + + namespace rsutils { -namespace json { -nlohmann::json const null_json = {}; -nlohmann::json const empty_json_string = nlohmann::json::value_type( nlohmann::json::value_t::string ); -nlohmann::json const empty_json_object = nlohmann::json::object(); +json const null_json = {}; +json const missing_json = json::value_t::discarded; +json const empty_json_string = json::value_t::string; +json const empty_json_object = json::object(); -void patch( nlohmann::json & j, nlohmann::json const & patches, std::string const & what ) +// Recursively patches existing JSON with contents of 'overrides', which must be a JSON object. +// A 'null' value inside erases previous contents. Any other value overrides. +// See: https://json.nlohmann.me/api/basic_json/merge_patch/ +// Example below, for load_app_settings. +// Use 'what' to denote what it is we're patching in, if a failure happens. The std::runtime_error will populate with +// it. +// +// NOTE: called 'override' to agree with terminology elsewhere, and to avoid collisions with the json patch(), +// merge_patch(), existing functions. +// +void json_base::override( json_ref patches, std::string const & what ) { if( ! patches.is_object() ) { @@ -23,7 +37,7 @@ void patch( nlohmann::json & j, nlohmann::json const & patches, std::string cons try { - j.merge_patch( patches ); + static_cast< json * >( this )->merge_patch( patches ); } catch( std::exception const & e ) { @@ -33,30 +47,97 @@ void patch( nlohmann::json & j, nlohmann::json const & patches, std::string cons } -nlohmann::json load_app_settings( nlohmann::json const & global, - std::string const & application, - std::string const & subkey, - std::string const & error_context ) +// Load the contents of a file into a JSON object. +// +// Throws if any errors are encountered with the file or its contents. +// Returns the contents. If the file wasn't there, returns missing_json. +// +json json_config::load_from_file( std::string const & filename ) +{ + std::ifstream f( filename ); + if( f.good() ) + { + try + { + return json::parse( f ); + } + catch( std::exception const & e ) + { + throw std::runtime_error( "failed to load configuration file (" + filename + + "): " + std::string( e.what() ) ); + } + } + return missing_json; +} + + + +// Loads configuration settings from 'global' content (loaded by load_from_file()?). +// E.g., a configuration file may contain: +// { +// "context": { +// "dds": { +// "enabled": false, +// "domain" : 5 +// } +// }, +// ... +// } +// This function will load a specific key 'context' inside and return it. The result will be a disabling of dds: +// Besides this "global" key, application-specific settings can override the global settings, e.g.: +// { +// "context": { +// "dds": { +// "enabled": false, +// "domain" : 5 +// } +// }, +// "realsense-viewer": { +// "context": { +// "dds": { "enabled": null } +// } +// }, +// ... +// } +// If the current application is 'realsense-viewer', then the global 'context' settings will be patched with the +// application-specific 'context' and returned: +// { +// "dds": { +// "domain" : 5 +// } +// } +// See rules for patching in patch(). +// The 'application' is usually any single-word executable name (without extension). +// The 'subkey' is mandatory. +// The 'error_context' is used for error reporting, to show what failed. Like application, it should be a single word +// that can be used to denote hierarchy within the global json. +// +json json_config::load_app_settings( json const & global, + std::string const & application, + json_key const & subkey, + std::string const & error_context ) { // Take the global subkey settings out of the configuration - nlohmann::json settings; - if( auto global_subkey = rsutils::json::nested( global, subkey ) ) - patch( settings, global_subkey, "global " + error_context + '/' + subkey ); + json settings; + if( auto global_subkey = global.nested( subkey ) ) + settings.override( global_subkey, "global " + error_context + '/' + subkey ); // Patch any application-specific subkey settings - if( auto application_subkey = rsutils::json::nested( global, application, subkey ) ) - patch( settings, application_subkey, error_context + '/' + application + '/' + subkey ); + if( auto application_subkey = global.nested( application, subkey ) ) + settings.override( application_subkey, error_context + '/' + application + '/' + subkey ); return settings; } -nlohmann::json -load_settings( nlohmann::json const & global, std::string const & subkey, std::string const & error_context ) +// Same as above, but automatically takes the application name from the executable-name +// +json json_config::load_settings( json const & global, + json_key const & subkey, + std::string const & error_context ) { return load_app_settings( global, rsutils::os::executable_name(), subkey, error_context ); } -} // namespace json } // namespace rsutils diff --git a/tools/dds/dds-adapter/lrs-device-controller.cpp b/tools/dds/dds-adapter/lrs-device-controller.cpp index bc6e622ab0a..c00b1f7419c 100644 --- a/tools/dds/dds-adapter/lrs-device-controller.cpp +++ b/tools/dds/dds-adapter/lrs-device-controller.cpp @@ -20,7 +20,7 @@ using rsutils::string::hexarray; #include #include -using nlohmann::json; +using rsutils::json; using namespace realdds; using tools::lrs_device_controller; @@ -337,7 +337,7 @@ extrinsics_map get_extrinsics_map( const rs2::device & dev ) } -std::shared_ptr< dds_stream_profile > create_dds_stream_profile( std::string const & type_string, nlohmann::json const & j ) +std::shared_ptr< dds_stream_profile > create_dds_stream_profile( std::string const & type_string, rsutils::json const & j ) { if( "motion" == type_string ) return dds_stream_profile::from_json< dds_motion_stream_profile >( j ); @@ -503,7 +503,7 @@ lrs_device_controller::lrs_device_controller( rs2::device dev, std::shared_ptr< return query_option( option ); } ); _dds_device_server->on_control( - [this]( std::string const & id, nlohmann::json const & control, nlohmann::json & reply ) + [this]( std::string const & id, rsutils::json const & control, rsutils::json & reply ) { return on_control( id, control, reply ); } ); _device_sn = _rs_dev.get_info( RS2_CAMERA_INFO_SERIAL_NUMBER ); @@ -599,7 +599,7 @@ lrs_device_controller::lrs_device_controller( rs2::device dev, std::shared_ptr< _bridge.on_error( [this]( std::string const & error_string ) { - nlohmann::json j = nlohmann::json::object( { + rsutils::json j = rsutils::json::object( { { "id", "error" }, { "error", error_string }, } ); @@ -622,7 +622,7 @@ lrs_device_controller::~lrs_device_controller() } -bool lrs_device_controller::on_open_streams( nlohmann::json const & control, nlohmann::json & reply ) +bool lrs_device_controller::on_open_streams( rsutils::json const & control, rsutils::json & reply ) { // Note that this function is called "start-streaming" but it's really a response to "open-streams" so does not // actually start streaming. It simply sets and locks in which streams should be open when streaming starts. @@ -630,7 +630,7 @@ bool lrs_device_controller::on_open_streams( nlohmann::json const & control, nlo // out, a sensor is reset back to its default state using implicit stream selection. // (For example, the 'Stereo Module' sensor controls Depth, IR1, IR2: but turning on all 3 has performance // implications and may not be desirable. So you can open only Depth and IR1/2 will stay inactive...) - if( rsutils::json::get< bool >( control, "reset", true ) ) + if( control.nested( "reset" ).default_value( true ) ) _bridge.reset(); auto const & msg_profiles = control["stream-profiles"]; @@ -653,7 +653,7 @@ bool lrs_device_controller::on_open_streams( nlohmann::json const & control, nlo } // We're here so all the profiles were acceptable; lock them in -- with no implicit profiles! - if( rsutils::json::get< bool >( control, "commit", true ) ) + if( control.nested( "commit" ).default_value( true ) ) _bridge.commit(); // We don't touch the reply - it's already filled in for us @@ -666,7 +666,7 @@ void lrs_device_controller::publish_frame_metadata( const rs2::frame & f, realdd if( ! _dds_device_server->has_metadata_readers() ) return; - nlohmann::json md_header = nlohmann::json::object( { + rsutils::json md_header = rsutils::json::object( { { "frame-number", f.get_frame_number() }, // communicated; up to client to pick up { "timestamp", timestamp.to_ns() }, // syncer key: needs to match the image timestamp, bit-for-bit! { "timestamp-domain", f.get_frame_timestamp_domain() } // needed if we're dealing with different domains! @@ -674,7 +674,7 @@ void lrs_device_controller::publish_frame_metadata( const rs2::frame & f, realdd if( f.is< rs2::depth_frame >() ) md_header["depth-units"] = f.as< rs2::depth_frame >().get_units(); - nlohmann::json metadata = nlohmann::json::object(); + rsutils::json metadata = rsutils::json::object(); for( size_t i = 0; i < static_cast< size_t >( RS2_FRAME_METADATA_COUNT ); ++i ) { rs2_frame_metadata_value val = static_cast< rs2_frame_metadata_value >( i ); @@ -682,7 +682,7 @@ void lrs_device_controller::publish_frame_metadata( const rs2::frame & f, realdd metadata[rs2_frame_metadata_to_string( val )] = f.get_frame_metadata( val ); } - nlohmann::json md_msg = nlohmann::json::object( { + rsutils::json md_msg = rsutils::json::object( { { "stream-name", stream_name_from_rs2( f.get_profile() ) }, { "header", std::move( md_header ) }, { "metadata", std::move( metadata ) }, @@ -838,9 +838,9 @@ size_t lrs_device_controller::get_index_of_profile( const realdds::dds_stream_pr } -bool lrs_device_controller::on_control( std::string const & id, nlohmann::json const & control, nlohmann::json & reply ) +bool lrs_device_controller::on_control( std::string const & id, rsutils::json const & control, rsutils::json & reply ) { - static std::map< std::string, bool ( lrs_device_controller::* )( nlohmann::json const &, nlohmann::json & ) > const + static std::map< std::string, bool ( lrs_device_controller::* )(rsutils::json const &, rsutils::json & ) > const control_handlers{ { "hw-reset", &lrs_device_controller::on_hardware_reset }, { "open-streams", &lrs_device_controller::on_open_streams }, @@ -854,14 +854,14 @@ bool lrs_device_controller::on_control( std::string const & id, nlohmann::json c } -bool lrs_device_controller::on_hardware_reset( nlohmann::json const & control, nlohmann::json & reply ) +bool lrs_device_controller::on_hardware_reset( rsutils::json const & control, rsutils::json & reply ) { _rs_dev.hardware_reset(); return true; } -bool lrs_device_controller::on_hwm( nlohmann::json const & control, nlohmann::json & reply ) +bool lrs_device_controller::on_hwm( rsutils::json const & control, rsutils::json & reply ) { rs2::debug_protocol dp( _rs_dev ); if( ! dp ) @@ -870,22 +870,22 @@ bool lrs_device_controller::on_hwm( nlohmann::json const & control, nlohmann::js rsutils::string::hexarray data; uint32_t opcode; - if( rsutils::json::get_ex( control, "opcode", &opcode ) ) + if( control.nested( "opcode" ).get_ex( opcode ) ) { // In the presence of 'opcode', we're asked to build the command using optional parameters uint32_t param1 = 0, param2 = 0, param3 = 0, param4 = 0; - rsutils::json::get_ex( control, "param1", ¶m1 ); - rsutils::json::get_ex( control, "param2", ¶m2 ); - rsutils::json::get_ex( control, "param3", ¶m3 ); - rsutils::json::get_ex( control, "param4", ¶m4 ); + control.nested( "param1" ).get_ex( param1 ); + control.nested( "param2" ).get_ex( param2 ); + control.nested( "param3" ).get_ex( param3 ); + control.nested( "param4" ).get_ex( param4 ); - rsutils::json::get_ex( control, "data", &data ); // optional + control.nested( "data" ).get_ex( data ); // optional // Build the HWM command data = dp.build_command( opcode, param1, param2, param3, param4, data.get_bytes() ); // And, if told to not actually run it, we return the HWM command - if( rsutils::json::get< bool >( control, "build-command", false ) ) + if( control.nested( "build-command" ).default_value( false ) ) { reply["data"] = data; return true; @@ -893,7 +893,7 @@ bool lrs_device_controller::on_hwm( nlohmann::json const & control, nlohmann::js } else { - if( ! rsutils::json::get_ex( control, "data", &data ) ) + if( ! control.nested( "data" ).get_ex( data ) ) throw std::runtime_error( "no 'data' in HWM control" ); } diff --git a/tools/dds/dds-adapter/lrs-device-controller.h b/tools/dds/dds-adapter/lrs-device-controller.h index 50503f0aa10..77fec4813d4 100644 --- a/tools/dds/dds-adapter/lrs-device-controller.h +++ b/tools/dds/dds-adapter/lrs-device-controller.h @@ -1,12 +1,12 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2022 Intel Corporation. All Rights Reserved. - #pragma once + #include // Include RealSense Cross Platform API #include #include -#include +#include #include #include @@ -40,10 +40,10 @@ class lrs_device_controller void publish_frame_metadata( const rs2::frame & f, realdds::dds_time const & ); - bool on_control( std::string const & id, nlohmann::json const & control, nlohmann::json & reply ); - bool on_hardware_reset( nlohmann::json const &, nlohmann::json & ); - bool on_hwm( nlohmann::json const &, nlohmann::json & ); - bool on_open_streams( nlohmann::json const &, nlohmann::json & ); + bool on_control( std::string const & id, rsutils::json const & control, rsutils::json & reply ); + bool on_hardware_reset( rsutils::json const &, rsutils::json & ); + bool on_hwm( rsutils::json const &, rsutils::json & ); + bool on_open_streams( rsutils::json const &, rsutils::json & ); void override_default_profiles( const std::map< std::string, realdds::dds_stream_profiles > & stream_name_to_profiles, std::map< std::string, size_t > & stream_name_to_default_profile ) const; diff --git a/tools/dds/dds-adapter/rs-dds-adapter.cpp b/tools/dds/dds-adapter/rs-dds-adapter.cpp index 91a071d751b..c125545488f 100644 --- a/tools/dds/dds-adapter/rs-dds-adapter.cpp +++ b/tools/dds/dds-adapter/rs-dds-adapter.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,7 @@ std::string get_topic_root( std::string const & name, std::string const & serial topics::device_info rs2_device_to_info( rs2::device const & dev ) { - nlohmann::json j; + rsutils::json j; // Name is mandatory std::string const name = dev.get_info( RS2_CAMERA_INFO_NAME ); @@ -74,35 +75,24 @@ topics::device_info rs2_device_to_info( rs2::device const & dev ) } -static nlohmann::json load_settings( nlohmann::json const & local_settings ) +static rsutils::json load_settings( rsutils::json const & local_settings ) { - nlohmann::json config; - // Load the realsense configuration file settings - std::ifstream f( rsutils::os::get_special_folder( rsutils::os::special_folder::app_data ) + RS2_CONFIG_FILENAME ); - if( f.good() ) - { - try - { - config = nlohmann::json::parse( f ); - } - catch( std::exception const & e ) - { - throw std::runtime_error( "failed to load configuration file: " + std::string( e.what() ) ); - } - } + std::string const filename = rsutils::os::get_special_folder( rsutils::os::special_folder::app_data ) + RS2_CONFIG_FILENAME; + auto config = rsutils::json_config::load_from_file( filename ); - config = rsutils::json::load_settings( config, "context", "config-file" ); + // Take just the 'context' part + config = rsutils::json_config::load_settings( config, "context", "config-file" ); // Take the "dds" settings only - config = rsutils::json::nested( config, "dds" ); + config = config.nested( "dds" ); // We should always have DDS enabled if( config.is_object() ) config.erase( "enabled" ); // Patch the given local settings into the configuration - rsutils::json::patch( config, local_settings, "local settings" ); + config.override( local_settings, "local settings" ); return config; } @@ -157,7 +147,7 @@ try // Create a DDS participant auto participant = std::make_shared< dds_participant >(); { - nlohmann::json dds_settings = nlohmann::json::object(); + rsutils::json dds_settings = rsutils::json::object(); dds_settings = load_settings( dds_settings ); participant->init( domain, "rs-dds-adapter", std::move( dds_settings ) ); } @@ -173,7 +163,7 @@ try std::cout << "Start listening to RS devices.." << std::endl; // Create a RealSense context - nlohmann::json j = { + rsutils::json j = { { "dds", false }, // Don't discover DDS devices from the network, we want local devices only { "format-conversion", "basic" } // Don't convert raw sensor formats (except interleaved) will be done by receiver }; diff --git a/tools/dds/dds-sniffer/rs-dds-sniffer.cpp b/tools/dds/dds-sniffer/rs-dds-sniffer.cpp index 360b0a3e521..064ac7ed9ed 100644 --- a/tools/dds/dds-sniffer/rs-dds-sniffer.cpp +++ b/tools/dds/dds-sniffer/rs-dds-sniffer.cpp @@ -26,6 +26,7 @@ #include #include #include +#include using namespace TCLAP; using namespace eprosima::fastdds::dds; @@ -194,35 +195,24 @@ dds_sniffer::~dds_sniffer() } -static nlohmann::json load_settings( nlohmann::json const & local_settings ) +static rsutils::json load_settings( rsutils::json const & local_settings ) { - nlohmann::json config; - // Load the realsense configuration file settings - std::ifstream f( rsutils::os::get_special_folder( rsutils::os::special_folder::app_data ) + "realsense-config.json" ); - if( f.good() ) - { - try - { - config = nlohmann::json::parse( f ); - } - catch( std::exception const & e ) - { - throw std::runtime_error( "failed to load configuration file: " + std::string( e.what() ) ); - } - } + std::string const filename = rsutils::os::get_special_folder( rsutils::os::special_folder::app_data ) + "realsense-config.json"; + auto config = rsutils::json_config::load_from_file( filename ); - config = rsutils::json::load_settings( config, "context", "config-file" ); + // Take just the 'context' part + config = rsutils::json_config::load_settings( config, "context", "config-file" ); // Take the "dds" settings only - config = rsutils::json::nested( config, "dds" ); + config = config.nested( "dds" ); // We should always have DDS enabled if( config.is_object() ) config.erase( "enabled" ); // Patch the given local settings into the configuration - rsutils::json::patch( config, local_settings, "local settings" ); + config.override( local_settings, "local settings" ); return config; } @@ -254,7 +244,7 @@ bool dds_sniffer::init( realdds::dds_domain_id domain ) on_type_discovery( topic_name, dyn_type ); } ); - nlohmann::json settings( nlohmann::json::object() ); + rsutils::json settings( rsutils::json::object() ); settings = load_settings( settings ); _participant.init( domain, rsutils::os::executable_name(), std::move( settings ) ); diff --git a/tools/enumerate-devices/rs-enumerate-devices.cpp b/tools/enumerate-devices/rs-enumerate-devices.cpp index d2c1ede52a1..1daf7f55a6e 100644 --- a/tools/enumerate-devices/rs-enumerate-devices.cpp +++ b/tools/enumerate-devices/rs-enumerate-devices.cpp @@ -11,8 +11,8 @@ #include #include -#include -using nlohmann::json; +#include +using rsutils::json; #include "tclap/CmdLine.h" diff --git a/tools/realsense-viewer/realsense-viewer.cpp b/tools/realsense-viewer/realsense-viewer.cpp index 29ed3c05a72..3715542b969 100644 --- a/tools/realsense-viewer/realsense-viewer.cpp +++ b/tools/realsense-viewer/realsense-viewer.cpp @@ -332,7 +332,7 @@ int main(int argc, const char** argv) try std::shared_ptr device_models = std::make_shared(); - nlohmann::json settings = nlohmann::json::object(); + rsutils::json settings = rsutils::json::object(); if( only_sw_arg.getValue() ) { #if defined( BUILD_WITH_DDS ) diff --git a/tools/terminal/rs-terminal.cpp b/tools/terminal/rs-terminal.cpp index 4eb62800b8f..800318194a0 100644 --- a/tools/terminal/rs-terminal.cpp +++ b/tools/terminal/rs-terminal.cpp @@ -12,7 +12,7 @@ #include "parser.hpp" #include "auto-complete.h" -#include +#include #include @@ -197,9 +197,9 @@ int main(int argc, char** argv) // parse command.xml rs2::log_to_file(RS2_LOG_SEVERITY_WARN, "librealsense.log"); - nlohmann::json settings; + rsutils::json settings; #ifdef BUILD_WITH_DDS - nlohmann::json dds; + rsutils::json dds; if( domain_arg.isSet() ) dds["domain"] = domain_arg.getValue(); if( only_sw_arg.isSet() ) diff --git a/unit-tests/dds/test-control-reply.py b/unit-tests/dds/test-control-reply.py index 7de2cf9506b..bc1f505561b 100644 --- a/unit-tests/dds/test-control-reply.py +++ b/unit-tests/dds/test-control-reply.py @@ -36,7 +36,7 @@ def _on_control( server, id, control, reply ): reply['sequence'] = n_replies # to show that we've processed it reply['nested-json'] = { 'more': True } # to show off return True # otherwise the control will be flagged as error - server.on_control( _on_control ) + subscription = server.on_control( _on_control ) raise StopIteration() # exit the 'with' statement diff --git a/unit-tests/rsutils/string/test-hexarray.cpp b/unit-tests/rsutils/string/test-hexarray.cpp index 2c84a00317e..ad7a79ff7f4 100644 --- a/unit-tests/rsutils/string/test-hexarray.cpp +++ b/unit-tests/rsutils/string/test-hexarray.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include using rsutils::string::hexdump; @@ -399,30 +399,30 @@ TEST_CASE( "hexarray", "[hexarray]" ) } SECTION( "to json" ) { - nlohmann::json j; + rsutils::json j; j["blah"] = hexarray( std::move( ba ) ); CHECK( j.dump() == "{\"blah\":\"00010203040506070809\"}"); } SECTION( "(same as using hexarray::to_string)" ) { - nlohmann::json j; + rsutils::json j; j["blah"] = hexarray::to_string( ba ); CHECK( j.dump() == "{\"blah\":\"00010203040506070809\"}" ); } SECTION( "from json" ) { - auto j = nlohmann::json::parse( "{\"blah\":\"00010203040506070809\"}" ); + auto j = rsutils::json::parse( "{\"blah\":\"00010203040506070809\"}" ); CHECK( j["blah"].get< hexarray >().get_bytes() == ba ); } SECTION( "from json shuld accept bytearrays, too" ) { - auto j = nlohmann::json::parse( "{\"blah\":[0,1,2,3,4,5,6,7,8,9]}" ); + auto j = rsutils::json::parse( "{\"blah\":[0,1,2,3,4,5,6,7,8,9]}" ); CHECK( j["blah"].get< hexarray >().get_bytes() == ba ); - j = nlohmann::json::parse( "{\"blah\":[0,1,256]}" ); // out-of-range + j = rsutils::json::parse( "{\"blah\":[0,1,256]}" ); // out-of-range CHECK_THROWS( j["blah"].get< hexarray >().get_bytes() ); - j = nlohmann::json::parse( "{\"blah\":[0,1,2.0]}" ); // must be integer + j = rsutils::json::parse( "{\"blah\":[0,1,2.0]}" ); // must be integer CHECK_THROWS( j["blah"].get< hexarray >().get_bytes() ); } } diff --git a/wrappers/python/pyrs_context.cpp b/wrappers/python/pyrs_context.cpp index cd56f62558f..a8eb15fdbb7 100644 --- a/wrappers/python/pyrs_context.cpp +++ b/wrappers/python/pyrs_context.cpp @@ -18,7 +18,7 @@ void init_context(py::module &m) { py::class_< rs2::context >( m, "context", "Librealsense context class. Includes realsense API version." ) .def( py::init< char const * >(), py::arg( "json-settings" ) = nullptr ) - .def( py::init<>( []( nlohmann::json const & j ) { return rs2::context( j.dump() ); } ), py::arg( "json-settings" ) ) + .def( py::init<>( []( rsutils::json const & j ) { return rs2::context( j.dump() ); } ), py::arg( "json-settings" ) ) .def("query_devices", (rs2::device_list(rs2::context::*)() const) &rs2::context::query_devices, "Create a static" " snapshot of all connected devices at the time of the call.") .def( "query_devices", ( rs2::device_list( rs2::context::* )(int) const ) & rs2::context::query_devices, "Create a static"