Dev:Module Storage

= Introduction = The ModData system allows you attach custom data to clients, channel, channel members or channel memberships.

= Registering custom data = Register the custom data by calling the following from  (similar like registering channel modes). ModDataInfo *example_md = NULL;

DLLFUNC int MOD_INIT(example)(ModuleInfo *modinfo) { ModDataInfo mreq;

memset(&mreq, 0, sizeof(mreq)); mreq.type = MODDATATYPE_CLIENT; mreq.name = "example"; mreq.sync = 1; mreq.free = example_free; mreq.serialize = example_serialize; mreq.unserialize = example_unserialize; example_md = ModDataAdd(modinfo->handle, mreq);

First, you select where to attach your custom data to, by setting type which may be one of: Detail: The last two are less common, but in case you wonder, the difference between Member and Membership is that Member is found by looking at the channel and iterating through the member list (users that are a member of the channel), while Membership is found by looking at the user and then iterating through the channel list (channels the user is a member of). Depending on the type of access you use either MODDATATYPE_MEMBER, MODDATATYPE_MEMBERSHIP or sometimes both.
 * MODDATATYPE_CLIENT: attach data to clients (these clients may be persons, servers, etc)
 * MODDATATYPE_CHANNEL: attach data to channels
 * MODDATATYPE_MEMBER: attach data to Member structures
 * MODDATATYPE_MEMBERSHIP: attach data to Membership structures.

Second, you give your module data entry an unique name (within each MODDATATYPE_*'s namespace).

Third, there's a field called sync. This decides whether you want to sync all ModData of the clients & channels upon server-linking.

Finally, the following functions are registered:
 * free
 * serialize (optional: if sync=0 and you don't use any moddata_xxx_set/moddata_xxx_get functions then you don't need this)
 * unserialize (optional: see serialize)

The functions are described below. Be sure to also read the section on Acquiring and storing moddata as well.

Free
This function is called when the ModData for this user/client/member needs to be freed and nullified. Example code if you use simple strings: void example_free(ModData *m) {   if (m->str) MyFree(m->str); m->str = NULL; }

Serialize
This function is called when you want to fetch a ModData and convert it to a string. Usage and example (using strings): char *example_serialize(ModData *m) {   if (!m->str) return NULL; return m->str; }

Unserialize
This function is called when there's data to store in your ModData. You receive a string and you convert it to your own (binary) data if necessary. Example using strings: void example_unserialize(char *str, ModData *m) {   if (m->str) MyFree(m->str); m->str = strdup(str); }

= Acquiring and storing moddata for a client =

Direct access
This method is very fast and easy to use (especially if you store integers) moddata_client(acptr, example_md).something = xyz; Where:
 * acptr: The client you want to change a property of
 * example_md: Is a global variable in the module, returned by ModDataAdd - see earlier on this page

moddata_client gives you a ModData union with the following members (pick one instead of something):
 * i: to store an integer
 * l: to store a long integer
 * str: to store a string
 * ptr: to store a pointer (void *), allowing any other type of storage

So, to store an integer for example you can do: moddata_client(acptr, example_md).i = 1234;

And, to store a string: moddata_client(acptr, example_md).str = strdup("1234"); // note: better free first if necessary ;)

Finally, if you have some custom structure: SomeCustomType *custom = moddata_client(acptr, example_md).ptr; custom.one = 1234; if (custom.two) MyFree(custom.two); custom.two = strdup("lalala");

Indirect access (serializing/unserializing data)
We also offer a more 'high level' way to store and retrieve data. It uses the serialize/unserialize functions behind the scenes. It can be used if you want to get/set mod data from other modules or if you don't like the low level way for some reason. It's a slower method as it involves lookups for the variable name and the serialize/unserialize string conversions but since C is fast the difference in speed may not be noticeable.

To set: moddata_client_set_string(acptr, "example", "1234"); /* SET */ This will call your unserialize function to store the actual data.

To get: char *value = moddata_client_get_string(acptr, "example"); /* GET */ This will call your serialize function to acquire a serialized representation of the data. Note that value may be NULL at this point if there was no value set for "example".

= See also =
 * src/modules/certfp.c (Certificate fingerprint, using ModData on a client object)
 * src/modules/m_mdex.c (Example module, not compiled by default)