Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tree/dataframe/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ endif()
if(builtin_nlohmannjson)
target_include_directories(ROOTDataFrame PRIVATE ${CMAKE_SOURCE_DIR}/builtins)
else()
target_link_libraries(ROOTDataFrame PUBLIC nlohmann_json::nlohmann_json)
target_link_libraries(ROOTDataFrame PRIVATE nlohmann_json::nlohmann_json)
endif()

ROOT_ADD_TEST_SUBDIRECTORY(test)
28 changes: 25 additions & 3 deletions tree/dataframe/inc/ROOT/RDF/RMetaData.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,21 @@
#ifndef ROOT_RDF_RMETADATA
#define ROOT_RDF_RMETADATA

#include <nlohmann/json.hpp>
#include <string>
#include <memory>

namespace ROOT {

namespace Internal {
namespace RDF {
// To avoid unnecessary dependence on nlohman json in the interface. Note that
// we should not forward declare nlohmann::json directly, since its declaration
// might change (it is currently a typedef). With this wrapper type, we are
// completely decoupled on nlohmann::json in the RMetaData interface.
struct RMetaDataJson;
}
}

namespace RDF {
namespace Experimental {

Expand All @@ -27,9 +38,17 @@ namespace Experimental {
Once a dataframe is built with RMetaData object, it could be accessed via DefinePerSample.
*/
class RMetaData {
nlohmann::json fJson;

public:

RMetaData();
// Note: each RMetaData instance should own its own fJson object, just as if
// the underlying nlohmann::json object would be owned by value.
RMetaData(RMetaData const&);
RMetaData(RMetaData &&);
RMetaData & operator=(RMetaData const&);
RMetaData & operator=(RMetaData &&);
~RMetaData();

void Add(const std::string &key, int val);
void Add(const std::string &key, double val);
void Add(const std::string &key, const std::string &val);
Expand All @@ -41,6 +60,9 @@ public:
int GetI(const std::string &key, int defaultVal) const;
double GetD(const std::string &key, double defaultVal) const;
const std::string GetS(const std::string &key, const std::string &defaultVal) const;

private:
std::unique_ptr<Internal::RDF::RMetaDataJson> fJson;
};

} // namespace Experimental
Expand Down
65 changes: 43 additions & 22 deletions tree/dataframe/src/RMetaData.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -9,84 +9,105 @@
*************************************************************************/

#include "ROOT/RDF/RMetaData.hxx"
#include <nlohmann/json.hpp>
#include <stdexcept> // std::logic_error

struct ROOT::Internal::RDF::RMetaDataJson {
nlohmann::json payload;
};

namespace ROOT {
namespace RDF {
namespace Experimental {

RMetaData::RMetaData() : fJson{std::make_unique<Internal::RDF::RMetaDataJson>()} {}

RMetaData::RMetaData(RMetaData const &other) : fJson{std::make_unique<Internal::RDF::RMetaDataJson>(*other.fJson)} {}

RMetaData::RMetaData(RMetaData &&) = default;

RMetaData &RMetaData::operator=(RMetaData const &other)
{
fJson = std::make_unique<Internal::RDF::RMetaDataJson>(*other.fJson);
return *this;
}

RMetaData &RMetaData::operator=(RMetaData &&) = default;

RMetaData::~RMetaData() = default;

void RMetaData::Add(const std::string &key, int val)
{
fJson[key] = val;
fJson->payload[key] = val;
}

void RMetaData::Add(const std::string &key, double val)
{
fJson[key] = val;
fJson->payload[key] = val;
}

void RMetaData::Add(const std::string &key, const std::string &val)
{
fJson[key] = val;
fJson->payload[key] = val;
}

std::string RMetaData::Dump(const std::string &key) const
{
return fJson[key].dump();
return fJson->payload[key].dump();
}

int RMetaData::GetI(const std::string &key) const
{
if (!fJson.contains(key))
if (!fJson->payload.contains(key))
throw std::logic_error("No key with name " + key + " in the metadata object.");
if (!fJson[key].is_number_integer())
if (!fJson->payload[key].is_number_integer())
throw std::logic_error("Key " + key + " is not of type int.");
return fJson[key].get<int>();
return fJson->payload[key].get<int>();
}

double RMetaData::GetD(const std::string &key) const
{
if (!fJson.contains(key))
if (!fJson->payload.contains(key))
throw std::logic_error("No key with name " + key + " in the metadata object.");
if (!fJson[key].is_number_float())
if (!fJson->payload[key].is_number_float())
throw std::logic_error("Key " + key + " is not of type double.");
return fJson[key].get<double>();
return fJson->payload[key].get<double>();
}

std::string RMetaData::GetS(const std::string &key) const
{
if (!fJson.contains(key))
if (!fJson->payload.contains(key))
throw std::logic_error("No key with name " + key + " in the metadata object.");
if (!fJson[key].is_string())
if (!fJson->payload[key].is_string())
throw std::logic_error("Key " + key + " is not of type string.");
return fJson[key].get<std::string>();
return fJson->payload[key].get<std::string>();
}

int RMetaData::GetI(const std::string &key, int defaultVal) const
{
if (!fJson.contains(key))
if (!fJson->payload.contains(key))
return defaultVal;
if (!fJson[key].is_number_integer())
if (!fJson->payload[key].is_number_integer())
throw std::logic_error("Key " + key + " is not of type int.");
return fJson[key].get<int>();
return fJson->payload[key].get<int>();
}

double RMetaData::GetD(const std::string &key, double defaultVal) const
{
if (!fJson.contains(key))
if (!fJson->payload.contains(key))
return defaultVal;
if (!fJson[key].is_number_float())
if (!fJson->payload[key].is_number_float())
throw std::logic_error("Key " + key + " is not of type double.");
return fJson[key].get<double>();
return fJson->payload[key].get<double>();
}

const std::string RMetaData::GetS(const std::string &key, const std::string &defaultVal) const
{
if (!fJson.contains(key))
if (!fJson->payload.contains(key))
return defaultVal;
if (!fJson[key].is_string())
if (!fJson->payload[key].is_string())
throw std::logic_error("Key " + key + " is not of type string.");
return fJson[key].get<std::string>();
return fJson->payload[key].get<std::string>();
}

} // namespace Experimental
Expand Down