1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993 Free Software Foundation, Inc.
4 Author: Kresten Krab Thorup
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2, or (at your option) any later version.
12 GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 You should have received a copy of the GNU General Public License along with
18 GNU CC; see the file COPYING. If not, write to the Free Software
19 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* As a special exception, if you link this library with files compiled with
22 GCC to produce an executable, this does not cause the resulting executable
23 to be covered by the GNU General Public License. This exception does not
24 however invalidate any other reasons why the executable file might be
25 covered by the GNU General Public License. */
28 ** Note: This version assumes that int and longs are both 32bit.
34 #include "typedstream.h"
36 #define __objc_fatal(format, args...) \
37 { fprintf(stderr, "archiving: "); \
38 fprintf(stderr, format, ## args); \
39 fprintf(stderr, "\n"); abort(); }
41 /* Declare some functions... */
44 objc_read_class (struct objc_typed_stream
* stream
, Class
** class);
47 objc_sizeof_type(const char* type
);
50 objc_write_use_common (struct objc_typed_stream
* stream
, unsigned int key
);
53 objc_write_register_common (struct objc_typed_stream
* stream
,
57 objc_write_class (struct objc_typed_stream
* stream
,
58 struct objc_class
* class);
61 __objc_skip_type (const char* type
);
63 static void __objc_finish_write_root_object(struct objc_typed_stream
*);
64 static void __objc_finish_read_root_object(struct objc_typed_stream
*);
67 __objc_code_unsigned_char (unsigned char* buf
, unsigned char val
)
69 if ((val
&_B_VALUE
) == val
)
76 buf
[0] = _B_NINT
|0x01;
83 objc_write_unsigned_char (struct objc_typed_stream
* stream
,
86 unsigned char buf
[sizeof (unsigned char)+1];
87 int len
= __objc_code_unsigned_char (buf
, value
);
88 return (*stream
->write
)(stream
->physical
, buf
, len
);
92 __objc_code_char (unsigned char* buf
, char val
)
95 return __objc_code_unsigned_char (buf
, val
);
98 buf
[0] = _B_NINT
|_B_SIGN
|0x01;
105 objc_write_char (struct objc_typed_stream
* stream
, char value
)
107 unsigned char buf
[sizeof (char)+1];
108 int len
= __objc_code_char (buf
, value
);
109 return (*stream
->write
)(stream
->physical
, buf
, len
);
112 static __inline__
int
113 __objc_code_unsigned_short (unsigned char* buf
, unsigned short val
)
116 return __objc_code_unsigned_char (buf
, val
);
120 buf
[0] = _B_NINT
|0x02;
128 objc_write_unsigned_short (struct objc_typed_stream
* stream
, unsigned short value
)
130 unsigned char buf
[sizeof (unsigned short)+1];
131 int len
= __objc_code_unsigned_short (buf
, value
);
132 return (*stream
->write
)(stream
->physical
, buf
, len
);
135 static __inline__
int
136 __objc_code_short (unsigned char* buf
, short val
)
139 return __objc_code_unsigned_short (buf
, val
);
141 if (val
> -0x7f) /* val > -128 */
142 return __objc_code_char (buf
, val
);
146 int len
= __objc_code_unsigned_short (buf
, -val
);
153 objc_write_short (struct objc_typed_stream
* stream
, short value
)
155 unsigned char buf
[sizeof (short)+1];
156 int len
= __objc_code_short (buf
, value
);
157 return (*stream
->write
)(stream
->physical
, buf
, len
);
161 static __inline__
int
162 __objc_code_unsigned_int (unsigned char* buf
, unsigned int val
)
165 return __objc_code_unsigned_short (buf
, val
%0x10000);
167 else if (val
< 0x1000000)
170 buf
[1] = val
/0x10000;
171 buf
[2] = (val
%0x10000)/0x100;
179 buf
[1] = val
/0x1000000;
180 buf
[2] = (val
%0x1000000)/0x10000;
181 buf
[3] = (val
%0x10000)/0x100;
188 objc_write_unsigned_int (struct objc_typed_stream
* stream
, unsigned int value
)
190 unsigned char buf
[sizeof(unsigned int)+1];
191 int len
= __objc_code_unsigned_int (buf
, value
);
192 return (*stream
->write
)(stream
->physical
, buf
, len
);
195 static __inline__
int
196 __objc_code_int (unsigned char* buf
, int val
)
199 return __objc_code_unsigned_int (buf
, val
);
202 return __objc_code_char (buf
, val
);
206 int len
= __objc_code_unsigned_int (buf
, -val
);
213 objc_write_int (struct objc_typed_stream
* stream
, int value
)
215 unsigned char buf
[sizeof(int)+1];
216 int len
= __objc_code_int (buf
, value
);
217 return (*stream
->write
)(stream
->physical
, buf
, len
);
221 objc_write_string (struct objc_typed_stream
* stream
,
222 const unsigned char* string
, unsigned int nbytes
)
224 unsigned char buf
[sizeof(unsigned int)+1];
225 int len
= __objc_code_unsigned_int (buf
, nbytes
);
227 if ((buf
[0]&_B_CODE
) == _B_SINT
)
228 buf
[0] = (buf
[0]&_B_VALUE
)|_B_SSTR
;
231 buf
[0] = (buf
[0]&_B_VALUE
)|_B_NSTR
;
233 if ((*stream
->write
)(stream
->physical
, buf
, len
) != 0)
234 return (*stream
->write
)(stream
->physical
, string
, nbytes
);
240 objc_write_string_atomic (struct objc_typed_stream
* stream
,
241 unsigned char* string
, unsigned int nbytes
)
244 if ((key
= (unsigned int)hash_value_for_key (stream
->stream_table
, string
)))
245 return objc_write_use_common (stream
, key
);
249 hash_add (&stream
->stream_table
, (void*)key
=(unsigned int)string
, string
);
250 if ((length
= objc_write_register_common (stream
, key
)))
251 return objc_write_string (stream
, string
, nbytes
);
257 objc_write_register_common (struct objc_typed_stream
* stream
, unsigned int key
)
259 unsigned char buf
[sizeof (unsigned int)+2];
260 int len
= __objc_code_unsigned_int (buf
+1, key
);
263 buf
[0] = _B_RCOMM
|0x01;
265 return (*stream
->write
)(stream
->physical
, buf
, len
+1);
269 buf
[1] = (buf
[1]&_B_VALUE
)|_B_RCOMM
;
270 return (*stream
->write
)(stream
->physical
, buf
+1, len
);
275 objc_write_use_common (struct objc_typed_stream
* stream
, unsigned int key
)
277 unsigned char buf
[sizeof (unsigned int)+2];
278 int len
= __objc_code_unsigned_int (buf
+1, key
);
281 buf
[0] = _B_UCOMM
|0x01;
283 return (*stream
->write
)(stream
->physical
, buf
, 2);
287 buf
[1] = (buf
[1]&_B_VALUE
)|_B_UCOMM
;
288 return (*stream
->write
)(stream
->physical
, buf
+1, len
);
292 static __inline__
int
293 __objc_write_extension (struct objc_typed_stream
* stream
, unsigned char code
)
295 if (code
<= _B_VALUE
)
297 unsigned char buf
= code
|_B_EXT
;
298 return (*stream
->write
)(stream
->physical
, &buf
, 1);
305 __objc_write_object (struct objc_typed_stream
* stream
, id object
)
307 unsigned char buf
= '\0';
308 SEL write_sel
= sel_get_uid ("write:");
311 __objc_write_extension (stream
, _BX_OBJECT
);
312 objc_write_class (stream
, object
->class_pointer
);
313 (*objc_msg_lookup(object
, write_sel
))(object
, write_sel
, stream
);
314 return (*stream
->write
)(stream
->physical
, &buf
, 1);
317 return objc_write_use_common(stream
, 0);
321 objc_write_object_reference (struct objc_typed_stream
* stream
, id object
)
324 if ((key
= (unsigned int)hash_value_for_key (stream
->object_table
, object
)))
325 return objc_write_use_common (stream
, key
);
327 __objc_write_extension (stream
, _BX_OBJREF
);
328 return objc_write_unsigned_int (stream
, (unsigned int)object
);
332 objc_write_root_object (struct objc_typed_stream
* stream
, id object
)
335 if (stream
->writing_root_p
)
336 __objc_fatal ("objc_write_root_object called recursively")
339 stream
->writing_root_p
= 1;
340 __objc_write_extension (stream
, _BX_OBJROOT
);
341 if((len
= objc_write_object (stream
, object
)))
342 __objc_finish_write_root_object(stream
);
343 stream
->writing_root_p
= 0;
349 objc_write_object (struct objc_typed_stream
* stream
, id object
)
352 if ((key
= (unsigned int)hash_value_for_key (stream
->object_table
, object
)))
353 return objc_write_use_common (stream
, key
);
355 else if (object
== nil
)
356 return objc_write_use_common(stream
, 0);
361 hash_add (&stream
->object_table
, (void*)key
=(unsigned int)object
, object
);
362 if ((length
= objc_write_register_common (stream
, key
)))
363 return __objc_write_object (stream
, object
);
369 __objc_write_class (struct objc_typed_stream
* stream
, struct objc_class
* class)
371 __objc_write_extension (stream
, _BX_CLASS
);
372 objc_write_string_atomic(stream
, (char*)class->name
,
373 strlen((char*)class->name
));
374 return objc_write_unsigned_int (stream
, CLS_GETNUMBER(class));
379 objc_write_class (struct objc_typed_stream
* stream
,
380 struct objc_class
* class)
383 if ((key
= (unsigned int)hash_value_for_key (stream
->stream_table
, class)))
384 return objc_write_use_common (stream
, key
);
388 hash_add (&stream
->stream_table
, (void*)key
=(unsigned int)class, class);
389 if ((length
= objc_write_register_common (stream
, key
)))
390 return __objc_write_class (stream
, class);
397 __objc_write_selector (struct objc_typed_stream
* stream
, SEL selector
)
399 const char* sel_name
= sel_get_name (selector
);
400 __objc_write_extension (stream
, _BX_SEL
);
401 return objc_write_string (stream
, sel_name
, strlen ((char*)sel_name
));
405 objc_write_selector (struct objc_typed_stream
* stream
, SEL selector
)
407 const char* sel_name
= sel_get_name (selector
);
409 if ((key
= (unsigned int)hash_value_for_key (stream
->stream_table
, sel_name
)))
410 return objc_write_use_common (stream
, key
);
414 hash_add (&stream
->stream_table
, (void*)key
=(unsigned int)sel_name
, (char*)sel_name
);
415 if ((length
= objc_write_register_common (stream
, key
)))
416 return __objc_write_selector (stream
, selector
);
428 objc_read_char (struct objc_typed_stream
* stream
, char* val
)
432 len
= (*stream
->read
)(stream
->physical
, &buf
, 1);
435 if ((buf
& _B_CODE
) == _B_SINT
)
436 (*val
) = (buf
& _B_VALUE
);
438 else if ((buf
& _B_NUMBER
) == 1)
440 len
= (*stream
->read
)(stream
->physical
, val
, 1);
446 __objc_fatal("expected 8bit signed int, got %dbit int",
447 (int)(buf
&_B_NUMBER
)*8);
454 objc_read_unsigned_char (struct objc_typed_stream
* stream
, unsigned char* val
)
458 if ((len
= (*stream
->read
)(stream
->physical
, &buf
, 1)))
460 if ((buf
& _B_CODE
) == _B_SINT
)
461 (*val
) = (buf
& _B_VALUE
);
463 else if ((buf
& _B_NUMBER
) == 1)
464 len
= (*stream
->read
)(stream
->physical
, val
, 1);
467 __objc_fatal("expected 8bit unsigned int, got %dbit int",
468 (int)(buf
&_B_NUMBER
)*8);
474 objc_read_short (struct objc_typed_stream
* stream
, short* value
)
476 unsigned char buf
[sizeof(short)+1];
478 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
480 if ((buf
[0] & _B_CODE
) == _B_SINT
)
481 (*value
) = (buf
[0] & _B_VALUE
);
486 int nbytes
= buf
[0] & _B_NUMBER
;
487 if (nbytes
> sizeof (short))
488 __objc_fatal("expected short, got bigger (%dbits)", nbytes
*8);
489 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
491 while (pos
<= nbytes
)
492 (*value
) = ((*value
)*0x100) + buf
[pos
++];
493 if (buf
[0] & _B_SIGN
)
494 (*value
) = -(*value
);
501 objc_read_unsigned_short (struct objc_typed_stream
* stream
,
502 unsigned short* value
)
504 unsigned char buf
[sizeof(unsigned short)+1];
506 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
508 if ((buf
[0] & _B_CODE
) == _B_SINT
)
509 (*value
) = (buf
[0] & _B_VALUE
);
514 int nbytes
= buf
[0] & _B_NUMBER
;
515 if (nbytes
> sizeof (short))
516 __objc_fatal("expected short, got int or bigger");
517 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
519 while (pos
<= nbytes
)
520 (*value
) = ((*value
)*0x100) + buf
[pos
++];
528 objc_read_int (struct objc_typed_stream
* stream
, int* value
)
530 unsigned char buf
[sizeof(int)+1];
532 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
534 if ((buf
[0] & _B_CODE
) == _B_SINT
)
535 (*value
) = (buf
[0] & _B_VALUE
);
540 int nbytes
= buf
[0] & _B_NUMBER
;
541 if (nbytes
> sizeof (int))
542 __objc_fatal("expected int, got bigger");
543 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
545 while (pos
<= nbytes
)
546 (*value
) = ((*value
)*0x100) + buf
[pos
++];
547 if (buf
[0] & _B_SIGN
)
548 (*value
) = -(*value
);
555 __objc_read_nbyte_uint (struct objc_typed_stream
* stream
,
556 unsigned int nbytes
, unsigned int* val
)
559 unsigned char buf
[sizeof(unsigned int)+1];
561 if (nbytes
> sizeof (int))
562 __objc_fatal("expected int, got bigger");
564 len
= (*stream
->read
)(stream
->physical
, buf
, nbytes
);
567 (*val
) = ((*val
)*0x100) + buf
[pos
++];
573 objc_read_unsigned_int (struct objc_typed_stream
* stream
,
576 unsigned char buf
[sizeof(unsigned int)+1];
578 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
580 if ((buf
[0] & _B_CODE
) == _B_SINT
)
581 (*value
) = (buf
[0] & _B_VALUE
);
584 len
= __objc_read_nbyte_uint (stream
, (buf
[0] & _B_VALUE
), value
);
591 objc_read_string (struct objc_typed_stream
* stream
,
594 unsigned char buf
[sizeof(unsigned int)+1];
596 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
598 unsigned int key
= 0;
600 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
602 len
= __objc_read_nbyte_uint(stream
, (buf
[0] & _B_VALUE
), &key
);
603 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
606 switch (buf
[0]&_B_CODE
) {
609 int length
= buf
[0]&_B_VALUE
;
610 (*string
) = (char*)__objc_xmalloc(length
+1);
612 hash_add (&stream
->stream_table
, (void*)key
, *string
);
613 len
= (*stream
->read
)(stream
->physical
, *string
, length
);
614 (*string
)[length
] = '\0';
621 len
= __objc_read_nbyte_uint (stream
, (buf
[0] & _B_VALUE
), &key
);
622 tmp
= hash_value_for_key (stream
->stream_table
, (void*)key
);
623 *string
= __objc_xmalloc (strlen (tmp
) + 1);
624 strcpy (*string
, tmp
);
630 unsigned int nbytes
= buf
[0]&_B_VALUE
;
631 len
= __objc_read_nbyte_uint(stream
, nbytes
, &nbytes
);
633 (*string
) = (char*)__objc_xmalloc(nbytes
+1);
635 hash_add (&stream
->stream_table
, (void*)key
, *string
);
636 len
= (*stream
->read
)(stream
->physical
, *string
, nbytes
);
637 (*string
)[nbytes
] = '\0';
643 __objc_fatal("expected string, got opcode %c\n", (buf
[0]&_B_CODE
));
652 objc_read_object (struct objc_typed_stream
* stream
, id
* object
)
654 unsigned char buf
[sizeof (unsigned int)];
656 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
658 SEL read_sel
= sel_get_uid ("read:");
659 unsigned int key
= 0;
661 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register common */
663 len
= __objc_read_nbyte_uint(stream
, (buf
[0] & _B_VALUE
), &key
);
664 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
667 if (buf
[0] == (_B_EXT
| _BX_OBJECT
))
672 len
= objc_read_class (stream
, &class);
674 /* create instance */
675 (*object
) = class_create_instance(class);
679 hash_add (&stream
->object_table
, (void*)key
, *object
);
682 if (__objc_responds_to (*object
, read_sel
))
683 (*get_imp(class, read_sel
))(*object
, read_sel
, stream
);
685 /* check null-byte */
686 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
688 __objc_fatal("expected null-byte, got opcode %c", buf
[0]);
691 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
694 __objc_fatal("cannot register use upcode...");
695 len
= __objc_read_nbyte_uint(stream
, (buf
[0] & _B_VALUE
), &key
);
696 (*object
) = hash_value_for_key (stream
->object_table
, (void*)key
);
699 else if (buf
[0] == (_B_EXT
| _BX_OBJREF
)) /* a forward reference */
701 struct objc_list
* other
;
702 len
= objc_read_unsigned_int (stream
, &key
);
703 other
= (struct objc_list
*)hash_value_for_key (stream
->object_refs
, (void*)key
);
704 hash_add (&stream
->object_refs
, (void*)key
, (void*)list_cons(object
, other
));
707 else if (buf
[0] == (_B_EXT
| _BX_OBJROOT
)) /* a root object */
710 __objc_fatal("cannot register root object...");
711 len
= objc_read_object (stream
, object
);
712 __objc_finish_read_root_object (stream
);
716 __objc_fatal("expected object, got opcode %c", buf
[0]);
722 objc_read_class (struct objc_typed_stream
* stream
, Class
** class)
724 unsigned char buf
[sizeof (unsigned int)];
726 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
728 unsigned int key
= 0;
730 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
732 len
= __objc_read_nbyte_uint(stream
, (buf
[0] & _B_VALUE
), &key
);
733 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
736 if (buf
[0] == (_B_EXT
| _BX_CLASS
))
742 len
= objc_read_string (stream
, &class_name
);
743 (*class) = objc_get_class(class_name
);
748 hash_add (&stream
->stream_table
, (void*)key
, *class);
750 objc_read_unsigned_int(stream
, &version
);
751 hash_add (&stream
->class_table
, (*class)->name
, (void*)version
);
754 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
757 __objc_fatal("cannot register use upcode...");
758 len
= __objc_read_nbyte_uint(stream
, (buf
[0] & _B_VALUE
), &key
);
759 (*class) = hash_value_for_key (stream
->stream_table
, (void*)key
);
761 __objc_fatal("cannot find class for key %x", key
);
765 __objc_fatal("expected class, got opcode %c", buf
[0]);
771 objc_read_selector (struct objc_typed_stream
* stream
, SEL
* selector
)
773 unsigned char buf
[sizeof (unsigned int)];
775 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
777 unsigned int key
= 0;
779 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
781 len
= __objc_read_nbyte_uint(stream
, (buf
[0] & _B_VALUE
), &key
);
782 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
785 if (buf
[0] == (_B_EXT
|_BX_SEL
)) /* selector! */
790 len
= objc_read_string (stream
, &selector_name
);
791 (*selector
) = sel_get_uid(selector_name
);
792 free (selector_name
);
796 hash_add (&stream
->stream_table
, (void*)key
, *selector
);
799 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
802 __objc_fatal("cannot register use upcode...");
803 len
= __objc_read_nbyte_uint(stream
, (buf
[0] & _B_VALUE
), &key
);
804 (*selector
) = hash_value_for_key (stream
->stream_table
, (void*)key
);
808 __objc_fatal("expected selector, got opcode %c", buf
[0]);
814 objc_sizeof_type(const char* type
)
817 case _C_ID
: return sizeof(id
);
821 return sizeof(Class
*);
833 return sizeof(unsigned char);
837 return sizeof(short);
841 return sizeof(unsigned short);
851 return sizeof(unsigned int);
856 return sizeof(char*);
860 fprintf(stderr
, "objc_sizeof_type: cannot parse typespec: %s\n", type
);
867 __objc_skip_type (const char* type
)
889 while(isdigit(*++type
));
890 type
= __objc_skip_type(type
);
891 if (*type
== _C_ARY_E
)
894 __objc_fatal("cannot parse typespec: %s", type
);
898 fprintf(stderr
, "__objc_skip_type: cannot parse typespec: %s\n", type
);
904 ** USER LEVEL FUNCTIONS
908 ** Write one object, encoded in TYPE and pointed to by DATA to the
909 ** typed stream STREAM.
913 objc_write_type(TypedStream
* stream
, const char* type
, const void* data
)
917 return objc_write_object (stream
, *(id
*)data
);
921 return objc_write_class (stream
, *(Class
**)data
);
925 return objc_write_selector (stream
, *(SEL
*)data
);
929 return objc_write_char(stream
, *(char*)data
);
933 return objc_write_unsigned_char(stream
, *(unsigned char*)data
);
937 return objc_write_short(stream
, *(short*)data
);
941 return objc_write_unsigned_short(stream
, *(unsigned short*)data
);
946 return objc_write_int(stream
, *(int*)data
);
951 return objc_write_unsigned_int(stream
, *(unsigned int*)data
);
955 return objc_write_string (stream
, *(char**)data
, strlen(*(char**)data
));
959 return objc_write_string_atomic (stream
, *(char**)data
, strlen(*(char**)data
));
964 int len
= atoi(type
+1);
965 while (isdigit(*++type
));
966 return objc_write_array (stream
, type
, len
, data
);
971 fprintf(stderr
, "objc_write_type: cannot parse typespec: %s\n", type
);
977 ** Read one object, encoded in TYPE and pointed to by DATA to the
978 ** typed stream STREAM. DATA specifies the address of the types to
979 ** read. Expected type is checked against the type actually present
984 objc_read_type(TypedStream
* stream
, const char* type
, void* data
)
989 return objc_read_object (stream
, (id
*)data
);
993 return objc_read_class (stream
, (Class
**)data
);
997 return objc_read_selector (stream
, (SEL
*)data
);
1001 return objc_read_char (stream
, (char*)data
);
1005 return objc_read_unsigned_char (stream
, (unsigned char*)data
);
1009 return objc_read_short (stream
, (short*)data
);
1013 return objc_read_unsigned_short (stream
, (unsigned short*)data
);
1018 return objc_read_int (stream
, (int*)data
);
1023 return objc_read_unsigned_int (stream
, (unsigned int*)data
);
1028 return objc_read_string (stream
, (char**)data
);
1033 int len
= atoi(type
+1);
1034 while (isdigit(*++type
));
1035 return objc_read_array (stream
, type
, len
, data
);
1040 fprintf(stderr
, "objc_read_type: cannot parse typespec: %s\n", type
);
1046 ** Write the object specified by the template TYPE to STREAM. Last
1047 ** arguments specify addresses of values to be written. It might
1048 ** seem surprising to specify values by address, but this is extremely
1049 ** convenient for copy-paste with objc_read_types calls. A more
1050 ** down-to-the-earth cause for this passing of addresses is that values
1051 ** of arbitrary size is not well supported in ANSI C for functions with
1052 ** variable number of arguments.
1056 objc_write_types (TypedStream
* stream
, const char* type
, ...)
1062 va_start(args
, type
);
1064 for (c
= type
; *c
; c
= __objc_skip_type (c
))
1068 res
= objc_write_object (stream
, *va_arg (args
, id
*));
1072 res
= objc_write_class (stream
, *va_arg(args
, Class
**));
1076 res
= objc_write_selector (stream
, *va_arg(args
, SEL
*));
1080 res
= objc_write_char (stream
, *va_arg (args
, char*));
1084 res
= objc_write_unsigned_char (stream
,
1085 *va_arg (args
, unsigned char*));
1089 res
= objc_write_short (stream
, *va_arg(args
, short*));
1093 res
= objc_write_unsigned_short (stream
,
1094 *va_arg(args
, unsigned short*));
1099 res
= objc_write_int(stream
, *va_arg(args
, int*));
1104 res
= objc_write_unsigned_int(stream
, *va_arg(args
, unsigned int*));
1109 char** str
= va_arg(args
, char**);
1110 res
= objc_write_string (stream
, *str
, strlen(*str
));
1116 char** str
= va_arg(args
, char**);
1117 res
= objc_write_string_atomic (stream
, *str
, strlen(*str
));
1123 int len
= atoi(c
+1);
1125 while (isdigit(*++t
));
1126 res
= objc_write_array (stream
, t
, len
, va_arg(args
, void*));
1127 t
= __objc_skip_type (t
);
1129 __objc_fatal("expected `]', got: %s", t
);
1134 fprintf(stderr
, "objc_write_types: cannot parse typespec: %s\n", type
);
1144 ** Last arguments specify addresses of values to be read. Expected
1145 ** type is checked against the type actually present on the stream.
1149 objc_read_types(TypedStream
* stream
, const char* type
, ...)
1155 va_start(args
, type
);
1157 for (c
= type
; *c
; c
= __objc_skip_type(c
))
1161 res
= objc_read_object(stream
, va_arg(args
, id
*));
1165 res
= objc_read_class(stream
, va_arg(args
, Class
**));
1169 res
= objc_read_selector(stream
, va_arg(args
, SEL
*));
1173 res
= objc_read_char(stream
, va_arg(args
, char*));
1177 res
= objc_read_unsigned_char(stream
, va_arg(args
, unsigned char*));
1181 res
= objc_read_short(stream
, va_arg(args
, short*));
1185 res
= objc_read_unsigned_short(stream
, va_arg(args
, unsigned short*));
1190 res
= objc_read_int(stream
, va_arg(args
, int*));
1195 res
= objc_read_unsigned_int(stream
, va_arg(args
, unsigned int*));
1201 char** str
= va_arg(args
, char**);
1202 res
= objc_read_string (stream
, str
);
1208 int len
= atoi(c
+1);
1210 while (isdigit(*++t
));
1211 res
= objc_read_array (stream
, t
, len
, va_arg(args
, void*));
1212 t
= __objc_skip_type (t
);
1214 __objc_fatal("expected `]', got: %s", t
);
1219 fprintf(stderr
, "objc_read_types: cannot parse typespec: %s\n", type
);
1228 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1229 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1233 objc_write_array (TypedStream
* stream
, const char* type
,
1234 int count
, const void* data
)
1236 int off
= objc_sizeof_type(type
);
1237 const char* where
= data
;
1241 objc_write_type(stream
, type
, where
);
1248 ** Read an array of COUNT elements of TYPE into the memory address
1249 ** DATA. The memory pointed to by data is supposed to be allocated
1250 ** by the callee. This is equivalent of
1251 ** objc_read_type (stream, "[N<type>]", data)
1255 objc_read_array (TypedStream
* stream
, const char* type
,
1256 int count
, void* data
)
1258 int off
= objc_sizeof_type(type
);
1259 char* where
= (char*)data
;
1263 objc_read_type(stream
, type
, where
);
1270 __objc_fread(FILE* file
, char* data
, int len
)
1272 return fread(data
, len
, 1, file
);
1276 __objc_fwrite(FILE* file
, char* data
, int len
)
1278 return fwrite(data
, len
, 1, file
);
1282 __objc_feof(FILE* file
)
1288 __objc_no_write(FILE* file
, char* data
, int len
)
1290 __objc_fatal ("TypedStream not open for writing");
1294 __objc_no_read(FILE* file
, char* data
, int len
)
1296 __objc_fatal ("TypedStream not open for reading");
1300 __objc_read_typed_stream_signature (TypedStream
* stream
)
1305 (*stream
->read
)(stream
->physical
, buffer
+pos
, 1);
1306 while (buffer
[pos
++] != '\0');
1307 sscanf (buffer
, "GNU TypedStream %d", &stream
->version
);
1308 if (stream
->version
!= OBJC_TYPED_STREAM_VERSION
)
1309 __objc_fatal ("cannot handle TypedStream version %d", stream
->version
);
1314 __objc_write_typed_stream_signature (TypedStream
* stream
)
1317 sprintf(buffer
, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION
);
1318 stream
->version
= OBJC_TYPED_STREAM_VERSION
;
1319 (*stream
->write
)(stream
->physical
, buffer
, strlen(buffer
)+1);
1323 static void __objc_finish_write_root_object(struct objc_typed_stream
* stream
)
1325 hash_delete (stream
->object_table
);
1326 stream
->object_table
= hash_new(64,
1327 (hash_func_type
)hash_ptr
,
1328 (compare_func_type
)compare_ptrs
);
1331 static void __objc_finish_read_root_object(struct objc_typed_stream
* stream
)
1334 SEL awake_sel
= sel_get_uid ("awake");
1336 /* resolve object forward references */
1337 for (node
= hash_next (stream
->object_refs
, NULL
); node
;
1338 node
= hash_next (stream
->object_refs
, node
))
1340 struct objc_list
* reflist
= node
->value
;
1341 const void* key
= node
->key
;
1342 id object
= hash_value_for_key (stream
->object_table
, key
);
1345 *((id
*)reflist
->head
) = object
;
1346 reflist
= reflist
->tail
;
1348 list_free (node
->value
);
1351 /* empty object reference table */
1352 hash_delete (stream
->object_refs
);
1353 stream
->object_refs
= hash_new(8, (hash_func_type
)hash_ptr
,
1354 (compare_func_type
)compare_ptrs
);
1356 /* call -awake for all objects read */
1359 for (node
= hash_next (stream
->object_table
, NULL
); node
;
1360 node
= hash_next (stream
->object_table
, node
))
1362 id object
= node
->value
;
1363 if (__objc_responds_to (object
, awake_sel
))
1364 (*objc_msg_lookup(object
, awake_sel
))(object
, awake_sel
);
1368 /* empty object table */
1369 hash_delete (stream
->object_table
);
1370 stream
->object_table
= hash_new(64,
1371 (hash_func_type
)hash_ptr
,
1372 (compare_func_type
)compare_ptrs
);
1376 ** Open the stream PHYSICAL in MODE
1380 objc_open_typed_stream (FILE* physical
, int mode
)
1384 TypedStream
* s
= (TypedStream
*)__objc_xmalloc(sizeof(TypedStream
));
1387 s
->physical
= physical
;
1388 s
->stream_table
= hash_new(64,
1389 (hash_func_type
)hash_ptr
,
1390 (compare_func_type
)compare_ptrs
);
1391 s
->object_table
= hash_new(64,
1392 (hash_func_type
)hash_ptr
,
1393 (compare_func_type
)compare_ptrs
);
1394 s
->eof
= (objc_typed_eof_func
)__objc_feof
;
1395 s
->flush
= (objc_typed_flush_func
)fflush
;
1396 s
->writing_root_p
= 0;
1397 if (mode
== OBJC_READONLY
)
1399 s
->class_table
= hash_new(8, (hash_func_type
)hash_string
,
1400 (compare_func_type
)compare_strings
);
1401 s
->object_refs
= hash_new(8, (hash_func_type
)hash_ptr
,
1402 (compare_func_type
)compare_ptrs
);
1403 s
->read
= (objc_typed_read_func
)__objc_fread
;
1404 s
->write
= (objc_typed_write_func
)__objc_no_write
;
1405 __objc_read_typed_stream_signature (s
);
1407 else if (mode
== OBJC_WRITEONLY
)
1411 s
->read
= (objc_typed_read_func
)__objc_no_read
;
1412 s
->write
= (objc_typed_write_func
)__objc_fwrite
;
1413 __objc_write_typed_stream_signature (s
);
1417 objc_close_typed_stream (s
);
1420 s
->type
= OBJC_FILE_STREAM
;
1425 ** Open the file named by FILE_NAME in MODE
1429 objc_open_typed_stream_for_file (const char* file_name
, int mode
)
1434 if (mode
== OBJC_READONLY
)
1435 file
= fopen (file_name
, "r");
1437 file
= fopen (file_name
, "w");
1441 s
= objc_open_typed_stream (file
, mode
);
1443 s
->type
|= OBJC_MANAGED_STREAM
;
1451 ** Close STREAM freeing the structure it self. If it was opened with
1452 ** objc_open_typed_stream_for_file, the file will also be closed.
1456 objc_close_typed_stream (TypedStream
* stream
)
1458 if (stream
->mode
== OBJC_READONLY
)
1460 __objc_finish_read_root_object (stream
); /* Just in case... */
1461 hash_delete (stream
->class_table
);
1462 hash_delete (stream
->object_refs
);
1465 hash_delete (stream
->stream_table
);
1466 hash_delete (stream
->object_table
);
1468 if (stream
->type
== (OBJC_MANAGED_STREAM
| OBJC_FILE_STREAM
))
1469 fclose ((FILE*)stream
->physical
);
1475 objc_end_of_typed_stream (TypedStream
* stream
)
1477 return (*stream
->eof
)(stream
->physical
);
1481 objc_flush_typed_stream (TypedStream
* stream
)
1483 (*stream
->flush
)(stream
->physical
);
1487 objc_get_stream_class_version (TypedStream
* stream
, Class
* class)
1489 if (stream
->class_table
)
1490 return (int) hash_value_for_key (stream
->class_table
, class->name
);
1492 return class_get_version (class);
1495 #endif /* __alpha__ */