Enumeration of supported models

Jef Driesen jefdriesen at telenet.be
Wed Apr 4 14:55:08 UTC 2012


Hi,

I have been prototyping the device enumeration code (item #14 on the 
roadmap). I have a couple of questions for which I would like to get 
some feedback from users of the api. It's mainly about the naming of 
functions and data structures.

> typedef dc_model_t {
>        const char *manufacturer;
>        const char *name;
>        device_type_t type;
>        unsigned int model;
> } dc_model_t;

I'm not that satisfied with the name "dc_model_t". I think it's too 
easy to confuse with the model code. Does anyone have some suggestions 
for a better name? The only alternative I came up with is the more 
general "dc_descriptor_t".

A similar question for the "device_type_t" and "parser_type_t" enums. 
As explained before (see item #10 on the roadmap), I would like to merge 
both into a single enum. A simple change, but I'm still looking after a 
good general name for the new enum. Currently I have two suggestions: 
"dc_backend_t" or "dc_family_t". The dc_backend_t name feels a bit 
heavyweight to my taste, because I usually use the term backend to refer 
to the device/parser handle itself, rather than its type. Any other 
suggestions?

And last but not least, how about the "manufacturer" and "name" fields? 
Everywhere else I'm using the term "vendor" instead of "manufacturer" 
(e.g. the vendor extensions in the events). Which name would you prefer 
here? And would you keep the "name" field, or rename it into "product". 
The full name of the device is in fact the concatenation of the 
manufacturer and the product name (e.g. Suunto Vyper). The reason for 
using two separate fields is to allow easy grouping by manufacturer in a 
GUI application. I assume most applications will use such grouping 
rather than showing one huge list to choose from, so having the two 
separated makes sense I think.

> One possibility would be an iterator style api, similar to this:
>
> dc_iterator_t *iterator = dc_get_supported_models ();

For retrieving the iterator, which name is preferred?

dc_xxx_get_iterator (xxx, &iterator)
dc_xxx_iterator (xxx, &iterator)
dc_xxx_iterate (xxx, &iterator)

I usually consider a getter (or setter) function as a lightweight 
function that just accesses some internal field of an opaque object. But 
depending on the underlying implementation this function could perform 
some more heavyweight action. Imagine we use the iterator concept for 
downloading dives too. There are several devices that maintain an index 
with the available dives. This index needs to be downloaded first to be 
able to locate the actual dive profiles. Downloading this index could be 
done when getting the iterator, or it could be delayed until you 
actually try to download the first dive. In the first case getting the 
iterator will perform some heavyweight I/O, while in the second case 
it's only creating a placeholder and the real work is done in the 
dc_iterator_next() function.

For functions that perform real work, I usually use a verb. For example 
the dc_device_read function. But in this case, it's not really the 
dc_xxx_iterate() function that will be doing the enumeration. The 
dc_xxx_iterator() function would fall somewhere in between the other two 
options.

> while (dc_iterator_next (iterator)) {
>      dc_model_t *model = dc_iterator_current (iterator);
>
>      /* Do stuff here */
>      dc_model_get_name (model);
>      dc_model_get_manufacturer (model);
>      ...
> }

For the iterator loop, an alternative would be to integrate the 
dc_iterator_current() functionality directly into the 
dc_iterator_next(), like this:

while (dc_iterator_next (it, &item)) {
    ...
}

The benefit would be a little less overhead, because there is only one 
function call left. I don't see any disadvantages. Of course you can't 
iterate without fetching the item, but why would you need to do that in 
the first place?

And last but not least, which status code should the dc_iterator_next() 
return to indicate: (a) an item has been returned, (b) the iterator has 
reached past the last item (e.g. an EOF condition).

Either we introduce some new status code for the EOF condition:

while ((status = dc_iterator_next (it, &item)) == DC_STATUS_SUCCESS) {
    ...
}
if (status != DC_STATUS_DONE) {
    /* Handle errors */
}

Or we use the new status code to indicate a data item has been 
retrieved:

while ((status = dc_iterator_next (it, &item)) == DC_STATUS_DATA) {
    ...
}
if (status != DC_STATUS_SUCCESS) {
    /* Handle errors */
}

Remember DC_STATUS_SUCCESS is equal to zero, and error codes are 
negative. So I think it makes sense to use a positive value (e.g. the 
number one) for this new status code, so it is clearly distinct from the 
real errors.

Jef




More information about the Devel mailing list