include/strutils: add strdup_between_structs()

* improve strdup_to_offset() readability

* add strdup_between_offsets() and strdup_between_structs() to have
  better support for use-cases when we copy structs

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2019-10-23 12:28:09 +02:00
parent 779e3c97aa
commit 787226dc28
1 changed files with 36 additions and 4 deletions

View File

@ -124,29 +124,61 @@ nothing:
return NULL; return NULL;
} }
/* Copy string @str to struct @stru to member addressed by @offset */
static inline int strdup_to_offset(void *stru, size_t offset, const char *str) static inline int strdup_to_offset(void *stru, size_t offset, const char *str)
{ {
char *n = NULL;
char **o; char **o;
char *p = NULL;
if (!stru) if (!stru)
return -EINVAL; return -EINVAL;
o = (char **) ((char *) stru + offset); o = (char **) ((char *) stru + offset);
if (str) { if (str) {
n = strdup(str); p = strdup(str);
if (!n) if (!p)
return -ENOMEM; return -ENOMEM;
} }
free(*o); free(*o);
*o = n; *o = p;
return 0; return 0;
} }
/* Copy string __str to struct member _m of the struct _s */
#define strdup_to_struct_member(_s, _m, _str) \ #define strdup_to_struct_member(_s, _m, _str) \
strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str) strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str)
/* Copy string addressed by @offset between two structs */
static inline int strdup_between_offsets(void *stru_dst, void *stru_src, size_t offset)
{
char **src;
char **dst;
char *p = NULL;
if (!stru_src || !stru_dst)
return -EINVAL;
src = (char **) ((char *) stru_src + offset);
dst = (char **) ((char *) stru_dst + offset);
if (*src) {
p = strdup(*src);
if (!p)
return -ENOMEM;
}
free(*dst);
*dst = p;
return 0;
}
/* Copy string addressed by struct member between two instances of the same
* struct type */
#define strdup_between_structs(_dst, _src, _m) \
strdup_between_offsets((void *)_dst, (void *)_src, offsetof(__typeof__(*(_src)), _m))
extern char *xstrmode(mode_t mode, char *str); extern char *xstrmode(mode_t mode, char *str);
/* Options for size_to_human_string() */ /* Options for size_to_human_string() */