// // Copyright (c) Microsoft Corporation. All rights reserved. // #include #include 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; iptail) { 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; ipdata[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 \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; imax_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; imax_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; imax_size; i++) { p = &ptable->pdata[i]; while (p != 0) { if (!p->key) { break; } for (j=0; jmax_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) { 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