Add utility function for merging directory names with filenames, and fix issue in mj_addfileVFS where directory names without trailing filesystem separators won't append correctly.
PiperOrigin-RevId: 545450158 Change-Id: I550394f11ac2837d35f3d869f8718a119a9eac38
This commit is contained in:
committed by
Copybara-Service
parent
82e85e24e5
commit
95167fab2d
@@ -1046,7 +1046,8 @@ mj_addFileVFS
|
||||
|
||||
.. mujoco-include:: mj_addFileVFS
|
||||
|
||||
Add file to VFS, return 0: success, 1: full, 2: repeated name, -1: failed to load.
|
||||
Add file to VFS. The directory argument is optional and can be NULL or empty. Returns 0 on success, 1 when VFS is full,
|
||||
2 on name collision, or -1 when an internal error occurs.
|
||||
|
||||
.. _mj_makeEmptyFileVFS:
|
||||
|
||||
|
||||
@@ -22,6 +22,11 @@ this data structure. The common usage pattern is to first clear it with mj_defau
|
||||
mj_addFileVFS (which allocates memory buffers and loads the file content in memory), then call mj_loadXML or
|
||||
mj_loadModel, and then clear everything with mj_deleteVFS.
|
||||
|
||||
.. _mj_addFileVFS:
|
||||
|
||||
Add file to VFS. The directory argument is optional and can be NULL or empty. Returns 0 on success, 1 when VFS is full,
|
||||
2 on name collision, or -1 when an internal error occurs.
|
||||
|
||||
.. _Parseandcompile:
|
||||
|
||||
The key function here is :ref:`mj_loadXML`. It invokes the built-in parser and compiler, and either returns a pointer to
|
||||
|
||||
@@ -1177,6 +1177,51 @@ char* mju_strncpy(char *dst, const char *src, int n) {
|
||||
|
||||
|
||||
|
||||
// assemble full filename from directory and filename, return 0 on success
|
||||
int mju_makefullname(char* full, size_t nfull, const char* dir, const char* file) {
|
||||
int dirlen = (!dir) ? 0 : strlen(dir);
|
||||
int filelen = (!file) ? 0 : strlen(file);
|
||||
char* filepos = full + dirlen;
|
||||
|
||||
// missing filename
|
||||
if (!filelen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// no directory then just copy filename over
|
||||
if (!dirlen) {
|
||||
// make sure full has space
|
||||
if (filelen >= nfull) {
|
||||
return -1;
|
||||
}
|
||||
strcpy(full, file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make sure full has space
|
||||
if (dirlen + filelen >= nfull) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// dir doesn't end with a slash
|
||||
if (dir[dirlen - 1] != '\\' && dir[dirlen - 1] != '/') {
|
||||
// need extra space for forward slash
|
||||
if ((dirlen + filelen + 1) >= nfull) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// add forward slash
|
||||
*filepos++ = '/';
|
||||
}
|
||||
|
||||
// copy directory and file over
|
||||
memcpy(full, dir, sizeof(char) * dirlen);
|
||||
strcpy(filepos, file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// sigmoid function over 0<=x<=1 using quintic polynomial
|
||||
mjtNum mju_sigmoid(mjtNum x) {
|
||||
// fast return
|
||||
|
||||
@@ -49,7 +49,7 @@ MJAPI mjtNum mju_muscleDynamics(mjtNum ctrl, mjtNum act, const mjtNum prm[3]);
|
||||
// all 3 semi-axes of a geom
|
||||
MJAPI void mju_geomSemiAxes(const mjModel* m, int geom_id, mjtNum semiaxes[3]);
|
||||
|
||||
//------------------------------ misclellaneous ----------------------------------------------------
|
||||
//------------------------------ miscellaneous ----------------------------------------------------
|
||||
|
||||
// convert contact force to pyramid representation
|
||||
MJAPI void mju_encodePyramid(mjtNum* pyramid, const mjtNum* force,
|
||||
@@ -130,6 +130,10 @@ MJAPI mjtNum mju_Halton(int index, int base);
|
||||
// call strncpy, then set dst[n-1] = 0
|
||||
MJAPI char* mju_strncpy(char *dst, const char *src, int n);
|
||||
|
||||
// assemble full filename from directory and filename, return 0 on success
|
||||
MJAPI int mju_makefullname(char* full, size_t nfull,
|
||||
const char* dir, const char* file);
|
||||
|
||||
// sigmoid function over 0<=x<=1 using quintic polynomial
|
||||
MJAPI mjtNum mju_sigmoid(mjtNum x);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "engine/engine_vfs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "engine/engine_array_safety.h"
|
||||
#include "engine/engine_plugin.h"
|
||||
@@ -72,11 +71,8 @@ int mj_addFileVFS(mjVFS* vfs, const char* directory, const char* filename) {
|
||||
|
||||
// make full name
|
||||
char fullname[1000];
|
||||
if (directory) {
|
||||
mjSTRNCPY(fullname, directory);
|
||||
mjSTRNCAT(fullname, filename);
|
||||
} else {
|
||||
mjSTRNCPY(fullname, filename);
|
||||
if (mju_makefullname(fullname, sizeof(fullname), directory, filename)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// strip path
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
namespace mujoco {
|
||||
namespace {
|
||||
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::DoubleNear;
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::Ne;
|
||||
using ::testing::StrEq;
|
||||
|
||||
TEST_F(MujocoTest, PrintsMemoryWarning) {
|
||||
EXPECT_THAT(mju_warningText(mjWARN_CNSTRFULL, pow(2, 10)),
|
||||
@@ -127,6 +129,91 @@ TEST_F(MujocoTest, SmoothMuscleDynamics) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname) {
|
||||
char buffer[1000];
|
||||
constexpr char path[] = "engine/testdata/";
|
||||
constexpr char file[] = "file";
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
ASSERT_THAT(buffer, StrEq("engine/testdata/file"));
|
||||
EXPECT_THAT(n, 0);
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname2) {
|
||||
char buffer[1000];
|
||||
constexpr char path[] = "engine\\testdata\\";
|
||||
constexpr char file[] = "file";
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
ASSERT_THAT(buffer, StrEq("engine\\testdata\\file"));
|
||||
EXPECT_THAT(n, 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname_missingSlash) {
|
||||
char buffer[1000];
|
||||
constexpr char path[] = "engine/testdata";
|
||||
constexpr char file[] = "file";
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
ASSERT_THAT(buffer, StrEq("engine/testdata/file"));
|
||||
EXPECT_THAT(n, 0);
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname_withoutDir) {
|
||||
char buffer[1000];
|
||||
constexpr char *path = NULL;
|
||||
constexpr char file[] = "file";
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
ASSERT_THAT(buffer, StrEq("file"));
|
||||
EXPECT_THAT(n, 0);
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname_withoutDir2) {
|
||||
char buffer[1000];
|
||||
constexpr char path[] = "";
|
||||
constexpr char file[] = "file";
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
ASSERT_THAT(buffer, StrEq("file"));
|
||||
EXPECT_THAT(n, 0);
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname_error) {
|
||||
char buffer[1000];
|
||||
constexpr char path[] = "engine/testdata";
|
||||
constexpr char *file = NULL;
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
EXPECT_THAT(n, Ne(0));
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname_error2) {
|
||||
char buffer[1000];
|
||||
constexpr char path[] = "engine/testdata";
|
||||
constexpr char file[] = "";
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
EXPECT_THAT(n, Ne(0));
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname_error3) {
|
||||
char buffer[20];
|
||||
constexpr char path[] = "engine/testdata/";
|
||||
constexpr char file[] = "file";
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
EXPECT_THAT(n, Ne(0));
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname_error4) {
|
||||
char buffer[20];
|
||||
constexpr char path[] = "engine/testdata";
|
||||
constexpr char file[] = "file";
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
EXPECT_THAT(n, Ne(0));
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, mju_makefullname_error5) {
|
||||
char buffer[4];
|
||||
constexpr char path[] = "";
|
||||
constexpr char file[] = "file";
|
||||
int n = mju_makefullname(buffer, sizeof(buffer), path, file);
|
||||
EXPECT_THAT(n, Ne(0));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mujoco
|
||||
|
||||
Reference in New Issue
Block a user