diff options
author | Cedric BAIL <cedric@osg.samsung.com> | 2014-12-03 08:31:11 +0100 |
---|---|---|
committer | Cedric BAIL <cedric@osg.samsung.com> | 2014-12-17 07:44:15 +0100 |
commit | 207ecace9986ea2cb2ca037099d8c2cd3531ee44 (patch) | |
tree | 336e88f3cf4f979d8cbe1d4338df0ce4cd1fb159 | |
parent | a322d76949f2886438799e0efb4a1e6f9220ff80 (diff) | |
download | efl-devs/cedric/ector.tar.gz |
eina: start adding a compressed integer buffer.devs/cedric/ector
-rw-r--r-- | src/lib/eina/eina_intbuf.h | 85 | ||||
-rw-r--r-- | src/lib/eina/eina_intbuf.x | 84 |
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; +} |