2 nslcd-common.h - helper macros for reading and writing in
5 Copyright (C) 2006 West Consulting
6 Copyright (C) 2006, 2007 Arthur de Jong
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 #ifndef _NSLCD_COMMON_H
25 #define _NSLCD_COMMON_H 1
30 /* define a debugging macro to output logging */
33 #define DEBUG_PRINT(fmt,arg) \
34 fprintf(stderr,"%s:%d:%s: " fmt "\n",__FILE__,__LINE__,__PRETTY_FUNCTION__,arg);
35 #else /* DEBUG_PROT */
36 /* define an empty debug macro to disable logging */
37 #define DEBUG_PRINT(fmt,arg)
38 #endif /* not DEBUG_PROT */
40 #ifdef DEBUG_PROT_DUMP
41 /* define a debugging macro to output detailed logging */
44 #endif /* HAVE_STDINT_H */
45 static void debug_dump(const void *ptr,size_t size)
49 fprintf(stderr," %02x",((const uint8_t *)ptr)[i]);
52 #define DEBUG_DUMP(ptr,size) \
53 fprintf(stderr,"%s:%d:%s:",__FILE__,__LINE__,__PRETTY_FUNCTION__); \
55 #else /* DEBUG_PROT_DUMP */
56 /* define an empty debug macro to disable logging */
57 #define DEBUG_DUMP(ptr,size)
58 #endif /* not DEBUG_PROT_DUMP */
60 /* WRITE marcos, used for writing data, on write error they will
61 call the ERROR_OUT_WRITEERROR macro
62 these macros may require the availability of the following
64 int32_t tmpint32; - temporary variable
67 #define WRITE(fp,ptr,size) \
68 DEBUG_PRINT("WRITE : var="__STRING(ptr)" size=%d",(int)size); \
69 DEBUG_DUMP(ptr,size); \
70 if (tio_write(fp,ptr,(size_t)size)) \
72 DEBUG_PRINT("WRITE : var="__STRING(ptr)" error: %s",strerror(errno)); \
73 ERROR_OUT_WRITEERROR(fp); \
76 #define WRITE_TYPE(fp,field,type) \
77 WRITE(fp,&(field),sizeof(type))
79 #define WRITE_INT32(fp,i) \
80 DEBUG_PRINT("WRITE_INT32 : var="__STRING(i)" int32=%d",(int)i); \
81 tmpint32=(int32_t)(i); \
82 WRITE_TYPE(fp,tmpint32,int32_t)
84 #define WRITE_STRING(fp,str) \
85 DEBUG_PRINT("WRITE_STRING: var="__STRING(str)" string=\"%s\"",str); \
92 WRITE_INT32(fp,strlen(str)); \
94 { WRITE(fp,str,tmpint32); } \
97 #define WRITE_FLUSH(fp) \
98 if (tio_flush(fp)<0) \
100 DEBUG_PRINT("WRITE_FLUSH : error: %s",strerror(errno)); \
101 ERROR_OUT_WRITEERROR(fp); \
104 #define WRITE_STRINGLIST(fp,arr) \
105 /* first determin length of array */ \
106 for (tmp3int32=0;(arr)[tmp3int32]!=NULL;tmp3int32++) \
108 /* write number of strings */ \
109 DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
110 WRITE_TYPE(fp,tmp3int32,int32_t); \
111 /* write strings */ \
112 for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
114 WRITE_STRING(fp,(arr)[tmp2int32]); \
117 #define WRITE_STRINGLIST_EXCEPT(fp,arr,not) \
118 /* first determin length of array */ \
119 for (tmp3int32=0;(arr)[tmp3int32]!=NULL;tmp3int32++) \
121 /* write number of strings (mius one because we intend to skip one) */ \
123 DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
124 WRITE_TYPE(fp,tmp3int32,int32_t); \
126 /* write strings */ \
127 for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
129 if (strcmp((arr)[tmp2int32],(not))!=0) \
131 WRITE_STRING(fp,(arr)[tmp2int32]); \
135 /* READ macros, used for reading data, on read error they will
136 call the ERROR_OUT_READERROR or ERROR_OUT_BUFERROR macro
137 these macros may require the availability of the following
139 int32_t tmpint32; - temporary variable
140 char *buffer; - pointer to a buffer for reading strings
141 size_t buflen; - the size of the buffer
142 size_t bufptr; - the current position in the buffer
145 #define READ(fp,ptr,size) \
146 if (tio_read(fp,ptr,(size_t)size)) \
148 DEBUG_PRINT("READ : var="__STRING(ptr)" error: %s",strerror(errno)); \
149 ERROR_OUT_READERROR(fp); \
151 DEBUG_PRINT("READ : var="__STRING(ptr)" size=%d",(int)size); \
152 DEBUG_DUMP(ptr,size);
154 #define READ_TYPE(fp,field,type) \
155 READ(fp,&(field),sizeof(type))
157 #define READ_INT32(fp,i) \
158 READ_TYPE(fp,tmpint32,int32_t); \
160 DEBUG_PRINT("READ_INT32 : var="__STRING(i)" int32=%d",(int)i);
162 /* current position in the buffer */
166 /* check that the buffer has sz bytes left in it */
167 #define BUF_CHECK(fp,sz) \
168 if ((bufptr+(size_t)(sz))>buflen) \
171 DEBUG_PRINT("READ : buffer error: %d bytes too small",(bufptr+(sz)-(buflen))); \
172 ERROR_OUT_BUFERROR(fp); \
175 /* move the buffer pointer */
176 #define BUF_SKIP(sz) \
177 bufptr+=(size_t)(sz);
179 /* move BUF_CUR foreward so that it is aligned to the specified
181 #define BUF_ALIGN(fp,type) \
182 /* figure out number of bytes to skip foreward */ \
183 tmp2int32=(sizeof(type)-((BUF_CUR-(char *)NULL)%sizeof(type)))%sizeof(type); \
184 /* check and skip */ \
185 BUF_CHECK(fp,tmp2int32); \
188 /* allocate a piece of the buffer to store an array in */
189 #define BUF_ALLOC(fp,ptr,type,num) \
190 /* align to the specified type width */ \
191 BUF_ALIGN(fp,type); \
192 /* check that we have enough room */ \
193 BUF_CHECK(fp,(size_t)(num)*sizeof(type)); \
194 /* store the pointer */ \
195 (ptr)=(type *)BUF_CUR; \
196 /* reserve the space */ \
197 BUF_SKIP((size_t)(num)*sizeof(type));
199 /* read string in the buffer (using buffer, buflen and bufptr)
200 and store the actual location of the string in field */
201 #define READ_STRING_BUF(fp,field) \
202 /* read the size of the string */ \
203 READ_TYPE(fp,tmpint32,int32_t); \
204 DEBUG_PRINT("READ_STRING: var="__STRING(field)" strlen=%d",tmpint32); \
205 /* check if read would fit */ \
206 BUF_CHECK(fp,tmpint32+1); \
207 /* read string from the stream */ \
209 { READ(fp,BUF_CUR,(size_t)tmpint32); } \
210 /* null-terminate string in buffer */ \
211 BUF_CUR[tmpint32]='\0'; \
212 DEBUG_PRINT("READ_STRING: var="__STRING(field)" string=\"%s\"",BUF_CUR); \
213 /* prepare result */ \
215 BUF_SKIP(tmpint32+1);
217 /* read a string in a fixed-size "normal" buffer */
218 #define READ_STRING_BUF2(fp,buffer,buflen) \
219 /* read the size of the string */ \
220 READ_TYPE(fp,tmpint32,int32_t); \
221 DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" strlen=%d",tmpint32); \
222 /* check if read would fit */ \
223 if (((size_t)tmpint32)>=(buflen)) \
226 DEBUG_PRINT("READ : buffer error: %d bytes too large",(tmpint32-(buflen))+1); \
227 ERROR_OUT_BUFERROR(fp); \
229 /* read string from the stream */ \
231 { READ(fp,buffer,(size_t)tmpint32); } \
232 /* null-terminate string in buffer */ \
233 buffer[tmpint32]='\0'; \
234 DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" string=\"%s\"",buffer);
236 /* read a binary blob into the buffer */
237 #define READ_BUF(fp,ptr,sz) \
238 /* check that there is enough room and read */ \
240 READ(fp,BUF_CUR,(size_t)sz); \
241 /* store pointer and skip */ \
245 /* read an array from a stram and store the length of the
246 array in num (size for the array is allocated) */
247 #define READ_STRINGLIST_NUM(fp,arr,num) \
248 /* read the number of entries */ \
249 READ_INT32(fp,(num)); \
250 DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d",(int)(num)); \
251 /* allocate room for *char[num] */ \
252 BUF_ALLOC(fp,arr,char *,tmpint32); \
253 /* read all the strings */ \
254 for (tmp2int32=0;tmp2int32<(int32_t)(num);tmp2int32++) \
256 READ_STRING_BUF(fp,(arr)[tmp2int32]); \
259 /* read an array from a stram and store it as a null-terminated
260 array list (size for the array is allocated) */
261 #define READ_STRINGLIST_NULLTERM(fp,arr) \
262 /* read the number of entries */ \
263 READ_TYPE(fp,tmp3int32,int32_t); \
264 DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
265 /* allocate room for *char[num+1] */ \
266 BUF_ALLOC(fp,arr,char *,tmp3int32+1); \
267 /* read all entries */ \
268 for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
270 READ_STRING_BUF(fp,(arr)[tmp2int32]); \
272 /* set last entry to NULL */ \
273 (arr)[tmp2int32]=NULL;
275 /* skip a number of bytes foreward
276 Note that this macro modifies the sz variable */
277 #define SKIP(fp,sz) \
278 DEBUG_PRINT("READ : skip %d bytes",(int)(sz)); \
279 /* read (skip) the specified number of bytes */ \
280 if (tio_skip(fp,sz)) \
282 DEBUG_PRINT("READ : skip error: %s",strerror(errno)); \
283 ERROR_OUT_READERROR(fp); \
286 /* read a string from the stream but don't do anything with the result */
287 #define SKIP_STRING(fp) \
288 /* read the size of the string */ \
289 READ_TYPE(fp,tmpint32,int32_t); \
290 DEBUG_PRINT("READ_STRING: skip %d bytes",(int)tmpint32); \
291 /* read (skip) the specified number of bytes */ \
294 /* skip a loop of strings */
295 #define SKIP_STRINGLIST(fp) \
296 /* read the number of entries */ \
297 READ_TYPE(fp,tmp3int32,int32_t); \
298 DEBUG_PRINT("READ_STRLST: skip %d strings",(int)tmp3int32); \
299 /* read all entries */ \
300 for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
305 #endif /* not _NSLCD_COMMON_H */