pack.c (7603B)
1 /* 2 Catlib Copyright Notice 3 4 The author of this software is Christopher Adam Telfer 5 Copyright (c) 1998, 1999, 2000, 2001, 2002 6 by Christopher Adam Telfer. All Rights Reserved. 7 8 Permission to use, copy, modify, and distribute this software for any 9 purpose without fee is hereby granted, provided that the above copyright 10 notice, this paragraph, and the following two paragraphs appear in all 11 copies, modifications, and distributions. 12 13 IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 14 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, 15 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 16 THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17 18 THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF 21 ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO 22 OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 23 MODIFICATIONS. 24 25 */ 26 27 #include "platform.h" 28 #include "pack.h" 29 #include "le_architecture.h" 30 31 #if ! (defined(_WIN32) && defined(cbNDRContext)) 32 typedef unsigned char byte; 33 #endif 34 typedef unsigned short half; 35 typedef unsigned int word; 36 typedef signed char sbyte; 37 typedef signed short shalf; 38 typedef signed int sword; 39 40 41 int 42 EXTRACTOR_common_cat_unpack (const void *buf, 43 const char *fmt, 44 ...) 45 { 46 va_list ap; 47 word maxlen, len, *wordp; 48 void *arr; 49 byte *bp, *bytep, *newbuf; 50 half *halfp; 51 long long *ll; 52 sbyte *sbytep; 53 shalf *shalfp; 54 sword *swordp; 55 int npacked; 56 unsigned int nreps, i, isnonprefixed = 1; /* used for 'a' types only */ 57 struct cat_bvec *cbvp; 58 char *cp; 59 60 bp = (byte *) buf; 61 npacked = 0; 62 63 va_start (ap, fmt); 64 65 while (*fmt) 66 { 67 nreps = 1; 68 69 if (isdigit ( (unsigned char) *fmt)) 70 { 71 /* We use cp instead of format to keep the 'const' qualifier of fmt */ 72 nreps = strtoul (fmt, &cp, 0); 73 fmt = cp; 74 if (*fmt == 'a') 75 isnonprefixed = 0; 76 } 77 78 switch (*fmt) 79 { 80 case 'B': 81 case 'b': 82 bytep = va_arg (ap, byte *); 83 for (i = 0; i < nreps; ++i) 84 { 85 *bytep = *bp++; 86 ++bytep; 87 npacked += 1; 88 } 89 break; 90 91 92 case 'h': 93 halfp = va_arg (ap, half *); 94 for (i = 0; i < nreps; ++i) 95 { 96 *halfp = *bp++; 97 *halfp |= *bp++ << 8; 98 ++halfp; 99 npacked += 2; 100 } 101 break; 102 103 case 'H': 104 halfp = va_arg (ap, half *); 105 for (i = 0; i < nreps; ++i) 106 { 107 *halfp = *bp++ << 8; 108 *halfp |= *bp++; 109 ++halfp; 110 npacked += 2; 111 } 112 break; 113 114 115 case 'w': 116 wordp = va_arg (ap, word *); 117 for (i = 0; i < nreps; ++i) 118 { 119 *wordp = *bp++; 120 *wordp |= *bp++ << 8; 121 *wordp |= *bp++ << 16; 122 *wordp |= *bp++ << 24; 123 ++wordp; 124 npacked += 4; 125 } 126 break; 127 128 case 'x': 129 ll = va_arg (ap, long long *); 130 for (i = 0; i < nreps; ++i) 131 { 132 *ll = ((long long) *bp++); 133 *ll |= ((long long) *bp++) << 8; 134 *ll |= ((long long) *bp++) << 16; 135 *ll |= ((long long) *bp++) << 24; 136 *ll |= ((long long) *bp++) << 32; 137 *ll |= ((long long) *bp++) << 40; 138 *ll |= ((long long) *bp++) << 48; 139 *ll |= ((long long) *bp++) << 56; 140 ++ll; 141 npacked += 8; 142 } 143 break; 144 145 case 'W': 146 wordp = va_arg (ap, word *); 147 for (i = 0; i < nreps; ++i) 148 { 149 *wordp = *bp++ << 24; 150 *wordp |= *bp++ << 16; 151 *wordp |= *bp++ << 8; 152 *wordp |= *bp++; 153 ++wordp; 154 npacked += 4; 155 } 156 break; 157 158 case 'X': 159 ll = va_arg (ap, long long *); 160 for (i = 0; i < nreps; ++i) 161 { 162 *ll = ((long long) *bp++) << 56; 163 *ll |= ((long long) *bp++) << 48; 164 *ll |= ((long long) *bp++) << 40; 165 *ll |= ((long long) *bp++) << 32; 166 *ll |= ((long long) *bp++) << 24; 167 *ll |= ((long long) *bp++) << 18; 168 *ll |= ((long long) *bp++) << 8; 169 *ll |= ((long long) *bp++); 170 ++ll; 171 npacked += 8; 172 } 173 break; 174 175 176 case 'A': 177 if (isnonprefixed) 178 { 179 maxlen = va_arg (ap, word); 180 arr = va_arg (ap, void *); 181 182 len = *bp++ << 24; 183 len |= *bp++ << 16; 184 len |= *bp++ << 8; 185 len |= *bp++; 186 187 if (len > maxlen) 188 { 189 va_end (ap); 190 return -1; 191 } 192 193 memmove (arr, bp, len); 194 bp += len; 195 196 npacked += len; 197 } 198 else 199 { 200 cbvp = va_arg (ap, struct cat_bvec *); 201 for (i = 0; i < nreps; ++i) 202 { 203 maxlen = cbvp->len; 204 arr = cbvp->data; 205 206 len = *bp++ << 24; 207 len |= *bp++ << 16; 208 len |= *bp++ << 8; 209 len |= *bp++; 210 211 if (len > maxlen) 212 return -1; 213 214 memmove (arr, bp, len); 215 cbvp->len = len; 216 bp += len; 217 218 ++cbvp; 219 npacked += len; 220 } 221 isnonprefixed = 1; 222 } 223 break; 224 225 case 'C': 226 case 'c': 227 sbytep = va_arg (ap, sbyte *); 228 for (i = 0; i < nreps; ++i) 229 { 230 *sbytep = *bp++; 231 232 if ((sizeof (sbyte) > 1) && (*sbytep & 0x80)) 233 *sbytep |= (~0) << ((sizeof (sbyte) - 1) * 8); 234 235 ++sbytep; 236 npacked += 1; 237 } 238 break; 239 240 241 case 's': 242 shalfp = va_arg (ap, shalf *); 243 for (i = 0; i < nreps; ++i) 244 { 245 *shalfp = *bp++; 246 *shalfp |= *bp++ << 8; 247 248 if ((sizeof (shalf) > 2) && (*shalfp & 0x8000)) 249 *shalfp |= (~0) << ((sizeof (shalf) - 2) * 8); 250 251 ++shalfp; 252 npacked += 2; 253 } 254 break; 255 256 case 'S': 257 shalfp = va_arg (ap, shalf *); 258 for (i = 0; i < nreps; ++i) 259 { 260 *shalfp = *bp++ << 8; 261 *shalfp |= *bp++; 262 263 if ((sizeof (shalf) > 2) && (*shalfp & 0x8000)) 264 *shalfp |= (~0) << ((sizeof (shalf) - 2) * 8); 265 266 ++shalfp; 267 npacked += 2; 268 } 269 break; 270 271 case 'l': 272 swordp = va_arg (ap, sword *); 273 for (i = 0; i < nreps; ++i) 274 { 275 *swordp = *bp++; 276 *swordp |= *bp++ << 8; 277 *swordp |= *bp++ << 16; 278 *swordp |= *bp++ << 24; 279 280 if ((sizeof (swordp) > 4) && (*swordp & 0x80000000)) 281 *swordp |= (~0) << ((sizeof (sword) - 4) * 8); 282 283 ++swordp; 284 npacked += 4; 285 } 286 break; 287 288 case 'L': 289 swordp = va_arg (ap, sword *); 290 for (i = 0; i < nreps; ++i) 291 { 292 *swordp = *bp++ << 24; 293 *swordp |= *bp++ << 16; 294 *swordp |= *bp++ << 8; 295 *swordp |= *bp++; 296 297 if ((sizeof (swordp) > 4) && (*swordp & 0x80000000)) 298 *swordp |= (~0) << ((sizeof (sword) - 4) * 8); 299 300 ++swordp; 301 npacked += 4; 302 } 303 break; 304 305 case 'P': 306 cbvp = va_arg (ap, struct cat_bvec *); 307 for (i = 0; i < nreps; ++i) 308 { 309 len = *bp++ << 24; 310 len |= *bp++ << 16; 311 len |= *bp++ << 8; 312 len |= *bp++; 313 314 newbuf = (byte *) malloc (len); 315 316 if (! newbuf) 317 { 318 int j; 319 for (j = 0; j < i; j++) 320 free (cbvp[i].data); 321 va_end (ap); 322 return -1; 323 } 324 325 memmove (newbuf, bp, len); 326 cbvp[i].data = newbuf; 327 cbvp[i].len = len; 328 329 bp += len; 330 npacked += len; 331 } 332 break; 333 334 default: 335 va_end (ap); 336 return -1; 337 } 338 339 ++fmt; 340 } 341 342 va_end (ap); 343 return 0; 344 }