#define MBITS "\020\01EXISTS\02SELECTED\03NEW\04UNSEEN"
-/*
- * type for holding the sequence set of a message
- */
+/* A vector of bits for tracking the sequence membership of a single
+ * message. Do not access the struct members; use vector.c.
+ * Do not move or copy this struct as it may contain a pointer to
+ * itself; use bvector_copy(). */
+struct bvector {
+ unsigned long *bits;
+ size_t maxsize;
+ unsigned long tiny[2]; /* Default fixed-size storage for bits. */
+};
typedef struct bvector *bvector_t;
bvector_t bvector_create (void);
+void bvector_init(struct bvector *bv);
void bvector_copy (bvector_t, bvector_t);
void bvector_free (bvector_t);
+void bvector_fini(struct bvector *bv);
void bvector_clear (bvector_t, size_t);
void bvector_clear_all (bvector_t);
void bvector_set (bvector_t, size_t);
* in a particular sequence.
*/
size_t num_msgstats;
- bvector_t *msgstats; /* msg status */
+ struct bvector *msgstats; /* msg status */
/*
* A FILE handle containing an open filehandle for the sequence file
/*
* macros for message and sequence manipulation
*/
-#define msgstat(mp,n) (mp)->msgstats[(n) - mp->lowoff]
+#define msgstat(mp,n) ((mp)->msgstats + (n) - mp->lowoff)
#define clear_msg_flags(mp,msgnum) bvector_clear_all (msgstat(mp, msgnum))
#define copy_msg_flags(mp,i,j) bvector_copy (msgstat(mp,i), msgstat(mp,j))
#define get_msg_flags(mp,ptr,msgnum) bvector_copy (ptr, msgstat(mp, msgnum))
folder_free (struct msgs *mp)
{
size_t i;
- bvector_t *v;
+ struct bvector *v;
if (!mp)
return;
svector_free (mp->msgattrs);
for (i = 0, v = mp->msgstats; i < mp->num_msgstats; ++i, ++v) {
- bvector_free (*v);
+ bvector_fini(v);
}
free (mp->msgstats);
struct msgs *mp;
struct dirent *dp;
DIR *dd;
- bvector_t *v;
+ struct bvector *v;
size_t i;
name = m_mailpath (name);
mp->num_msgstats = MSGSTATNUM (mp->lowoff, mp->hghoff);
mp->msgstats = mh_xmalloc (MSGSTATSIZE(mp));
for (i = 0, v = mp->msgstats; i < mp->num_msgstats; ++i, ++v) {
- *v = bvector_create ();
+ bvector_init(v);
}
mp->msgattrs = svector_create (0);
struct msgs *
folder_realloc (struct msgs *mp, int lo, int hi)
{
+ struct bvector *tmpstats, *t;
+ size_t i;
int msgnum;
/* sanity checks */
if (lo == mp->lowoff && hi == mp->hghoff)
return mp;
- if (lo == mp->lowoff) {
- bvector_t *v;
- size_t old_size = mp->num_msgstats;
- size_t new_size = hi - lo + 1;
- size_t i;
-
- /*
- * We are just extending (or shrinking) the end of message
- * status array. So we don't have to move anything and can
- * just realloc the message status array.
- */
-
- for (i = old_size, v = &mp->msgstats[old_size-1]; i > new_size;
- --i, --v) {
- bvector_free (*v);
- }
- mp->num_msgstats = MSGSTATNUM (lo, hi);
- mp->msgstats =
- mh_xrealloc (mp->msgstats, MSGSTATSIZE(mp));
- for (i = old_size, v = &mp->msgstats[old_size]; i < new_size;
- ++i, ++v) {
- *v = bvector_create ();
- }
- } else {
- /*
- * We are changing the offset of the message status
- * array. So we will need to shift everything.
- */
- bvector_t *tmpstats, *t;
- size_t i;
-
- /* first allocate the new message status space */
- mp->num_msgstats = MSGSTATNUM (lo, hi);
- tmpstats = mh_xmalloc (MSGSTATSIZE(mp));
- for (i = 0, t = tmpstats; i < mp->num_msgstats; ++i, ++t) {
- *t = bvector_create ();
- }
-
- /* then copy messages status array with shift */
- if (mp->nummsg > 0) {
- for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++)
- bvector_copy (tmpstats[msgnum - lo], msgstat (mp, msgnum));
- }
- free(mp->msgstats);
- mp->msgstats = tmpstats;
+ /* first allocate the new message status space */
+ mp->num_msgstats = MSGSTATNUM (lo, hi);
+ tmpstats = mh_xmalloc (MSGSTATSIZE(mp));
+ for (i = 0, t = tmpstats; i < mp->num_msgstats; ++i, ++t) {
+ bvector_init(t);
}
- mp->lowoff = lo;
- mp->hghoff = hi;
-
- /*
- * Clear all the flags for entries outside
- * the current message range for this folder.
- */
+ /* then copy messages status array with shift */
if (mp->nummsg > 0) {
- for (msgnum = mp->lowoff; msgnum < mp->lowmsg; msgnum++)
- clear_msg_flags (mp, msgnum);
- for (msgnum = mp->hghmsg + 1; msgnum <= mp->hghoff; msgnum++)
- clear_msg_flags (mp, msgnum);
- } else {
- /* no messages, so clear entire range */
- for (msgnum = mp->lowoff; msgnum <= mp->hghoff; msgnum++)
- clear_msg_flags (mp, msgnum);
+ for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++)
+ bvector_copy (tmpstats + msgnum - lo, msgstat (mp, msgnum));
}
+ free(mp->msgstats);
+ mp->msgstats = tmpstats;
+ mp->lowoff = lo;
+ mp->hghoff = hi;
return mp;
}
/* The number of elements bits needs to cover bit n, measured in bytes. */
#define BVEC_BYTES(n) (((n) / BVEC_BITS_BITS + 1) * BVEC_SIZEOF_BITS)
-struct bvector {
- unsigned long *bits;
- size_t maxsize;
- unsigned long tiny[2]; /* Default fixed-size storage for bits. */
-};
-
/* bvector_resize ensures the storage used for bits can cover bit
* newsize. It always increases the size of the storage used for bits,
* even if newsize would have been covered by the existing storage.
assert (sizeof *vec->bits <= sizeof 1ul);
NEW(vec);
- vec->bits = vec->tiny;
- vec->maxsize = BVEC_INIT_SIZE;
- memset(vec->tiny, 0, sizeof vec->tiny);
+ bvector_init(vec);
return vec;
}
+void bvector_init(struct bvector *bv)
+{
+ bv->bits = bv->tiny;
+ bv->maxsize = BVEC_INIT_SIZE;
+ memset(bv->tiny, 0, sizeof bv->tiny);
+}
+
void
bvector_copy (bvector_t dest, bvector_t src) {
size_t bytes = BVEC_BYTES(src->maxsize);
void
bvector_free (bvector_t vec) {
- if (vec->bits != vec->tiny)
- free(vec->bits);
+ bvector_fini(vec);
free (vec);
}
+void bvector_fini(struct bvector *bv)
+{
+ if (bv->bits != bv->tiny)
+ free(bv->bits);
+}
+
void
bvector_clear (bvector_t vec, size_t n) {
if (n < vec->maxsize)