eddy_em: (Default)
[personal profile] eddy_em
Закинул код на гитхаб. Помимо старого hashtest добавил еще hashgen, который может генерировать по заданной таблице команд заголовочный файл и исходник, принимающий пользовательскую строку на вход, вычисляющий хеш команды (первое слово) и запускающий соответствующую функцию. Можно проверить это при помощи test.c.

Проверять на словаре с 43000 словами, конечно, можно, но код получается дюже длинный (за 41мс оно мне сгенерило исходник размером в 8МБ - 300тыс строк - и заголовочник на 2.5МБ). Поэтому для примера беру компактный словарик:
hello
world
what
put
change
set
         clear
reset
  get
out
in

и запускаю time ./hashgen -Fd testdic. Через 2мс получаю заголовочный файл:
int parsecmd(char *cmdwargs);

#define CMD_CHANGE      (3110904043)
#define CMD_CLEAR       (2063720716)
#define CMD_GET         (2963126085)
#define CMD_HELLO       (3433426201)
#define CMD_IN          (89558876)
#define CMD_OUT         (2963261277)
#define CMD_PUT         (2963277918)
#define CMD_RESET       (1907803304)
#define CMD_SET         (2963325777)
#define CMD_WHAT        (25570233)
#define CMD_WORLD       (3313868845)

и исходник:
#include <stdint.h>
#include <stddef.h>
#include "hash.h"

#ifndef _U_
#define _U_ __attribute__((__unused__))
#endif

#ifndef TRUE_INLINE
#define TRUE_INLINE  __attribute__((always_inline)) static inline
#endif

TRUE_INLINE int fn_change(_U_ uint32_t hash,  _U_ char *args){ // change (3110904043)
    return 1;
}

TRUE_INLINE int fn_clear(_U_ uint32_t hash,  _U_ char *args){ // clear (2063720716)
    return 1;
}

TRUE_INLINE int fn_get(_U_ uint32_t hash,  _U_ char *args){ // get (2963126085)
    return 1;
}

TRUE_INLINE int fn_hello(_U_ uint32_t hash,  _U_ char *args){ // hello (3433426201)
    return 1;
}

TRUE_INLINE int fn_in(_U_ uint32_t hash,  _U_ char *args){ // in (89558876)
    return 1;
}

TRUE_INLINE int fn_out(_U_ uint32_t hash,  _U_ char *args){ // out (2963261277)
    return 1;
}

TRUE_INLINE int fn_put(_U_ uint32_t hash,  _U_ char *args){ // put (2963277918)
    return 1;
}

TRUE_INLINE int fn_reset(_U_ uint32_t hash,  _U_ char *args){ // reset (1907803304)
    return 1;
}

TRUE_INLINE int fn_set(_U_ uint32_t hash,  _U_ char *args){ // set (2963325777)
    return 1;
}

TRUE_INLINE int fn_what(_U_ uint32_t hash,  _U_ char *args){ // what (25570233)
    return 1;
}

TRUE_INLINE int fn_world(_U_ uint32_t hash,  _U_ char *args){ // world (3313868845)
    return 1;
}

static uint32_t hashf(const char *str){
    uint32_t hash = 5381;
    uint32_t c;
    while((c = (uint32_t)*str++))
        hash = ((hash << 7) + hash) + c;
    return hash;
}

int parsecmd(char *cmdwargs){
    if(!cmdwargs || !*cmdwargs) return 0;
    char cmd[32];
    int i = 0;
    char *args = cmdwargs;
    while(*args && *args < 33) ++args;
    if(!args || !*args) return 0;
    while(*args > 33 && i < 31){
        cmd[i++] = *args++;
    }
    cmd[i] = 0;
    if(i == 31) args = NULL;
    if(args){
        while(*args && *args < 33) ++args;
        if(!*args) args = NULL;
    }
    uint32_t h = hashf(cmd);
    switch(h){
        case CMD_CHANGE:
            return fn_change(h, args);
        break;
        case CMD_CLEAR:
            return fn_clear(h, args);
        break;
        case CMD_GET:
            return fn_get(h, args);
        break;
        case CMD_HELLO:
            return fn_hello(h, args);
        break;
        case CMD_IN:
            return fn_in(h, args);
        break;
        case CMD_OUT:
            return fn_out(h, args);
        break;
        case CMD_PUT:
            return fn_put(h, args);
        break;
        case CMD_RESET:
            return fn_reset(h, args);
        break;
        case CMD_SET:
            return fn_set(h, args);
        break;
        case CMD_WHAT:
            return fn_what(h, args);
        break;
        case CMD_WORLD:
            return fn_world(h, args);
        break;
        default: return 0;
    }
    return 0;
}


Остается лишь заполнить содержимое пустых функций. Можно собрать тест и проверить:
gcc test.c hash.c -o test
./test "hell1o clear ass asdlf"
hell1o clear ass asdlf not found
./test "hello clear ass asdlf"
All OK

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org

May 2025

S M T W T F S
    123
45678910
11121314151617
1819202122 2324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 1st, 2025 01:23 am
Powered by Dreamwidth Studios