lbxdir = $(includedir)/lbx
lbx_HEADERS = src/lbx.h src/image.h
-noinst_HEADERS += src/byteorder.h src/misc.h src/tools.h
+noinst_HEADERS += src/byteorder.h src/misc.h src/tools.h src/pack.h
lib_LTLIBRARIES += liblbx.la
-liblbx_la_SOURCES = src/misc.c src/lbx.c src/image.c
+liblbx_la_SOURCES = src/misc.c src/lbx.c src/image.c src/pack.c
bin_PROGRAMS += lbxtool
lbxtool_SOURCES = src/lbxtool.c
#include <sys/stat.h>
#include <sys/mman.h>
-#include "byteorder.h"
+#include "pack.h"
#include "misc.h"
#include "lbx.h"
-#define LBX_MAGIC 0x0000fead
+#define LBX_MAGIC 0x0000fead
+#define LBX_HDR_SIZE 8
int lbx_errno = 0;
uint32_t offsets[];
};
-struct lbx_state *lbx_fopen(FILE *f, const char *name)
+static struct lbx_state *lbx_init(unsigned char hdr[static LBX_HDR_SIZE])
{
- struct lbx_state *new = NULL;
- uint16_t nfiles, version;
- uint32_t magic;
-
- if (fread(&nfiles, sizeof nfiles, 1, f) != 1) goto readerr;
- if (fread(&magic, sizeof magic, 1, f) != 1) goto readerr;
- if (fread(&version, sizeof version, 1, f) != 1) goto readerr;
-
- nfiles = letohs(nfiles);
- magic = letohl(magic);
- version = letohs(version);
+ unsigned short nfiles = unpack_16_le(hdr+0);
+ unsigned long magic = unpack_32_le(hdr+2);
+ unsigned short version = unpack_16_le(hdr+6);
+ struct lbx_state *lbx;
if (magic != LBX_MAGIC) {
- lbx_errno = LBX_EMAGIC;
+ lbx_errno = -LBX_EMAGIC;
return NULL;
}
-
- new = malloc(sizeof *new + (nfiles+1)*(sizeof *new->offsets));
- if (!new) {
+
+ lbx = malloc(sizeof *lbx + sizeof lbx->offsets[0] * (nfiles+1));
+ if (!lbx) {
lbx_errno = -errno;
return NULL;
}
-
- *new = (struct lbx_state){
- .name = name,
+
+ *lbx = (struct lbx_state) {
.nfiles = nfiles,
- .f = f,
- .foff = sizeof nfiles + sizeof magic + sizeof version,
};
-
- if (fread(new->offsets, sizeof *new->offsets, nfiles+1, f) != nfiles+1)
- goto readerr;
- new->foff += sizeof *new->offsets * (nfiles+1);
- return new;
-readerr:
- if (feof(f)) {
- lbx_errno = LBX_EEOF;
- } else {
+ return lbx;
+}
+
+struct lbx_state *lbx_fopen(FILE *f, const char *name)
+{
+ unsigned char hdr_buf[LBX_HDR_SIZE];
+ struct lbx_state *lbx;
+
+ if (fread(hdr_buf, 1, sizeof hdr_buf, f) != sizeof hdr_buf) {
lbx_errno = -errno;
+ return NULL;
}
- free(new);
- return NULL;
+ lbx = lbx_init(hdr_buf);
+ if (!lbx)
+ return NULL;
+
+ lbx->name = name;
+ lbx->f = f;
+ lbx->foff = sizeof hdr_buf;
+
+ for (unsigned i = 0; i <= lbx->nfiles; i++) {
+ unsigned char buf[4];
+
+ if (fread(buf, 1, sizeof buf, f) != sizeof buf) {
+ lbx_errno = -errno;
+ if (feof(f))
+ lbx_errno = LBX_EEOF;
+ free(lbx);
+ return NULL;
+ }
+
+ lbx->offsets[i] = unpack_32_le(buf);
+ lbx->foff += sizeof buf;
+ }
+
+ return lbx;
}
static int _lbx_memcpy(void *dest, struct lbx_state *src, size_t size)
--- /dev/null
+/*
+ * Portable binary serialisation of integral types.
+ * Copyright (C) 2009 Nick Bowler
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#include "pack.h"
+
+/* Unsigned integer packing. */
+#define DEFPACK_BE(bits, type) void pack_ ## bits ## _be ( \
+ unsigned char *out, type v \
+) { \
+ unsigned i; \
+ for (i = 1; i <= bits/8; i++) { \
+ out[bits/8 - i] = v % 256; \
+ v /= 256; \
+ } \
+}
+
+#define DEFPACK_LE(bits, type) void pack_ ## bits ## _le ( \
+ unsigned char *out, type v \
+) { \
+ unsigned i; \
+ for (i = 0; i < bits/8; i++) { \
+ out[i] = v % 256; \
+ v /= 256; \
+ } \
+}
+
+DEFPACK_BE(16, unsigned short)
+DEFPACK_BE(32, unsigned long)
+#if PACK_HAVE_64BIT
+DEFPACK_BE(64, unsigned long long)
+#endif
+
+DEFPACK_LE(16, unsigned short)
+DEFPACK_LE(32, unsigned long)
+#if PACK_HAVE_64BIT
+DEFPACK_LE(64, unsigned long long)
+#endif
+
+#define DEFUNPACK_BE(bits, type) type unpack_ ## bits ## _be ( \
+ const unsigned char *in \
+) { \
+ type v = 0; \
+ unsigned i; \
+ for (i = 0; i < bits/8; i++) { \
+ v *= 256; \
+ v += in[i]; \
+ } \
+ return v; \
+}
+
+#define DEFUNPACK_LE(bits, type) type unpack_ ## bits ## _le ( \
+ const unsigned char *in \
+) { \
+ type v = 0; \
+ unsigned i; \
+ for (i = 1; i <= bits/8; i++) { \
+ v *= 256; \
+ v += in[bits/8 - i]; \
+ } \
+ return v; \
+}
+
+DEFUNPACK_BE(16, unsigned short)
+DEFUNPACK_BE(32, unsigned long)
+#if PACK_HAVE_64BIT
+DEFUNPACK_BE(64, unsigned long long)
+#endif
+
+DEFUNPACK_LE(16, unsigned short)
+DEFUNPACK_LE(32, unsigned long)
+#if PACK_HAVE_64BIT
+DEFUNPACK_LE(64, unsigned long long)
+#endif
+
+/*
+ * Two's complement signed integer packing. This is unlikely to work on
+ * systems that don't themselves use two's complement.
+ */
+
+#define DEFUNPACK_SBE(bits, max, type) type unpack_s ## bits ## _be ( \
+ const unsigned char *in \
+) { \
+ type v = 0; \
+ unsigned i; \
+ int sign = (in[0] & 0x80) ? 1 : 0; \
+ for (i = 0; i < bits/8; i++) { \
+ v *= 256; \
+ v += in[i] & (i == 0 ? 0x7f : 0xff); \
+ } \
+ return sign*(-max-1) + v; \
+}
+
+#define DEFUNPACK_SLE(bits, max, type) type unpack_s ## bits ## _le ( \
+ const unsigned char *in \
+) { \
+ type v = 0; \
+ unsigned i; \
+ int sign = (in[bits/8 - 1] & 0x80) ? 1 : 0; \
+ for (i = 1; i <= bits/8; i++) { \
+ v *= 256; \
+ v += in[bits/8 - i] & (i == 1 ? 0x7f : 0xff); \
+ } \
+ return sign*(-max-1) + v; \
+}
+
+DEFUNPACK_SBE(16, 32767, short)
+DEFUNPACK_SBE(32, 2147483647l, long)
+#if PACK_HAVE_64BIT
+DEFUNPACK_SBE(64, 9223372036854775807ll, long long)
+#endif
+
+DEFUNPACK_SLE(16, 32767, short)
+DEFUNPACK_SLE(32, 2147483647l, long)
+#if PACK_HAVE_64BIT
+DEFUNPACK_SLE(64, 9223372036854775807ll, long long)
+#endif
--- /dev/null
+/*
+ * Portable binary serialisation of integral types.
+ * Copyright (C) 2009 Nick Bowler
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. This file is offered as-is,
+ * without any warranty.
+ */
+
+#ifndef PACK_H_
+#define PACK_H_
+
+#include <limits.h>
+#if !defined(PACK_HAVE_64BIT) && defined(ULLONG_MAX) && defined(LLONG_MAX)
+# define PACK_HAVE_64BIT 1
+#endif
+
+void pack_16_be(unsigned char *, unsigned short);
+void pack_32_be(unsigned char *, unsigned long);
+#if PACK_HAVE_64BIT
+void pack_64_be(unsigned char *, unsigned long long);
+#endif
+
+void pack_16_le(unsigned char *, unsigned short);
+void pack_32_le(unsigned char *, unsigned long);
+#if PACK_HAVE_64BIT
+void pack_64_le(unsigned char *, unsigned long long);
+#endif
+
+unsigned short unpack_16_be(const unsigned char *);
+unsigned long unpack_32_be(const unsigned char *);
+#if PACK_HAVE_64BIT
+unsigned long long unpack_64_be(const unsigned char *);
+#endif
+
+unsigned short unpack_16_le(const unsigned char *);
+unsigned long unpack_32_le(const unsigned char *);
+#if PACK_HAVE_64BIT
+unsigned long long unpack_64_le(const unsigned char *);
+#endif
+
+short unpack_s16_be(const unsigned char *);
+long unpack_s32_be(const unsigned char *);
+#if PACK_HAVE_64BIT
+long long unpack_s64_be(const unsigned char *);
+#endif
+
+short unpack_s16_le(const unsigned char *);
+long unpack_s32_le(const unsigned char *);
+#if PACK_HAVE_64BIT
+long long unpack_s64_le(const unsigned char *);
+#endif
+
+#endif