mirror of
https://github.com/albfan/miraclecast.git
synced 2025-03-09 23:38:56 +00:00
shl: update macro/util helpers
Add few small helpers to shl-macro/util. This includes some _cleanup_ helpers and the qstr suite for quoted/escaped strings. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
parent
fe11d1d863
commit
0ce874d7ce
4 changed files with 244 additions and 6 deletions
|
@ -35,17 +35,12 @@
|
||||||
#ifndef MIRACLE_H
|
#ifndef MIRACLE_H
|
||||||
#define MIRACLE_H
|
#define MIRACLE_H
|
||||||
|
|
||||||
static inline void cleanup_free(void *p)
|
|
||||||
{
|
|
||||||
free(*(void**)p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void cleanup_sd_bus_message(sd_bus_message **ptr)
|
static inline void cleanup_sd_bus_message(sd_bus_message **ptr)
|
||||||
{
|
{
|
||||||
sd_bus_message_unref(*ptr);
|
sd_bus_message_unref(*ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _cleanup_free_ _shl_cleanup_(cleanup_free)
|
#define _cleanup_free_ _shl_cleanup_free_
|
||||||
#define _cleanup_sd_bus_error_ _shl_cleanup_(sd_bus_error_free)
|
#define _cleanup_sd_bus_error_ _shl_cleanup_(sd_bus_error_free)
|
||||||
#define _cleanup_sd_bus_message_ _shl_cleanup_(cleanup_sd_bus_message)
|
#define _cleanup_sd_bus_message_ _shl_cleanup_(cleanup_sd_bus_message)
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,21 @@
|
||||||
#define _shl_weakref_(_val) __attribute__((__weakref__(#_val)))
|
#define _shl_weakref_(_val) __attribute__((__weakref__(#_val)))
|
||||||
#define _shl_cleanup_(_val) __attribute__((__cleanup__(_val)))
|
#define _shl_cleanup_(_val) __attribute__((__cleanup__(_val)))
|
||||||
|
|
||||||
|
static inline void shl_freep(void *p)
|
||||||
|
{
|
||||||
|
free(*(void**)p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _shl_cleanup_free_ _shl_cleanup_(shl_freep)
|
||||||
|
|
||||||
|
static inline void shl_set_errno(int *r)
|
||||||
|
{
|
||||||
|
errno = *r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SHL_PROTECT_ERRNO \
|
||||||
|
_shl_cleanup_(shl_set_errno) _shl_unused_ int shl__errno = errno
|
||||||
|
|
||||||
/* 2-level stringify helper */
|
/* 2-level stringify helper */
|
||||||
#define SHL__STRINGIFY(_val) #_val
|
#define SHL__STRINGIFY(_val) #_val
|
||||||
#define SHL_STRINGIFY(_val) SHL__STRINGIFY(_val)
|
#define SHL_STRINGIFY(_val) SHL__STRINGIFY(_val)
|
||||||
|
|
209
src/shl_util.c
209
src/shl_util.c
|
@ -321,3 +321,212 @@ char *shl_strjoin(const char *first, ...) {
|
||||||
*p = 0;
|
*p = 0;
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* strv
|
||||||
|
*/
|
||||||
|
|
||||||
|
void shl_strv_free(char **strv)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!strv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; strv[i]; ++i)
|
||||||
|
free(strv[i]);
|
||||||
|
|
||||||
|
free(strv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quoted Strings
|
||||||
|
*/
|
||||||
|
|
||||||
|
char shl_qstr_unescape_char(char c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case 'a':
|
||||||
|
return '\a';
|
||||||
|
case 'b':
|
||||||
|
return '\b';
|
||||||
|
case 'f':
|
||||||
|
return '\f';
|
||||||
|
case 'n':
|
||||||
|
return '\n';
|
||||||
|
case 'r':
|
||||||
|
return '\r';
|
||||||
|
case 't':
|
||||||
|
return '\t';
|
||||||
|
case 'v':
|
||||||
|
return '\v';
|
||||||
|
case '"':
|
||||||
|
return '"';
|
||||||
|
case '\'':
|
||||||
|
return '\'';
|
||||||
|
case '\\':
|
||||||
|
return '\\';
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shl_qstr_decode_n(char *str, size_t length)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
bool escaped;
|
||||||
|
char *pos, c, quoted;
|
||||||
|
|
||||||
|
quoted = 0;
|
||||||
|
escaped = false;
|
||||||
|
pos = str;
|
||||||
|
|
||||||
|
for (i = 0; i < length; ++i) {
|
||||||
|
if (escaped) {
|
||||||
|
escaped = false;
|
||||||
|
c = shl_qstr_unescape_char(str[i]);
|
||||||
|
if (c) {
|
||||||
|
*pos++ = c;
|
||||||
|
} else if (!str[i]) {
|
||||||
|
/* ignore binary 0 */
|
||||||
|
} else {
|
||||||
|
*pos++ = '\\';
|
||||||
|
*pos++ = str[i];
|
||||||
|
}
|
||||||
|
} else if (quoted) {
|
||||||
|
if (str[i] == '\\')
|
||||||
|
escaped = true;
|
||||||
|
else if (str[i] == '"' && quoted == '"')
|
||||||
|
quoted = 0;
|
||||||
|
else if (str[i] == '\'' && quoted == '\'')
|
||||||
|
quoted = 0;
|
||||||
|
else if (!str[i])
|
||||||
|
/* ignore binary 0 */ ;
|
||||||
|
else
|
||||||
|
*pos++ = str[i];
|
||||||
|
} else {
|
||||||
|
if (str[i] == '\\')
|
||||||
|
escaped = true;
|
||||||
|
else if (str[i] == '"' || str[i] == '\'')
|
||||||
|
quoted = str[i];
|
||||||
|
else if (!str[i])
|
||||||
|
/* ignore binary 0 */ ;
|
||||||
|
else
|
||||||
|
*pos++ = str[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (escaped)
|
||||||
|
*pos++ = '\\';
|
||||||
|
|
||||||
|
*pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int shl__qstr_push(char ***strv,
|
||||||
|
size_t *strv_num,
|
||||||
|
size_t *strv_size,
|
||||||
|
const char *str,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
size_t strv_need;
|
||||||
|
char *ns;
|
||||||
|
|
||||||
|
strv_need = (*strv_num + 2) * sizeof(**strv);
|
||||||
|
if (!shl_greedy_realloc0((void**)strv, strv_size, strv_need))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ns = malloc(len + 1);
|
||||||
|
memcpy(ns, str, len);
|
||||||
|
ns[len] = 0;
|
||||||
|
|
||||||
|
shl_qstr_decode_n(ns, len);
|
||||||
|
(*strv)[*strv_num] = ns;
|
||||||
|
*strv_num += 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int shl_qstr_tokenize_n(const char *str, size_t length, char ***out)
|
||||||
|
{
|
||||||
|
char **strv, quoted;
|
||||||
|
size_t i, strv_num, strv_size;
|
||||||
|
const char *pos;
|
||||||
|
bool escaped;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!out)
|
||||||
|
return -EINVAL;
|
||||||
|
if (!str)
|
||||||
|
str = "";
|
||||||
|
|
||||||
|
strv_num = 0;
|
||||||
|
strv_size = sizeof(*strv);
|
||||||
|
strv = malloc(strv_size);
|
||||||
|
if (!strv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
quoted = 0;
|
||||||
|
escaped = false;
|
||||||
|
pos = str;
|
||||||
|
|
||||||
|
for (i = 0; i < length; ++i) {
|
||||||
|
if (escaped) {
|
||||||
|
escaped = false;
|
||||||
|
} else if (str[i] == '\\') {
|
||||||
|
escaped = true;
|
||||||
|
} else if (quoted) {
|
||||||
|
if (str[i] == '"' && quoted == '"')
|
||||||
|
quoted = 0;
|
||||||
|
else if (str[i] == '\'' && quoted == '\'')
|
||||||
|
quoted = 0;
|
||||||
|
} else if (str[i] == '"' && quoted == '"') {
|
||||||
|
quoted = '"';
|
||||||
|
} else if (str[i] == '\'' && quoted == '\'') {
|
||||||
|
quoted = '\'';
|
||||||
|
} else if (str[i] == ' ') {
|
||||||
|
/* ignore multiple separators */
|
||||||
|
if (pos != &str[i]) {
|
||||||
|
r = shl__qstr_push(&strv,
|
||||||
|
&strv_num,
|
||||||
|
&strv_size,
|
||||||
|
pos,
|
||||||
|
&str[i] - pos);
|
||||||
|
if (r < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = &str[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy trailing token if available */
|
||||||
|
if (i > 0 && pos != &str[i]) {
|
||||||
|
r = shl__qstr_push(&strv,
|
||||||
|
&strv_num,
|
||||||
|
&strv_size,
|
||||||
|
pos,
|
||||||
|
&str[i] - pos);
|
||||||
|
if (r < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)strv_num < (ssize_t)strv_num) {
|
||||||
|
r = -ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
strv[strv_num] = NULL;
|
||||||
|
*out = strv;
|
||||||
|
return strv_num;
|
||||||
|
|
||||||
|
error:
|
||||||
|
for (i = 0; i < strv_num; ++i)
|
||||||
|
free(strv[i]);
|
||||||
|
free(strv);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int shl_qstr_tokenize(const char *str, char ***out)
|
||||||
|
{
|
||||||
|
return shl_qstr_tokenize_n(str, str ? strlen(str) : 0, out);
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "shl_macro.h"
|
||||||
|
|
||||||
/* strict atoi */
|
/* strict atoi */
|
||||||
|
|
||||||
|
@ -93,4 +94,22 @@ static inline char *shl_startswith(const char *str, const char *prefix)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* strv */
|
||||||
|
|
||||||
|
void shl_strv_free(char **strv);
|
||||||
|
|
||||||
|
static inline void shl_strv_freep(char ***strv)
|
||||||
|
{
|
||||||
|
shl_strv_free(*strv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _shl_cleanup_strv_ _shl_cleanup_(shl_strv_freep)
|
||||||
|
|
||||||
|
/* quoted strings */
|
||||||
|
|
||||||
|
char shl_qstr_unescape_char(char c);
|
||||||
|
void shl_qstr_decode_n(char *str, size_t length);
|
||||||
|
int shl_qstr_tokenize_n(const char *str, size_t length, char ***out);
|
||||||
|
int shl_qstr_tokenize(const char *str, char ***out);
|
||||||
|
|
||||||
#endif /* SHL_UTIL_H */
|
#endif /* SHL_UTIL_H */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue