Imagine: A World Without Strcmp

Recently, I’ve been working on implementing the config file for DMP Photo Booth, and luckily for me, GLib has the answer for this: GKeyFile. GKeyFile is GLib’s implementation of those flat config files you tend to see in Linux applications:

#Some comment! [section] value=words some_bool=true

…like that. I happily set to work, satisfied that today was not the day that I’d have to begin dealing with FILE pointers. Unfortunately, though I don’t have to deal with straight up file IO, I do still have to deal with functions that will fail if you so much as look at them funny. All the functions of GKeyFile take a group and key name string to look up, and if you pass in a bad string, things go off the rails. At first I had planned to use #defined strings, but halfway through implementing input validation in my first access function, I thought that there must be a better way. Strings are “difficult” to compare against known values, and it all seemed like so much work!

Next, I thought of using magic integers, but I’d have to come up with some way to resolve them to a string. Since this was all starting to sound like the beginnings of implementing a hash table, I turned to GLib for its implementation. This also seemed like more effort than it was worth. As I was poking around the docs, I found my answer!

Introducing Quark!

I’m talking about the GQuark. A GQuark functions in a similar manner to a hash table (in fact, if you dig through the source, you’ll see that GQuark uses a hash table.) GQuarks are a two-way association between a non-zero guint32 and a gchar * (A GQuark value of 0 resolves to NULL.) Basically, once you register a string as a quark, you can pass the GQuark object around and use it to obtain the string. You can also attempt to resolve a string to get its integer value if it has been registered. The best part about a GQuark is you can directly compare the GQuark object using operator==, avoiding a call to strcmp(), reducing boilerplate code.

Notable Functions

GQuarks do not have a lot of moving parts. Below are some important functions for using GQuark:

G_DEFINE_QUARK(some_string, function_name)

This macro defines a function named function_name_quark that returns a quark for “some_string”. Basically, this is your replacement for:

#define MAGIC_STRING_NAME "magic_string_literal"

Where you might use the MAGIC_STRING_NAME before, you can now just call your newly defined quark function! Notice up above that in the macro parameter, some_string is not in quotation marks. This is important; the function defined by the macro will strigify the first parameter. For example, if you enter this:

G_DEFINE_QUARK(The quick brown fox jumped over the lazy dog's back\n, dog_fox)

You’ll get a function:

GQuark dog_fox_quark()

…that returns a GQuark for the string:

"The quick brown fox jumped over the lazy dog's back\n"

The second thing to note about this macro is that it declares AND implements the function. In other words, it expands to something like this:

GQuark name_quark() { ...code... }

As you can see, it would be an error to place a semicolon behind the macro.

All of that may seem like a lot to remember, but if you want to define several quarks, it will save you hours of typing.

g_quark_to/from_string and friends

These functions are your GQuark manipulation functions. They will let you convert strings and GQuarks to each other. For instance, if you enter:

g_printf("%s\n", g_quark_to_string(some_quark));

You will print the string contained in some_quark. Pretty straight-forward.

Thread Safety

You may be thinking: “gee, this sounds like it uses a whole lot of globals! Is this thread safe?” I know I was, so I did a little investigation. Looking through the source for GQuark, all the functions that access global variables are protected by a mutex; therefore you may feel free to use this from multiple threads.

Trackbacks / Pingbacks

  1. DMP Photo Booth: Throw It All Out | Doing My Programming... - November 26, 2013

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: