Jump to content

Hash Tables


Tutorial

Recommended Posts

INTRODUCTION

 

Hash Tables is something that you find within mIRC itself. Theres a few commands that allow you to store data into a file that you can then retreive and use in whatever way you wish.

 

In my personal opionion , hash tables is the best thing Khaled added to mIRC. They have an unlimited potential and the process of your data is usually very fast.....in most cases i find the process time to be instant. Hense why I would always strongly recommand people to use Hash Tables to store data. But of course this is just my opionion, it's totally up to you on how you code and store data.

 

In the commands section, you will basically find all the commands related to hash tables. Now this is taken straight from mIRC's own help file but since not all scripts are released with the help file in them. I've added them here for your conveniance

 

The "How I Use" section is simply as it says. How I use them. I don't explain how i would use every hash table command, most of them I do use. This section just explains how i use the commands that I do use and what I general do with them.

 

snippets section is just a few pieces of code that you can play around with or change to suit your own needs. Basically do whatever you want to do with them.

 

Lastly learning hash tables has helped me alot and I got KiX to thank for that. He spent a good half hour or longer teaching me how best to use them. Much appreciated KiX

 

COMMANDS

 

/hmake -s <name> <N>

 

 

Creates a new hash table with N slots.

 

A hash table can store an unlimited number of items regardless of the N you choose, however the bigger N is, the faster it will work, depending on the number of items stored.

 

eg. if you expect that you'll be storing 1000 items in the table, a table of N set to 100 is quite sufficient.

 

The -s switch makes the command display the result.

 

/hfree -sw <name>

 

Frees an existing hash table.

 

The -w switch indicates that name is a wildcard, all matching tables are freed.

 

/hadd -smbczuN <name> <item> [data | &binvar]

 

 

Adds an item to an existing hash table.

 

If the item you're adding already exists, the old item is replaced.

 

The -m switch makes /hadd create the hash table if it doesn't already exist.

 

The -uN switch unsets the item after N seconds.

 

The -b indicates that you're adding a &binvar item to the hash table.

 

The -c switch chops the &binvar up to the first null value and treats it as plain text.

 

The -z switch decreases hash item once per second until it reaches zero and then unsets it.

 

The /hinc and /hdec commands use the same parameters as /hadd and increase or decrease the number value of an item.

 

When used with /hinc or /hdec, the -c switch increases or decreases the value once per second.

 

/hdel -sw <name> <item>

 

 

Deletes an item from a hash table.

 

The -w switch indicates that item is a wildcard, all matching items are freed.

 

/hload -sbni <name> <filename> [section]
/hsave -sbnioau <name> <filename> [section]

 

Load or save a table to/from a file.

 

These load/save plain text to a text file, with item and data on separate lines. $cr and $lf characters are stripped from text when saving as plain text.

 

The -b switch loads or saves binary files. $cr and $lf are preserved when saving as binary files.

 

You can use -n to load or save files as data only, with no items. When loading with -n each line of data is assigned an N item value, starting at N = 1.

 

/hsave also supports -o to overwite an existing file, and -a to append to an existing file.

 

By default /hsave excludes items that are in the /hadd -uN unset list, the -u switch forces it to include the unset items.

 

The -i switch treats the file as an ini file. You can specify an optional section name after the filename.

 

Note: /hload does not create the table, it must already have been created by /hmake.

 

$hget(name/N)

 

 

Returns name of a hash table if it exists, or returns the name of the Nth hash table.

 

Properties: size

 

$hget(moo).size returns the N size of table, as specified in /hmake

$hget(name/N, item)

 

 

Returns the data associated with an item in the specified hash table.

 

Properties: unset

 

The unset property returns the time remaining before an item is unset.

 

$hget(name/N, item, &binvar)

Assigns the contents of an item to a &binvar.

 

$hget(name/N, N).item

This allows you to reference the table as an index from 0 to N, in order to look up the Nth item in the table.

 

If N is zero, returns the total number of items in the table.

 

You can also reference the Nth data value directly with $hget().data.

 

Note: This method is provided as a convenience, it is not an efficient way to use the hash table.

 

$hfind(name/N, text, N, M)

Searches table for the Nth item name which matches text. Returns item name.

 

Properties: data

 

If you specify the .data property, searches for a matching data value.

 

M is optional, and can be:

 

