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);
 

Reply via email to