diff --git a/src/ctl/CMakeLists.txt b/src/ctl/CMakeLists.txt index 8b0e469..0219f19 100644 --- a/src/ctl/CMakeLists.txt +++ b/src/ctl/CMakeLists.txt @@ -53,7 +53,8 @@ set(miracle-wfdctl_SRCS ctl-cli.c wfd-session.c wfd-out-session.c wfdctl.c - wfd.c) + wfd.c + wfd-arg.c) include_directories(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src diff --git a/src/ctl/wfd-arg.c b/src/ctl/wfd-arg.c new file mode 100644 index 0000000..d0f7061 --- /dev/null +++ b/src/ctl/wfd-arg.c @@ -0,0 +1,61 @@ +/* + * MiracleCast - Wifi-Display/Miracast Implementation + * + * Copyright (c) 2013-2014 David Herrmann + * + * MiracleCast is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * MiracleCast is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MiracleCast; If not, see . + */ +#include +#include +#include +#include "wfd-arg.h" + +int wfd_arg_list_new(struct wfd_arg_list **out) +{ + assert(out); + + struct wfd_arg_list *l = calloc(1, sizeof(struct wfd_arg_list)); + if(!l) { + return -ENOMEM; + } + + l->dynamic = true; + + *out = l; + + return 0; +} + +void wfd_arg_list_clear(struct wfd_arg_list *l) +{ + int i; + struct wfd_arg *arg; + + if(!l || !l->dynamic) { + return; + } + + arg = l->discrete ? l->argv : l->args; + for(i = 0; i < l->len; i ++) { + if((WFD_ARG_STR == arg->type || WFD_ARG_PTR == arg->type) + && arg->ptr && arg->free) { + (*arg->free)(arg->ptr); + } + } + + if(l->discrete) { + free(l->argv); + } +} + diff --git a/src/ctl/wfd-arg.h b/src/ctl/wfd-arg.h new file mode 100644 index 0000000..189e0ef --- /dev/null +++ b/src/ctl/wfd-arg.h @@ -0,0 +1,210 @@ +/* + * MiracleCast - Wifi-Display/Miracast Implementation + * + * Copyright (c) 2013-2014 David Herrmann + * + * MiracleCast is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * MiracleCast is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MiracleCast; If not, see . + */ +#include +#include +#include +#include "shl_macro.h" + +#ifndef CTL_ARG_H +#define CTL_ARG_H + +#define wfd_arg_i8(v) { .type = WFD_ARG_I8, .i8 = (v) } +#define wfd_arg_u8(v) { .type = WFD_ARG_U8, .u8 = (v) } +#define wfd_arg_i16(v) { .type = WFD_ARG_I16, .i16 = (v) } +#define wfd_arg_u16(v) { .type = WFD_ARG_U16, .u16 = (v) } +#define wfd_arg_i32(v) { .type = WFD_ARG_I32, .i32 = (v) } +#define wfd_arg_u32(v) { .type = WFD_ARG_U32, .u32 = (v) } +#define wfd_arg_i64(v) { .type = WFD_ARG_I64, .i64 = (v) } +#define wfd_arg_u64(v) { .type = WFD_ARG_U64, .u64 = (v) } +#define wfd_arg_cstr(v) { .type = WFD_ARG_CSTR, .ptr = (v) } +#define wfd_arg_cptr(v) { .type = WFD_ARG_CPTR, .ptr = (v) } +#define wfd_arg_dict(_k, _v) { \ + .type = WFD_ARG_DICT, \ + .k = (struct wfd_arg[]){_k}, \ + .v = (struct wfd_arg[]){_v} \ +} + +#define wfd_arg_type_id(_t) _Generic((_t), \ + int8_t: WFD_ARG_I8, \ + uint8_t: WFD_ARG_U8, \ + int16_t: WFD_ARG_I16, \ + uint16_t: WFD_ARG_U16, \ + int32_t: WFD_ARG_I32, \ + uint32_t: WFD_ARG_U32, \ + int64_t: WFD_ARG_I64, \ + uint64_t: WFD_ARG_U64, \ + const char *: WFD_ARG_CSTR, \ + char *: WFD_ARG_STR, \ + const void *: WFD_ARG_CPTR, \ + default: WFD_ARG_PTR) + +#define wfd_arg_list(...) { \ + .argv = (struct wfd_arg[]) { \ + __VA_ARGS__ \ + }, \ + .discrete = true, \ + .dynamic = false, \ + .len = (sizeof((struct wfd_arg[]){ __VA_ARGS__ })/sizeof(struct wfd_arg)) \ +} + +#define wfd_arg_get(_a, _v) ({ \ + *(_v) = _Generic((*_v), \ + int8_t: wfd_arg_get_i8, \ + uint8_t: wfd_arg_get_u8, \ + int16_t: wfd_arg_get_i16, \ + uint16_t: wfd_arg_get_u16, \ + int32_t: wfd_arg_get_i32, \ + uint32_t: wfd_arg_get_u32, \ + int64_t: wfd_arg_get_i64, \ + uint64_t: wfd_arg_get_u64, \ + char *: wfd_arg_get_str, \ + const char *: wfd_arg_get_cstr, \ + const void *: wfd_arg_get_cptr, \ + default: wfd_arg_get_ptr \ + )(_a); \ +}) + +#define wfd_arg_getkv(_a, _k, _v) ({ \ + assert(_a); \ + assert(WFD_ARG_DICT == (_a)->type); \ + wfd_arg_get((_a)->k, (_k)); \ + wfd_arg_get((_a)->v, (_v)); \ +}) + +#define wfd_arg_list_get(_l, _i, _v) ({ \ + assert(_l); \ + assert((_i) >= 0 && (_i) < (_l)->len); \ + struct wfd_arg *arg = (_l)->discrete \ + ? &(_l)->argv[(_i)] \ + : &(_l)->args[(_i)]; \ + wfd_arg_get(arg, _v); \ +}) + +#define wfd_arg_list_getkv(_l, _i, _k, _v) ({ \ + assert(_l); \ + assert((_i) >= 0 && (_i) < (_l)->len); \ + struct wfd_arg *arg = (_l)->discrete \ + ? &(_l)->argv[(_i)] \ + : &(_l)->args[(_i)]; \ + wfd_arg_getkv(arg, (_k), (_v)); \ +}) + +enum wfd_arg_type +{ + WFD_ARG_NONE, + WFD_ARG_I8, + WFD_ARG_I16, + WFD_ARG_I32, + WFD_ARG_I64, + WFD_ARG_U8, + WFD_ARG_U16, + WFD_ARG_U32, + WFD_ARG_U64, + WFD_ARG_STR, + WFD_ARG_CSTR, + WFD_ARG_PTR, + WFD_ARG_CPTR, + WFD_ARG_DICT, + WFD_ARG_CB, +}; + +struct wfd_arg +{ + enum wfd_arg_type type; + union + { + int8_t i8; + uint8_t u8; + int16_t i16; + uint16_t u16; + int32_t i32; + uint32_t u32; + int64_t i64; + uint64_t u64; + struct { + void *ptr; + void (*free)(void *); + }; + struct { + struct wfd_arg *k; + struct wfd_arg *v; + }; + }; +}; + +struct wfd_arg_list +{ + size_t len: sizeof(size_t) - 2; + bool discrete: 1; + bool dynamic: 1; + + union { + struct wfd_arg * argv; + struct wfd_arg args[0]; + }; +}; + +int wfd_arg_list_new(struct wfd_arg_list **out); +void wfd_arg_list_clear(struct wfd_arg_list *l); +static inline void wfd_arg_list_free(struct wfd_arg_list *l); + +static inline enum wfd_arg_type wfd_arg_get_type(struct wfd_arg *a); +static inline void wfd_arg_free_ptr(struct wfd_arg *a); +static inline void wfd_arg_clear(struct wfd_arg *a); + +static inline int8_t wfd_arg_get_i8(const struct wfd_arg *a); +static inline void wfd_arg_set_i8(struct wfd_arg *a, int8_t v); + +static inline uint8_t wfd_arg_get_u8(const struct wfd_arg *a); +static inline void wfd_arg_set_u8(struct wfd_arg *a, uint8_t v); + +static inline int16_t wfd_arg_get_i16(const struct wfd_arg *a); +static inline void wfd_arg_set_i16(struct wfd_arg *a, int16_t v); + +static inline uint16_t wfd_arg_get_u16(const struct wfd_arg *a); +static inline void wfd_arg_set_u16(struct wfd_arg *a, uint16_t v); + +static inline int32_t wfd_arg_get_i32(const struct wfd_arg *a); +static inline void wfd_arg_set_i32(struct wfd_arg *a, int32_t v); + +static inline uint32_t wfd_arg_get_u32(const struct wfd_arg *a); +static inline void wfd_arg_set_u32(struct wfd_arg *a, uint32_t v); + +static inline int64_t wfd_arg_get_i64(const struct wfd_arg *a); +static inline void wfd_arg_set_i64(struct wfd_arg *a, int64_t v); + +static inline uint64_t wfd_arg_get_u64(const struct wfd_arg *a); +static inline void wfd_arg_set_u64(struct wfd_arg *a, uint64_t v); + +static inline const char * wfd_arg_get_cstr(const struct wfd_arg *a); +static inline void wfd_arg_set_cstr(struct wfd_arg *a, const char * v); + +static inline void wfd_arg_take_str(struct wfd_arg *a, char *v); +static inline char * wfd_arg_get_str(const struct wfd_arg *a); +static inline int wfd_arg_set_str(struct wfd_arg *a, const char *v);; + +static inline const void * wfd_arg_get_cptr(const struct wfd_arg *a); +static inline void wfd_arg_set_cptr(struct wfd_arg *a, const void * v); + +static inline void wfd_arg_take_ptr(struct wfd_arg *a, void *v, void (*f)(void *)); +static inline void * wfd_arg_get_ptr(const struct wfd_arg *a); + +#include "wfd-arg.inc" + +#endif /* CTL_ARG_H */ diff --git a/src/ctl/wfd-arg.inc b/src/ctl/wfd-arg.inc new file mode 100644 index 0000000..327ce67 --- /dev/null +++ b/src/ctl/wfd-arg.inc @@ -0,0 +1,166 @@ +/* + * MiracleCast - Wifi-Display/Miracast Implementation + * + * Copyright (c) 2013-2014 David Herrmann + * + * MiracleCast is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * MiracleCast is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MiracleCast; If not, see . + */ +#define wfd_arg_getter(_t, _s, _S) \ +static inline _t wfd_arg_get_##_s(const struct wfd_arg *a) \ +{ \ + assert(a); \ + assert(WFD_ARG_##_S == a->type); \ + return a->_s; \ +} + +#define wfd_arg_setter(_t, _s, _S) \ +static inline void wfd_arg_set_##_t(struct wfd_arg *a, _t v) \ +{ \ + assert(a); \ + assert(!a->type || WFD_ARG_##_S == a->type); \ + *a = (struct wfd_arg) { .type = WFD_ARG_##_S, ._s = v }; \ +} + +wfd_arg_getter(int8_t, i8, I8) +wfd_arg_setter(int8_t, i8, I8) +wfd_arg_getter(uint8_t, u8, U8) +wfd_arg_setter(uint8_t, u8, U8) +wfd_arg_getter(int16_t, i16, I16) +wfd_arg_setter(int16_t, i16, I16) +wfd_arg_getter(uint16_t, u16, U16) +wfd_arg_setter(uint16_t, u16, U16) +wfd_arg_getter(int32_t, i32, I32) +wfd_arg_setter(int32_t, i32, I32) +wfd_arg_getter(uint32_t, u32, U32) +wfd_arg_setter(uint32_t, u32, U32) +wfd_arg_getter(int64_t, i64, I64) +wfd_arg_setter(int64_t, i64, I64) +wfd_arg_getter(uint64_t, u64, U64) +wfd_arg_setter(uint64_t, u64, U64) + +static inline void wfd_arg_list_free(struct wfd_arg_list *l) +{ + wfd_arg_list_clear(l); + free(l); +} + +static inline enum wfd_arg_type wfd_arg_get_type(struct wfd_arg *a) +{ + assert(a); + + return a->type; +} + +static inline void wfd_arg_free_ptr(struct wfd_arg *a) +{ + if(!a || (WFD_ARG_STR != a->type && WFD_ARG_PTR != a->type)) { + return; + } + + if(a->ptr && a->free) { + (*a->free)(a->ptr); + } +} + +static inline void wfd_arg_clear(struct wfd_arg *a) +{ + if(a) { + wfd_arg_free_ptr(a); + memset(a, 0, sizeof(*a)); + } +} + +static inline const char * wfd_arg_get_cstr(const struct wfd_arg *a) +{ + assert(a); + assert(WFD_ARG_CSTR == a->type || WFD_ARG_STR == a->type); + + return a->ptr; +} + +static inline void wfd_arg_set_cstr(struct wfd_arg *a, const char * v) +{ + assert(a); + assert(!a->type || WFD_ARG_CSTR == a->type); + + *a = (struct wfd_arg) { .type = WFD_ARG_CSTR, .ptr = (void *) v }; +} + +static inline char * wfd_arg_get_str(const struct wfd_arg *a) +{ + assert(a); + assert(WFD_ARG_STR == a->type); + + return a->ptr; +} + +static inline void wfd_arg_take_str(struct wfd_arg *a, char *v) +{ + assert(a); + assert(!a->type || WFD_ARG_STR == a->type || WFD_ARG_CSTR == a->type); + + wfd_arg_free_ptr(a); + *a = (struct wfd_arg) { .type = WFD_ARG_STR, .ptr = v, .free = free }; +} + +static inline int wfd_arg_set_str(struct wfd_arg *a, const char *v) +{ + char *s; + + assert(a); + assert(!a->type || WFD_ARG_STR == a->type); + + s = strdup(v); + if(!s) { + return -ENOMEM; + } + + wfd_arg_take_str(a, s); + + return 0; +} + +static inline const void * wfd_arg_get_cptr(const struct wfd_arg *a) +{ + assert(a); + assert(WFD_ARG_PTR <= a->type && WFD_ARG_CPTR == a->type); + + return a->ptr; +} + +static inline void wfd_arg_set_cptr(struct wfd_arg *a, const void * v) +{ + assert(a); + assert(!a->type || WFD_ARG_CSTR == a->type); + + *a = (struct wfd_arg) { .type = WFD_ARG_CPTR, .ptr = (void *) v }; +} + +static inline void * wfd_arg_get_ptr(const struct wfd_arg *a) +{ + assert(a); + assert(WFD_ARG_PTR == a->type || WFD_ARG_STR == a->type); + + return a->ptr; +} + +static inline void wfd_arg_take_ptr(struct wfd_arg *a, void *v, void (*f)(void *)) +{ + assert(a); + assert(!a->type || WFD_ARG_PTR == a->type); + + wfd_arg_free_ptr(a); + *a = (struct wfd_arg) { .type = WFD_ARG_PTR, .ptr = v, .free = f }; +} +