Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDF.cc update calls to use sdf::Errors output #1295

Merged
merged 9 commits into from
Jun 26, 2024
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
94 changes: 94 additions & 0 deletions include/sdf/SDFImpl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,34 @@ namespace sdf
bool _searchLocalPath = true,
bool _useCallback = false);

/// \brief Find the absolute path of a file.
///
/// The search order in the function is as follows:
/// 1. Using the global URI path map, search in paths associated with the URI
/// scheme of the input.
/// 2. Seach in the path defined by the macro `SDF_SHARE_PATH`.
/// 3. Search in the the libsdformat install path. The path is formed by
/// has the pattern `SDF_SHARE_PATH/sdformat<major version>/<version>/`
/// 4. Directly check if the input path exists in the filesystem.
/// 5. Seach in the path defined by the environment variable `SDF_PATH`.
/// 6. If enabled via _searchLocalPath, prepend the input with the current
/// working directory and check if the result path exists.
/// 7. If enabled via _useCallback and the global callback function is set,
/// invoke the function and return its result.
///
/// \param[out] _errors Vector of errors.
/// \param[in] _filename Name of the file to find.
/// \param[in] _searchLocalPath True to search for the file in the current
/// working directory.
/// \param[in] _useCallback True to find a file based on a registered
/// callback if the file is not found via the normal mechanism.
/// \return File's full path.
SDFORMAT_VISIBLE
std::string findFile(sdf::Errors &_errors,
const std::string &_filename,
bool _searchLocalPath = true,
bool _useCallback = false);

/// \brief Find the absolute path of a file.
///
/// This overload uses the URI path map and and the callback function
Expand All @@ -99,6 +127,26 @@ namespace sdf
bool _useCallback,
const ParserConfig &_config);

/// \brief Find the absolute path of a file.
///
/// This overload uses the URI path map and and the callback function
/// configured in the input ParserConfig object instead of their global
/// counterparts.
///
/// \param[out] _errors Vector of errors.
/// \param[in] _filename Name of the file to find.
/// \param[in] _searchLocalPath True to search for the file in the current
/// working directory.
/// \param[in] _useCallback True to find a file based on a registered
/// callback if the file is not found via the normal mechanism.
/// \param[in] _config Custom parser configuration.
/// \return File's full path.
SDFORMAT_VISIBLE
std::string findFile(sdf::Errors &_errors,
const std::string &_filename,
bool _searchLocalPath,
bool _useCallback,
const ParserConfig &_config);

/// \brief Associate paths to a URI.
/// Example paramters: "model://", "/usr/share/models:~/.gazebo/models"
Expand All @@ -121,22 +169,45 @@ namespace sdf
/// \brief Destructor
public: ~SDF();
public: void PrintDescription();
public: void PrintDescription(sdf::Errors &_errors);
public: void PrintDoc();
public: void Write(const std::string &_filename);
public: void Write(sdf::Errors &_errors, const std::string &_filename);

/// \brief Output SDF's values to stdout.
/// \param[in] _config Configuration for printing the values.
public: void PrintValues(const PrintConfig &_config = PrintConfig());

/// \brief Output SDF's values to stdout.
/// \param[out] _errors Vector of errrors.
/// \param[in] _config Configuration for printing the values.
public: void PrintValues(sdf::Errors &_errors,
const PrintConfig &_config = PrintConfig());

/// \brief Convert the SDF values to a string representation.
/// \param[in] _config Configuration for printing the values.
/// \return The string representation.
public: std::string ToString(
const PrintConfig &_config = PrintConfig()) const;

/// \brief Convert the SDF values to a string representation.
/// \param[out] _errors Vector of errors.
/// \param[in] _config Configuration for printing the values.
/// \return The string representation.
public: std::string ToString(
sdf::Errors &_errors,
const PrintConfig &_config = PrintConfig()) const;

/// \brief Set SDF values from a string
/// \param[in] sdfData String with the values to load.
public: void SetFromString(const std::string &_sdfData);

/// \brief Set SDF values from a string
/// \param[out] _errors Vector of errors.
/// \param[in] sdfData String with the values to load.
public: void SetFromString(sdf::Errors &_Errors,
const std::string &_sdfData);

/// \brief Clear the data in this object.
public: void Clear();

Expand Down Expand Up @@ -182,6 +253,13 @@ namespace sdf
/// \return a wrapped clone of the SDF element
public: static ElementPtr WrapInRoot(const ElementPtr &_sdf);

/// \brief wraps the SDF element into a root element with the version info.
/// \param[out] _errors Vector of errors.
/// \param[in] _sdf the sdf element. Will be cloned by this function.
/// \return a wrapped clone of the SDF element
public: static ElementPtr WrapInRoot(sdf::Errors &_errors,
const ElementPtr &_sdf);

/// \brief Get a string representation of an SDF specification file.
/// This function uses a built-in version of a .sdf file located in
/// the sdf directory. The parser.cc code uses this function, which avoids
Expand All @@ -198,6 +276,22 @@ namespace sdf
public: static const std::string &EmbeddedSpec(
const std::string &_filename, const bool _quiet);

/// \brief Get a string representation of an SDF specification file.
/// This function uses a built-in version of a .sdf file located in
/// the sdf directory. The parser.cc code uses this function, which avoids
/// touching the filesystem.
///
/// Most people should not use this function.
///
/// \param[out] _errors Vector of errors.
/// \param[in] _filename Base name of the SDF specification file to
/// load. For example "root.sdf" or "world.sdf".
/// \return A string that contains the contents of the specified
/// _filename. An empty string is returned if the _filename could not be
/// found.
public: static const std::string &EmbeddedSpec(
azeey marked this conversation as resolved.
Show resolved Hide resolved
sdf::Errors &_errors, const std::string &_filename);

/// \internal
/// \brief Pointer to private data.
private: std::unique_ptr<SDFPrivate> dataPtr;
Expand Down
124 changes: 110 additions & 14 deletions src/SDF.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
#include "sdf/parser.hh"
#include "sdf/Assert.hh"
#include "sdf/Console.hh"
#include "sdf/Error.hh"
#include "sdf/Filesystem.hh"
#include "sdf/SDFImpl.hh"
#include "SDFImplPrivate.hh"
#include "sdf/sdf_config.h"
#include "EmbeddedSdf.hh"
#include "Utils.hh"

#include <gz/utils/Environment.hh>

Expand Down Expand Up @@ -61,14 +63,40 @@ void setFindCallback(std::function<std::string(const std::string &)> _cb)
/////////////////////////////////////////////////
std::string findFile(
const std::string &_filename, bool _searchLocalPath, bool _useCallback)
{
sdf::Errors errors;
std::string result = findFile(errors, _filename, _searchLocalPath,
_useCallback, ParserConfig::GlobalConfig());
sdf::throwOrPrintErrors(errors);
return result;
}

/////////////////////////////////////////////////
std::string findFile(
sdf::Errors &_errors, const std::string &_filename, bool _searchLocalPath,
bool _useCallback)
{
return findFile(
_filename, _searchLocalPath, _useCallback, ParserConfig::GlobalConfig());
_errors, _filename, _searchLocalPath,
_useCallback, ParserConfig::GlobalConfig());
}

/////////////////////////////////////////////////
std::string findFile(const std::string &_filename, bool _searchLocalPath,
bool _useCallback, const ParserConfig &_config)
{
sdf::Errors errors;
std::string result = findFile(errors, _filename, _searchLocalPath,
_useCallback, _config);
sdf::throwOrPrintErrors(errors);
return result;
}


/////////////////////////////////////////////////
std::string findFile(sdf::Errors &_errors, const std::string &_filename,
bool _searchLocalPath, bool _useCallback,
const ParserConfig &_config)
{
// Check to see if _filename is URI. If so, resolve the URI path.
for (const auto &[uriScheme, paths] : _config.URIPathMap())
Expand Down Expand Up @@ -162,8 +190,9 @@ std::string findFile(const std::string &_filename, bool _searchLocalPath,
{
if (!_config.FindFileCallback())
{
sdferr << "Tried to use callback in sdf::findFile(), but the callback "
"is empty. Did you call sdf::setFindCallback()?\n";
_errors.push_back({sdf::ErrorCode::FILE_READ,
"Tried to use callback in sdf::findFile(), but the callback "
"is empty. Did you call sdf::setFindCallback()?"});
return std::string();
}
else
Expand Down Expand Up @@ -195,13 +224,29 @@ SDF::~SDF()
/////////////////////////////////////////////////
void SDF::PrintDescription()
{
this->Root()->PrintDescription("");
sdf::Errors errors;
this->PrintDescription(errors);
sdf::throwOrPrintErrors(errors);
}

/////////////////////////////////////////////////
void SDF::PrintDescription(sdf::Errors &_errors)
{
this->Root()->PrintDescription(_errors, "");
}

/////////////////////////////////////////////////
void SDF::PrintValues(const PrintConfig &_config)
{
this->Root()->PrintValues("", _config);
sdf::Errors errors;
this->PrintValues(errors, _config);
sdf::throwOrPrintErrors(errors);
}

/////////////////////////////////////////////////
void SDF::PrintValues(sdf::Errors &_errors, const PrintConfig &_config)
{
this->Root()->PrintValues(_errors, "", _config);
}

/////////////////////////////////////////////////
Expand Down Expand Up @@ -319,13 +364,22 @@ void SDF::PrintDoc()
/////////////////////////////////////////////////
void SDF::Write(const std::string &_filename)
{
std::string string = this->Root()->ToString("");
sdf::Errors errors;
this->Write(errors, _filename);
sdf::throwOrPrintErrors(errors);
}

/////////////////////////////////////////////////
void SDF::Write(sdf::Errors &_errors, const std::string &_filename)
{
std::string string = this->Root()->ToString(_errors, "");

std::ofstream out(_filename.c_str(), std::ios::out);

if (!out)
{
sdferr << "Unable to open file[" << _filename << "] for writing\n";
_errors.push_back({sdf::ErrorCode::FILE_READ,
"Unable to open file[" + _filename + "] for writing."});
return;
}
out << string;
Expand All @@ -334,6 +388,16 @@ void SDF::Write(const std::string &_filename)

/////////////////////////////////////////////////
std::string SDF::ToString(const PrintConfig &_config) const
{
sdf::Errors errors;
std::string result = this->ToString(errors, _config);
sdf::throwOrPrintErrors(errors);
return result;
}

/////////////////////////////////////////////////
std::string SDF::ToString(sdf::Errors &_errors,
const PrintConfig &_config) const
{
std::ostringstream stream;

Expand All @@ -343,7 +407,7 @@ std::string SDF::ToString(const PrintConfig &_config) const
stream << "<sdf version='" << SDF::Version() << "'>\n";
}

stream << this->Root()->ToString("", _config);
stream << this->Root()->ToString(_errors, "", _config);

if (this->Root()->GetName() != "sdf")
{
Expand All @@ -355,11 +419,21 @@ std::string SDF::ToString(const PrintConfig &_config) const

/////////////////////////////////////////////////
void SDF::SetFromString(const std::string &_sdfData)
{
sdf::Errors errors;
this->SetFromString(errors, _sdfData);
sdf::throwOrPrintErrors(errors);
}

/////////////////////////////////////////////////
void SDF::SetFromString(sdf::Errors &_errors,
const std::string &_sdfData)
{
sdf::initFile("root.sdf", this->Root());
if (!sdf::readString(_sdfData, this->Root()))
if (!sdf::readString(_sdfData, this->Root(), _errors))
{
sdferr << "Unable to parse sdf string[" << _sdfData << "]\n";
_errors.push_back({sdf::ErrorCode::PARSING_ERROR,
"Unable to parse sdf string[" + _sdfData + "]"});
}
}

Expand Down Expand Up @@ -429,19 +503,41 @@ void SDF::Version(const std::string &_version)

/////////////////////////////////////////////////
ElementPtr SDF::WrapInRoot(const ElementPtr &_sdf)
{
sdf::Errors errors;
ElementPtr result = SDF::WrapInRoot(errors, _sdf);
sdf::throwOrPrintErrors(errors);
return result;
}

/////////////////////////////////////////////////
ElementPtr SDF::WrapInRoot(sdf::Errors &_errors, const ElementPtr &_sdf)
{
ElementPtr root(new Element);
root->SetName("sdf");
std::stringstream v;
v << Version();
root->AddAttribute("version", "string", v.str(), true, "version");
root->AddAttribute("version", "string", v.str(), true, _errors, "version");
root->InsertElement(_sdf->Clone());
return root;
}

/////////////////////////////////////////////////
const std::string &SDF::EmbeddedSpec(
const std::string &_filename, const bool _quiet)
{
sdf::Errors errors;
const std::string &result = EmbeddedSpec(errors, _filename);
if (!_quiet)
{
sdf::throwOrPrintErrors(errors);
}
return result;
}

/////////////////////////////////////////////////
const std::string &SDF::EmbeddedSpec(
sdf::Errors &_errors, const std::string &_filename)
{
try
{
Expand All @@ -450,9 +546,9 @@ const std::string &SDF::EmbeddedSpec(
}
catch(const std::out_of_range &)
{
if (!_quiet)
sdferr << "Unable to find SDF filename[" << _filename << "] with "
<< "version " << SDF::Version() << "\n";
_errors.push_back({sdf::ErrorCode::FILE_READ,
"Unable to find SDF filename[" + _filename + "] with " +
"version " + SDF::Version()});
}

// An empty SDF string is returned if a query into the embeddedSdf map fails.
Expand Down
Loading
Loading