1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/* common macros for reading and writing from streams */
#ifndef _NSLCD_COMMON_H
#define _NSLCD_COMMON_H 1
/* WRITE marcos, used for writing data, on write error they will
call the ERROR_OUT_WRITEERROR macro
these macros may require the availability of the following
variables:
int32_t tmpint32; - temporary variable
*/
#ifdef DEBUG_PROT
#define DEBUG_PRINT(args...) fprintf(stderr, ## args)
#else /* DEBUG_PROT */
#define DEBUG_PRINT(args...)
#endif /* not DEBUG_PROT */
#define WRITE(fp,ptr,size) \
DEBUG_PRINT("WRITE()\n"); \
if (fwrite(ptr,size,1,fp)<1) \
{ ERROR_OUT_WRITEERROR(fp) }
#define WRITE_TYPE(fp,field,type) \
DEBUG_PRINT("WRITE_TYPE()\n"); \
WRITE(fp,&(field),sizeof(type))
#define WRITE_INT32(fp,i) \
DEBUG_PRINT("WRITE_INT32(%d)\n",(int)i); \
tmpint32=(int32_t)(i); \
WRITE_TYPE(fp,tmpint32,int32_t)
#define WRITE_STRING(fp,str) \
DEBUG_PRINT("WRITE_STRING(\"%s\"=%d)\n",str,strlen(str)); \
WRITE_INT32(fp,strlen(str)); \
if (tmpint32>0) \
{ WRITE(fp,str,tmpint32); }
#define WRITE_FLUSH(fp) \
DEBUG_PRINT("WRITE_FLUSH()\n"); \
if (fflush(fp)<0) \
{ ERROR_OUT_WRITEERROR(fp) }
/* READ macros, used for reading data, on read error they will
call the ERROR_OUT_READERROR or ERROR_OUT_BUFERROR macro
these macros may require the availability of the following
variables:
int32_t tmpint32; - temporary variable
char *buffer; - pointer to a buffer for reading strings
size_t buflen; - the size of the buffer
size_t bufptr; - the current position in the buffer
*/
#define READ(fp,ptr,size) \
if (fread(ptr,size,1,fp)<1) \
{ ERROR_OUT_READERROR(fp) } \
DEBUG_PRINT("READ()\n");
#define READ_TYPE(fp,field,type) \
READ(fp,&(field),sizeof(type)) \
DEBUG_PRINT("READ_TYPE()\n");
#define READ_INT32(fp,i) \
READ_TYPE(fp,tmpint32,int32_t); \
i=tmpint32; \
DEBUG_PRINT("READ_INT32(%d)\n",(int)i);
/* read string in the buffer (using buffer, buflen and bufptr)
and store the actual location of the string in field */
#define READ_STRING_BUF(fp,field) \
/* read the size of the string */ \
READ_TYPE(fp,tmpint32,int32_t); \
/* check if read would fit */ \
if ((bufptr+(size_t)tmpint32+1)>buflen) \
{ ERROR_OUT_BUFERROR(fp) } /* will not fit */ \
/* read string from the stream */ \
if (tmpint32>0) \
{ READ(fp,buffer+bufptr,(size_t)tmpint32); } \
/* null-terminate string in buffer */ \
buffer[bufptr+tmpint32]='\0'; \
DEBUG_PRINT("READ_STRING_BUF(\"%s\"=%d)\n",buffer+bufptr,strlen(buffer+bufptr)); \
/* prepare result */ \
(field)=buffer+bufptr; \
bufptr+=(size_t)tmpint32+1;
/* read a string from the stream dynamically allocating memory
for the string (don't forget to call free() later on) */
#define READ_STRING_ALLOC(fp,field) \
/* read the size of the string */ \
READ_TYPE(fp,tmpint32,int32_t); \
/* allocate memory */ \
(field)=(char *)malloc((size_t)(tmpint32+1)); \
if ((field)==NULL) \
{ ERROR_OUT_ALLOCERROR(fp) } /* problem allocating */ \
/* read string from the stream */ \
if (tmpint32>0) \
{ READ(fp,name,(size_t)tmpint32); } \
/* null-terminate string in buffer */ \
(name)[tmpint32]='\0'; \
DEBUG_PRINT("READ_STRING(\"%s\"=%d)\n",(name),strlen(name));
/* read an array from a stram and store the length of the
array in num (size for the array is allocated) */
#define READ_LOOP_NUM(fp,num,arr,opr) \
READ_TYPE(fp,tmpint32,int32_t); \
(num)=tmpint32; \
/* allocate room for *char[num] */ \
tmpint32*=sizeof(char *); \
if ((bufptr+(size_t)tmpint32)>buflen) \
{ ERROR_OUT_BUFERROR(fp) } /* will not fit */ \
(arr)=(char **)(buffer+bufptr); \
bufptr+=(size_t)tmpint32; \
for (tmp2int32=0;tmp2int32<(num);tmp2int32++) \
{ \
opr \
}
/* read an array from a stram and store it as a null-terminated
array list (size for the array is allocated) */
#define READ_LOOP_NULLTERM(fp,arr,opr) \
READ_TYPE(fp,tmpint32,int32_t); \
/* allocate room for *char[num+1] */ \
tmp2int32=(tmpint32+1)*sizeof(char *); \
if ((bufptr+(size_t)tmp2int32)>buflen) \
{ ERROR_OUT_BUFERROR(fp) } /* will not fit */ \
(arr)=(char **)(buffer+bufptr); \
/* read all entries */ \
bufptr+=(size_t)tmpint32; \
for (tmp2int32=0;tmp2int32<tmpint32;tmp2int32++) \
{ \
opr \
} \
/* set last entry to NULL */ \
(arr)[tmp2int32]=NULL;
/* read a string from the stream but don't do anything with the result */
#define SKIP_STRING(fp) \
/* read the size of the string */ \
READ_TYPE(fp,tmpint32,int32_t); \
/* seek in the stream past the string contents */ \
fseek(fp,(long)tmpint32,SEEK_CUR); \
DEBUG_PRINT("SKIP_STRING()\n");
/* skip a loop of strings */
#define SKIP_LOOP(fp) \
READ_TYPE(fp,tmpint32,int32_t); \
/* read all entries */ \
for (tmp2int32=0;tmp2int32<tmpint32;tmp2int32++) \
{ \
SKIP_STRING(fp); \
}
#endif /* not _NSLCD_COMMON_H */
|