summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2014-12-03 08:31:11 +0100
committerCedric BAIL <cedric@osg.samsung.com>2014-12-17 07:44:15 +0100
commit207ecace9986ea2cb2ca037099d8c2cd3531ee44 (patch)
tree336e88f3cf4f979d8cbe1d4338df0ce4cd1fb159
parenta322d76949f2886438799e0efb4a1e6f9220ff80 (diff)
downloadefl-devs/cedric/ector.tar.gz
eina: start adding a compressed integer buffer.devs/cedric/ector
-rw-r--r--src/lib/eina/eina_intbuf.h85
-rw-r--r--src/lib/eina/eina_intbuf.x84
2 files changed, 169 insertions, 0 deletions
diff --git a/src/lib/eina/eina_intbuf.h b/src/lib/eina/eina_intbuf.h
new file mode 100644
index 0000000000..b1b635f115
--- /dev/null
+++ b/src/lib/eina/eina_intbuf.h
@@ -0,0 +1,85 @@
+#ifndef EINA_INTBUF_H
+#define EINA_INTBUF_H
+
+/**
+ * @addtogroup Eina_Integer_Buffer_Group Compressed Integer Buffer
+ *
+ * @brief The functions provide compressed integer buffers management.
+ *
+ * The compressed integer buffer data type is designed to be compress once,
+ * but being read very often and very fast. The data set that it is designed
+ * for should be incremental integer (positive and negative direction
+ * are supported).
+ */
+
+/**
+ * @addtogroup Eina_Data_Types_Group Data Types
+ *
+ * @{
+ */
+
+/**
+ * @defgroup Eina_Integer_Buffer_Group Compressed Ieger Buffer
+ *
+ * @{
+ */
+
+/**
+ * @typedef Eina_Intbuf
+ * Type for a compressed integer buffer.
+ */
+typedef struct _Eina_Intbuf Eina_Intbuf;
+
+struct _Eina_Intbuf
+{
+ int last_data;
+ unsigned int length;
+
+ unsigned char *bytes;
+};
+
+/**
+ * @brief Create a new compressed integer buffer.
+ *
+ * @return Newly allocated compressed integer buffer instance.
+ */
+static inline Eina_Intbuf *eina_intbuf_new(void);
+
+/**
+ * @brief Free a compressed integer buffer.
+ *
+ * @param buf The compressed integer buffer to free.
+ */
+static void eina_intbuf_free(Eina_Intbuf *buf);
+
+/**
+ * @brief Push an integer at the end of an compressed integer buffer.
+ *
+ * @param buf The compressed integer buffer tofree.
+ * @param data The integer to push in.
+ */
+static inline void eina_intbuf_push(Eina_Intbuf *buf, int data);
+
+/**
+ * @brief
+ */
+static inline inline Eina_Bool
+eina_intbuf_read(Eina_Intbuf *buf,
+ unsigned int *buffer_offset,
+ int *data);
+
+#define EINA_INTBUF_FOREACH(buf, it, data) \
+ for (it = 0, data = eina_intbuf_read(buf, &it, data); \
+ eina_intbuf_read(buf, &it, &data); )
+
+#include "eina_intbuf.x"
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif
diff --git a/src/lib/eina/eina_intbuf.x b/src/lib/eina/eina_intbuf.x
new file mode 100644
index 0000000000..b68396eaad
--- /dev/null
+++ b/src/lib/eina/eina_intbuf.x
@@ -0,0 +1,84 @@
+static inline Eina_Intbuf *eina_intbuf_new(void)
+{
+ Eina_Intbuf *buf;
+
+ buf = calloc(1, sizeof (Eina_Intbuf));
+ return buf;
+}
+
+static void eina_intbuf_free(Eina_Intbuf *buf)
+{
+ free(buf->bytes);
+ free(buf);
+}
+
+static inline void eina_intbuf_push(Eina_Intbuf *buf, int data)
+{
+ int delta = data - buf->last_data;
+ unsigned char *tmp;
+ unsigned char data[5];
+ unsigned char idx = 4;
+ Eina_Bool neg = EINA_FALSE;
+
+ /* detect negative value */
+ if (delta < 0)
+ {
+ delta *= -1;
+ neg = EINA_TRUE;
+ }
+
+ /* Special case for storing negative value and no continuation bit */
+ data[idx] = (delta & 0x3F) | (neg ? 0x40 : 0x0);
+
+ /* Update index and delta after storing data */
+ delta = delta >> 6;
+ idx--;
+
+ while (delta)
+ {
+ /* Normal case where we store the data with the continuing bit */
+ data[idx] = (delta & 0x7F) | 0x80;
+
+ /* Update index and delta after storing data */
+ delta = delta >> 7;
+ idx--;
+ }
+
+ /* resize bytes buffer and store data at the end of the buffer */
+ tmp = realloc(buf->bytes, buf->length + 5 - idx);
+ if (!tmp) return ;
+
+ buf->bytes = tmp;
+ memcpy(tmp, data + idx + 1, 5 - idx);
+
+ /* update last data to the last pushed data */
+ buf->last_data = data;
+}
+
+static inline inline Eina_Bool eina_intbuf_read(Eina_Intbuf *buf,
+ unsigned int *buffer_offset,
+ int *data)
+{
+ int delta = 0;
+
+ /* end of the buffer ! */
+ if (*buffer_offset >= buf->length)
+ return EINA_FALSE;
+
+ /* as long as we find the continuation bit */
+ while (buf->bytes[*buffer_offset] & 0x80)
+ {
+ /* we can add those bit to the current delta value */
+ delta = (delta << 7) + (buf->bytes[*buffer_offset] & 0x7F);
+ (*buffer_offset)++;
+ }
+
+ /* handling the specific case of negative value and end of integer stream */
+ delta = (delta << 7) + (buf->bytes[*buffer_offset] & 0x3F);
+ if (buf->bytes[*buffer_offset] & 0x40)
+ delta *= -1;
+
+ /* update data by delta value */
+ *data += delta;
+ return EINA_TRUE;
+}