n normal text comparison (default if M isn't specified)

w text is wildcard text

W hash table item/data is wildcard text

 

r text is regular expression

R hash table item/data is regular expression

 

HOW I MAKE AND LOAD

 

If you have looked at the commands, you will see before you add anything to a hash table, you need to "make" the hash table to begin with. This is acheived threw the command "hmake"

 

Since with hash tables you have to make the table and then load the previous table that you saved before. I use a alias like the one below to acheive this.

 

alias fserv.main.make { hmake fserv.main | hload fserv.main $+(",$scriptdirhashtables\fservmain.hsh,") }

 

As you can see, this makes a hash table called fserv.main and loads into that table, the contents found in fservmain.hsh .

 

To explain the $+(",$scriptdirhashtables\fservmain.hsh,") part . The remote that you are codeing into, is obviouslly stored in a specfic folder within your main mirc directory. The $scriptdir command takes you straight to that folder. Hense I have everything in a folder marked System. Within that folder is the remote .mrc file that im codeing on. Also within the System folder is another folder marked hashtables. The codeing above for $scriptdir, will go straight to the folder system which contains my .mrc file and then go into the hashtable folder and will look for the fservmain.hsh file in there. The $+(",,") part makes this work when there spaces in the path as well.

 

Now here I'll get you to run a test here

 

In your mirc type /hmake -s testing

 

You should see * Made hash table 'testing' (100)

 

The (100) part is what im interested in here. When you make a hash table, you can define a number which dictates how many items you can add to the table. But with what you just typed. i didn't define a number there, so mirc used the default number of 100 which equals 1000 items that can be added. I never bother with adding a number in as the default number is always going be more than sufficent.

 

To define a number of items, You would do this

 

/hmake -s testing 50

 

This means you can add 500 items then

 

Last thing, in your codeing, i would advise not having the -s switch, as this shows the hash table being made and loaded, which users of the addon or script your making, won't wish to see this all the time

 

HOW I ADD

 

I'll explain how your data is added and what format it is like.

 

If you have read the commands section, you will have seen that the command /hadd is what you use to add items and data to table

 

Now for a test, In your mirc type the following in order

 

1) /hmake -s testing

 

2) /hadd -s testing nicks nick1 nick2 nick3

 

On your active window, you should see the same as below

 

* Made hash table 'testing' (100)

* Added item 'nicks' to hash table 'testing'

 

As you can see, you made the hash table testing and added to the main item name "nicks" to it. Now you don't see the nick1 nick2 nick3 part but is in the hash table. To see the full information type the folowing

 

//echo -a $hget(testing,1).item $hget(testing,1).data

 

In your active window, you should now see the same as below

 

nicks nick1 nick2 nick3

 

Now I'll explain what you typed. The command $hget is what you use to retreive information stored.

 

$hget(testing,1).item . This returns the main item name for line 1 in the hash table named testing.

 

$hget(testing,1).data . This returns the data associated with the item name on line 1 in the hash table.

 

As you will see item can only ever be one word and have no spaces, where the data can be added in way you wish and does have a large scale of data that can be adding in there. If i remember correctly in a test i did awhile ago. I managed to fit roughly about 17 full paths and filenames in one line. You will see that should be more than enough room for you to work with.

 

Now when you returning information, you don't need to add .item or .data onto the end of the $hget. You can just use the following

 

$hget(testing,nicks)

 

The above will return the data associated with nicks

 

Well just decided to split this up into two sections. so click on the link to the left, How i use hash tables to see what i do with them.

 

HOW I USE

 

Theres two types of way i use hash tables to store data. Now I'll use an example to explain both ways. The example I'll use is codeing from my own channel protection.

 

FIRST WAY

 

The first way is , a single data word that defines something in the feature in my script.

 

Meaning for example in my own channel protection, the edit field where someone would define how many texts before the feature kicks/bans user for flooding.

 

I store this in the main hash table i use. Kinda like the variables section of mirc

 

Example:

 

