Move opts/ into util/opts/

This commit is contained in:
Kamil Trzcinski
2022-09-02 22:00:01 +02:00
parent 9a592fb00e
commit f5726fc9b2
34 changed files with 48 additions and 48 deletions

26
util/opts/control.c Normal file
View File

@ -0,0 +1,26 @@
#include "control.h"
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
int device_option_normalize_name(const char *in, char *outp)
{
// The output is always shorter, so `outp=in`
// colour_correction_matrix => colourcorrectionmatrix
// Colour Correction Matrix => colourcorrectionmatrix
// ColourCorrectionMatrix => colourcorrectionmatrix
char *out = outp;
while (*in) {
if (isalnum(*in)) {
*out++ = tolower(*in++);
} else {
in++;
}
}
*out++ = 0;
return out - outp;
}

1
util/opts/control.h Normal file
View File

@ -0,0 +1 @@
int device_option_normalize_name(const char *in, char *out);

21
util/opts/fourcc.c Normal file
View File

@ -0,0 +1,21 @@
#include "fourcc.h"
fourcc_string fourcc_to_string(unsigned format)
{
fourcc_string fourcc;
char *ptr = fourcc.buf;
*ptr++ = format & 0x7F;
*ptr++ = (format >> 8) & 0x7F;
*ptr++ = (format >> 16) & 0x7F;
*ptr++ = (format >> 24) & 0x7F;
if (format & ((unsigned)1 << 31)) {
*ptr++ = '-';
*ptr++ = 'B';
*ptr++ = 'E';
*ptr++ = '\0';
} else {
*ptr++ = '\0';
}
*ptr++ = 0;
return fourcc;
}

10
util/opts/fourcc.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <time.h>
#include <linux/videodev2.h>
typedef struct {
char buf[10];
} fourcc_string;
fourcc_string fourcc_to_string(unsigned format);

103
util/opts/log.c Normal file
View File

@ -0,0 +1,103 @@
#include "util/opts/log.h"
#include "util/opts/opts.h"
#include <string.h>
char *
strstrn(const char *s, const char *find, size_t len)
{
char c, sc;
if ((c = *find++) != 0) {
len--;
do {
do {
if ((sc = *s++) == 0)
return (NULL);
} while (sc != c);
} while (strncmp(s, find, len) != 0);
s--;
}
return ((char *)s);
}
bool filter_log(const char *filename)
{
if (!log_options.filter[0])
return false;
const char *ptr = log_options.filter;
do {
const char *next = strchr(ptr, OPTION_VALUE_LIST_SEP[0]);
if (!next)
next = ptr + strlen(ptr);
if(strstrn(filename, ptr, next - ptr))
return true;
ptr = next;
} while(*ptr++);
return false;
}
int shrink_to_block(int size, int block)
{
return size / block * block;
}
uint64_t get_time_us(clockid_t clock, struct timespec *ts, struct timeval *tv, int64_t delays_us)
{
struct timespec now;
if (clock != CLOCK_FROM_PARAMS) {
clock_gettime(clock, &now);
} else if (ts) {
now = *ts;
} else if (tv) {
now.tv_sec = tv->tv_sec;
now.tv_nsec = tv->tv_usec * 1000;
} else {
return -1;
}
if (delays_us > 0) {
#define NS_IN_S (1000LL * 1000LL * 1000LL)
int64_t nsec = now.tv_nsec + delays_us * 1000LL;
now.tv_nsec = nsec % NS_IN_S;
now.tv_sec += nsec / NS_IN_S;
}
if (ts) {
*ts = now;
}
if (tv) {
tv->tv_sec = now.tv_sec;
tv->tv_usec = now.tv_nsec / 1000;
}
return now.tv_sec * 1000000LL + now.tv_nsec / 1000;
}
uint64_t get_monotonic_time_us(struct timespec *ts, struct timeval *tv)
{
return get_time_us(CLOCK_MONOTONIC, ts, tv, 0);
}
int ioctl_retried(const char *name, int fd, int request, void *arg)
{
#define MAX_RETRIES 4
int retries = 4;
int ret = -1;
while (retries-- > 0) {
ret = ioctl(fd, request, arg);
if (errno != EINTR && errno != EAGAIN && errno != ETIMEDOUT)
break;
}
if (ret && retries <= 0) {
LOG_PERROR(NULL, "%s: ioctl(%08x) retried %u times; giving up", name, request, MAX_RETRIES);
}
return ret;
}

