Files
djhackersdev_bemanitools/src/main/config/usages.c
T

179 lines
3.9 KiB
C

#include <windows.h>
#include <ctype.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "config/resource.h"
#include "util/array.h"
#include "util/log.h"
#include "util/str.h"
#include "util/winres.h"
struct usage {
uint16_t id;
char name[128];
};
struct usage_page {
uint16_t id;
struct array usages;
char wildcard[128];
};
static struct array usages;
static bool usages_begin_page(const char *line, struct usage_page *page);
static bool usages_read_usage(const char *line, struct usage_page *page);
void usages_init(HINSTANCE inst)
{
struct resource res;
struct usage_page *cur_page;
struct usage_page tmp_page;
char line[512];
size_t line_no;
size_t nchars;
resource_open(&res, inst, "USAGES", IDR_USAGES);
array_init(&usages);
cur_page = NULL;
line_no = 0;
while (resource_fgets(&res, line, sizeof(line))) {
line_no++;
nchars = strlen(line);
if (nchars == 0 || line[0] == '#' ||
strspn(line, " \t\r\n") == nchars) {
continue;
}
str_trim(line);
if (!isspace(line[0])) {
if (!usages_begin_page(line, &tmp_page)) {
log_fatal(
"IDR_USAGES:%u: Invalid usage page",
(unsigned int) line_no);
break;
}
cur_page = array_append(struct usage_page, &usages);
memcpy(cur_page, &tmp_page, sizeof(tmp_page));
} else {
if (cur_page == NULL) {
log_fatal(
"IDR_USAGES:%u: Usage before first page",
(unsigned int) line_no);
break;
}
if (!usages_read_usage(line, cur_page)) {
log_fatal(
"IDR_USAGES:%u: Invalid usage", (unsigned int) line_no);
break;
}
}
}
}
static bool usages_begin_page(const char *line, struct usage_page *page)
{
int id;
if (sscanf(line, "%i", &id) != 1) {
return false;
}
page->id = (uint16_t) id;
array_init(&page->usages);
return true;
}
static bool usages_read_usage(const char *line, struct usage_page *page)
{
struct usage *usage;
int id;
int offset;
char c;
if (sscanf(line, " %c %n", &c, &offset) == 1 && c == '*') {
str_cpy(page->wildcard, sizeof(page->wildcard), &line[offset]);
page->wildcard[sizeof(page->wildcard) - 1] = '\0';
return true;
} else if (sscanf(line, " %i %n", &id, &offset) == 1) {
usage = array_append(struct usage, &page->usages);
usage->id = (uint16_t) id;
str_cpy(usage->name, sizeof(usage->name), &line[offset]);
usage->name[sizeof(usage->name) - 1] = '\0';
return true;
} else {
return false;
}
}
void usages_get(char *chars, size_t nchars, uint32_t usage_id)
{
const struct usage_page *page;
const struct usage *usage;
uint16_t hi;
uint16_t lo;
size_t i;
size_t j;
hi = ((usage_id >> 16) & 0xFFFF);
lo = ((usage_id >> 0) & 0xFFFF);
for (i = 0; i < usages.nitems; i++) {
page = array_item(struct usage_page, &usages, i);
if (page->id != hi) {
continue;
}
for (j = 0; j < page->usages.nitems; j++) {
usage = array_item(struct usage, &page->usages, j);
if (usage->id == lo) {
str_cpy(chars, nchars, usage->name);
chars[nchars - 1] = '\0';
return;
}
}
if (page->wildcard[0]) {
str_format(chars, nchars, page->wildcard, lo);
return;
}
}
str_format(chars, nchars, "%#08x", usage_id);
}
void usages_fini(void)
{
size_t i;
for (i = 0; i < usages.nitems; i++) {
array_fini(&array_item(struct usage_page, &usages, i)->usages);
}
array_fini(&usages);
}