1
0
Fork 0
mirror of https://github.com/albfan/miraclecast.git synced 2025-02-12 19:51:54 +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:
David Herrmann 2014-02-11 11:32:38 +01:00
parent fe11d1d863
commit 0ce874d7ce
4 changed files with 244 additions and 6 deletions

View file

@ -35,17 +35,12 @@
#ifndef 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)
{
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_message_ _shl_cleanup_(cleanup_sd_bus_message)

View file

@ -43,6 +43,21 @@
#define _shl_weakref_(_val) __attribute__((__weakref__(#_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 */
#define SHL__STRINGIFY(_val) #_val
#define SHL_STRINGIFY(_val) SHL__STRINGIFY(_val)

View file

@ -321,3 +321,212 @@ char *shl_strjoin(const char *first, ...) {
*p = 0;
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);
}

View file

@ -17,6 +17,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "shl_macro.h"
/* strict atoi */
@ -93,4 +94,22 @@ static inline char *shl_startswith(const char *str, const char *prefix)
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 */