summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/bliss/bliss_bitpacker.c
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2015-04-11 22:03:59 +0200
committerYves-Alexis Perez <corsac@debian.org>2015-04-11 22:03:59 +0200
commit83b8aebb19fe6e49e13a05d4e8f5ab9a06177642 (patch)
tree51255545ba43b84aa5d673bd0eb557cbd0155c9e /src/libstrongswan/plugins/bliss/bliss_bitpacker.c
parent2b8de74ff4c334c25e89988c4a401b24b5bcf03d (diff)
downloadvyos-strongswan-83b8aebb19fe6e49e13a05d4e8f5ab9a06177642.tar.gz
vyos-strongswan-83b8aebb19fe6e49e13a05d4e8f5ab9a06177642.zip
Imported Upstream version 5.3.0
Diffstat (limited to 'src/libstrongswan/plugins/bliss/bliss_bitpacker.c')
-rw-r--r--src/libstrongswan/plugins/bliss/bliss_bitpacker.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/bliss/bliss_bitpacker.c b/src/libstrongswan/plugins/bliss/bliss_bitpacker.c
new file mode 100644
index 000000000..4d8446119
--- /dev/null
+++ b/src/libstrongswan/plugins/bliss/bliss_bitpacker.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY;https://www.hsr.ch/HSR-intern-Anmeldung.4409.0.html?&no_cache=1 without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "bliss_bitpacker.h"
+
+typedef struct private_bliss_bitpacker_t private_bliss_bitpacker_t;
+
+/**
+ * Private data structure for bliss_bitpacker_t object
+ */
+struct private_bliss_bitpacker_t {
+ /**
+ * Public interface.
+ */
+ bliss_bitpacker_t public;
+
+ /**
+ * Current number of bits written to buffer
+ */
+ size_t bits;
+
+ /**
+ * Bit buffer for up to 32 bits
+ */
+ uint32_t bits_buf;
+
+ /**
+ * Bits left in the bit buffer
+ */
+ size_t bits_left;
+
+ /**
+ * Buffer
+ */
+ chunk_t buf;
+
+ /**
+ * Read/Write pointer into buffer
+ */
+ chunk_t pos;
+
+};
+
+METHOD(bliss_bitpacker_t, get_bits, size_t,
+ private_bliss_bitpacker_t *this)
+{
+ return this->bits;
+}
+
+METHOD(bliss_bitpacker_t, write_bits, bool,
+ private_bliss_bitpacker_t *this, uint32_t value, size_t bits)
+{
+ if (bits == 0)
+ {
+ return TRUE;
+ }
+ if (bits > 32)
+ {
+ return FALSE;
+ }
+ if (bits < 32)
+ {
+ value &= (1 << bits) - 1;
+ }
+ this->bits += bits;
+
+ while (TRUE)
+ {
+ if (bits <= this->bits_left)
+ {
+ this->bits_buf |= value << (this->bits_left - bits);
+ this->bits_left -= bits;
+ return TRUE;
+ }
+
+ this->bits_buf |= value >> (bits - this->bits_left);
+ value &= (1 << (bits - this->bits_left)) - 1;
+ bits -= this->bits_left;
+
+ if (this->pos.len < 8)
+ {
+ return FALSE;
+ }
+ htoun32(this->pos.ptr, this->bits_buf);
+ this->pos = chunk_skip(this->pos, 4);
+ this->bits_buf = 0;
+ this->bits_left = 32;
+ }
+}
+
+METHOD(bliss_bitpacker_t, read_bits, bool,
+ private_bliss_bitpacker_t *this, uint32_t *value, size_t bits)
+{
+ if (bits > 32)
+ {
+ return FALSE;
+ }
+ *value = 0;
+
+ while (TRUE)
+ {
+ if (this->bits_left == 0)
+ {
+ if (this->pos.len < 4)
+ {
+ return FALSE;
+ }
+ this->bits_buf = untoh32(this->pos.ptr);
+ this->pos = chunk_skip(this->pos, 4);
+ this->bits_left = 32;
+ }
+ if (bits <= this->bits_left)
+ {
+ *value |= this->bits_buf >> (this->bits_left - bits);
+ this->bits_buf &= (1 << (this->bits_left - bits)) - 1;
+ this->bits_left -= bits;
+
+ return TRUE;
+ }
+ *value |= this->bits_buf << (bits - this->bits_left);
+ bits -= this->bits_left;
+ this->bits_left = 0;
+ }
+}
+
+METHOD(bliss_bitpacker_t, extract_buf, chunk_t,
+ private_bliss_bitpacker_t *this)
+{
+ chunk_t buf;
+
+ htoun32(this->pos.ptr, this->bits_buf);
+ this->pos.len -= 4;
+ buf = this->buf;
+ buf.len = this->buf.len - this->pos.len - this->bits_left/8;
+ this->buf = this->pos = chunk_empty;
+
+ return buf;
+}
+
+METHOD(bliss_bitpacker_t, destroy, void,
+ private_bliss_bitpacker_t *this)
+{
+ free(this->buf.ptr);
+ free(this);
+}
+
+/**
+ * See header.
+ */
+bliss_bitpacker_t *bliss_bitpacker_create(uint16_t max_bits)
+{
+ private_bliss_bitpacker_t *this;
+
+ INIT(this,
+ .public = {
+ .get_bits = _get_bits,
+ .write_bits = _write_bits,
+ .read_bits = _read_bits,
+ .extract_buf = _extract_buf,
+ .destroy = _destroy,
+ },
+ .bits_left = 32,
+ .buf = chunk_alloc(round_up(max_bits, 32)/8),
+ );
+
+ this->pos = this->buf;
+
+ return &this->public;
+}
+
+/**
+ * See header.
+ */
+bliss_bitpacker_t *bliss_bitpacker_create_from_data(chunk_t data)
+{
+ private_bliss_bitpacker_t *this;
+
+ INIT(this,
+ .public = {
+ .get_bits = _get_bits,
+ .write_bits = _write_bits,
+ .read_bits = _read_bits,
+ .extract_buf = _extract_buf,
+ .destroy = _destroy,
+ },
+ .bits = 8 * data.len,
+ .buf = chunk_alloc(round_up(data.len, 4)),
+ );
+
+ memset(this->buf.ptr + this->buf.len - 4, 0x00, 4);
+ memcpy(this->buf.ptr, data.ptr, data.len);
+ this->pos = this->buf;
+
+ return &this->public;
+}