on *:dialog:jacp:edit:*:{
if ( $did == 21 ) { hadd system cp.t.count $did(21).text | system.update }

 

When someone types in the edit field. this auto writes to the hash table named system. And it adds the item name "cp.t.count" and the data associated with the item, which is whatever is in that edit field.

 

The system.update is my alias to save the hash table. Read the section related to saving to see more information on that.

 

To return this information , on my init event for the channel protection, i have the line below in this event to add the information into the edit field again.

 

did -a jacp 21 $hget(system,cp.t.count)

 

You should already know about $hget, if not go back and read the previous section.

 

If i wished to delete this item from the hash table all together, I would just type the following or have this line on a button event in a dialog.

 

/hdel system cp.t.count

 

You don't need to type the data associated with the item to delete, just the item you wish to delete.

 

SECOND WAY

 

The second way i use hash tables is, say in my channel protection, i have a channels list that this feature will protect. So i have a line in my main hash table for this and it reads like below

 

ITEM: cp.chans DATA: chan1 chan2 chan3

 

As you can see, i have more than one field in my data information here. Hense it's not as simple to adjust this item line as it is with the above way.

 

I use 3 aliases to do the following , one allows me to add channel, one allows me to delete channel and one allows me to input information into a listbox

 

alias cp.add.chan {
var %cur = $hget(system,cp.chans)
var %new.chans = %cur $did(79).text
hadd system cp.chans %new.chans
did -r jacp 79
system.update
cp.get.chans
}

 

This alias above as you can see, sets a temp variable called %cur , with the data stored in the item marked cp.chans

 

Then i set another temp variable called %new.chans . This contains the current listed channels stored in the variable %cur and also the new channel that has been inputed in the edit field within the dialog.

 

Then i add the new information to the hash table named system

 

You will notice i don't delete previous information, thats cause i rarely have to delete a line from a hash table. As when you readd, it just auto removes previous information stored in cp.chans item line and adds the new information into there

 

the cp.get.chans is the alias i use to return the information associated with the cp.chans item line and that is shown below

 

alias cp.get.chans {
did -r jacp 82
var %cur = $hget(system,cp.chans)
var %i = 1
while ( $gettok(%cur,%i,32) ) {
var %chan = $ifmatch
did -a jacp 82 %chan
inc %i
}
}

 

Now you see that %cur temp variable is set with the channel list again. Then i use a while loop along with $gettok to return the information. You can read about while loops and $gettok in mircs own help file. But you do have the above alias you can copy and paste into your remote and change to suit your needs.

 

When I wish to delete a channel from my list , I use the alias below to do so

 

alias cp.del.chan {
var %cur = $hget(system,cp.chans)
var %rem = $did(jacp,82).seltext
var %new.chans = $remove(%cur,%rem)
hadd system cp.chans %new.chans
system.update
cp.get.chans
}

 

Yet again, i set the temp variable %cur but this time i also set another variable %rem . This is the line that I have selected in the listbox which gets set here

 

Then i use $remove command to remove the information stored in %rem from the channel list stored in %cur . Then obviouslly i readd to hash table and return the new information threw my cp.get.chans alias

 

HOW I SAVE/FREE

 

When you have added to a hash table, you would more and likely wish to save that information. Well the /hsave command is what you want to use.

 

I use a alias to save to hash table and an example is below

 

alias system.update { hsave -o system $+(",$scriptdirhashtables\system.hsh,") }

 

You would have seen the system.update alias listed in previous pieces of code i showed in other sections. This is it above and something i generally advise, is everytime you add something new to a hash table, always have a alias that saves the hash table as well.

 

The above code obviouslly saves the new information to the system.hsh table found in the hashtables folder. I'm sure you have already read the make/load hash table section and will already know about the use of $scriptdir and $+(",,")

 

The -o switch is needed everytime you save to a hash table, well in my opionion it is. As this switch overwrites the previous information stored in the hash table.

 

Now you may wish to free the information from mIRC's memory after you have used the data for whatever, this really depends on what your using the hash table for. With the above table in my example in mind here. This is basically my variables hash table, so i have this loaded all the time in my own script as its used alot threwout my script. Hense i only free the hash table when you shutdown the script.

 

But in other areas of my script, where i have hash tables that aren't used as much, i do use the /hfree command to free the information from memory. In the example below ive added the hfree line to the above example and shown how i would free the table if i wished to .

 

alias system.update { hsave -o system $+(",$scriptdirhashtables\system.hsh,") | hfree system }

 

Not much to it really, just a simple command to free the system hash table.

 

SNIPPET

 

;Instructions

 

if the hash table is needed to be made and loaded first

You will see a dialog appearing asking you to locate directory containing hash table

you want to make and load

 

if you want to make and load hash table first, then add "-z" to end

if you don't want to free hash table at end, then add a "-x" after the z

space in between the -z and -x , see usage below

 

if you previouslly saved the hash table as a binary file, data only or ini format

you will need to apply the respective switches for this, hense what the is for

-b = binary file , -n = data read only , -i = hash table treated like a ini file

 

USAGE: /get.hash -z -x

 

Now its very important you have 3 items after the hash table name, even if you don't want to

use a certain part. so any part you don't want to use, replace with a "no", see below

 

 

USAGE; /get.hash no no -x

 

alias get.hash {
window -ak(0) @hash
aline @hash Item $chr(9) $chr(9) Data
aline @hash ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var %hash.name = $1
var %switches = $2
if ( $3 == -z ) {
var %hashtable = $+(",$sfile($mircdir),")
hmake %hash.name
if ( %switches == no ) { hload %hash.name %hashtable }
else { hload %switches %hash.name %hashtable }
}
var %i = 1
while ( $hget(%hash.name,%i).item ) {
var %item = $ifmatch , %data = $hget(%hash.name,%i).data
aline @hash %item $chr(9) $chr(9) %data
inc %i
}
if ( $4 == -x ) { hfree %hash.name }
}

Link to comment
Share on other sites

×
×
  • Create New...