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