A plain simple pointer + length describing a linear memory region.
lib/eina/eina_promise.h \
lib/eina/eina_bezier.h \
lib/eina/eina_safepointer.h \
-lib/eina/eina_inline_safepointer.x
+lib/eina/eina_inline_safepointer.x \
+lib/eina/eina_slice.h \
+lib/eina/eina_inline_slice.x
lib_eina_libeina_la_SOURCES = \
lib/eina/eina_abi.c \
tests/eina/eina_test_vector.c \
tests/eina/eina_test_promise.c \
tests/eina/eina_test_bezier.c \
-tests/eina/eina_test_safepointer.c
+tests/eina/eina_test_safepointer.c \
+tests/eina/eina_test_slice.c
tests_eina_eina_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-DTESTS_WD=\"`pwd`\" \
#include <eina_promise.h>
#include <eina_bezier.h>
#include <eina_safepointer.h>
+#include <eina_slice.h>
#undef EAPI
#define EAPI
--- /dev/null
+/* EINA - EFL data type library
+ * Copyright (C) 2016 ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _EINA_INLINE_SLICE_H
+#define _EINA_INLINE_SLICE_H
+
+static inline Eina_Slice
+eina_rw_slice_slice_get(const Eina_Rw_Slice rw_slice)
+{
+ Eina_Slice ret;
+ ret.len = rw_slice.len;
+ ret.mem = rw_slice.mem;
+ return ret;
+}
+
+static inline Eina_Rw_Slice
+eina_slice_dup(const Eina_Slice slice)
+{
+ Eina_Rw_Slice ret;
+
+ ret.len = slice.len;
+ ret.mem = NULL;
+ if (ret.len == 0) return ret;
+
+ ret.mem = malloc(ret.len);
+ if (!ret.mem)
+ ret.len = 0;
+ else
+ memcpy(ret.mem, slice.mem, ret.len);
+
+ return ret;
+}
+
+static inline Eina_Rw_Slice
+eina_rw_slice_dup(const Eina_Rw_Slice rw_slice)
+{
+ return eina_slice_dup(eina_rw_slice_slice_get(rw_slice));
+}
+
+static inline int
+eina_slice_compare(const Eina_Slice a, const Eina_Slice b)
+{
+ const size_t len = a.len <= b.len ? a.len : b.len;
+ if (len > 0)
+ {
+ int r = memcmp(a.mem, b.mem, len);
+ if (r != 0) return r;
+ }
+ if (a.len < b.len) return -1;
+ else if (a.len > b.len) return 1;
+ else return 0;
+}
+
+static inline int
+eina_rw_slice_compare(const Eina_Rw_Slice a, const Eina_Rw_Slice b)
+{
+ return eina_slice_compare(eina_rw_slice_slice_get(a),
+ eina_rw_slice_slice_get(b));
+}
+
+static inline Eina_Rw_Slice
+eina_rw_slice_copy(const Eina_Rw_Slice dst, const Eina_Slice src)
+{
+ const size_t len = src.len <= dst.len ? src.len : dst.len;
+ Eina_Rw_Slice ret;
+
+ ret.len = len;
+ ret.mem = dst.mem;
+ if (len > 0) memcpy(ret.mem, src.mem, len);
+ return ret;
+}
+
+static inline Eina_Slice
+eina_slice_seek(const Eina_Slice slice, ssize_t offset, int whence)
+{
+ Eina_Slice ret;
+
+ ret.len = 0;
+ ret.mem = slice.mem;
+
+ if (whence == SEEK_END)
+ {
+ whence = SEEK_SET;
+ offset += slice.len;
+ }
+
+ if (whence != SEEK_SET)
+ return ret;
+
+ if (offset < 0)
+ offset = 0;
+ else if ((size_t)offset > slice.len)
+ offset = slice.len;
+
+ ret.len = slice.len - offset;
+ ret.mem = (const void *)(slice.bytes + offset);
+ return ret;
+}
+
+static inline Eina_Rw_Slice
+eina_rw_slice_seek(const Eina_Rw_Slice rw_slice, ssize_t offset, int whence)
+{
+ Eina_Rw_Slice ret;
+
+ ret.len = 0;
+ ret.mem = rw_slice.mem;
+
+ if (whence == SEEK_END)
+ {
+ whence = SEEK_SET;
+ offset += rw_slice.len;
+ }
+
+ if (whence != SEEK_SET)
+ return ret;
+
+ if (offset < 0)
+ offset = 0;
+ else if ((size_t)offset > rw_slice.len)
+ offset = rw_slice.len;
+
+ ret.len = rw_slice.len - offset;
+ ret.mem = (void *)(rw_slice.bytes + offset);
+ return ret;
+}
+
+static inline const void *
+eina_slice_strchr(const Eina_Slice slice, int c)
+{
+ if (slice.len == 0) return NULL;
+ return memchr(slice.mem, c, slice.len);
+}
+
+static inline const void *
+eina_slice_find(const Eina_Slice slice, const Eina_Slice needle)
+{
+ Eina_Slice s, n;
+ uint8_t c;
+
+ if (slice.len == 0) return NULL;
+ if (needle.len == 0) return NULL;
+ if (slice.len < needle.len) return NULL;
+ if (slice.len == 1) return eina_slice_strchr(slice, needle.bytes[0]);
+ if ((slice.len == needle.len) &&
+ (memcmp(slice.mem, needle.mem, needle.len) == 0))
+ return slice.mem;
+
+ s.mem = slice.mem;
+ s.len = slice.len - needle.len;
+
+ c = needle.bytes[0];
+ n.mem = (const void *)(needle.bytes + 1);
+ n.len = needle.len - 1;
+
+ while (s.len > 0)
+ {
+ const uint8_t *p = (const uint8_t *)eina_slice_strchr(s, c);
+ size_t offset;
+
+ if (!p) return NULL;
+
+ p++;
+ if (memcmp(p, n.mem, n.len) == 0)
+ return (const void *)(p - 1);
+
+ offset = p - s.bytes;
+ s.bytes += offset;
+ s.len -= offset;
+ }
+
+ return NULL;
+}
+
+static inline void *
+eina_rw_slice_strchr(const Eina_Rw_Slice rw_slice, int c)
+{
+ if (rw_slice.len == 0) return NULL;
+ return memchr(rw_slice.mem, c, rw_slice.len);
+}
+
+static inline void *
+eina_rw_slice_find(const Eina_Rw_Slice rw_slice, const Eina_Slice needle)
+{
+ return (void *)eina_slice_find(eina_rw_slice_slice_get(rw_slice), needle);
+}
+
+static inline const void *
+eina_slice_end_get(const Eina_Slice slice)
+{
+ return (const void *)(slice.bytes + slice.len);
+}
+
+static inline void *
+eina_rw_slice_end_get(const Eina_Rw_Slice rw_slice)
+{
+ return (void *)(rw_slice.bytes + rw_slice.len);
+}
+
+static inline char *
+eina_slice_strdup(const Eina_Slice slice)
+{
+ if (slice.len == 0)
+ return strdup("");
+ else
+ return strndup((const char *)slice.mem, slice.len);
+}
+
+static inline char *
+eina_rw_slice_strdup(const Eina_Rw_Slice rw_slice)
+{
+ if (rw_slice.len == 0)
+ return strdup("");
+ else
+ return strndup((const char *)rw_slice.mem, rw_slice.len);
+}
+
+#endif /* _EINA_INLINE_SLICE_H */
--- /dev/null
+/* EINA - EFL data type library
+ * Copyright (C) 2016 ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _EINA_SLICE_H
+#define _EINA_SLICE_H
+
+#include "eina_types.h"
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/**
+ * @addtogroup Eina_Slice_Group Memory Slices
+ *
+ * @brief These functions provide memory slices in read-only and
+ * read-write forms.
+ *
+ * Memory slices define a contiguous linear memory starting at a given
+ * pointer (@c mem) and spanning for a given length (@c len).
+ *
+ * They may be read-only (Eina_Slice) or read-write (Eina_Rw_Slice).
+ *
+ * @since 1.19
+ */
+
+/**
+ * @addtogroup Eina_Data_Types_Group Data Types
+ *
+ * @{
+ */
+
+/**
+ * @defgroup Eina_Slice_Group Memory Slices
+ *
+ * @{
+ */
+
+/**
+ * @typedef Eina_Slice
+ * Defines a read-only memory region.
+ *
+ * The slice is a memory starting at @c mem and accessible up to @c
+ * len bytes.
+ *
+ * @see Eina_Rw_Slice for read-write memory regions.
+ *
+ * @since 1.19
+ */
+typedef struct _Eina_Slice Eina_Slice;
+
+/**
+ * @typedef Eina_Rw_Slice
+ * Defines a read-and-write able memory region.
+ *
+ * The slice is a memory starting at @c mem and accessible up to @c
+ * len bytes.
+ *
+ * @see Eina_Slice for read-only memory regions.
+ *
+ * @since 1.19
+ */
+typedef struct _Eina_Rw_Slice Eina_Rw_Slice;
+
+/**
+ * @struct _Eina_Slice
+ * Defines a read-only memory region.
+ *
+ * The slice is a memory starting at @c mem and accessible up to @c
+ * len bytes.
+ *
+ * @see Eina_Rw_Slice for read-write memory regions.
+ *
+ * @since 1.19
+ */
+struct _Eina_Slice
+{
+ size_t len; /**< size of memory pointed by @c mem */
+ union {
+ const void *mem; /**< memory pointed by this slice. Just read, never modify it. */
+ const uint8_t *bytes; /**< memory as uint8_t pointer */
+ };
+};
+
+/**
+ * @struct _Eina_Rw_Slice
+ * Defines a read-and-write able memory region.
+ *
+ * The slice is a memory starting at @c mem and accessible up to @c
+ * len bytes.
+ *
+ * @see Eina_Slice for read-only memory regions.
+ *
+ * @since 1.19
+ */
+struct _Eina_Rw_Slice
+{
+ size_t len; /**< size of memory pointed by @c mem */
+ union {
+ void *mem; /**< memory pointed by this slice. It's write able. */
+ uint8_t *bytes; /**< memory as uint8_t pointer */
+ };
+};
+
+/**
+ * @brief Convert the Read-write slice to read-only.
+ *
+ * @param rw_slice the read-write slice to convert.
+ * @return the red-only slice matching the slice.
+ */
+static inline Eina_Slice eina_rw_slice_slice_get(const Eina_Rw_Slice rw_slice);
+
+/**
+ * @brief Creates a duplicate of slice's memory.
+ *
+ * @param slice the input to duplicate
+ * @return a new read-write slice with new @c mem that matches @a slice
+ * contents. The new @c mem is allocated with malloc() and must
+ * be released with free().
+ *
+ * @see eina_rw_slice_copy()
+ * @see eina_rw_slice_dup()
+ *
+ * @since 1.19
+ */
+static inline Eina_Rw_Slice eina_slice_dup(const Eina_Slice slice) EINA_WARN_UNUSED_RESULT;
+
+/**
+ * @brief Creates a duplicate of slice's memory.
+ *
+ * @param rw_slice the input to duplicate
+ * @return a new read-write slice with new @c mem that matches @a slice
+ * contents. The new @c mem is allocated with malloc() and must
+ * be released with free().
+ *
+ * @see eina_rw_slice_copy()
+ * @see eina_slice_dup()
+ *
+ * @since 1.19
+ */
+static inline Eina_Rw_Slice eina_rw_slice_dup(const Eina_Rw_Slice rw_slice) EINA_WARN_UNUSED_RESULT;
+
+/**
+ * @brief Compare two slices, similar to memcmp()
+ *
+ * @param a the first slice to compare.
+ * @param b the second slice to compare.
+ * @return 0 if equal, < 0 if a < b, > 0 if a > b
+ *
+ * @since 1.19
+ */
+static inline int eina_slice_compare(const Eina_Slice a, const Eina_Slice b);
+
+/**
+ * @brief Compare two slices, similar to memcmp()
+ *
+ * @param a the first slice to compare.
+ * @param b the second slice to compare.
+ * @return 0 if equal, < 0 if a < b, > 0 if a > b
+ *
+ * @since 1.19
+ */
+static inline int eina_rw_slice_compare(const Eina_Rw_Slice a, const Eina_Rw_Slice b);
+
+/**
+ * @brief Copy a read-only slice to a read-write one, similar to memcpy().
+ *
+ * @param dest where to write the memory.
+ * @param src where to load memory.
+ *
+ * @return a new slice with the resulting write. Note that the length
+ * (@c len) will be the smallest of @a dest and @a src.
+ *
+ * @see eina_rw_slice_dup()
+ * @see eina_slice_dup()
+ *
+ * @since 1.19
+ */
+static inline Eina_Rw_Slice eina_rw_slice_copy(const Eina_Rw_Slice dest, const Eina_Slice src);
+
+/**
+ * @brief Seek within a slice, similar to fseek().
+ *
+ * @param slice the containing slice to seek inside.
+ * @param offset how to get to the new position.
+ * @param whence SEEK_SET, SEEK_END as fseek().
+ * @return a new slice contained inside, it will start at the given
+ * offset and have a length that goes until the end of the @a
+ * slice. If an invalid @a whence, a zero-sized slice starting
+ * at @a slice mem will be returned. The slice is guaranteed
+ * to be contained within @a slice, even if offset causes it
+ * to go out of bounds, then it will be clamped to 0 and
+ * slice.len.
+ *
+ * @since 1.19
+ */
+static inline Eina_Slice eina_slice_seek(const Eina_Slice slice, ssize_t offset, int whence);
+
+/**
+ * @brief Seek within a read-write slice, similar to fseek().
+ *
+ * @param rw_slice the containing slice to seek inside.
+ * @param offset how to get to the new position.
+ * @param whence SEEK_SET, SEEK_END as fseek().
+ * @return a new slice contained inside, it will start at the given
+ * offset and have a length that goes until the end of the @a
+ * rw_slice. If an invalid @a whence, a zero-sized slice
+ * starting at @a rw_slice mem will be returned. The slice is
+ * guaranteed to be contained within @a rw_slice, even if
+ * offset causes it to go out of bounds, then it will be
+ * clamped to 0 and slice.len.
+ *
+ * @since 1.19
+ */
+static inline Eina_Rw_Slice eina_rw_slice_seek(const Eina_Rw_Slice rw_slice, ssize_t offset, int whence);
+
+
+/**
+ * @brief Find a character inside the slice, similar to memchr().
+ *
+ * @param slice the reference memory.
+ * @param c the byte (character) to find.
+ * @return the memory within slice or @c NULL if not found.
+ *
+ * @since 1.19
+ */
+static inline const void *eina_slice_strchr(const Eina_Slice slice, int c);
+
+/**
+ * @brief Find a needle inside the slice, similar to memmem().
+ *
+ * @param slice the reference memory.
+ * @param needle what to find.
+ * @return the memory within slice or @c NULL if not found.
+ *
+ * @since 1.19
+ */
+static inline const void *eina_slice_find(const Eina_Slice slice, const Eina_Slice needle);
+
+/**
+ * @brief Find a character inside the slice, similar to memchr().
+ *
+ * @param rw_slice the reference memory.
+ * @param c the byte (character) to find.
+ * @return the memory within slice or @c NULL if not found.
+ *
+ * @since 1.19
+ */
+static inline void *eina_rw_slice_strchr(const Eina_Rw_Slice rw_slice, int c);
+
+/**
+ * @brief Find a needle inside the slice, similar to memmem().
+ *
+ * @param rw_slice the reference memory.
+ * @param needle what to find.
+ * @return the memory within slice or @c NULL if not found.
+ *
+ * @since 1.19
+ */
+static inline void *eina_rw_slice_find(const Eina_Rw_Slice rw_slice, const Eina_Slice needle);
+
+/**
+ * @brief The memory position where the slice ends.
+ *
+ * @note this is out-of the slice, the first byte after it ends and
+ * must not be accessed.
+ *
+ * @param slice the reference memory.
+ * @return the first byte after the slice ends.
+ *
+ * @since 1.19
+ */
+static inline const void *eina_slice_end_get(const Eina_Slice slice);
+
+/**
+ * @brief The memory position where the slice ends.
+ *
+ * @note this is out-of the slice, the first byte after it ends and
+ * must not be accessed.
+ *
+ * @param rw_slice the reference memory.
+ * @return the first byte after the slice ends.
+ *
+ * @since 1.19
+ */
+static inline void *eina_rw_slice_end_get(const Eina_Rw_Slice rw_slice);
+
+/**
+ * @brief A null-terminated string for this slice.
+ *
+ * @param slice the reference memory.
+ * @return newly allocated memory or @c NULL on error
+ *
+ * @since 1.19
+ */
+static inline char *eina_slice_strdup(const Eina_Slice slice);
+
+/**
+ * @brief A null-terminated string for this slice.
+ *
+ * @param slice the reference memory.
+ * @return newly allocated memory or @c NULL on error
+ *
+ * @since 1.19
+ */
+static inline char *eina_rw_slice_strdup(const Eina_Rw_Slice rw_slice);
+
+/**
+ * @def EINA_SLICE_ARRAY(buf)
+ *
+ * Initializer for arrays of any kind.
+ *
+ * It is often useful for globals.
+ *
+ * @note This macro is usable with both Eina_Slice or Eina_Rw_Slice.
+ *
+ * @code
+ * static uint8_t buf[1024];
+ * static Eina_Slice rw_slice = EINA_SLICE_ARRAY(buf);
+ * @endcode
+ *
+ * @see EINA_SLICE_STR_LITERAL() for specific version that checks for string literals.
+ *
+ * @since 1.19
+ */
+#ifdef __cplusplus
+#define EINA_SLICE_ARRAY(buf) {((sizeof(buf) / sizeof((buf)[0])) * sizeof((buf)[0])), (buf)}
+#else
+#define EINA_SLICE_ARRAY(buf) {.len = ((sizeof(buf) / sizeof((buf)[0])) * sizeof((buf)[0])), .mem = (buf)}
+#endif
+
+
+/**
+ * @def EINA_RW_SLICE_DECLARE(name, length)
+ *
+ * Declare a local (stack) array for storage at given @a length and
+ * initialize an Eina_Rw_Slice called @a name.
+ *
+ * @param name the name of the variable to be the Eina_Rw_Slice
+ * @param length the size in bytes of the storage.
+ *
+ * @since 1.19
+ */
+#define EINA_RW_SLICE_DECLARE(name, length) \
+ uint8_t _eina_slice_storage_ ## name [(length)] = { 0 }; \
+ Eina_Rw_Slice name = EINA_SLICE_ARRAY(_eina_slice_storage_ ## name)
+
+/**
+ * @def EINA_SLICE_STR_LITERAL(buf)
+ *
+ * Initializer for string literals (those declared as
+ * double-quoted). The size will @b NOT include the trainling
+ * null-terminator.
+ *
+ * It is often useful for globals.
+ *
+ * @note This macro is usable with both Eina_Slice or Eina_Rw_Slice.
+ *
+ * @code
+ * static const Eina_Slice ro_slice = EINA_SLICE_STR_LITERAL("hello world");
+ * @endcode
+ *
+ * @see EINA_SLICE_STR() for more generic version.
+ * @see EINA_SLICE_ARRAY() for version that uses a general array.
+ *
+ * @since 1.19
+ */
+#ifdef __cplusplus
+#define EINA_SLICE_STR_LITERAL(buf) {(sizeof("" buf) - 1), (buf)}
+#else
+#define EINA_SLICE_STR_LITERAL(buf) {.len = (sizeof("" buf) - 1), .mem = (buf)}
+#endif
+
+/**
+ * @def EINA_SLICE_STR(str)
+ *
+ * Initializer for strings (uses strlen()).
+ *
+ * @note This macro is usable with both Eina_Slice or Eina_Rw_Slice.
+ *
+ * @code
+ * Eina_Slice ro_slice = EINA_SLICE_STR("hello world");
+ * @endcode
+ *
+ * @see EINA_SLICE_STR() for specific version using literals.
+ *
+ * @since 1.19
+ */
+#ifdef __cplusplus
+#define EINA_SLICE_STR(str) {strlen((str)), (str)}
+#else
+#define EINA_SLICE_STR(str) {.len = strlen((str)), .mem = (str)}
+#endif
+
+/**
+ * @def EINA_SLICE_STR_FMT
+ *
+ * To be used in printf()-like statements, prints the slice as a
+ * string, its @c len is to be used, then it doesn need the null
+ * terminator.
+ *
+ * Use with EINA_SLICE_STR_PRINT()
+ *
+ * @note This macro is usable with both Eina_Slice or Eina_Rw_Slice.
+ *
+ * @code
+ * Eina_Slice s = EINA_SLICE_STR_LITERAL("hello");
+ * printf("s=" EINA_SLICE_STR_FMT "\n", EINA_SLICE_STR_PRINT(s));
+ * @endcode
+ *
+ * @since 1.19
+ */
+#define EINA_SLICE_STR_FMT "%.*s"
+
+/**
+ * @def EINA_SLICE_STR_PRINT(s)
+ *
+ * To be used in printf()-like statements when EINA_SLICE_STR_FMT was
+ * used, it will print the slice as a string up to @c len.
+ *
+ * Use with EINA_SLICE_STR_FMT.
+ *
+ * @note This macro is usable with both Eina_Slice or Eina_Rw_Slice.
+ *
+ * @code
+ * Eina_Slice s = EINA_SLICE_STR_LITERAL("hello");
+ * printf("s=" EINA_SLICE_STR_FMT "\n", EINA_SLICE_STR_PRINT(s));
+ * @endcode
+ *
+ * @since 1.19
+ */
+#define EINA_SLICE_STR_PRINT(s) (int)(s).len, (const char *)(s).mem
+
+/**
+ * @def EINA_SLICE_FMT
+ *
+ * To be used in printf()-like statements, prints the slice as
+ * @c 0x1234+12 (@c mem + @c len).
+ *
+ * Use with EINA_SLICE_PRINT()
+ *
+ * @note This macro is usable with both Eina_Slice or Eina_Rw_Slice.
+ *
+ * @code
+ * Eina_Slice s = EINA_SLICE_STR_LITERAL("hello");
+ * printf("s=" EINA_SLICE_FMT "\n", EINA_SLICE_PRINT(s));
+ * @endcode
+ *
+ * @since 1.19
+ */
+#define EINA_SLICE_FMT "%p+%zu"
+
+/**
+ * @def EINA_SLICE_PRINT(s)
+ *
+ * To be used in printf()-like statements when EINA_SLICE_FMT was
+ * used, it will print the slice @c mem and @c len.
+ *
+ * Use with EINA_SLICE_FMT.
+ *
+ * @note This macro is usable with both Eina_Slice or Eina_Rw_Slice.
+ *
+ * @param s the slice
+ *
+ * @code
+ * Eina_Slice s = EINA_SLICE_STR_LITERAL("hello");
+ * printf("s=" EINA_SLICE_FMT "\n", EINA_SLICE_PRINT(s));
+ * @endcode
+ *
+ * @since 1.19
+ */
+#define EINA_SLICE_PRINT(s) (s).mem, (s).len
+
+/**
+ * @def EINA_SLICE_FOREACH(s, itr)
+ *
+ * Iterate over the slice memory, using @c itr. Each increment will be
+ * using the size of @c itr pointer (int32_t* will do in increments of
+ * 4 bytes).
+ *
+ * @note This macro is usable with both Eina_Slice or Eina_Rw_Slice.
+ *
+ * @note Be aware of memory alignment! Accessing unaligned memory may
+ * not be supported in some architectures.
+ *
+ * @param s the slice
+ * @param itr the iterator to hold each byte. Use a proper type, not
+ * "void*" or "const void*" as it doesn't have an intrinsic
+ * size.
+ *
+ * @since 1.19
+ */
+#ifdef __cplusplus
+#define EINA_SLICE_FOREACH(s, itr) \
+ for ((itr) = static_cast<__typeof__(itr)>((s).mem); \
+ (itr) < static_cast<__typeof__(itr)>(static_cast<void *>((s).bytes + (s).len)); \
+ (itr)++)
+#else
+#define EINA_SLICE_FOREACH(s, itr) \
+ for ((itr) = (s).mem; \
+ (void *)(itr) < (void *)((s).bytes + (s).len); \
+ (itr)++)
+#endif
+
+#include "eina_inline_slice.x"
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* _EINA_SLICE_H */
type @extern Eina.Error: int;
struct @extern @free(eina_binbuf_free) Eina.Binbuf;
+
+struct @extern Eina.Slice {
+ [[A linear, read-only, memory segment]]
+ len: size;
+ mem: const(void_ptr);
+}
+
+struct @extern Eina.Rw_Slice {
+ [[A linear, read-write, memory segment]]
+ len: size;
+ mem: void_ptr;
+}
{ "Promise", eina_test_promise },
{ "Bezier", eina_test_bezier },
{ "SafePointer", eina_test_safepointer },
+ { "Slice", eina_test_slice },
{ NULL, NULL }
};
void eina_test_promise(TCase *tc);
void eina_test_bezier(TCase *tc);
void eina_test_safepointer(TCase *tc);
+void eina_test_slice(TCase *tc);
#endif /* EINA_SUITE_H_ */
--- /dev/null
+/* EINA - EFL data type library
+ * Copyright (C) 2016 ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <Eina.h>
+
+#include "eina_suite.h"
+
+START_TEST(eina_test_slice_init)
+{
+ Eina_Rw_Slice a = EINA_SLICE_STR_LITERAL("hello world");
+ char buf[1024] = "";
+ Eina_Rw_Slice b = EINA_SLICE_ARRAY(buf);
+ Eina_Rw_Slice c = EINA_SLICE_STR("hi there");
+ EINA_RW_SLICE_DECLARE(d, 512);
+
+ eina_init();
+
+ fail_unless(a.len == sizeof("hello world") - 1);
+ fail_unless(strcmp(a.mem, "hello world") == 0);
+
+ fail_unless(b.len == sizeof(buf));
+
+ fail_unless(c.len == strlen("hi there"));
+ fail_unless(strcmp(c.mem, "hi there") == 0);
+
+ fail_unless(d.len == 512);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_test_slice_ro)
+{
+ Eina_Slice slice = EINA_SLICE_STR_LITERAL("hi there");
+ Eina_Slice a, needle;
+ Eina_Rw_Slice dup;
+ const void *p;
+ char *str;
+
+ dup = eina_slice_dup(slice);
+ fail_unless(dup.len == slice.len);
+ fail_unless(dup.mem != slice.mem);
+ fail_unless(eina_slice_compare(eina_rw_slice_slice_get(dup), slice) == 0);
+ free(dup.mem);
+
+ str = eina_slice_strdup(slice);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "hi there") == 0);
+ free(str);
+
+ a = eina_slice_seek(slice, strlen("hi "), SEEK_SET);
+ fail_unless(a.mem == slice.bytes + strlen("hi "));
+ fail_unless(a.len == slice.len - strlen("hi "));
+
+ a = eina_slice_seek(slice, 0, SEEK_SET);
+ fail_unless(a.mem == slice.bytes + 0);
+ fail_unless(a.len == slice.len);
+
+ a = eina_slice_seek(slice, -1, SEEK_END);
+ fail_unless(a.mem == slice.bytes + slice.len - 1);
+ fail_unless(a.len == 1);
+
+ a = eina_slice_seek(slice, 0, SEEK_END);
+ fail_unless(a.mem == eina_slice_end_get(slice));
+ fail_unless(a.len == 0);
+
+ p = eina_slice_end_get(slice);
+ fail_unless(p == slice.bytes + slice.len);
+
+ slice = (Eina_Slice)EINA_SLICE_STR_LITERAL("HELLO WORLD");
+ slice.len = strlen("hi there"); /* crop... */
+
+ p = eina_slice_strchr(slice, ' ');
+ fail_unless(p == slice.bytes + 5); /* 5 = index of ' ' in HELLO WORLD.. */
+
+ p = eina_slice_strchr(slice, '!');
+ fail_unless(p == NULL);
+
+ needle = (Eina_Slice)EINA_SLICE_STR_LITERAL(" W");
+ p = eina_slice_find(slice, needle);
+ fail_unless(p == slice.bytes + 5); /* 5 = index of ' W' in HELLO WORLD..*/
+
+ needle = (Eina_Slice)EINA_SLICE_STR_LITERAL("LO");
+ p = eina_slice_find(slice, needle);
+ fail_unless(p == slice.bytes + 3); /* 3 = index of 'LO' in HELLO WORLD..*/
+
+ needle = (Eina_Slice)EINA_SLICE_STR_LITERAL("HELLO");
+ p = eina_slice_find(slice, needle);
+ fail_unless(p == slice.mem);
+
+ needle = (Eina_Slice)EINA_SLICE_STR_LITERAL("WORLD"); /* would go out of boundaries */
+ p = eina_slice_find(slice, needle);
+ fail_unless(p == NULL);
+}
+END_TEST
+
+START_TEST(eina_test_slice_rw)
+{
+ uint8_t buf[] = "hi there";
+ Eina_Rw_Slice rw_slice = EINA_SLICE_ARRAY(buf);
+ Eina_Slice ro_slice;
+ Eina_Rw_Slice a;
+ const void *p;
+ char *str;
+
+ buf[sizeof(buf) - 1] = 0xff;
+ rw_slice.len--; /* do not account \0 (now 0xff) */
+ ro_slice = eina_rw_slice_slice_get(rw_slice);
+
+ fail_unless(rw_slice.len == ro_slice.len);
+ fail_unless(rw_slice.mem == ro_slice.mem);
+
+ a = eina_slice_dup(ro_slice);
+ fail_unless(a.len == ro_slice.len);
+ fail_unless(a.mem != ro_slice.mem);
+ fail_unless(eina_rw_slice_compare(a, rw_slice) == 0);
+ free(a.mem);
+
+ str = eina_rw_slice_strdup(rw_slice);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "hi there") == 0);
+ free(str);
+
+ a = eina_rw_slice_seek(rw_slice, strlen("hi "), SEEK_SET);
+ fail_unless(a.mem == rw_slice.bytes + strlen("hi "));
+ fail_unless(a.len == rw_slice.len - strlen("hi "));
+
+ a = eina_rw_slice_seek(rw_slice, 0, SEEK_SET);
+ fail_unless(a.mem == rw_slice.bytes + 0);
+ fail_unless(a.len == rw_slice.len);
+
+ a = eina_rw_slice_seek(rw_slice, -1, SEEK_END);
+ fail_unless(a.mem == rw_slice.bytes + rw_slice.len - 1);
+ fail_unless(a.len == 1);
+
+ a = eina_rw_slice_seek(rw_slice, 0, SEEK_END);
+ fail_unless(a.mem == eina_rw_slice_end_get(rw_slice));
+ fail_unless(a.len == 0);
+
+ p = eina_rw_slice_end_get(rw_slice);
+ fail_unless(p == rw_slice.bytes + rw_slice.len);
+
+ ro_slice = (Eina_Slice)EINA_SLICE_STR_LITERAL("HELLO WORLD, big string to be cropped");
+ a = eina_rw_slice_copy(rw_slice, ro_slice);
+
+ fail_unless(a.mem == rw_slice.mem);
+ fail_unless(a.len == rw_slice.len);
+ fail_unless(strncmp(a.mem, "HELLO WO", a.len) == 0);
+
+ p = eina_rw_slice_strchr(rw_slice, ' ');
+ fail_unless(p == rw_slice.bytes + 5); /* 5 = index of ' ' in HELLO WORLD.. */
+
+ p = eina_rw_slice_strchr(rw_slice, '!');
+ fail_unless(p == NULL);
+
+ ro_slice = (Eina_Slice)EINA_SLICE_STR_LITERAL(" W");
+ p = eina_rw_slice_find(rw_slice, ro_slice);
+ fail_unless(p == rw_slice.bytes + 5); /* 5 = index of ' W' in HELLO WORLD..*/
+
+ ro_slice = (Eina_Slice)EINA_SLICE_STR_LITERAL("LO");
+ p = eina_rw_slice_find(rw_slice, ro_slice);
+ fail_unless(p == rw_slice.bytes + 3); /* 3 = index of 'LO' in HELLO WORLD..*/
+
+ ro_slice = (Eina_Slice)EINA_SLICE_STR_LITERAL("HELLO");
+ p = eina_rw_slice_find(rw_slice, ro_slice);
+ fail_unless(p == rw_slice.mem);
+
+ ro_slice = (Eina_Slice)EINA_SLICE_STR_LITERAL("WORLD"); /* would go out of boundaries */
+ p = eina_rw_slice_find(rw_slice, ro_slice);
+ fail_unless(p == NULL);
+
+ fail_unless(buf[sizeof(buf) - 1] == 0xff);
+}
+END_TEST
+
+START_TEST(eina_test_slice_print)
+{
+ char buf[] = "Hello World";
+ Eina_Slice slice = {.len = strlen("Hello"), .mem = buf};
+ char a[128], b[128];
+
+ snprintf(a, sizeof(a), EINA_SLICE_FMT, EINA_SLICE_PRINT(slice));
+ snprintf(b, sizeof(b), "%p+%zu", slice.mem, slice.len);
+ fail_unless(strcmp(a, b) == 0);
+
+ snprintf(a, sizeof(a), EINA_SLICE_STR_FMT, EINA_SLICE_STR_PRINT(slice));
+ fail_unless(strcmp(a, "Hello") == 0);
+}
+END_TEST
+
+void
+eina_test_slice(TCase *tc)
+{
+ tcase_add_test(tc, eina_test_slice_init);
+ tcase_add_test(tc, eina_test_slice_ro);
+ tcase_add_test(tc, eina_test_slice_rw);
+ tcase_add_test(tc, eina_test_slice_print);
+}