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
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										209
									
								
								src/shl_util.c
									
										
									
									
									
								
							
							
						
						
									
										209
									
								
								src/shl_util.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue