jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, 00004 * Ryan Eatmon, Robert Norris 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00019 */ 00020 00021 /* these are useful utilities for data serialisation */ 00022 00023 #include "util.h" 00024 00025 /* 00026 * ser_string_get() and ser_int_get() retrieve a string (null-terminated) or 00027 * an int (sizeof(int) chars) from source, and store it in dest. source is a 00028 * pointer into buf, and will be updated before the call returns. 00029 * buf is a pointer to the start of the source buffer, and len is the length 00030 * of the buffer. if retrieving the data would take us pass the end of the 00031 * array, a non-zero value will be returned. if the call succeeds, 0 is 00032 * returned. 00033 */ 00034 00035 int ser_string_get(char **dest, int *source, const char *buf, int len) 00036 { 00037 const char *end, *c; 00038 00039 /* end of the buffer */ 00040 end = buf + ((sizeof(char) * (len - 1))); 00041 00042 /* make sure we have a \0 before the end of the buffer */ 00043 c = &(buf[*source]); 00044 while(c <= end && *c != '\0') c++; 00045 if(c > end) 00046 /* we ran past the end, fail */ 00047 return 1; 00048 00049 /* copy the string */ 00050 *dest = strdup(&(buf[*source])); 00051 00052 /* and move the pointer */ 00053 *source += strlen(*dest) + 1; 00054 00055 return 0; 00056 } 00057 00058 int ser_int_get(int *dest, int *source, const char *buf, int len) 00059 { 00060 union 00061 { 00062 char c[sizeof(int)]; 00063 int i; 00064 } u; 00065 int i; 00066 00067 /* we need sizeof(int) bytes */ 00068 if(&(buf[*source]) + sizeof(int) > buf + (sizeof(char) * len)) 00069 return 1; 00070 00071 /* copy the bytes into the union. we do it this way to avoid alignment problems */ 00072 for(i = 0; i < sizeof(int); i++) 00073 { 00074 u.c[i] = buf[*source]; 00075 (*source)++; 00076 } 00077 *dest = u.i; 00078 00079 return 0; 00080 } 00081 00082 /* 00083 * ser_string_set() and ser_int_set() stores the string or int referenced by 00084 * source into buf, starting at dest. len holds the current length of the 00085 * buffer. if storing the data would overrun the end of the buffer, the buffer 00086 * will be grown to accomodate. buf, dest and len will be updated. 00087 */ 00088 00089 /* shamelessy stolen from nad.c */ 00090 00091 #define BLOCKSIZE 1024 00092 00094 static int _ser_realloc(void **oblocks, int len) 00095 { 00096 void *nblocks; 00097 int nlen; 00098 00099 /* round up to standard block sizes */ 00100 nlen = (((len-1)/BLOCKSIZE)+1)*BLOCKSIZE; 00101 00102 /* keep trying till we get it */ 00103 while((nblocks = realloc(*oblocks, nlen)) == NULL) sleep(1); 00104 *oblocks = nblocks; 00105 return nlen; 00106 } 00107 00109 #define SER_SAFE(blocks, size, len) if((size) > len) len = _ser_realloc((void**)&(blocks),(size)); 00110 00111 void ser_string_set(char *source, int *dest, char **buf, int *len) 00112 { 00113 int need = sizeof(char) * (strlen(source) + 1); 00114 00115 /* make more space if necessary */ 00116 SER_SAFE(*buf, *dest + need, *len); 00117 00118 /* copy it in */ 00119 strcpy(*buf + *dest, source); 00120 00121 /* and shift the pointer */ 00122 *dest += need; 00123 } 00124 00125 void ser_int_set(int source, int *dest, char **buf, int *len) 00126 { 00127 union 00128 { 00129 char c[sizeof(int)]; 00130 int i; 00131 } u; 00132 int i; 00133 00134 /* make more space if necessary */ 00135 SER_SAFE(*buf, *dest + sizeof(int), *len) 00136 00137 /* copy it in */ 00138 u.i = source; 00139 for(i = 0; i < sizeof(int); i++) 00140 (*buf)[*dest + i] = u.c[i]; 00141 00142 /* and shift the pointer */ 00143 *dest += sizeof(int); 00144 }