1/* 2 Copyright (C) 2000-2005 SKYRIX Software AG 3 4 This file is part of SOPE. 5 6 SOPE is free software; you can redistribute it and/or modify it under 7 the terms of the GNU Lesser General Public License as published by the 8 Free Software Foundation; either version 2, or (at your option) any 9 later version. 10 11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 14 License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with SOPE; see the file COPYING. If not, write to the 18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19 02111-1307, USA. 20*/ 21 22#include "config.h" 23 24#if !defined(WIN32) 25# if HAVE_SYS_TYPES_H 26# include <sys/types.h> 27# endif 28# if HAVE_SYS_SOCKET_H 29# include <sys/socket.h> 30# endif 31# if HAVE_NETINET_IN_H 32# include <netinet/in.h> 33# endif 34# include <arpa/inet.h> 35#endif 36 37#include "common.h" 38#include "NGStream+serialization.h" 39 40#if NeXT_RUNTIME 41# include <objc/objc-class.h> 42#endif 43 44@implementation NGStream(serialization) 45 46// serialization 47 48- (void)serializeChar:(char)_value { 49 NGStreamSerializeObjC(self, &_value, @encode(char), nil); 50} 51- (void)serializeShort:(short)_value { 52 NGStreamSerializeObjC(self, &_value, @encode(short), nil); 53} 54- (void)serializeInt:(int)_value { 55 NGStreamSerializeObjC(self, &_value, @encode(int), nil); 56} 57- (void)serializeLong:(long)_value { 58 NGStreamSerializeObjC(self, &_value, @encode(long), nil); 59} 60 61- (void)serializeFloat:(float)_value { 62 NGStreamSerializeObjC(self, &_value, @encode(float), nil); 63} 64- (void)serializeDouble:(double)_value { 65 NGStreamSerializeObjC(self, &_value, @encode(double), nil); 66} 67- (void)serializeLongLong:(long long)_value { 68 NGStreamSerializeObjC(self, &_value, @encode(long long), nil); 69} 70 71- (void)serializeCString:(const char *)_value { 72 NGStreamSerializeObjC(self, &_value, @encode(char *), nil); 73} 74 75#if USE_SERIALIZER 76- (void)serializeDataAt:(const void*)_value ofObjCType:(const char*)_type 77 context:(id<NSObjCTypeSerializationCallBack>)_callback 78{ 79 NGStreamSerializeObjC(self, _value, _type, _callback); 80} 81#endif 82 83// deserialization 84 85- (char)deserializeChar { 86 char c; 87 NGStreamDeserializeObjC(self, &c, @encode(char), nil); 88 return c; 89} 90- (short)deserializeShort { 91 short s; 92 NGStreamDeserializeObjC(self, &s, @encode(short), nil); 93 return s; 94} 95- (int)deserializeInt { 96 int i; 97 NGStreamDeserializeObjC(self, &i, @encode(int), nil); 98 return i; 99} 100- (long)deserializeLong { 101 long l; 102 NGStreamDeserializeObjC(self, &l, @encode(long), nil); 103 return l; 104} 105- (float)deserializeFloat { 106 float f; 107 NGStreamDeserializeObjC(self, &f, @encode(float), nil); 108 return f; 109} 110 111- (double)deserializeDouble { 112 double d; 113 NGStreamDeserializeObjC(self, &d, @encode(double), nil); 114 return d; 115} 116- (long long)deserializeLongLong { 117 long long l; 118 NGStreamDeserializeObjC(self, &l, @encode(long long), nil); 119 return l; 120} 121 122- (char *)deserializeCString { 123 char *result = NULL; 124 NGStreamDeserializeObjC(self, &result, @encode(char *), nil); 125 return result; 126} 127 128#if USE_SERIALIZER 129- (void)deserializeDataAt:(void *)_value ofObjCType:(const char *)_type 130 context:(id<NSObjCTypeSerializationCallBack>)_callback 131{ 132 NGStreamDeserializeObjC(self, _value, _type, _callback); 133} 134#endif 135 136@end 137 138void NGStreamSerializeObjC(id<NGStream> self, 139 const void *_value, const char *_type, 140#if USE_SERIALIZER 141 id<NSObjCTypeSerializationCallBack> _callback 142#else 143 id _callback 144#endif 145 ) 146{ 147 switch (*_type) { 148 case _C_ID: 149 case _C_CLASS: 150 [_callback serializeObjectAt:(id *)_value 151 ofObjCType:_type 152 intoData:(NSMutableData *)self]; 153 break; 154 155 case _C_CHARPTR: { 156 const char *cstr = *(char **)_value; 157 int len = cstr ? (int)strlen(cstr) : -1; 158 159 NGStreamSerializeObjC(self, &len, @encode(int), _callback); 160 if (cstr) 161 [self safeWriteBytes:cstr count:len]; 162 163 break; 164 } 165 166 case _C_ARY_B: { 167 int i, offset, itemSize, count; 168 169 count = atoi(_type + 1); // skip '[' and get dimension 170 171 while (isdigit((int)*++_type)) ; // skip '[' and dimension 172 itemSize = objc_sizeof_type(_type); 173 174 for (i = offset = 0; i < count; i++, offset += itemSize) 175 NGStreamSerializeObjC(self, (char *)_value + offset, _type, _callback); 176 break; 177 } 178 179 case _C_STRUCT_B: { 180 int offset = 0; 181 182 while ((*_type != _C_STRUCT_E) && (*_type++ != '=')) ; // skip '<name>=' 183 184 while (YES) { 185 NGStreamSerializeObjC(self, (char *)_value + offset, _type, _callback); 186 187 offset += objc_sizeof_type(_type); 188 _type = objc_skip_typespec(_type); 189 190 if (*_type != _C_STRUCT_E) { 191 int align, remainder; 192 193 align = objc_alignof_type(_type); 194 if ((remainder = offset % align)) 195 offset += align - remainder; 196 } 197 else // done with structure 198 break; 199 } 200 break; 201 } 202 203 case _C_PTR: 204 NGStreamSerializeObjC(self, *(char **)_value, _type + 1, _callback); 205 break; 206 207 case _C_CHR: 208 case _C_UCHR: 209 [self safeWriteBytes:_value count:1]; 210 break; 211 212 case _C_SHT: 213 case _C_USHT: { 214 short netValue = htons(*(short *)_value); 215 [self safeWriteBytes:&netValue count:2]; 216 break; 217 } 218 219 case _C_INT: 220 case _C_UINT: { 221 int netValue = htonl(*(int *)_value); 222 [self safeWriteBytes:&netValue count:4]; 223 break; 224 } 225 226 case _C_LNG: 227 case _C_ULNG: { 228 long netValue = htonl(*(long *)_value); 229 [self safeWriteBytes:&netValue count:sizeof(long)]; 230 break; 231 } 232 233 case _C_FLT: { 234 union fconv { 235 float value; 236 unsigned long ul; 237 } fc; 238 fc.value = *(float *)_value; 239 fc.ul = htonl(fc.ul); 240 [self safeWriteBytes:&fc count:sizeof(unsigned long)]; 241 break; 242 } 243 case _C_DBL: { 244 [self safeWriteBytes:_value count:8]; 245 break; 246 } 247 248 default: 249 NSCAssert1(0, @"unsupported C type %s ..", _type); 250 break; 251 } 252} 253 254void NGStreamDeserializeObjC(id<NGStream> self, 255 void *_value, const char *_type, 256#if USE_SERIALIZER 257 id<NSObjCTypeSerializationCallBack> _callback 258#else 259 id _callback 260#endif 261 ) 262{ 263 if ((_value == NULL) || (_type == NULL)) 264 return; 265 266 switch (*_type) { 267 case _C_ID: 268 case _C_CLASS: 269 [_callback deserializeObjectAt:(id *)_value 270 ofObjCType:_type 271 fromData:(NSData *)self 272 atCursor:0]; 273 break; 274 275 case _C_CHARPTR: { // malloced C-string 276 int len = -1; 277 278 NGStreamDeserializeObjC(self, &len, @encode(int), _callback); 279 280 if (len == -1) // NULL-string 281 *(char **)_value = NULL; 282 else { 283 char *result = NULL; 284 285#if LIB_FOUNDATION_LIBRARY 286 result = NSZoneMallocAtomic(NULL, len + 1); 287#else 288 result = NSZoneMalloc(NULL, len + 1); 289#endif 290 result[len] = '\0'; 291 292 if (len > 0) [self safeReadBytes:result count:len]; 293 *(char **)_value = result; 294 } 295 break; 296 } 297 298 case _C_ARY_B: { 299 int i, offset, itemSize, count; 300 301 count = atoi(_type + 1); // skip '[' and get dimension 302 303 while (isdigit((int)*++_type)) ; // skip '[' and dimension 304 itemSize = objc_sizeof_type(_type); 305 306 for (i = offset = 0; i < count; i++, offset += itemSize) 307 NGStreamDeserializeObjC(self, (char *)_value + offset, _type, _callback); 308 309 break; 310 } 311 312 case _C_STRUCT_B: { 313 int offset = 0; 314 315 while ((*_type != _C_STRUCT_E) && (*_type++ != '=')) ; // skip '<name>=' 316 317 while (YES) { 318 NGStreamDeserializeObjC(self, (char *)_value + offset, _type, _callback); 319 320 offset += objc_sizeof_type(_type); 321 _type = objc_skip_typespec(_type); 322 323 if (*_type != _C_STRUCT_E) { 324 int align, remainder; 325 326 align = objc_alignof_type(_type); 327 if ((remainder = offset % align)) 328 offset += align - remainder; 329 } 330 else // done with structure 331 break; 332 } 333 break; 334 } 335 336 case _C_PTR: { 337 // skip '^', type of the value the ptr points to 338 void *result = NULL; 339 340 result = NSZoneMalloc(NULL, objc_sizeof_type(_type + 1)); 341 342 NGStreamDeserializeObjC(self, result, _type + 1, _callback); 343 344 *(char **)_value = result; 345 result = NULL; 346 347 break; 348 } 349 350 case _C_CHR: 351 case _C_UCHR: 352 [self safeReadBytes:_value count:1]; 353 break; 354 355 case _C_SHT: 356 case _C_USHT: 357 [self safeReadBytes:_value count:2]; 358 *(short *)_value = ntohs(*(short *)_value); 359 break; 360 361 case _C_INT: 362 case _C_UINT: 363 [self safeReadBytes:_value count:4]; 364 *(int *)_value = ntohl(*(int *)_value); 365 break; 366 367 case _C_LNG: 368 case _C_ULNG: 369 [self safeReadBytes:_value count:4]; 370 *(long *)_value = ntohl(*(long *)_value); 371 break; 372 373 case _C_FLT: { 374 [self safeReadBytes:_value count:4]; 375 *(long *)_value = ntohl(*(long *)_value); 376 break; 377 } 378 case _C_DBL: { 379 [self safeReadBytes:_value count:8]; 380 break; 381 } 382 383 default: 384 NSLog(@"unsupported C type %s ..", _type); 385 break; 386 } 387} 388 389void __link_NGStream_serialization(void) { 390 __link_NGStream_serialization(); 391} 392