Skip to content

Instantly share code, notes, and snippets.

@DaelonSuzuka
Last active April 4, 2020 01:12
Show Gist options
  • Save DaelonSuzuka/4751e264a4dadf15286f4719fda4e779 to your computer and use it in GitHub Desktop.
Save DaelonSuzuka/4751e264a4dadf15286f4719fda4e779 to your computer and use it in GitHub Desktop.
gperf script
#include "usb_json_hash.h"
#include "os/serial_port.h"
#include "os/shell/shell_command_processor.h"
#include <stdint.h>
#include <string.h>
/* ************************************************************************** */
/* [[[cog
import cogutils as utils, codegen as code
keys = utils.search('src/usb/usb_messages.c', r'(?<={nKey, ").*?(?="})')
prefix = 'hash_'
enum = code.Enum(
name = 'hash_value_t',
values = keys,
prefix = prefix,
typedef = True,
explicit = True
)
struct = code.Struct(
'key',
['const char *name', f'{enum.name} value'],
).assemble()
cog.outl()
cog.outl(utils.Gperf([f'{k}, {prefix}{k}' for k in keys], struct).run())
func = code.Function(
name = 'json_hash',
return_type = enum.name,
params = 'const char *string',
extern = True
)
code.Header(
name = cog.inFile.replace('.c', '.h'),
includes = '<stdint.h>',
contents = [enum.assemble(), func.assemble()]
).write()
]]] */
/* ANSI-C code produced by gperf version 3.1 */
/* Command-line: 'C:\\ProgramData\\chocolatey\\lib\\gperf\\tools\\gperf.exe' -m
* 100 -r -n strings.gperf */
/* Computed positions: -k'3-4,9' */
#if !( \
(' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) && ('%' == 37) && \
('&' == 38) && ('\'' == 39) && ('(' == 40) && (')' == 41) && \
('*' == 42) && ('+' == 43) && (',' == 44) && ('-' == 45) && ('.' == 46) && \
('/' == 47) && ('0' == 48) && ('1' == 49) && ('2' == 50) && ('3' == 51) && \
('4' == 52) && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) && \
('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) && ('=' == 61) && \
('>' == 62) && ('?' == 63) && ('A' == 65) && ('B' == 66) && ('C' == 67) && \
('D' == 68) && ('E' == 69) && ('F' == 70) && ('G' == 71) && ('H' == 72) && \
('I' == 73) && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) && \
('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) && ('R' == 82) && \
('S' == 83) && ('T' == 84) && ('U' == 85) && ('V' == 86) && ('W' == 87) && \
('X' == 88) && ('Y' == 89) && ('Z' == 90) && ('[' == 91) && \
('\\' == 92) && (']' == 93) && ('^' == 94) && ('_' == 95) && \
('a' == 97) && ('b' == 98) && ('c' == 99) && ('d' == 100) && \
('e' == 101) && ('f' == 102) && ('g' == 103) && ('h' == 104) && \
('i' == 105) && ('j' == 106) && ('k' == 107) && ('l' == 108) && \
('m' == 109) && ('n' == 110) && ('o' == 111) && ('p' == 112) && \
('q' == 113) && ('r' == 114) && ('s' == 115) && ('t' == 116) && \
('u' == 117) && ('v' == 118) && ('w' == 119) && ('x' == 120) && \
('y' == 121) && ('z' == 122) && ('{' == 123) && ('|' == 124) && \
('}' == 125) && ('~' == 126))
/* The character set is not based on ISO-646. */
#error \
"gperf generated tables don't work with this execution character set. Please report a bug to <[email protected]>."
#endif
struct key {
const char *name;
hash_value_t value;
};
#define TOTAL_KEYWORDS 18
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 19
#define MIN_HASH_VALUE 0
#define MAX_HASH_VALUE 17
/* maximum key range = 18, duplicates = 0 */
#ifdef __GNUC__
#else
#ifdef __cplusplus
#endif
#endif
static uint16_t hash(const char *str, uint8_t len) {
static const uint8_t asso_values[] = {
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 6, 18, 18, 18, 16, 7, 13, 8, 1, 18, 4, 11, 18,
18, 3, 0, 3, 1, 3, 5, 4, 1, 3, 4, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18};
uint16_t hval = 0;
switch (len) {
default:
hval += asso_values[(uint8_t)str[8]];
/*FALLTHROUGH*/
case 8:
case 7:
case 6:
case 5:
case 4:
hval += asso_values[(uint8_t)str[3]];
/*FALLTHROUGH*/
case 3:
hval += asso_values[(uint8_t)str[2]];
/*FALLTHROUGH*/
case 2:
break;
}
return hval;
}
static const struct key wordlist[] = {
{"ok", hash_ok},
{"ping", hash_ping},
{"toggle", hash_toggle},
{"minor", hash_minor},
{"auto", hash_auto},
{"compile_time", hash_compile_time},
{"command", hash_command},
{"set_antenna", hash_set_antenna},
{"device_info", hash_device_info},
{"serial", hash_serial},
{"compiler_version", hash_compiler_version},
{"compile_date", hash_compile_date},
{"message_id", hash_message_id},
{"request_device_info", hash_request_device_info},
{"major", hash_major},
{"software_version", hash_software_version},
{"name", hash_name},
{"patch", hash_patch},
};
const struct key *in_word_set(const char *str, uint8_t len) {
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) {
uint16_t key = hash(str, len);
if (key <= MAX_HASH_VALUE) {
const char *s = wordlist[key].name;
if (*str == *s && !strcmp(str + 1, s + 1))
return &wordlist[key];
}
}
return 0;
}
/* [[[end]]] */
/* ************************************************************************** */
#if TOTAL_KEYWORDS != (MAX_HASH_VALUE + 1)
#error Gperf output is not minimal!
#endif
hash_value_t json_hash(const char *string) {
const struct key *result = in_word_set(string, strlen(string));
return result->value;
}
/* ************************************************************************** */
void sh_hash(int argc, char **argv) {
if (argc == 1) {
println("you didn't give me a string");
return;
}
for (uint8_t i = 1; i < argc; i++) {
const struct key *result = in_word_set(argv[i], strlen(argv[i]));
if (!result) {
printf("'%s' wasn't in the word list\r\n", argv[i]);
} else {
printf("found '%s' [%d]\r\n", result->name, result->value);
}
}
}
REGISTER_SHELL_COMMAND(sh_hash, "hash");
#ifndef _USB_JSON_HASH_H_
#define _USB_JSON_HASH_H_
#include <stdint.h>
/* ************************************************************************** */
typedef enum {
hash_message_id = 0,
hash_serial = 1,
hash_major = 2,
hash_minor = 3,
hash_patch = 4,
hash_compiler_version = 5,
hash_compile_date = 6,
hash_compile_time = 7,
hash_request_device_info = 8,
hash_ping = 9,
hash_command = 10,
hash_set_antenna = 11,
hash_auto = 12,
hash_toggle = 13,
hash_device_info = 14,
hash_name = 15,
hash_software_version = 16,
hash_ok = 17,
} hash_value_t;
extern hash_value_t json_hash(const char *string);
#endif /* _USB_JSON_HASH_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment