mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-12 19:20:27 +09:00
tokens: Add low-level function to exlclude, prepend lists
These functions are needed for openssh -,^ features. Signed-off-by: Norbert Pocs <npocs@redhat.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
committed by
Jakub Jelen
parent
23cebfadea
commit
61218df5d5
@@ -49,6 +49,11 @@ char *ssh_remove_duplicates(const char *list);
|
|||||||
|
|
||||||
char *ssh_append_without_duplicates(const char *list,
|
char *ssh_append_without_duplicates(const char *list,
|
||||||
const char *appended_list);
|
const char *appended_list);
|
||||||
|
char *ssh_prefix_without_duplicates(const char *list,
|
||||||
|
const char *prefixed_list);
|
||||||
|
char *ssh_remove_all_matching(const char *list,
|
||||||
|
const char *remove_list);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
145
src/token.c
145
src/token.c
@@ -376,6 +376,7 @@ char *ssh_append_without_duplicates(const char *list,
|
|||||||
{
|
{
|
||||||
size_t concat_len = 0;
|
size_t concat_len = 0;
|
||||||
char *ret = NULL, *concat = NULL;
|
char *ret = NULL, *concat = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
if (list != NULL) {
|
if (list != NULL) {
|
||||||
concat_len = strlen(list);
|
concat_len = strlen(list);
|
||||||
@@ -396,12 +397,144 @@ char *ssh_append_without_duplicates(const char *list,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list != NULL) {
|
rc = snprintf(concat, concat_len, "%s%s%s",
|
||||||
strcpy(concat, list);
|
list == NULL ? "" : list,
|
||||||
strncat(concat, ",", concat_len - strlen(concat) - 1);
|
list == NULL ? "" : ",",
|
||||||
}
|
appended_list == NULL ? "" : appended_list);
|
||||||
if (appended_list != NULL) {
|
if (rc < 0) {
|
||||||
strncat(concat, appended_list, concat_len - strlen(concat) - 1);
|
SAFE_FREE(concat);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ssh_remove_duplicates(concat);
|
||||||
|
|
||||||
|
SAFE_FREE(concat);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Given two strings containing lists of tokens, return a newly
|
||||||
|
* allocated string containing the elements of the first list without the
|
||||||
|
* elements of the second list. The order of the elements will be preserved.
|
||||||
|
*
|
||||||
|
* @param[in] list The first list
|
||||||
|
* @param[in] remove_list The list to be removed
|
||||||
|
*
|
||||||
|
* @return A newly allocated copy list containing elements of the
|
||||||
|
* list without the elements of remove_list; NULL in case of error.
|
||||||
|
*/
|
||||||
|
char *ssh_remove_all_matching(const char *list,
|
||||||
|
const char *remove_list)
|
||||||
|
{
|
||||||
|
struct ssh_tokens_st *l_tok = NULL, *r_tok = NULL;
|
||||||
|
int i, j, cmp;
|
||||||
|
char *ret = NULL;
|
||||||
|
size_t len, pos = 0;
|
||||||
|
bool exclude;
|
||||||
|
|
||||||
|
if ((list == NULL)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (remove_list == NULL) {
|
||||||
|
return strdup (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
l_tok = ssh_tokenize(list, ',');
|
||||||
|
if (l_tok == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
r_tok = ssh_tokenize(remove_list, ',');
|
||||||
|
if (r_tok == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = calloc(1, strlen(list) + 1);
|
||||||
|
if (ret == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; l_tok->tokens[i]; i++) {
|
||||||
|
exclude = false;
|
||||||
|
for (j = 0; r_tok->tokens[j]; j++) {
|
||||||
|
cmp = strcmp(l_tok->tokens[i], r_tok->tokens[j]);
|
||||||
|
if (cmp == 0) {
|
||||||
|
exclude = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exclude == false) {
|
||||||
|
if (pos != 0) {
|
||||||
|
ret[pos] = ',';
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(l_tok->tokens[i]);
|
||||||
|
memcpy(&ret[pos], l_tok->tokens[i], len);
|
||||||
|
pos += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret[0] == '\0') {
|
||||||
|
SAFE_FREE(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
ssh_tokens_free(l_tok);
|
||||||
|
ssh_tokens_free(r_tok);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Given two strings containing lists of tokens, return a newly
|
||||||
|
* allocated string containing all the elements of the first list prefixed at
|
||||||
|
* the beginning of the second list, without duplicates.
|
||||||
|
*
|
||||||
|
* @param[in] list The first list
|
||||||
|
* @param[in] prefixed_list The list to use as a prefix
|
||||||
|
*
|
||||||
|
* @return A newly allocated list containing all the elements
|
||||||
|
* of the list prefixed with the elements of the prefixed_list without
|
||||||
|
* duplicates; NULL in case of error.
|
||||||
|
*/
|
||||||
|
char *ssh_prefix_without_duplicates(const char *list,
|
||||||
|
const char *prefixed_list)
|
||||||
|
{
|
||||||
|
size_t concat_len = 0;
|
||||||
|
char *ret = NULL, *concat = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (list != NULL) {
|
||||||
|
concat_len = strlen(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefixed_list != NULL) {
|
||||||
|
concat_len += strlen(prefixed_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (concat_len == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add room for ending '\0' and for middle ',' */
|
||||||
|
concat_len += 2;
|
||||||
|
concat = calloc(concat_len, 1);
|
||||||
|
if (concat == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = snprintf(concat, concat_len, "%s%s%s",
|
||||||
|
prefixed_list == NULL ? "" : prefixed_list,
|
||||||
|
prefixed_list == NULL ? "" : ",",
|
||||||
|
list == NULL ? "" : list);
|
||||||
|
if (rc < 0) {
|
||||||
|
SAFE_FREE(concat);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ssh_remove_duplicates(concat);
|
ret = ssh_remove_duplicates(concat);
|
||||||
|
|||||||
Reference in New Issue
Block a user