drgn/libdrgn/path.h
Omar Sandoval 87b7292aa5 Relicense drgn from GPLv3+ to LGPLv2.1+
drgn is currently licensed as GPLv3+. Part of the long term vision for
drgn is that other projects can use it as a library providing
programmatic interfaces for debugger functionality. A more permissive
license is better suited to this goal. We decided on LGPLv2.1+ as a good
balance between software freedom and permissiveness.

All contributors not employed by Meta were contacted via email and
consented to the license change. The only exception was the author of
commit c4fbf7e589 ("libdrgn: fix for compilation error"), who did not
respond. That commit reverted a single line of code to one originally
written by me in commit 640b1c011d ("libdrgn: embed DWARF index in
DWARF info cache").

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-01 17:05:16 -07:00

110 lines
2.9 KiB
C

// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* @file
*
* Paths.
*
* See @ref Paths.
*/
#ifndef DRGN_PATH_H
#define DRGN_PATH_H
#include <elfutils/libdw.h>
#include <stdbool.h>
#include <stddef.h>
#include "nstring.h" // IWYU pragma: export
/**
* @ingroup Internals
*
* @defgroup Paths Paths
*
* Utilities for working with paths.
*
* @{
*/
/**
* Path component iterator.
*
* This iterates over the components of a file path, joining multiple components
* and normalizing the result. Normalization:
*
* - Collapses redundant "/" separators.
* - Removes "." components.
* - Removes ".." components when possible.
*
* Components are emitted in @b reverse. So, "a/b/c" is emitted in the order
* "c", "b", "a" (this allows the implementation to operate in O(n) time and
* O(1) space).
*
* Absolute paths have an implicit empty component, so "/a/b" is emitted as "b",
* "a", "".
*
* Relative paths are emitted relative to a hypothetical current directory. A
* path referring to the current directory (e.g., "." or "a/..") does not emit
* any components.
*
* ".." components above the current directory are included, so "a/b/../../../c"
* is emitted as "c", "..". However, ".." components above an absolute path are
* not meaningful, so "/a/b/../../../c" is emitted as "c", "".
*
* A empty path does not emit any components.
*/
struct path_iterator {
/**
* Array of input components.
*
* The input components are treated as if they were joined with a "/".
* @ref nstring::str and @ref nstring::len should be initialized for
* each component. The latter will be modified as the path is iterated.
*/
struct nstring *components;
/** Number of components in @ref path_iterator::components. */
size_t num_components;
/**
* Current number of ".." components.
*
* Initialize this to 0.
*/
size_t dot_dot;
};
/**
* Get the next component from a @ref path_iterator.
*
* Components are emitted in reverse. This will never emit a "." component. It
* will emit an empty ("") component only for an absolute path. It may emit ".."
* components if there are any that go above the current directory.
*
* @param[in] it Iterator.
* @param[out] component_ret Returned component.
* @param[out] component_len_ret Length of @c component.
* @return @c true if we returned a componenent, @c false if there were no more
* components.
*/
bool path_iterator_next(struct path_iterator *it, const char **component_ret,
size_t *component_len_ret);
/**
* Return whether the path @p haystack ends with the path @p needle once both
* are normalized.
*
* The unit of comparison is a path component, not a character. Thus, "ab/cd/ef"
* ends with "cd/ef", but not "d/ef".
*
* @sa path_iterator
*/
bool path_ends_with(struct path_iterator *haystack,
struct path_iterator *needle);
bool die_matches_filename(Dwarf_Die *die, const char *filename);
/** @} */
#endif /* DRGN_PATH_H */