* mu-msg-fields: cleanup, use MuMsgFieldId rather than MuMsgField*

This commit is contained in:
Dirk-Jan C. Binnema 2010-11-20 14:41:21 +02:00
parent 7e96b1b483
commit de1deb4e80
2 changed files with 187 additions and 200 deletions

View File

@ -21,19 +21,19 @@
#include "mu-msg-fields.h"
/*
* note: the differences for our purposes between a xapian field and a term:
* - there is only a single value for some item in per document (msg), ie.
* one value containing the list of To: addresses
* - there can be multiple terms, each containing e.g. one of the To: addresses
* - searching uses terms, but to display some field, it must be in the
* value (at least when using MuMsgIter)
* note: the differences for our purposes between a xapian field and a
* term: - there is only a single value for some item in per document
* (msg), ie. one value containing the list of To: addresses - there
* can be multiple terms, each containing e.g. one of the To:
* addresses - searching uses terms, but to display some field, it
* must be in the value (at least when using MuMsgIter)
*/
enum _FieldFlags {
FLAG_GMIME = 1 << 1, /* field retrieved through gmime */
FLAG_XAPIAN_INDEX = 1 << 2, /* field is indexed in xapian */
FLAG_XAPIAN_TERM = 1 << 3, /* field stored as term in xapian */
FLAG_XAPIAN_VALUE = 1 << 4, /* field stored as value in xapian */
FLAG_XAPIAN_CONTACT = 1 << 5 /* field contains an e-mail address */
FLAG_GMIME = 1 << 0, /* field retrieved through gmime */
FLAG_XAPIAN_INDEX = 1 << 1, /* field is indexed in xapian */
FLAG_XAPIAN_TERM = 1 << 2, /* field stored as term in xapian */
FLAG_XAPIAN_VALUE = 1 << 3, /* field stored as value in xapian */
FLAG_XAPIAN_CONTACT = 1 << 4 /* field contains an e-mail address */
};
typedef enum _FieldFlags FieldFlags;
@ -44,10 +44,13 @@ struct _MuMsgField {
MuMsgFieldId _id; /* the id of the field */
MuMsgFieldType _type; /* the type of the field */
const char *_name; /* the name of the field */
const char *_shortcut; /* the shortcut for use in --fields and sorting */
const char *_xprefix; /* the Xapian-prefix */
FieldFlags _flags; /* the flags that tells us what to do */
const char _shortcut; /* the shortcut for use in
* --fields and sorting */
const char _xprefix; /* the Xapian-prefix */
FieldFlags _flags; /* the flags that tells us
* what to do */
};
typedef struct _MuMsgField MuMsgField;
/* the name and shortcut fields must be lower case, or they might be
* misinterpreted by the query-preprocesser which turns queries into
@ -56,247 +59,240 @@ static const MuMsgField FIELD_DATA[] = {
{
MU_MSG_FIELD_ID_BODY_TEXT,
MU_MSG_FIELD_TYPE_STRING,
"body", "b", "B",
"body", 'b', 'B',
FLAG_GMIME | FLAG_XAPIAN_INDEX
},
{
MU_MSG_FIELD_ID_BODY_HTML,
MU_MSG_FIELD_TYPE_STRING,
"bodyhtml", "h", NULL,
"bodyhtml", 'h', 0,
FLAG_GMIME
},
{
MU_MSG_FIELD_ID_CC,
MU_MSG_FIELD_TYPE_STRING,
"cc", "c", "C",
"cc", 'c', 'C',
FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_DATE,
MU_MSG_FIELD_TYPE_TIME_T,
"date", "d", "D",
"date", 'd', 'D',
FLAG_GMIME | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_FLAGS,
MU_MSG_FIELD_TYPE_INT,
"flags", "g", "G", /* flaGs */
"flags", 'g', 'G', /* flaGs */
FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_FROM,
MU_MSG_FIELD_TYPE_STRING,
"from", "f", "F",
"from", 'f', 'F',
FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_PATH,
MU_MSG_FIELD_TYPE_STRING,
"path", "l", "L", /* 'l' for location */
"path", 'l', 'L', /* 'l' for location */
FLAG_GMIME | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_MAILDIR,
MU_MSG_FIELD_TYPE_STRING,
"maildir", "m", "M",
"maildir", 'm', 'M',
FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_PRIO,
MU_MSG_FIELD_TYPE_INT,
"prio", "p", "P",
"prio", 'p', 'P',
FLAG_GMIME | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_SIZE,
MU_MSG_FIELD_TYPE_BYTESIZE,
"size", "z", "Z", /* siZe */
"size", 'z', 'Z', /* siZe */
FLAG_GMIME
},
{
MU_MSG_FIELD_ID_SUBJECT,
MU_MSG_FIELD_TYPE_STRING,
"subject", "s", "S",
"subject", 's', 'S',
FLAG_GMIME | FLAG_XAPIAN_INDEX | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_TO,
MU_MSG_FIELD_TYPE_STRING,
"to", "t", "T",
"to", 't', 'T',
FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_MSGID,
MU_MSG_FIELD_TYPE_STRING,
"msgid", "i", "I", /* 'i' for Id */
"msgid", 'i', 'I', /* 'i' for Id */
FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE
},
{
MU_MSG_FIELD_ID_TIMESTAMP,
MU_MSG_FIELD_TYPE_TIME_T,
"timestamp", "x", NULL,
"timestamp", 'x', 0,
FLAG_GMIME
}
};
/* the MsgField data in an array, indexed by the MsgFieldId;
* this allows for O(1) access
*/
static MuMsgField* _msg_field_data[MU_MSG_FIELD_ID_NUM];
static const MuMsgField* mu_msg_field (MuMsgFieldId id)
{
static gboolean _initialized = FALSE;
/* initialize the array, but only once... */
if (G_UNLIKELY(!_initialized)) {
int i;
for (i = 0; i != G_N_ELEMENTS(FIELD_DATA); ++i)
_msg_field_data[FIELD_DATA[i]._id] =
(MuMsgField*)&FIELD_DATA[i];
_initialized = TRUE;
}
return _msg_field_data[id];
}
void
mu_msg_field_foreach (MuMsgFieldForEachFunc func, gconstpointer data)
{
int i;
for (i = 0; i != sizeof(FIELD_DATA)/sizeof(FIELD_DATA[0]); ++i)
func (&FIELD_DATA[i], data);
}
typedef gboolean (*FieldMatchFunc) (const MuMsgField *field,
gconstpointer data);
static const MuMsgField*
find_field (FieldMatchFunc matcher, gconstpointer data)
{
int i;
for (i = 0; i != sizeof(FIELD_DATA)/sizeof(FIELD_DATA[0]); ++i)
if (matcher(&FIELD_DATA[i], data))
return &FIELD_DATA[i];
return NULL;
}
static gboolean
match_name (const MuMsgField *field, const gchar* name)
{
return strcmp (field->_name, name) == 0;
}
const MuMsgField*
mu_msg_field_from_name (const char* str)
{
g_return_val_if_fail (str, NULL);
return find_field ((FieldMatchFunc)match_name, str);
}
static gboolean
match_shortcut (const MuMsgField *field, char kar)
{
return field->_shortcut[0] == kar;
}
const MuMsgField*
mu_msg_field_from_shortcut (char kar)
{
return find_field ((FieldMatchFunc)match_shortcut,
GUINT_TO_POINTER((guint)kar));
}
static gboolean
match_id (const MuMsgField *field, MuMsgFieldId id)
{
return field->_id == id;
}
const MuMsgField*
mu_msg_field_from_id (MuMsgFieldId id)
{
return find_field ((FieldMatchFunc)match_id,
GUINT_TO_POINTER(id));
for (i = 0; i != MU_MSG_FIELD_ID_NUM; ++i)
func (i, data);
}
gboolean
mu_msg_field_gmime (const MuMsgField *field)
MuMsgFieldId
mu_msg_field_id_from_name (const char* str, gboolean err)
{
g_return_val_if_fail (field, FALSE);
return field->_flags & FLAG_GMIME;
}
int i;
gboolean
mu_msg_field_xapian_index (const MuMsgField *field)
{
g_return_val_if_fail (field, FALSE);
return field->_flags & FLAG_XAPIAN_INDEX;
}
gboolean
mu_msg_field_xapian_value (const MuMsgField *field)
{
g_return_val_if_fail (field, FALSE);
return field->_flags & FLAG_XAPIAN_VALUE;
}
gboolean
mu_msg_field_xapian_term (const MuMsgField *field)
{
g_return_val_if_fail (field, FALSE);
return field->_flags & FLAG_XAPIAN_TERM;
}
gboolean
mu_msg_field_xapian_contact (const MuMsgField *field)
{
g_return_val_if_fail (field, FALSE);
return field->_flags & FLAG_XAPIAN_CONTACT;
}
gboolean
mu_msg_field_is_numeric (const MuMsgField *field)
{
MuMsgFieldType type;
g_return_val_if_fail (str, MU_MSG_FIELD_ID_NONE);
g_return_val_if_fail (field, FALSE);
for (i = 0; i != G_N_ELEMENTS(FIELD_DATA); ++i)
if (strcmp(str, FIELD_DATA[i]._name) == 0)
return FIELD_DATA[i]._id;
if (err)
g_return_val_if_reached (MU_MSG_FIELD_ID_NONE);
return MU_MSG_FIELD_ID_NONE;
}
MuMsgFieldId
mu_msg_field_id_from_shortcut (char kar, gboolean err)
{
int i;
for (i = 0; i != G_N_ELEMENTS(FIELD_DATA); ++i)
if (kar == FIELD_DATA[i]._shortcut)
return FIELD_DATA[i]._id;
if (err)
g_return_val_if_reached (MU_MSG_FIELD_ID_NONE);
return MU_MSG_FIELD_ID_NONE;
}
gboolean
mu_msg_field_gmime (MuMsgFieldId id)
{
g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE);
return mu_msg_field(id)->_flags & FLAG_GMIME;
}
gboolean
mu_msg_field_xapian_index (MuMsgFieldId id)
{
g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE);
return mu_msg_field(id)->_flags & FLAG_XAPIAN_INDEX;
}
gboolean
mu_msg_field_xapian_value (MuMsgFieldId id)
{
g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE);
return mu_msg_field(id)->_flags & FLAG_XAPIAN_VALUE;
}
gboolean
mu_msg_field_xapian_term (MuMsgFieldId id)
{
g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE);
return mu_msg_field(id)->_flags & FLAG_XAPIAN_TERM;
}
gboolean
mu_msg_field_xapian_contact (MuMsgFieldId id)
{
g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE);
return mu_msg_field(id)->_flags & FLAG_XAPIAN_CONTACT;
}
gboolean
mu_msg_field_is_numeric (MuMsgFieldId mfid)
{
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid),FALSE);
type = mu_msg_field_type (field);
return type == MU_MSG_FIELD_TYPE_BYTESIZE ||
type == MU_MSG_FIELD_TYPE_TIME_T ||
type == MU_MSG_FIELD_TYPE_INT;
return mfid == MU_MSG_FIELD_TYPE_BYTESIZE ||
mfid == MU_MSG_FIELD_TYPE_TIME_T ||
mfid == MU_MSG_FIELD_TYPE_INT;
}
const char*
mu_msg_field_name (const MuMsgField *field)
mu_msg_field_name (MuMsgFieldId id)
{
g_return_val_if_fail (field, NULL);
return field->_name;
g_return_val_if_fail (mu_msg_field_id_is_valid(id),NULL);
return mu_msg_field(id)->_name;
}
const char*
mu_msg_field_shortcut (const MuMsgField *field)
{
g_return_val_if_fail (field, NULL);
return field->_shortcut;
char
mu_msg_field_shortcut (MuMsgFieldId id)
{
g_return_val_if_fail (mu_msg_field_id_is_valid(id),0);
return mu_msg_field(id)->_shortcut;
}
MuMsgFieldId
mu_msg_field_id (const MuMsgField *field)
{
g_return_val_if_fail (field, MU_MSG_FIELD_ID_NONE);
return field->_id;
}
const char*
mu_msg_field_xapian_prefix (const MuMsgField *field)
char
mu_msg_field_xapian_prefix (MuMsgFieldId id)
{
g_return_val_if_fail (field, NULL);
return field->_xprefix;
g_return_val_if_fail (mu_msg_field_id_is_valid(id),0);
return mu_msg_field(id)->_xprefix;
}
MuMsgFieldType
mu_msg_field_type (const MuMsgField *field)
mu_msg_field_type (MuMsgFieldId id)
{
g_return_val_if_fail (field, MU_MSG_FIELD_TYPE_NONE);
return field->_type;
g_return_val_if_fail (mu_msg_field_id_is_valid(id),
MU_MSG_FIELD_TYPE_NONE);
return mu_msg_field(id)->_type;
}

View File

@ -27,7 +27,7 @@ G_BEGIN_DECLS
/* don't change the order, add new types at the end, as these numbers
* are used in the database */
enum _MuMsgFieldId {
MU_MSG_FIELD_ID_BODY_TEXT,
MU_MSG_FIELD_ID_BODY_TEXT = 0,
MU_MSG_FIELD_ID_BODY_HTML,
MU_MSG_FIELD_ID_CC,
MU_MSG_FIELD_ID_DATE,
@ -42,13 +42,16 @@ enum _MuMsgFieldId {
MU_MSG_FIELD_ID_MSGID,
MU_MSG_FIELD_ID_TIMESTAMP,
MU_MSG_FIELD_ID_NUM,
MU_MSG_FIELD_ID_NUM
};
typedef enum _MuMsgFieldId MuMsgFieldId;
static const guint MU_MSG_FIELD_ID_NONE = MU_MSG_FIELD_ID_NUM + 1;
struct _MuMsgField;
typedef struct _MuMsgField MuMsgField;
static const guint MU_MSG_FIELD_ID_NONE = (guint)-1;
typedef guint MuMsgFieldId;
#define mu_msg_field_id_is_valid(MFID) \
((MFID) < MU_MSG_FIELD_ID_NUM)
/* don't change the order, add new types at the end (before _NUM)*/
enum _MuMsgFieldType {
@ -61,9 +64,11 @@ enum _MuMsgFieldType {
MU_MSG_FIELD_TYPE_NUM
};
typedef enum _MuMsgFieldType MuMsgFieldType;
static const guint MU_MSG_FIELD_TYPE_NONE = MU_MSG_FIELD_TYPE_NUM + 1;
static const guint MU_MSG_FIELD_TYPE_NONE = (guint)-1;
typedef void (*MuMsgFieldForEachFunc) (const MuMsgField *field,
typedef void (*MuMsgFieldForEachFunc) (MuMsgFieldId id,
gconstpointer data);
/**
@ -79,43 +84,32 @@ void mu_msg_field_foreach (MuMsgFieldForEachFunc func, gconstpointer data);
* get the name of the field -- this a name that can be use in queries,
* ie. 'subject:foo', with 'subject' being the name
*
* @param field a MuMsgField
*
* @param id a MuMsgFieldId
*
* @return the name of the field as a constant string, or
* NULL if the field is unknown
*/
const char* mu_msg_field_name (const MuMsgField *field) G_GNUC_CONST;
const char* mu_msg_field_name (MuMsgFieldId id) G_GNUC_PURE;
/**
* get the shortcut of the field -- this a shortcut that can be use in
* queries, ie. 's:foo', with 's' meaning 'subject' being the name
*
* @param field a MuMsgField
* @param id a MuMsgFieldId
*
* @return the shortcut of the field as a constant string, or
* NULL if the field is unknown
* @return the shortcut character, or 0 if the field is unknown
*/
const char* mu_msg_field_shortcut (const MuMsgField *field) G_GNUC_CONST;
char mu_msg_field_shortcut (MuMsgFieldId id) G_GNUC_PURE;
/**
* get the xapian prefix of the field -- that is, the prefix used in
* the Xapian database to identify the field
*
* @param field a MuMsgField
* @param id a MuMsgFieldId
*
* @return the xapian prefix of the field as a constant string, or
* NULL if the field is unknown
* @return the xapian prefix char or 0 if the field is unknown
*/
const char* mu_msg_field_xapian_prefix (const MuMsgField *field) G_GNUC_PURE;
/**
* get the numerical ID of the field
*
* @param field a MuMsgField
*
* @return an id, or MU_MSG_FIELD_TYPE_NONE if the field is not known
*/
MuMsgFieldId mu_msg_field_id (const MuMsgField *field) G_GNUC_CONST;
char mu_msg_field_xapian_prefix (MuMsgFieldId id) G_GNUC_PURE;
/**
@ -126,18 +120,17 @@ MuMsgFieldId mu_msg_field_id (const MuMsgField *field) G_GNUC_CONST;
* @return the type of the field (a #MuMsgFieldType), or
* MU_MSG_FIELD_TYPE_NONE if it is not found
*/
MuMsgFieldType mu_msg_field_type (const MuMsgField *field) G_GNUC_CONST;
MuMsgFieldType mu_msg_field_type (MuMsgFieldId id) G_GNUC_PURE;
/**
* is the field numeric (has type MU_MSG_FIELD_TYPE_(BYTESIZE|TIME_T|INT))?
*
* @param field a MuMsgField
* @param id a MuMsgFieldId
*
* @return TRUE if the field is numeric, FALSE otherwise
*/
gboolean mu_msg_field_is_numeric (const MuMsgField *field) G_GNUC_CONST;
gboolean mu_msg_field_is_numeric (MuMsgFieldId id) G_GNUC_PURE;
/**
@ -145,20 +138,20 @@ gboolean mu_msg_field_is_numeric (const MuMsgField *field) G_GNUC_CONST
* indexed in the in the Xapian database, so we can use the all the
* phrasing, stemming etc. magic
*
* @param field a MuMsgField
* @param id a MuMsgFieldId
*
* @return TRUE if the field is Xapian-enabled, FALSE otherwise
*/
gboolean mu_msg_field_xapian_index (const MuMsgField *field) G_GNUC_PURE;
gboolean mu_msg_field_xapian_index (MuMsgFieldId id) G_GNUC_PURE;
/**
* should this field be stored as a xapian term?
*
* @param field a MuMsgField
* @param id a MuMsgFieldId
*
* @return TRUE if the field is Xapian-enabled, FALSE otherwise
*/
gboolean mu_msg_field_xapian_term (const MuMsgField *field) G_GNUC_PURE;
gboolean mu_msg_field_xapian_term (MuMsgFieldId id) G_GNUC_PURE;
/**
* should this field be stored as a xapian value?
@ -167,57 +160,55 @@ gboolean mu_msg_field_xapian_term (const MuMsgField *field) G_GNUC_PURE;
*
* @return TRUE if the field is Xapian-enabled, FALSE otherwise
*/
gboolean mu_msg_field_xapian_value (const MuMsgField *field) G_GNUC_PURE;
gboolean mu_msg_field_xapian_value (MuMsgFieldId id) G_GNUC_PURE;
/**
* should this field be stored as contact information? This means that
* e-mail address will be stored as terms, and names will be indexed
*
* @param field a MuMsgField
* @param id a MuMsgFieldId
*
* @return TRUE if the field should be stored as contact information,
* FALSE otherwise
*/
gboolean mu_msg_field_xapian_contact (const MuMsgField *field) G_GNUC_PURE;
gboolean mu_msg_field_xapian_contact (MuMsgFieldId id) G_GNUC_PURE;
/**
* is the field gmime-enabled? That is, can be field be retrieved
* using GMime?
*
* @param field a MuMsgField
* @param id a MuMsgFieldId
*
* @return TRUE if the field is Gmime-enabled, FALSE otherwise
*/
gboolean mu_msg_field_gmime (const MuMsgField *field) G_GNUC_PURE;
gboolean mu_msg_field_gmime (MuMsgFieldId id) G_GNUC_PURE;
/**
* get the corresponding MuMsgField for a name (as in mu_msg_field_name)
*
* @param str a name
* @param err, if TRUE, when the shortcut is not found, will issue a
* g_critical warning
*
* @return a MuMsgField, or NULL if it could not be found
*/
const MuMsgField* mu_msg_field_from_name (const char* str) G_GNUC_PURE;
MuMsgFieldId mu_msg_field_id_from_name (const char* str,
gboolean err) G_GNUC_PURE;
/**
* get the corresponding MuMsgField for a shortcut (as in mu_msg_field_shortcut)
*
* @param kar a shortcut character
* @param err, if TRUE, when the shortcut is not found, will issue a
* g_critical warning
*
* @return a MuMsgField, or NULL if it could not be found
*/
const MuMsgField* mu_msg_field_from_shortcut (char kar) G_GNUC_CONST;
MuMsgFieldId mu_msg_field_id_from_shortcut (char kar,
gboolean err) G_GNUC_PURE;
/**
* get the corresponding MuMsgField for an id (as in mu_msg_field_id)
*
* @param id an id
*
* @return a MuMsgField, or NULL if it could not be found
*/
const MuMsgField* mu_msg_field_from_id (MuMsgFieldId id) G_GNUC_CONST;
G_END_DECLS