diff --git a/libpkgconf/fragment.c b/libpkgconf/fragment.c index 7576db7..a65cde4 100644 --- a/libpkgconf/fragment.c +++ b/libpkgconf/fragment.c @@ -440,20 +440,8 @@ pkgconf_fragment_len(const pkgconf_fragment_t *frag, bool escape) return len; } -/* - * !doc - * - * .. c:function:: size_t pkgconf_fragment_render_len(const pkgconf_list_t *list) - * - * Calculates the required memory to store a `fragment list` when rendered as a string. - * - * :param pkgconf_list_t* list: The `fragment list` being rendered. - * :param bool escape: Whether or not to escape special shell characters. - * :return: the amount of bytes required to represent the `fragment list` when rendered - * :rtype: size_t - */ -size_t -pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape) +static size_t +fragment_render_len(const pkgconf_list_t *list, bool escape) { size_t out = 1; /* trailing nul */ pkgconf_node_t *node; @@ -467,21 +455,8 @@ pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape) return out; } -/* - * !doc - * - * .. c:function:: void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen) - * - * Renders a `fragment list` into a buffer. - * - * :param pkgconf_list_t* list: The `fragment list` being rendered. - * :param char* buf: The buffer to render the fragment list into. - * :param size_t buflen: The length of the buffer. - * :param bool escape: Whether or not to escape special shell characters. - * :return: nothing - */ -void -pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape) +static void +fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape) { pkgconf_node_t *node; char *bptr = buf; @@ -520,6 +495,52 @@ pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen *bptr = '\0'; } +static const pkgconf_fragment_render_ops_t default_render_ops = { + .render_len = fragment_render_len, + .render_buf = fragment_render_buf +}; + +/* + * !doc + * + * .. c:function:: size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops) + * + * Calculates the required memory to store a `fragment list` when rendered as a string. + * + * :param pkgconf_list_t* list: The `fragment list` being rendered. + * :param bool escape: Whether or not to escape special shell characters. + * :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``. + * :return: the amount of bytes required to represent the `fragment list` when rendered + * :rtype: size_t + */ +size_t +pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops) +{ + ops = ops != NULL ? ops : &default_render_ops; + return ops->render_len(list, escape); +} + +/* + * !doc + * + * .. c:function:: void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops) + * + * Renders a `fragment list` into a buffer. + * + * :param pkgconf_list_t* list: The `fragment list` being rendered. + * :param char* buf: The buffer to render the fragment list into. + * :param size_t buflen: The length of the buffer. + * :param bool escape: Whether or not to escape special shell characters. + * :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``. + * :return: nothing + */ +void +pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops) +{ + ops = ops != NULL ? ops : &default_render_ops; + return ops->render_buf(list, buf, buflen, escape); +} + /* * !doc * @@ -529,16 +550,17 @@ pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen * * :param pkgconf_list_t* list: The `fragment list` being rendered. * :param bool escape: Whether or not to escape special shell characters. + * :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``. * :return: An allocated string containing the rendered `fragment list`. * :rtype: char * */ char * -pkgconf_fragment_render(const pkgconf_list_t *list, bool escape) +pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops) { - size_t buflen = pkgconf_fragment_render_len(list, escape); + size_t buflen = pkgconf_fragment_render_len(list, escape, ops); char *buf = calloc(1, buflen); - pkgconf_fragment_render_buf(list, buf, buflen, escape); + pkgconf_fragment_render_buf(list, buf, buflen, escape, ops); return buf; } diff --git a/libpkgconf/libpkgconf.h b/libpkgconf/libpkgconf.h index 85d6ae2..6357450 100644 --- a/libpkgconf/libpkgconf.h +++ b/libpkgconf/libpkgconf.h @@ -275,6 +275,11 @@ PKGCONF_API int pkgconf_argv_split(const char *src, int *argc, char ***argv); PKGCONF_API void pkgconf_argv_free(char **argv); /* fragment.c */ +typedef struct pkgconf_fragment_render_ops_ { + size_t (*render_len)(const pkgconf_list_t *list, bool escape); + void (*render_buf)(const pkgconf_list_t *list, char *buf, size_t len, bool escape); +} pkgconf_fragment_render_ops_t; + typedef bool (*pkgconf_fragment_filter_func_t)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data); PKGCONF_API bool pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value); PKGCONF_API void pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string); @@ -282,9 +287,9 @@ PKGCONF_API void pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_l PKGCONF_API void pkgconf_fragment_delete(pkgconf_list_t *list, pkgconf_fragment_t *node); PKGCONF_API void pkgconf_fragment_free(pkgconf_list_t *list); PKGCONF_API void pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func, void *data); -PKGCONF_API size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape); -PKGCONF_API void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t len, bool escape); -PKGCONF_API char *pkgconf_fragment_render(const pkgconf_list_t *list, bool escape); +PKGCONF_API size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops); +PKGCONF_API void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t len, bool escape, const pkgconf_fragment_render_ops_t *ops); +PKGCONF_API char *pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops); PKGCONF_API bool pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag); /* fileio.c */ diff --git a/main.c b/main.c index ccf7ffb..0494740 100644 --- a/main.c +++ b/main.c @@ -65,6 +65,7 @@ #define PKG_EXISTS (((uint64_t) 1) << 40) static pkgconf_client_t pkg_client; +static const pkgconf_fragment_render_ops_t *want_render_ops = NULL; static uint64_t want_flags; static int maximum_traverse_depth = 2000; @@ -393,7 +394,7 @@ apply_env_var(const char *prefix, pkgconf_client_t *client, pkgconf_pkg_t *world if (filtered_list.head == NULL) goto out; - render_buf = pkgconf_fragment_render(&filtered_list, true); + render_buf = pkgconf_fragment_render(&filtered_list, true, want_render_ops); printf("%s='%s'\n", prefix, render_buf); free(render_buf); @@ -443,7 +444,7 @@ apply_cflags(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int m if (filtered_list.head == NULL) goto out; - render_buf = pkgconf_fragment_render(&filtered_list, true); + render_buf = pkgconf_fragment_render(&filtered_list, true, want_render_ops); printf("%s", render_buf); free(render_buf); @@ -472,7 +473,7 @@ apply_libs(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int max if (filtered_list.head == NULL) goto out; - render_buf = pkgconf_fragment_render(&filtered_list, true); + render_buf = pkgconf_fragment_render(&filtered_list, true, want_render_ops); printf("%s", render_buf); free(render_buf);