names

Tuesday, 26 April 2011
Here we describe naming conventions in C and C++ used in thorn, and the use of y to mean thorn. While this is fairly boring, it's useful to start with rules about symbols used.

y

Tuesday, 26 April 2011
Glyph y sometimes substitutes for glyph þ (thorn) which once had a sound like th. For example, phrase ye olde (cf wikipedia) uses y as a substitute for the original thorn. Accordingly, y is just a convenient replacement for thorn þ, and is sometimes used as a prefix.

virtual

Wednesday, 04 May 2011
The following pure virtual C++ class illustrates translation into equivalent C. Perhaps you note absence of a virtual destructor, even though this would make sense. The C version won't have a virtual destructor, and the C++ version typically never needs to destroy an instance using the base class type. So a virtual destructor is unnecessary.
namespace cy { // gratuitous namespace

class Ear { // listener for key/val notifications
public:
    virtual void notify(int32_t key, int32_t val) = 0;
};

}; // namespace cy
I use shorter name ear instead of more conventional name listener, because brevity is especially helpful after conversion to C. This also shows my preference for very short names—three or four letters is always better than seven or eight.

The C version below is a mechanical translation though done by hand. I think the above, but then I write the following instead when working in C. Obviously the C version is more verbose. A function pointer typedef is unnecessary. I simply prefer it. When only one method is virtual, the function pointer field appears inline in a base class. Three or more virtual methods typcially go in a separate vtable struct, which is rather more involved.
#ifndef cy_ear_S
#define cy_ear_S 1
typedef struct cy_ear_ cy_ear; /* forward declaration */
#endif

typedef void (*cy_ear_notify_fn)(cy_ear* e, int32_t key, int32_t val);

struct cy_ear_ { /* listener for key/val notifications */
    cy_ear_notify_fn  ear_notify_fn; /* virtual notify() */
};

static inline void cy_ear_notify(cy_ear* e, int32_t key, int32_t val) {
    (*e->ear_notify_fn)(e, key, val);
}
C does not require forward declarations for structs if you don't mind using the struct keyword every time you name the type. But I do mind. I prefer a C++ style where a keyword before type name is unnecessarily verbose. And I'm willing to suffer forward declaration boilerplate to get it. (It costs me no attention, and cut and paste costs almost nothing.)

lowercase

Wednesday, 04 May 2011
C symbols in thorn are typically lowercase with underscores. This style is well accepted by current peers at work. (It's expected and no one complains.) But I use uppercase suffixes in defines. Here's an example:
#define cy_ear_MAX 128
That may look strange compared to all uppercase, which is more conventional for defined constants. I'm sure you won't get confused. I like consistent namespace prefixes, and a class (or struct) is a namespace as far as I'm concerned.

concatenation

Wednesday, 04 May 2011
C function names can suffer from ambiguity caused by running all parts together in a row with no clear separation between namespace, class name, method name, and argument types. Consider the following example of overloaded constructors.
#ifndef cy_iov_S
#define cy_iov_S 1
typedef struct cy_iov_ cy_iov; /* forward declaration */
#endif

struct cy_iov_ {
    cy_u8*  iov_base; /* 1st byte in memory fragment */
    cy_u32  iov_len;  /* length of fragment in bytes */
};

static inline void cy_iov_ctor(cy_iov* v, const void* p, cy_u32 n) {
    v->iov_base = (cy_u8*) p;
    v->iov_len = n;
}
static inline void cy_iov_ctor_cstr(cy_iov* v, const char* cstr) {
    v->iov_base = (cy_u8*) cstr;
    v->iov_len = (cstr)? strlen(cstr) : 0;
}
Here you see ctor() means constructor, and overloading requires different names, typically by adding a suffix denoting argument types. The conventional name of thorn destructors in C is bye() instead of dtor() because that would look too similar to ctor().

If instead of iov the type name was fancy_iov, the first constructor would be:
static inline void
cy_fancy_iov_ctor(cy_fancy_iov* v, const void* p, cy_u32 n) {
    v->iov_base = (cy_u8*) p;
    v->iov_len = n;
}
As you can see, nothing marks end of noun and start of verb, assuming types are usually nouns while methods are verbs. But the type of the first argument indirectly shows you how much of the method name is type prefix. You might dislike this style of naming C methods. I find it verbose myself, but it's not too horrible, and seems clear.

comically short names

Sunday, 08 May 2011
Thorn sometimes uses extremely short names, but usually just in alternative C++ class names. Very few C types consist of just one or two letters. Consider queues:

queues

Since queue is pronounced the same as q, thorn uses just one letter. And qe means queue element: a member inside a queue.
typedef struct cy_qe_ { /* queue element */
    cy_qe*    qe_next;
    cy_qe*    qe_prev;
    cy_q*     qe_q;
} cy_qe;

typedef struct cy_q_ { /* queue: double-ended linked list of elements */
    cy_qe       q_head;
    const char* q_name;
    cy_u32      q_size;
} cy_q;
These structs are used often in thorn: everywhere a list is maintained, and some parts have a lot of lists. It helps to learn q means queue early. As a suffix, a q at the end of a symbol means it is some kind of queue. For example, runq means run queue.