diablo2oo2 Posted March 14, 2012 Posted March 14, 2012 (edited) I was missing a comfortable way to manage complex data structures in MASM.Java coders will know the HashTable class, which is very useful to store data.i coded something similar with more functions for MASM and other programming languages.features:-it will organize memory itself (will use the windows Heap functions)-like in java you can access items via a key which can be a String or an integer-support for nested hashtables (so you can create very easy complex data trees)-save/load the hashtable to disk or memory (with nested hashtables)the example will show how to create following hashtable structure:; ht_1; |; +-0-->"hello 1"; +-1-->"hello 2"; +-2-->"hello 3"; +-"string key"-->"hello 4"; |; +-"ht_2"--->ht_2; |; +-0-->"i am in the second hashtable"; +-123->binary_datahashtable.zip Edited March 15, 2012 by diablo2oo2 1
diablo2oo2 Posted March 14, 2012 Author Posted March 14, 2012 Congratulations on reinventing the wheel I guess hehe, sure its nothing new. but i really missed this feature when i was cooding with MASM. so now you i have a library to save very easy project data structures.
mudlord Posted March 18, 2012 Posted March 18, 2012 Nice.With adding binary data, do we need to check the size of binary data when retrieving, or does your library return size when getting the data?
diablo2oo2 Posted March 18, 2012 Author Posted March 18, 2012 (edited) i have to admit its not a real hashtable, but its still useful.With adding binary data, do we need to check the size of binary data when retrieving, or does your library return size when getting the data?there are two functions to get the data from the table.;this one copy the data to a destination buffer and returns the sizeht_copy_item_data proc public uses ebx _ht,_key,_options,_dest fn ht_get_item,_ht,_key,_options .if eax mov ebx,eax .if [ebx].HT_ITEM.i_options & ITEM_DWORD mov edx,_dest m2m [edx],[ebx].HT_ITEM.i_data .else fn RtlMoveMemory,_dest,[ebx].HT_ITEM.i_data,[ebx].HT_ITEM.i_size .endif mov eax,[ebx].HT_ITEM.i_size ;return size .endif retht_copy_item_data endp;and this one just returns a pointer to the data,which is stored in the table;if the data is just a dword value (it will return directly the value and not a pointer)ht_get_item_data proc public uses ebx _ht,_key,_options fn ht_get_item,_ht,_key,_options .if eax mov ebx,eax mov eax,[ebx].HT_ITEM.i_data .endif retht_get_item_data endp Edited March 18, 2012 by diablo2oo2
diablo2oo2 Posted March 19, 2012 Author Posted March 19, 2012 (edited) Brilliant Any chance of a C header? hmm , can do it, but i cant promise that it works. i think your c is better than mine. i would like to translate. but how to handle different returntypes and function parameters? i know in java its possible, but i have no idea about c. Edited March 19, 2012 by diablo2oo2
Killboy Posted March 19, 2012 Posted March 19, 2012 In C, casting to and from void* is as close as it gets.
diablo2oo2 Posted March 19, 2012 Author Posted March 19, 2012 so far the header./* NOT WORKING ! NOT FINISHED ! * to do: * handle different return types & parameters */#define ITEM_STRING_KEY 1HANDLE __stdcall ht_create(); void __stdcall ht_close(HANDLE); void __stdcall ht_close_all(HANDLE); HANDLE __stdcall ht_clone(HANDLE); DWORD __stdcall ht_size(HANDLE);void __stdcall ht_put(HANDLE,DWORD,LPBYTE,DWORD,DWORD); void __stdcall ht_put_string(HANDLE,DWORD,LPSTR,DWORD); void __stdcall ht_put_dword(HANDLE,DWORD,DWORD,DWORD); void __stdcall ht_put_hashtable(HANDLE,DWORD,HANDLE,DWORD);void* __stdcall ht_get_item_data(HANDLE,DWORD,DWORD); DWORD __stdcall ht_get_item_size(HANDLE,DWORD,DWORD);DWORD __stdcall ht_copy_item_data(HANDLE,DWORD,DWORD,LPBYTE); void __stdcall ht_remove(HANDLE,DWORD,DWORD); void* __stdcall ht_memorydump_create(HANDLE,LPDWORD);void __stdcall ht_memorydump_close(HANDLE); HANDLE __stdcall ht_create_from_memorydump(LPVOID);DWORD __stdcall ht_write_to_file(HANDLE,LPSTR); HANDLE __stdcall ht_read_from_file(LPSTR);not sure how to define the functions for different parameters:ht_put(table_1,123,data,datasize,NULL);orht_put(table_1,"123",data,datasize,ITEM_STRING_KEY);here you can use DWORD or a String for the second parameter!
atom0s Posted March 30, 2012 Posted March 30, 2012 Something like this should help you out diablo, this is how I would convert your inc to C/C++ typedef struct _MD5_CHECKSUM { DWORD dword_1; DWORD dword_2; DWORD dword_3; DWORD dword_4;} MD5_CHECKSUM, *LPMD5_CHECKSUM;typedef struct _HT_HEADER { DWORD ht_head_sig_1; DWORD ht_head_sig_2; DWORD ht_heap; DWORD ht_items; DWORD ht_itemcount; DWORD ht_itemsize; DWORD ht_compareto; MD5_CHECKSUM ht_las_md5;} HT_HEADER, *LPHT_HEADER;HT_HEADER* __stdcall ht_create( void );void __stdcall ht_close( HT_HEADER* );void __stdcall ht_close_all( HT_HEADER* ); That's just for the first few calls, but from there it should be easy to figure out the rest. I tested these functions and they worked properly for me using my method posted here.
diablo2oo2 Posted March 30, 2012 Author Posted March 30, 2012 Something like this should help you out diablo, this is how I would convert your inc to C/C++ typedef struct _MD5_CHECKSUM { DWORD dword_1; DWORD dword_2; DWORD dword_3; DWORD dword_4;} MD5_CHECKSUM, *LPMD5_CHECKSUM;typedef struct _HT_HEADER { DWORD ht_head_sig_1; DWORD ht_head_sig_2; DWORD ht_heap; DWORD ht_items; DWORD ht_itemcount; DWORD ht_itemsize; DWORD ht_compareto; MD5_CHECKSUM ht_las_md5;} HT_HEADER, *LPHT_HEADER;HT_HEADER* __stdcall ht_create( void );void __stdcall ht_close( HT_HEADER* );void __stdcall ht_close_all( HT_HEADER* ); That's just for the first few calls, but from there it should be easy to figure out the rest. I tested these functions and they worked properly for me using my method posted here. but the HT_HEADER structure is not public, so just define it as HANDLE is enough.
atom0s Posted March 31, 2012 Posted March 31, 2012 (edited) Just a heads up, the build lib/dll don't export ht_close_all, it's missing from the .def file.Here's a full C/C++ header finished and tested:#ifndef __HASHTABLE_H_INCLUDED__#define __HASHTABLE_H_INCLUDED__#pragma comment( lib, "hashtable.lib" )#include <Windows.h>#define ITEM_STRING_KEY 1#define ITEM_DWORD 2#define ITEM_HASHTABLE 4#define ITEM_MD5_KEY 8#define ITEM_DATA_POINT 16#ifdef USE_HASH_STRUCTURES typedef struct _MD5_CHECKSUM { DWORD dword_1; DWORD dword_2; DWORD dword_3; DWORD dword_4; } MD5_CHECKSUM, *LPMD5_CHECKSUM; typedef struct _HT_HEADER { DWORD ht_head_sig_1; DWORD ht_head_sig_2; DWORD ht_heap; DWORD ht_items; DWORD ht_itemcount; DWORD ht_itemsize; DWORD ht_compareto; MD5_CHECKSUM ht_las_md5; } HT_HEADER, *LPHT_HEADER; #define HASHHANDLE HT_HEADER*#else #define HASHHANDLE HANDLE#endifHASHHANDLE __stdcall ht_create( void );void __stdcall ht_close( HASHHANDLE );void __stdcall ht_close_all( HASHHANDLE );HASHHANDLE __stdcall ht_clone( HASHHANDLE );DWORD __stdcall ht_size( HASHHANDLE );void __stdcall ht_put( HASHHANDLE, DWORD, LPVOID, DWORD, DWORD );void __stdcall ht_put_string( HASHHANDLE, LPVOID, const char*, DWORD );void __stdcall ht_put_dword( HASHHANDLE, DWORD, DWORD, DWORD );void __stdcall ht_put_hashtable( HASHHANDLE, const char*, HASHHANDLE, DWORD );LPVOID __stdcall ht_get_item_data( HASHHANDLE, LPVOID, DWORD );void __stdcall ht_get_item_size( HASHHANDLE, LPVOID, DWORD );void __stdcall ht_copy_item_data( HASHHANDLE, DWORD, DWORD, LPVOID );LPVOID __stdcall ht_memorydump_create( HASHHANDLE, DWORD );void __stdcall ht_memorydump_close( LPVOID );void __stdcall ht_create_from_memorydump( LPVOID );void __stdcall ht_write_to_file( HASHHANDLE, const char* );HASHHANDLE __stdcall ht_read_from_file( const char* );#endif // __HASHTABLE_H_INCLUDED__Example converted to C:// This is optional, to use the actual structures// for debugging purposes..#define USE_HASH_STRUCTURES#include <Windows.h>#include <stdio.h>#include "hashtable.h"BYTE btBinaryData[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };int __cdecl main( int argc, char* argv[] ){ HASHHANDLE ht_1; HASHHANDLE ht_2; LPVOID lpData; ht_1 = ht_create(); ht_2 = ht_create(); printf( "creating a hashtable and saving to file..\r\n" ); ht_put_string( ht_1, (LPVOID) 0, "hello 1", NULL ); ht_put_string( ht_1, (LPVOID) 1, "hello 2", NULL ); ht_put_string( ht_1, (LPVOID) 2, "hello 3", NULL ); ht_put_string( ht_1, "string key", "hello 4", ITEM_STRING_KEY ); ht_put_hashtable( ht_1, "ht_2", ht_2, ITEM_STRING_KEY ); ht_put_string( ht_2, (LPVOID) 0, "i am in the second hashtable", NULL ); ht_put( ht_2, 123, &btBinaryData, sizeof( btBinaryData ), NULL ); ht_write_to_file( ht_1, "file.bin" ); ht_close( ht_1 ); ht_close( ht_2 ); printf( "opening hashtable from saved file..\r\n" ); ht_1 = ht_read_from_file( "file.bin" ); lpData = ht_get_item_data( ht_1, (LPVOID) 0, NULL ); printf( (const char*) lpData ); printf( "\r\n" ); lpData = ht_get_item_data( ht_1, (LPVOID) 1, NULL ); printf( (const char*) lpData ); printf( "\r\n" ); lpData = ht_get_item_data( ht_1, (LPVOID) 2, NULL ); printf( (const char*) lpData ); printf( "\r\n" ); lpData = ht_get_item_data( ht_1, "string key", ITEM_STRING_KEY ); printf( (const char*) lpData ); printf( "\r\n" ); ht_2 = ht_get_item_data( ht_1, "ht_2", ITEM_STRING_KEY ); lpData = ht_get_item_data( ht_2, (LPVOID) 0, NULL ); printf( (const char*) lpData ); printf( "\r\n" ); lpData = ht_get_item_data( ht_2, (LPVOID) 123, NULL ); printf( (const char*) lpData ); printf( "\r\n" ); //ht_close_all( ht_1 ); // This wont work at the moment since the lib doesn't export it. return 0;} Edited March 31, 2012 by atom0s
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now