#include <assert.h>
#include <errno.h>
+#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "mdb.h"
#include "midl.h"
+#if (__BYTE_ORDER == __LITTLE_ENDIAN) == (__BYTE_ORDER == __BIG_ENDIAN)
+# error "Unknown or unsupported endianness (__BYTE_ORDER)"
+#elif (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF
+# error "Two's complement, reasonably sized integer types, please"
+#endif
+
/** @defgroup internal MDB Internals
* @{
*/
*/
#define DKEY(x) mdb_dkey(x, kbuf)
#else
-#define DKBUF
+#define DKBUF typedef int dummy_kbuf /* so we can put ';' after */
#define DKEY(x)
#endif
#define LAZY_RWLOCK_WRLOCK(x)
/** Grab the DB table read lock */
#define LAZY_RWLOCK_RDLOCK(x)
- /** Declare the DB table rwlock */
+ /** Declare the DB table rwlock. Should not be followed by ';'. */
#define LAZY_RWLOCK_DEF(x)
/** Initialize the DB table rwlock */
#define LAZY_RWLOCK_INIT(x,y)
typedef struct MDB_node {
/** lo and hi are used for data size on leaf nodes and for
* child pgno on branch nodes. On 64 bit platforms, flags
- * is also used for pgno. (branch nodes ignore flags)
+ * is also used for pgno. (Branch nodes have no flags).
+ * They are in in host byte order in case that lets some
+ * accesses be optimized into a 32-bit word access.
*/
- unsigned short mn_lo;
- unsigned short mn_hi; /**< part of dsize or pgno */
+#define mn_lo mn_offset[__BYTE_ORDER!=__LITTLE_ENDIAN]
+#define mn_hi mn_offset[__BYTE_ORDER==__LITTLE_ENDIAN] /**< part of dsize or pgno */
+ unsigned short mn_offset[2];
unsigned short mn_flags; /**< flags for special node types */
#define F_BIGDATA 0x01 /**< data put on overflow page */
#define F_SUBDATA 0x02 /**< data is a sub-database */
/** ID2L of pages that were written during a write txn */
ID2 me_dirty_list[MDB_IDL_UM_SIZE];
/** rwlock for the DB tables, if #LAZY_LOCKS is false */
- LAZY_RWLOCK_DEF(me_dblock);
+ LAZY_RWLOCK_DEF(me_dblock)
#ifdef _WIN32
HANDLE me_rmutex; /* Windows mutexes don't reside in shared mem */
HANDLE me_wmutex;
unsigned short *u, *c;
int x;
- u = a->mv_data + a->mv_size;
- c = b->mv_data + a->mv_size;
+ u = (unsigned short *) ((char *) a->mv_data + a->mv_size);
+ c = (unsigned short *) ((char *) b->mv_data + a->mv_size);
do {
x = *--u - *--c;
} while(!x && u > (unsigned short *)a->mv_data);
static int
memncmp(const MDB_val *a, const MDB_val *b)
{
- int diff, len_diff;
+ int diff;
+ ssize_t len_diff;
unsigned int len;
len = a->mv_size;
- len_diff = a->mv_size - b->mv_size;
- if (len_diff > 0)
+ len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size;
+ if (len_diff > 0) {
len = b->mv_size;
+ len_diff = 1;
+ }
+
diff = memcmp(a->mv_data, b->mv_data, len);
- return diff ? diff : len_diff;
+ return diff ? diff : len_diff<0 ? -1 : len_diff;
}
static int
memnrcmp(const MDB_val *a, const MDB_val *b)
{
const unsigned char *p1, *p2, *p1_lim;
- int diff, len_diff;
+ ssize_t len_diff;
+ int diff;
- if (b->mv_size == 0)
- return a->mv_size != 0;
- if (a->mv_size == 0)
- return -1;
+ p1_lim = (const unsigned char *)a->mv_data;
+ p1 = (const unsigned char *)a->mv_data + a->mv_size;
+ p2 = (const unsigned char *)b->mv_data + b->mv_size;
- p1 = (const unsigned char *)a->mv_data + a->mv_size - 1;
- p2 = (const unsigned char *)b->mv_data + b->mv_size - 1;
-
- len_diff = a->mv_size - b->mv_size;
- if (len_diff < 0)
- p1_lim = p1 - a->mv_size;
- else
- p1_lim = p1 - b->mv_size;
+ len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size;
+ if (len_diff > 0) {
+ p1_lim += len_diff;
+ len_diff = 1;
+ }
while (p1 > p1_lim) {
- diff = *p1 - *p2;
+ diff = *--p1 - *--p2;
if (diff)
return diff;
- p1--;
- p2--;
}
- return len_diff;
+ return len_diff<0 ? -1 : len_diff;
}
/* Search for key within a leaf page, using binary search.