60
util/opts/log.h Normal file
View File

@ -0,0 +1,60 @@
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#define __FILENAME__ __FILE__
typedef struct log_options_s {
bool debug;
bool verbose;
char filter[256];
} log_options_t;
extern log_options_t log_options;
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
bool filter_log(const char *filename);
// assumes that name is first item
#define dev_name(dev) (dev ? *(const char**)dev : "?")
#define LOG_ERROR(dev, _msg, ...) do { fprintf(stderr, "%s: %s: " _msg "\n", __FILENAME__, dev_name(dev), ##__VA_ARGS__); goto error; } while(0)
#define LOG_PERROR(dev, _msg, ...) do { fprintf(stderr, "%s: %s: " _msg "\n", __FILENAME__, dev_name(dev), ##__VA_ARGS__); exit(-1); } while(0)
#define LOG_INFO(dev, _msg, ...) do { fprintf(stderr, "%s: %s: " _msg "\n", __FILENAME__, dev_name(dev), ##__VA_ARGS__); } while(0)
#define LOG_VERBOSE(dev, _msg, ...) do { if (log_options.debug || log_options.verbose || filter_log(__FILENAME__)) { fprintf(stderr, "%s: %s: " _msg "\n", __FILENAME__, dev_name(dev), ##__VA_ARGS__); } } while(0)
#define LOG_DEBUG(dev, _msg, ...) do { if (log_options.debug || filter_log(__FILENAME__)) { fprintf(stderr, "%s: %s: " _msg "\n", __FILENAME__, dev_name(dev), ##__VA_ARGS__); } } while(0)
#define CLOCK_FROM_PARAMS -1
uint64_t get_monotonic_time_us(struct timespec *ts, struct timeval *tv);
uint64_t get_time_us(clockid_t clock, struct timespec *ts, struct timeval *tv, int64_t delays_us);
int shrink_to_block(int size, int block);
int ioctl_retried(const char *name, int fd, int request, void *arg);
#define ERR_IOCTL(dev, _fd, _request, _value, _msg, ...) do { \
int ret; \
if ((ret = ioctl_retried(dev_name(dev), _fd, _request, _value)) < 0) { \
LOG_ERROR(dev, "ioctl(ret=%d): " _msg, ret, ##__VA_ARGS__); \
} \
} while(0)

179
util/opts/opts.c Normal file
View File

