Hello all,
attached is a patch for some macros that help with getting things
(struct/lists) packed up for sending over a wire or through IPC. This
is presented as a patch to ecore_ipc, but I think its a bit ugly and
could use some tidying up. however, raster said it might be useful if
its namespaced... well I still think its ugly. anyway, the code is there
and it should be useful.
this is mostly from evoak, I added some extra macros for dealing with
evas_lists.
I have also attached a test program to show how to do the packing on
lists.
Comments? Suggestions?
any response is much appreciated.
Stafford
#include <Ecore.h>
#include <Ecore_Ipc.h>
#include <Ecore_Evas.h>
typedef struct _test_data Test_Data;
struct _test_data {
char * name;
char enabled;
};
ECORE_IPC_ENC_EVAS_LIST_PROTO(_test_macro_enc)
{
ECORE_IPC_ENC_EVAS_LIST_HEAD_START(Test_Data);
ECORE_IPC_CNTS(name);
ECORE_IPC_CNT8();
ECORE_IPC_ENC_EVAS_LIST_HEAD_FINISH();
int l1;
ECORE_IPC_SLEN(l1, name);
ECORE_IPC_PUTS(name, l1);
ECORE_IPC_PUT8(enabled);
ECORE_IPC_ENC_EVAS_LIST_FOOT();
}
ECORE_IPC_DEC_EVAS_LIST_PROTO(_test_macro_dec)
{
ECORE_IPC_DEC_EVAS_LIST_HEAD(Test_Data);
ECORE_IPC_GETS(name);
ECORE_IPC_GET8(enabled);
ECORE_IPC_DEC_EVAS_LIST_FOOT();
}
int main() {
Evas_List * list, *decoded_list;
Test_Data *d1, *d2, *d3;
char * encoded_data;
int size, i;
list = NULL;
decoded_list = NULL;
d1 = malloc(sizeof(Test_Data));
d1->name = strdup("test1 data");
d1->enabled = '_';
d2 = malloc(sizeof(Test_Data));
d2->name = strdup("test2 data, mother");
d2->enabled = '+';
d3 = malloc(sizeof(Test_Data));
d3->name = strdup("test3 its up man");
d3->enabled = '*';
list = evas_list_append(list, d1);
list = evas_list_append(list, d2);
list = evas_list_append(list, d3);
encoded_data = _test_macro_enc(list, &size);
for(i = 0; i < size; i++) {
printf("encoded_data[%d] = %c\n", i, encoded_data[i]);
}
decoded_list = _test_macro_dec(encoded_data, size);
/* list is leaked here, "its a test PGM who gives a damn" */
for (list = decoded_list; NULL != list; list = evas_list_next(list)) {
Test_Data * td;
td = evas_list_data(list);
printf("td->name = %s\n", td->name);
printf("td->enabled = %c\n", td->enabled);
}
}
? ipc_macros.diff
Index: Ecore_Ipc.h
===================================================================
RCS file: /cvsroot/enlightenment/e17/libs/ecore/src/lib/ecore_ipc/Ecore_Ipc.h,v
retrieving revision 1.6
diff -u -r1.6 Ecore_Ipc.h
--- Ecore_Ipc.h 4 Mar 2005 19:29:39 -0000 1.6
+++ Ecore_Ipc.h 7 Apr 2005 13:22:06 -0000
@@ -26,12 +26,187 @@
#ifdef __cplusplus
extern "C" {
#endif
-
+
#ifndef _ECORE_IPC_PRIVATE_H
typedef void Ecore_Ipc_Server; /**< An IPC connection handle */
typedef void Ecore_Ipc_Client; /**< An IPC connection handle */
#endif
+/**
+ * Macros used for generic data packing
+ */
+#ifdef WORDS_BIGENDIAN
+#define ECORE_IPC_SWAP2NET64(x) _ecore_ipc_swap_64(x)
+#define ECORE_IPC_SWAP2CPU64(x) _ecore_ipc_swap_64(x)
+#define ECORE_IPC_SWAP2NET32(x) _ecore_ipc_swap_32(x)
+#define ECORE_IPC_SWAP2CPU32(x) _ecore_ipc_swap_32(x)
+#define ECORE_IPC_SWAP2NET16(x) _ecore_ipc_swap_16(x)
+#define ECORE_IPC_SWAP2CPU16(x) _ecore_ipc_swap_16(x)
+#define ECORE_IPC_SWAP2NET8(x) (x)
+#define ECORE_IPC_SWAP2CPU8(x) (x)
+#else
+#define ECORE_IPC_SWAP2NET64(x) (x)
+#define ECORE_IPC_SWAP2CPU64(x) (x)
+#define ECORE_IPC_SWAP2NET32(x) (x)
+#define ECORE_IPC_SWAP2CPU32(x) (x)
+#define ECORE_IPC_SWAP2NET16(x) (x)
+#define ECORE_IPC_SWAP2CPU16(x) (x)
+#define ECORE_IPC_SWAP2NET8(x) (x)
+#define ECORE_IPC_SWAP2CPU8(x) (x)
+#endif
+
+/* 1, 2, 4 and 8 byte datatypes */
+/* unpacking */
+#define ECORE_IPC_GET64(v)\
+ { \
+ p->v = ECORE_IPC_SWAP2CPU64(*(long long *)(ptr)); \
+ ptr += 8; \
+ }
+#define ECORE_IPC_GET32(v)\
+ { \
+ p->v = ECORE_IPC_SWAP2CPU32(*(int *)(ptr)); \
+ ptr += 4; \
+ }
+#define ECORE_IPC_GET16(v)\
+ { \
+ p->v = ECORE_IPC_SWAP2CPU16(*(short *)(ptr)); \
+ ptr += 2; \
+ }
+#define ECORE_IPC_GET8(v) \
+ { \
+ p->v = ECORE_IPC_SWAP2CPU8(*(char *)(ptr)); \
+ ptr += 1; \
+ }
+/* packing */
+#define ECORE_IPC_PUT64(v)\
+ { \
+ *(long long *)(ptr) = ECORE_IPC_SWAP2NET64(p->v); \
+ ptr += 8; \
+ }
+#define ECORE_IPC_PUT32(v)\
+ { \
+ *(int *)(ptr) = ECORE_IPC_SWAP2NET32(p->v); \
+ ptr += 4; \
+ }
+#define ECORE_IPC_PUT16(v)\
+ { \
+ *(short *)(ptr) = ECORE_IPC_SWAP2NET16(p->v); \
+ ptr += 2; \
+ }
+#define ECORE_IPC_PUT8(v) \
+ { \
+ *(char *)(ptr) = ECORE_IPC_SWAP2NET8(p->v); \
+ ptr += 1; \
+ }
+/* padding data */
+#define ECORE_IPC_PAD8() ptr += 1
+#define ECORE_IPC_PAD16() ptr += 2
+#define ECORE_IPC_PAD32() ptr += 4
+#define ECORE_IPC_PAD64() ptr += 8
+
+/* counting data when encoding lists */
+#define ECORE_IPC_CNT8() len += 1
+#define ECORE_IPC_CNT16() len += 2
+#define ECORE_IPC_CNT32() len += 4
+#define ECORE_IPC_CNT64() len += 8
+
+/* strings */
+#define ECORE_IPC_CHEKS() if (*((unsigned char *)d + s - 1) != 0) return 0;
+#define ECORE_IPC_GETS(v) \
+ { \
+ if (ptr < ((unsigned char *)d + s)) \
+ { \
+ p->v = ptr; \
+ ptr += strlen(p->v) + 1; \
+ } \
+ }
+#define ECORE_IPC_PUTS(v, l)\
+ { \
+ strcpy(ptr, p->v); \
+ ptr += l + 1; \
+ }
+
+/* handy to calculate what sized block we need to alloc */
+#define ECORE_IPC_SLEN(l, v) ((l = strlen(p->v)) + 1)
+#define ECORE_IPC_CNTS(v) len += strlen(p->v) + 1
+
+/* saves typing function headers */
+#define ECORE_IPC_DEC_STRUCT_PROTO(x) static int x(void *d, int s, void *pp)
+#define ECORE_IPC_ENC_STRUCT_PROTO(x) static void *x(void *pp, int *s)
+#define ECORE_IPC_DEC_EVAS_LIST_PROTO(x) static Evas_List *x(void *d, int s)
+#define ECORE_IPC_ENC_EVAS_LIST_PROTO(x) static void *x(Evas_List *lp, int *s)
+
+/* decoder setup - saves typing. requires data packet of exact size, or fail */
+#define ECORE_IPC_DEC_STRUCT_HEAD_EXACT(typ, x) \
+ typ *p; \
+ unsigned char *ptr; \
+ p = (typ *)pp; \
+ if (!d) return 0; \
+ if (s != (x)) return 0; \
+ ptr = d;
+/* decoder setup - saves typing. requires data packet of a minimum size */
+#define ECORE_IPC_DEC_STRUCT_HEAD_MIN(typ, x) \
+ typ *p; \
+ unsigned char *ptr; \
+ p = (typ *)pp; \
+ if (!d) return 0; \
+ if (s < (x)) return 0; \
+ ptr = d;
+/* footer for the hell of it */
+#define ECORE_IPC_DEC_STRUCT_FOOT() return 1
+/* header for encoder - gives native strct type and size of flattened packet */
+#define ECORE_IPC_ENC_STRUCT_HEAD(typ, sz) \
+ typ *p; \
+ unsigned char *d, *ptr; \
+ int len; \
+ p = (typ *)pp; \
+ *s = 0; \
+ len = sz; \
+ d = malloc(len); \
+ if (!d) return NULL; \
+ *s = len; \
+ ptr = d;
+/* footer for the hell of it */
+#define ECORE_IPC_ENC_STRUCT_FOOT() return d
+
+#define ECORE_IPC_DEC_EVAS_LIST_HEAD(typ) \
+ unsigned char *ptr; \
+ Evas_List *l; \
+ typ *p; \
+ l = NULL; \
+ ptr = d; \
+ while(ptr < (unsigned char *)(d + s)) \
+ { \
+ p = malloc(sizeof(typ));
+
+#define ECORE_IPC_DEC_EVAS_LIST_FOOT() \
+ l = evas_list_append(l, p); \
+ } \
+ return l
+#define ECORE_IPC_ENC_EVAS_LIST_HEAD_START(typ) \
+ Evas_List *l; \
+ typ *p; \
+ unsigned char *d, *ptr; \
+ int len; \
+ *s = 0; \
+ len = 0; \
+ for (l = lp; l; l = l->next) \
+ { \
+ p = l->data;
+#define ECORE_IPC_ENC_EVAS_LIST_HEAD_FINISH() \
+ } \
+ d = malloc(len); \
+ if(!d) return NULL; \
+ *s = len; \
+ ptr = d; \
+ for (l = lp; l; l = l->next) \
+ { \
+ p = l->data;
+
+#define ECORE_IPC_ENC_EVAS_LIST_FOOT() \
+ } \
+ return d
+
typedef enum _Ecore_Ipc_Type
{
ECORE_IPC_LOCAL_USER,
Index: ecore_ipc.c
===================================================================
RCS file: /cvsroot/enlightenment/e17/libs/ecore/src/lib/ecore_ipc/ecore_ipc.c,v
retrieving revision 1.17
diff -u -r1.17 ecore_ipc.c
--- ecore_ipc.c 4 Mar 2005 19:29:39 -0000 1.17
+++ ecore_ipc.c 7 Apr 2005 13:22:07 -0000
@@ -28,6 +28,41 @@
#define DLT_R1 14
#define DLT_R2 15
+/* byte swappers - for dealing with big vs little endian machines */
+static unsigned short
+_ecore_ipc_swap_16(unsigned short v)
+{
+ unsigned char *s, t;
+
+ s = (unsigned char *)(&v);
+ t = s[0]; s[0] = s[1]; s[1] = t;
+ return v;
+}
+
+static unsigned int
+_ecore_ipc_swap_32(unsigned int v)
+{
+ unsigned char *s, t;
+
+ s = (unsigned char *)(&v);
+ t = s[0]; s[0] = s[3]; s[3] = t;
+ t = s[1]; s[1] = s[2]; s[2] = t;
+ return v;
+}
+
+static unsigned long long
+_ecore_ipc_swap_64(unsigned long long v)
+{
+ unsigned char *s, t;
+
+ s = (unsigned char *)(&v);
+ t = s[0]; s[0] = s[7]; s[7] = t;
+ t = s[1]; s[1] = s[6]; s[6] = t;
+ t = s[2]; s[2] = s[5]; s[5] = t;
+ t = s[3]; s[3] = s[4]; s[4] = t;
+ return v;
+}
+
static int _ecore_ipc_dlt_int(int out, int prev, int *mode);
static int _ecore_ipc_ddlt_int(int in, int prev, int mode);