Files
Sun1602/Tools/WzFtpManager/ATL/source/SProxy/utils/static_hash.c
T
2022-10-26 12:25:11 +08:00

876 lines
17 KiB
C

//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
#include <string.h>
#include <stdio.h>
char g_szClass[256] = { 0 };
char g_szLookup[256] = { 0 };
int g_nAssumeValid = 0;
char g_szData[256] = { 'c', 'h', 'a', 'r', ' ', '*', '\0' };
char g_szOutFile[256] = { 0 };
char g_szInFile[256] = { 0 };
int g_nUnicode = 0;
char * g_szpreamble = "";
int g_nPreamble = 0;
unsigned long hash_string( const char * sz, int nlen )
{
const char* pch;
unsigned long hash;
int i;
hash = 0;
pch = sz;
// while( *pch != 0 )
for (i=0; i<nlen; i++)
{
hash = (hash<<3)+hash+(*pch);
pch++;
}
return( hash );
}
struct static_hash_node
{
char * key;
unsigned long hash;
size_t link; // static time -- index, run time -- pointer
size_t entries;
char * data;
};
struct static_hash_table
{
struct static_hash_node *pdata;
int size;
int max_size;
int non_root_entries;
};
struct input_data
{
char * key;
int keylen;
char * data;
int datalen;
struct input_data * next;
};
struct input_table
{
struct input_data * phead;
struct input_data * ptail;
int size;
};
struct input_data * add_input_data(struct input_table * ptable)
{
struct input_data * pnew;
pnew = (struct input_data *) malloc(sizeof(*pnew));
if (pnew)
{
memset(pnew, 0x00, sizeof(*pnew));
if (ptable->ptail)
{
ptable->ptail->next = pnew;
}
ptable->ptail = pnew;
if (!ptable->phead)
{
ptable->phead = pnew;
}
ptable->size += 1;
}
return pnew;
}
int get_input_from_line(struct input_data * pdata, char ** pszline)
{
char * szcomma;
char * szendln;
char *szline;
szline = *pszline;
szcomma = strchr(szline, ',');
if (!szcomma)
{
return 0;
}
pdata->key = szline;
pdata->keylen = szcomma-szline;
szcomma++;
szendln = strchr(szcomma, '\n');
if (!szendln)
{
return 0;
}
pdata->data = szcomma;
pdata->datalen = szendln-szcomma;
if (*(szendln-1) == '\r')
{
pdata->datalen -= 1;
}
*pszline = szendln+1;
return 1;
}
void destroy_input_table(struct input_table * ptable)
{
struct input_data *pdata;
while (ptable->phead)
{
pdata = ptable->phead;
ptable->phead = ptable->phead->next;
free(pdata);
}
}
int choose_static_hash_size(struct static_hash_table * ptable)
{
return 2*(ptable->size);
}
void destroy_runtime_hash(struct static_hash_table *ptable)
{
int i;
struct static_hash_node *p;
struct static_hash_node *temp;
int size;
size=ptable->max_size;
p=(void*)0;
temp=(void*)0;
if (!ptable || !ptable->pdata)
return;
for (i=0; i<size; i++)
{
p = &ptable->pdata[i];
if (p->key)
free(p->key);
if (p->data)
free(p->data);
p = (struct static_hash_node *)(p->link);
while (p)
{
temp = p;
p = (struct static_hash_node *)(p->link);
free(temp);
}
}
free(ptable->pdata);
}
int create_runtime_hash(struct static_hash_table *ptable, int max_size)
{
if (!ptable)
return 0;
if (ptable->pdata)
destroy_runtime_hash(ptable);
memset(ptable, 0x00, sizeof(ptable));
ptable->pdata = (struct static_hash_node *)malloc(max_size*sizeof(struct static_hash_node));
if (!ptable->pdata)
return 0;
memset(ptable->pdata, 0x00, max_size*sizeof(struct static_hash_node));
ptable->max_size = max_size;
ptable->size = 0;
return 1;
}
struct static_hash_node * runtime_lookup(struct static_hash_table *ptable, const char *key, int keylen, int *found, unsigned long *phash, unsigned long *pindex)
{
unsigned long hash;
struct static_hash_node *p;
*found = 0;
hash = hash_string(key, keylen);
if (phash)
*phash = hash;
// hash = hash % ptable->max_size;
p = &ptable->pdata[hash % ptable->max_size];
while (p->key)
{
if (p->hash==hash && !strncmp(key, p->key, keylen))
{
*found = 1;
break;
}
if (p->link)
p = (struct static_hash_node *)(p->link);
else
break;
}
if (pindex)
*pindex = hash % ptable->max_size;
return p;
}
char * _strndup(const char * str, int nlen)
{
char * str2;
if (nlen == -1)
{
nlen = strlen(str);
}
str2 = (char *) malloc(nlen+1);
if (str2)
{
memcpy(str2, str, nlen);
str2[nlen] = '\0';
}
return str2;
}
int set_runtime_element(struct static_hash_table *ptable, const char *key, int nkeylen, const char *data, int ndatalen)
{
struct static_hash_node *p;
struct static_hash_node *newnode;
int found;
unsigned long hash;
unsigned long index;
p = runtime_lookup(ptable, key, nkeylen, &found, &hash, &index);
if (found)
{
if (p->data)
free(p->data);
}
else // !found
{
if (p->key)
{
newnode = (struct static_hash_node *)malloc(sizeof(struct static_hash_node));
if (!newnode)
return 0;
memset(newnode, 0x00, sizeof(struct static_hash_node));
while (p->link != 0)
p = (struct static_hash_node *)(p->link);
p->link = (size_t)newnode;
ptable->pdata[index].entries++;
ptable->non_root_entries++;
p = newnode;
}
p->key = _strndup(key, nkeylen);
p->hash = hash;
if (!p->key)
return 0;
ptable->size++;
}
p->data = _strndup(data, ndatalen);
if (!p->data)
return 0;
return 1;
}
void generate_static_table(struct static_hash_table *ptable, /*FILE *fp,*/ const char * szTableName)
{
int i;
int counter;
struct static_hash_node *p;
const char *szkey;
const char *szdata;
const char *szkeyquote;
const char *szunicode;
char * szchartype;
char * szcmpfn;
int ideal_size;
FILE *fp;
counter=1;
ideal_size = choose_static_hash_size(ptable);
if (g_nUnicode)
{
szchartype = "wchar_t";
szcmpfn = "wcscmp";
}
else
{
szchartype = "char";
szcmpfn = "strcmp";
}
fp = fopen(g_szOutFile, "wb");
if (!fp)
{
printf("could not open file for write: %s\r\n", g_szOutFile);
return;
}
fprintf(fp, "#include <string.h>\r\n\r\n");
fprintf(fp, "%.*s", g_nPreamble, g_szpreamble);
fprintf(fp, "class %s\r\n"
"{\r\n"
"public:\r\n\r\n"
" struct HashNode\r\n"
" {\r\n"
" %s * key;\r\n"
" unsigned long hash;\r\n"
" size_t link;\r\n"
" size_t entries;\r\n"
" %s data;\r\n"
" };\r\n"
"\r\n"
"protected:\r\n"
" const static HashNode m_data[%d];\r\n"
" const static size_t m_size = %d;\r\n"
" const static size_t m_tableSize = %d;\r\n"
"\r\n"
"public:\r\n\r\n"
" static unsigned long Hash( const %s * sz )\r\n"
" {\r\n"
" unsigned long hash;\r\n"
" hash = 0;\r\n"
" while ( *sz != 0 )\r\n"
" {\r\n"
" hash = (hash<<3)+hash+(*sz);\r\n"
" sz++;\r\n"
" }\r\n"
" return hash;\r\n"
" }\r\n"
"\r\n"
" static const HashNode * %s( const %s * key )\r\n"
" {\r\n"
" unsigned long hash;\r\n"
" const HashNode * p;\r\n"
" unsigned long index;\r\n"
" hash = Hash(key);\r\n"
" index = hash %% m_size;\r\n"
" p = &m_data[index];\r\n"
" while (p->key)\r\n"
" {\r\n"
" if (p->hash==hash && !%s(key, p->key))\r\n"
" break;\r\n"
"\r\n"
" if (p->link)\r\n"
" {\r\n"
" p = &m_data[p->link];\r\n"
" }\r\n"
" else\r\n"
" {\r\n"
" p = 0;\r\n"
" break;\r\n"
" }\r\n"
" }\r\n"
"\r\n"
" if (p && p->key)\r\n"
" return p;\r\n"
" return NULL;\r\n"
" }\r\n"
"};\r\n"
"\r\n"
"const %s::HashNode %s::m_data[%d] =\r\n"
"{\r\n",
g_szClass,
szchartype,
g_szData,
ptable->max_size+ptable->non_root_entries,
ptable->max_size,
ptable->size,
szchartype,
g_szLookup,
szchartype,
szcmpfn,
g_szClass,
g_szClass,
ptable->max_size+ptable->non_root_entries
);
// fprintf(fp, "const static static_hash_node %s_data[%d] = \r\n{\r\n", szTableName, size);
// fprintf(fp, "static struct static_hash_node %s_data[%d] = \r\n{\r\n", szTableName, ptable->max_size+ptable->non_root_entries);
// initial loop
for (i=0; i<ptable->max_size; i++)
{
szkey = ptable->pdata[i].key;
szdata = ptable->pdata[i].data;
if (!szkey)
{
szkey = "0";
szkeyquote = "";
szunicode = "";
}
else
{
if (g_nUnicode)
szunicode = "L";
else
szunicode = "";
szkeyquote = "\"";
}
if (!szdata)
{
szdata = "";
// szdataquote = "";
}
// else
// szdataquote = "\"";
// fprintf(fp, "{ %s, %s, %u, %u },"
fprintf(fp, "\t{ %s%s%s%s, 0x%.08x, %u, %u, %s },\r\n",
szunicode,
szkeyquote,
szkey,
szkeyquote,
ptable->pdata[i].hash,
ptable->pdata[i].entries ? ptable->max_size+counter-1 : 0,
ptable->pdata[i].entries,
szdata);
counter+= ptable->pdata[i].entries;
}
counter = ptable->max_size+1;
// secondary loop (handles collisions)
for (i=0; i<ptable->max_size; i++)
{
p = &ptable->pdata[i];
p = (struct static_hash_node *)(p->link);
while (p)
{
szkey = p->key;
szdata = p->data;
if (!szkey)
{
szkey = "0";
szkeyquote = "";
szunicode = "";
}
else
{
if (g_nUnicode)
szunicode = "L";
else
szunicode = "";
szkeyquote = "\"";
}
if (!szdata)
{
szdata = "";
// szdataquote = "";
}
// else
// szdataquote = "\"";
// fprintf(fp, "{ %s, %s, %u, %u },"
fprintf(fp, "\t{ %s%s%s%s, 0x%.08x, %u, %u, %s },\r\n",
szunicode,
szkeyquote,
szkey,
szkeyquote,
p->hash,
p->link ? counter : 0,
0,
szdata);
counter++;
p = (struct static_hash_node *)(p->link);
}
}
fprintf(fp, "};\r\n\r\n");
#if 0
fprintf(fp, "struct static_hash_table %s_table = {"
" %s_data,"
" %d,"
" %d,"
" %d,};",
szTableName,
szTableName,
ptable->size,
ptable->max_size,
ptable->non_root_entries);
#endif
fclose(fp);
}
#if 0
struct static_hash_node * static_lookup(struct static_hash_table *ptable, const char *key, int *found, unsigned long *phash, unsigned long *pindex)
{
unsigned long hash;
struct static_hash_node *p;
unsigned long index;
*found = 0;
hash = hash_string(key);
if (phash)
*phash = hash;
index = hash % ptable->max_size;
p = &ptable->pdata[index];
while (p->key)
{
if (p->hash==hash && !strcmp(key, p->key))
{
*found = 1;
break;
}
if (p->link)
p = &ptable->pdata[p->link];
else
break;
}
if (pindex)
*pindex = index;
return p;
}
#endif
int all_hashes_unique(struct static_hash_table *ptable)
{
int i;
int j;
struct static_hash_node *p;
struct static_hash_node *p2;
for (i=0; i<ptable->max_size; i++)
{
p = &ptable->pdata[i];
while (p != 0)
{
if (!p->key)
{
break;
}
for (j=0; j<ptable->max_size; j++)
{
p2 = &ptable->pdata[j];
while (p2 != 0)
{
if (p2 != p && p2->hash==p->hash)
{
return 0;
}
if (p2->link)
p2 = (struct static_hash_node *)(p2->link);
else
p2 = 0;
}
}
if (p->link)
p = (struct static_hash_node *)(p->link);
else
p = 0;
}
}
return 1;
}
void print_usage(int i)
{
printf("usage: static_hash /i infile /o outfile [/c classname] [/d datatype] [/l lookupfunction] [/w] [/v]\r\n\r\n"
"/i infile - the input file (required)\r\n"
"/o outfile - the output file (required)\r\n"
"/c classname - the static hash class (optional - defaults to CStaticHash)\r\n"
"/d datatype - the datatype stored in the has (optional - defaults to char*)\r\n"
"/l lookupfunction - the name of the generated lookup function (optional - defaults to Lookup)\r\n"
"/v - assume no lookups with invalid keys (optional - defaults to false)\r\n"
"/w - use UNICODE keys\r\n");
exit(i);
}
void parse_cmd_line(int argc, char * argv[])
{
int i;
for (i=1; i<argc; i++)
{
if (argv[i][0] != '/')
{
printf("unknown option: %s\n", argv[i]);
print_usage(1);
}
switch(argv[i][1])
{
case 'C': case 'c':
{
if (++i >= argc)
{
printf("missing argument: %s\n", argv[i-1]);
print_usage(1);
}
strcpy(g_szClass, argv[i]);
break;
}
case 'D': case 'd':
{
if (++i >= argc)
{
printf("missing argument: %s\n", argv[i-1]);
print_usage(1);
}
strcpy(g_szData, argv[i]);
break;
}
case 'L': case 'l':
{
if (++i >= argc)
{
printf("missing argument: %s\n", argv[i-1]);
print_usage(1);
}
strcpy(g_szLookup, argv[i]);
break;
}
case 'V': case 'v':
{
g_nAssumeValid = 1;
break;
}
case 'W': case 'w':
{
g_nUnicode = 1;
break;
}
case 'I' : case 'i':
{
if (++i >= argc)
{
printf("missing argument: %s\n", argv[i-1]);
print_usage(1);
}
strcpy(g_szInFile, argv[i]);
break;
}
case 'O' : case 'o':
{
if (++i >= argc)
{
printf("missing argument: %s\n", argv[i-1]);
print_usage(1);
}
strcpy(g_szOutFile, argv[i]);
break;
}
default:
break;
}
}
if (!g_szClass[0])
{
strcpy(g_szClass, "CStaticHash");
}
if (!g_szLookup[0])
{
strcpy(g_szLookup, "Lookup");
}
if (!g_szOutFile[0])
{
printf("must specify output file\n");
print_usage(1);
}
if (!g_szInFile[0])
{
printf("must specify input file\n");
print_usage(1);
}
}
int preprocess_file(char **pszfile)
{
char *szfile;
char *szpct;
char *szendln;
szfile = *pszfile;
while (1)
{
szpct = strchr(szfile, '%');
szpct++;
if (!strncmp(szpct, "class=", sizeof("class=")-1))
{
szpct+= sizeof("class=")-1;
szendln = strchr(szpct, '\n');
if (!szendln)
goto error;
memcpy(g_szClass, szpct, szendln-szpct);
g_szClass[szendln-szpct] = '\0';
if (*(szendln-1) == '\r')
{
g_szClass[szendln-szpct-1] = '\0';
}
szfile = szendln+1;
continue;
}
if (!strncmp(szpct, "type=", sizeof("type=")-1))
{
szpct+= sizeof("type=")-1;
szendln = strchr(szpct, '\n');
if (!szendln)
goto error;
memcpy(g_szData, szpct, szendln-szpct);
g_szData[szendln-szpct] = '\0';
if (*(szendln-1) == '\r')
{
g_szData[szendln-szpct-1] = '\0';
}
szfile = szendln+1;
continue;
}
if (!strncmp(szpct, "preamble", sizeof("preamble")-1))
{
szpct+= sizeof("preamble")-1;
szendln = strchr(szpct, '\n');
if (!szendln)
goto error;
g_szpreamble = szendln+1;
szpct = strchr(szendln, '%');
if (!szpct)
goto error;
g_nPreamble = szpct-g_szpreamble;
szfile = szpct;
// printf("%.*s", g_nPreamble, g_szpreamble);
continue;
}
if (!strncmp(szpct, "data", sizeof("data")-1))
{
szendln = strchr(szpct, '\n');
if (!szendln)
goto error;
szfile = szendln+1;
break;
}
}
*pszfile = szfile;
return 1;
error:
printf("bad input file\r\n");
return 0;
}
#ifndef NO_MAIN
int main(int argc, char * argv[])
{
struct static_hash_table tbl;
struct input_table intbl;
struct input_data *pdata;
long length;
FILE *fp;
char * szfile;
char * szfileorg;
char * szend;
int ideal_size;
parse_cmd_line(argc, argv);
memset(&tbl, 0x00, sizeof(tbl));
memset(&intbl, 0x00, sizeof(intbl));
pdata = 0;
fp = fopen(g_szInFile, "rb");
if (!fp)
{
printf("could not open file for read: %s\r\n", g_szInFile);
return 1;
}
length = _filelength(_fileno(fp));
szfile = (char *) malloc(length*sizeof(char));
if (!szfile)
{
printf("out of memory\r\n");
return 1;
}
fread(szfile, length, 1, fp);
szend = szfile+length;
szfileorg = szfile;
if (!preprocess_file(&szfile))
{
return 1;
}
while (szfile != szend)
{
pdata = add_input_data(&intbl);
if (!pdata)
{
printf("out of memory\r\n");
return 1;
}
if (!get_input_from_line(pdata, &szfile))
{
printf("bad input file\r\n");
return 1;
}
// printf("%.*s, %.*s\r\n", pdata->keylen, pdata->key, pdata->datalen, pdata->data);
}
pdata = intbl.phead;
ideal_size = 2*(intbl.size);
create_runtime_hash(&tbl, ideal_size);
while (pdata)
{
set_runtime_element(&tbl, pdata->key, pdata->keylen, pdata->data, pdata->datalen);
pdata = pdata->next;
}
generate_static_table(&tbl, "soap_types");
destroy_runtime_hash(&tbl);
destroy_input_table(&intbl);
free(szfileorg);
fclose(fp);
#if 0
create_runtime_hash(&tbl, 17);
set_runtime_element(&tbl, "BSTR", "string");
set_runtime_element(&tbl, "int", "int");
set_runtime_element(&tbl, "long", "int");
set_runtime_element(&tbl, "char", "byte");
set_runtime_element(&tbl, "short", "short");
set_runtime_element(&tbl, "__int8", "byte");
set_runtime_element(&tbl, "__int16", "short");
set_runtime_element(&tbl, "__int32", "int");
set_runtime_element(&tbl, "__int64", "long");
set_runtime_element(&tbl, "float", "float");
set_runtime_element(&tbl, "double", "double");
set_runtime_element(&tbl, "unsigned int", "unsignedInt");
set_runtime_element(&tbl, "unsigned long", "unsignedInt");
set_runtime_element(&tbl, "unsigned char", "unsignedByte");
set_runtime_element(&tbl, "unsigned short", "unsignedShort");
set_runtime_element(&tbl, "unsigned __int8", "unsignedByte");
set_runtime_element(&tbl, "unsigned __int16", "unsignedShort");
set_runtime_element(&tbl, "unsigned __int32", "unsignedInt");
// printf("%d\n", all_hashes_unique(&tbl));
generate_static_table(&tbl, "soap_types");
destroy_runtime_hash(&tbl);
#endif
}
#endif