@ -0,0 +1,179 @@
#include "opts.h"
#include "util/opts/log.h"
#include <stddef.h>
#include <stdio.h>
#include <limits.h>
#define OPT_LENGTH 30
static void print_help(option_t *options, const char *cmd)
{
printf("Usage:\n");
printf("$ %s <options...>\n", cmd);
printf("\n");
printf("Options:\n");
for (int i = 0; options[i].name; i++) {
option_t *option = &options[i];
int len = 0;
len += printf(" -%s", option->name);
if (option->default_value) {
len += printf("[=%s]", option->default_value);
} else if (option->value_mapping) {
len += printf("=arg");
} else {
len += printf("=%s", option->format);
}
if (len < OPT_LENGTH) {
printf("%*s", OPT_LENGTH-len, " ");
}
printf("- %s", option->description);
if (option->value_mapping) {
printf(" Values: ");
for (int j = 0; option->value_mapping[j].name; j++) {
if (j > 0) printf(", ");
printf("%s", option->value_mapping[j].name);
}
printf(".");
}
printf("\n");
}
printf("\n");
printf("Configuration:\n");
for (int i = 0; options[i].name; i++) {
option_t *option = &options[i];
int len = 0;
if (option->value_list) {
char *string = option->value_list;
char *token;
if (!*string)
continue;
while ((token = strsep(&string, OPTION_VALUE_LIST_SEP)) != NULL) {
len = printf(" -%s=", option->name);
if (len < OPT_LENGTH) {
printf("%*s", OPT_LENGTH-len, " ");
}
printf("%s\n", token);
}
} else if (option->value_string) {
len += printf(" -%s=", option->name);
if (len < OPT_LENGTH) {
printf("%*s", OPT_LENGTH-len, " ");
}
printf(option->format, option->value_string);
printf("\n");
} else {
len += printf(" -%s=", option->name);
if (len < OPT_LENGTH) {
printf("%*s", OPT_LENGTH-len, " ");
}
if (option->value_mapping) {
for (int j = 0; option->value_mapping[j].name; j++) {
if (option->value_mapping[j].value == *option->value) {
printf("%s - ", option->value_mapping[j].name);
break;
}
}
}
unsigned mask = UINT_MAX >> ((sizeof(*option->value) - option->size) * 8);
printf(option->format, *option->value & mask);
printf("\n");
}
}
printf("\n");
}
static int parse_opt(option_t *options, const char *key)
{
option_t *option = NULL;
const char *value = strchr(key, '=');
for (int i = 0; options[i].name; i++) {
if (value) {
if (!strncmp(key, options[i].name, value - key)) {
option = &options[i];
value++; // ignore '='
break;
}
} else {
// require exact match
if (!strcmp(key, options[i].name)) {
option = &options[i];
value = option->default_value;
break;
}
}
}
LOG_DEBUG(NULL, "Parsing '%s'. Got value='%s', and option='%s'", key, value, option ? option->name : NULL);
if (!option || !value) {
return -EINVAL;
}
int ret = 0;
if (option->value_list) {
char *ptr = option->value_list;
if (*ptr) {
strcat(ptr, OPTION_VALUE_LIST_SEP);
ptr += strlen(ptr);
}
ret = sscanf(value, option->format, ptr);
} else if (option->value_string) {
ret = sscanf(value, option->format, option->value_string);
} else if (option->value_mapping) {
for (int j = 0; option->value_mapping[j].name; j++) {
if (!strcmp(option->value_mapping[j].name, value)) {
*option->value_uint = option->value_mapping[j].value;
return 1;
}
}
ret = sscanf(value, option->format, option->value);
} else {
ret = sscanf(value, option->format, option->value);
}
return ret;
}
int parse_opts(option_t *options, int argc, char *argv[])
{
int arg;
for (arg = 1; arg < argc; arg++) {
const char *key = argv[arg];
if (key[0] == '-') {
key++;
if (key[0] == '-')
key++;
} else {
LOG_ERROR(NULL, "The '%s' is not option (should start with - or --).", key);
}
if (!strcmp(key, "help")) {
print_help(options, argv[0]);
return -1;
}
int ret = parse_opt(options, key);
if (ret <= 0) {
LOG_ERROR(NULL, "Parsing '%s' returned '%d'.", argv[arg], ret);
}
}
return 0;
error:
return -1;
}

76
util/opts/opts.h Normal file
View File

@ -0,0 +1,76 @@
#pragma once
#include <stdbool.h>
typedef struct option_value_s {
const char *name;
unsigned value;
} option_value_t;
typedef struct options_s {
const char *name;
char *value_string;
char *value_list;
union {
unsigned *value;
unsigned *value_uint;
unsigned *value_hex;
bool *value_bool;
float *value_float;
};
const char *format;
const char *help;
option_value_t *value_mapping;
unsigned size;
const char *default_value;
const char *description;
} option_t;
#define OPTION_VALUE_LIST_SEP ";"
#define OPTION_FORMAT_uint "%u"
#define OPTION_FORMAT_hex "%08x"
#define OPTION_FORMAT_bool "%d"
#define OPTION_FORMAT_float "%f"
#define OPTION_FORMAT_string "%s"
#define OPTION_FORMAT_list "%s"
#define DEFINE_OPTION(_section, _name, _type, _desc) \
{ \
.name = #_section "-" #_name, \
.value_##_type = &_section##_options._name, \
.format = OPTION_FORMAT_##_type, \
.size = sizeof(_section##_options._name), \
.description = _desc, \
}
#define DEFINE_OPTION_DEFAULT(_section, _name, _type, _default_value, _desc) \
{ \
.name = #_section "-" #_name, \
.value_##_type = &_section##_options._name, \
.format = OPTION_FORMAT_##_type, \
.size = sizeof(_section##_options._name), \
.default_value = _default_value, \
.description = _desc, \
}
#define DEFINE_OPTION_VALUES(_section, _name, _value_mapping, _desc) \
{ \
.name = #_section "-" #_name, \
.value_hex = &_section##_options._name, \
.format = OPTION_FORMAT_hex, \
.value_mapping = _value_mapping, \
.size = sizeof(_section##_options._name), \
.description = _desc, \
}
#define DEFINE_OPTION_PTR(_section, _name, _type, _desc) \
{ \
.name = #_section "-" #_name, \
.value_##_type = _section##_options._name, \
.format = OPTION_FORMAT_##_type, \
.size = sizeof(_section##_options._name), \
.description = _desc, \
}
int parse_opts(option_t *options, int argc, char *argv[]);