[libcamera-devel] [PATCH v4 1/6] libcamera: utils: Add a C++ dirname implementation
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Sat Feb 22 11:27:18 CET 2020
Hi Kieran,
Thank you for the patch.
On Fri, Feb 21, 2020 at 04:31:25PM +0000, Kieran Bingham wrote:
> Provide a std::string based implementation which conforms to the
> behaviour of the dirname() fucntion defined by POSIX.
>
> Tests are added to cover expected corner cases of the implementation.
>
> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> ---
> src/libcamera/include/utils.h | 1 +
> src/libcamera/utils.cpp | 48 +++++++++++++++++++++++++++++++
> test/utils.cpp | 54 +++++++++++++++++++++++++++++++++++
> 3 files changed, 103 insertions(+)
>
> diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h
> index 080ea6614de0..940597760ee2 100644
> --- a/src/libcamera/include/utils.h
> +++ b/src/libcamera/include/utils.h
> @@ -33,6 +33,7 @@ namespace utils {
> const char *basename(const char *path);
>
> char *secure_getenv(const char *name);
> +std::string dirname(const std::string &path);
>
> template<class InputIt1, class InputIt2>
> unsigned int set_overlap(InputIt1 first1, InputIt1 last1,
> diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp
> index 453e3b3b5995..f566e88cec5b 100644
> --- a/src/libcamera/utils.cpp
> +++ b/src/libcamera/utils.cpp
> @@ -70,6 +70,54 @@ char *secure_getenv(const char *name)
> #endif
> }
>
> +/**
> + * \brief Identify the dirname portion of a path
> + * \param[in] path The full path to parse
> + *
> + * This function conforms with the behaviour of the %dirname() function as
> + * defined by POSIX.
> + *
> + * \return A string of the directory component of the path
> + */
> +std::string dirname(const std::string &path)
> +{
> + if (path.empty())
> + return ".";
> +
> + /*
> + * Skip all trailing slashes. If the path is only made of slashes,
> + * return "/".
> + */
> + size_t pos = path.size() - 1;
> + while (path[pos] == '/') {
> + if (!pos)
> + return "/";
> + pos--;
> + }
> +
> + /*
> + * Find the previous slash. If the path contains no non-trailing slash,
> + * return ".".
> + */
> + while (path[pos] != '/') {
> + if (!pos)
> + return ".";
> + pos--;
> + }
> +
> + /*
> + * Return the directory name up to (but not including) any trailing
> + * slash. If this would result in an empty string, return "/".
> + */
> + while (path[pos] == '/') {
> + if (!pos)
> + return "/";
> + pos--;
> + }
> +
> + return path.substr(0, pos + 1);
> +}
> +
> /**
> * \fn libcamera::utils::set_overlap(InputIt1 first1, InputIt1 last1,
> * InputIt2 first2, InputIt2 last2)
> diff --git a/test/utils.cpp b/test/utils.cpp
> index db1fbdde847d..e4184e39ce32 100644
> --- a/test/utils.cpp
> +++ b/test/utils.cpp
> @@ -19,6 +19,56 @@ using namespace libcamera;
> class UtilsTest : public Test
> {
> protected:
> + int testDirname()
> + {
> + std::vector<std::string> paths = {
You can make this const.
> + "",
> + "///",
> + "/bin",
> + "/usr/bin",
> + "//etc////",
> + "//tmp//d//",
> + "current_file",
> + "./current_file",
> + "./current_dir/",
> + "current_dir/",
> + };
> +
> + std::vector<std::string> expected = {
And this too.
> + ".",
> + "/",
> + "/",
> + "/usr",
> + "/",
> + "//tmp",
> + ".",
> + ".",
> + ".",
> + ".",
> + };
I was going to propose using the libc-provided dirname() function to
check for correctness instead of hardcoding the results, but that would
create a dependency on the libc implementation conforming with POSIX,
which may not be guaranteed on non-glibc platforms. Let's thus keep it
as-is.
> +
> + std::vector<std::string> results;
> +
> + for (const auto &path : paths)
> + results.push_back(utils::dirname(path));
> +
> + if (results != expected) {
> + cerr << "utils::dirname() tests failed" << endl;
> +
> + cerr << "expected: " << endl;
> + for (const auto &path : expected)
> + cerr << " " << path << endl;
"\t" instead of " " for additional clarity ?
> +
> + cerr << "results: " << endl;
> + for (const auto &path : results)
> + cerr << " " << path << endl;
Here too ?
> +
> + return TestFail;
> + }
> +
> + return 0;
return TestPass;
> + }
> +
> int run()
> {
> /* utils::hex() test. */
> @@ -71,6 +121,10 @@ protected:
> return TestFail;
> }
>
> + /* utils::dirname() tests. */
> + if (testDirname())
if (testDirname() != TestPass)
?
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> + return TestFail;
> +
> return TestPass;
> }
> };
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list