]> err.no Git - sope/blob - sope-core/NGStreams/NGStream+serialization.m
added PCH support for frameworks
[sope] / sope-core / NGStreams / NGStream+serialization.m
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
138 void 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
254 void 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 NeXT_Foundation_LIBRARY
286         result = NSZoneMalloc(NULL, len + 1);
287 #else
288         result = NSZoneMallocAtomic(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
389 void __link_NGStream_serialization(void) {
390   __link_NGStream_serialization();
391 }