3 /* GNU Objective C Runtime archiving
4 Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
5 Contributed by Kresten Krab Thorup
7 This file is part of GNU CC.
9 GNU CC is free software; you can redistribute it and/or modify it under the
10 terms of the GNU General Public License as published by the Free Software
11 Foundation; either version 2, or (at your option) any later version.
13 GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 You should have received a copy of the GNU General Public License along with
19 GNU CC; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* As a special exception, if you link this library with files compiled with
24 GCC to produce an executable, this does not cause the resulting executable
25 to be covered by the GNU General Public License. This exception does not
26 however invalidate any other reasons why the executable file might be
27 covered by the GNU General Public License. */
30 #include "typedstream.h"
40 extern int fflush(FILE*);
43 ({ typeof(V) __v=(V); typeof(A) __a=(A); \
44 __a*((__v+__a-1)/__a); })
46 #define PTR2LONG(P) (((char*)(P))-(char*)0)
47 #define LONG2PTR(L) (((char*)0)+(L))
49 /* Declare some functions... */
52 objc_read_class (struct objc_typed_stream* stream, Class* class);
54 int objc_sizeof_type(const char* type);
57 objc_write_use_common (struct objc_typed_stream* stream, unsigned long key);
60 objc_write_register_common (struct objc_typed_stream* stream,
64 objc_write_class (struct objc_typed_stream* stream,
65 struct objc_class* class);
67 const char* objc_skip_type (const char* type);
69 static void __objc_finish_write_root_object(struct objc_typed_stream*);
70 static void __objc_finish_read_root_object(struct objc_typed_stream*);
73 __objc_code_unsigned_char (unsigned char* buf, unsigned char val)
75 if ((val&_B_VALUE) == val)
82 buf[0] = _B_NINT|0x01;
89 objc_write_unsigned_char (struct objc_typed_stream* stream,
92 unsigned char buf[sizeof (unsigned char)+1];
93 int len = __objc_code_unsigned_char (buf, value);
94 return (*stream->write)(stream->physical, buf, len);
98 __objc_code_char (unsigned char* buf, char val)
101 return __objc_code_unsigned_char (buf, val);
104 buf[0] = _B_NINT|_B_SIGN|0x01;
111 objc_write_char (struct objc_typed_stream* stream, char value)
113 unsigned char buf[sizeof (char)+1];
114 int len = __objc_code_char (buf, value);
115 return (*stream->write)(stream->physical, buf, len);
118 static __inline__ int
119 __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
121 if ((val&_B_VALUE) == val)
123 buf[0] = val|_B_SINT;
132 for (c= sizeof(short); c != 0; c -= 1)
133 if (((val>>(8*(c-1)))%0x100) != 0)
138 for (b = 1; c != 0; c--, b++)
140 buf[b] = (val >> (8*(c-1)))%0x100;
148 objc_write_unsigned_short (struct objc_typed_stream* stream,
149 unsigned short value)
151 unsigned char buf[sizeof (unsigned short)+1];
152 int len = __objc_code_unsigned_short (buf, value);
153 return (*stream->write)(stream->physical, buf, len);
156 static __inline__ int
157 __objc_code_short (unsigned char* buf, short val)
159 int sign = (val < 0);
160 int size = __objc_code_unsigned_short (buf, sign ? -val : val);
167 objc_write_short (struct objc_typed_stream* stream, short value)
169 unsigned char buf[sizeof (short)+1];
170 int len = __objc_code_short (buf, value);
171 return (*stream->write)(stream->physical, buf, len);
175 static __inline__ int
176 __objc_code_unsigned_int (unsigned char* buf, unsigned int val)
178 if ((val&_B_VALUE) == val)
180 buf[0] = val|_B_SINT;
189 for (c= sizeof(int); c != 0; c -= 1)
190 if (((val>>(8*(c-1)))%0x100) != 0)
195 for (b = 1; c != 0; c--, b++)
197 buf[b] = (val >> (8*(c-1)))%0x100;
205 objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value)
207 unsigned char buf[sizeof(unsigned int)+1];
208 int len = __objc_code_unsigned_int (buf, value);
209 return (*stream->write)(stream->physical, buf, len);
212 static __inline__ int
213 __objc_code_int (unsigned char* buf, int val)
215 int sign = (val < 0);
216 int size = __objc_code_unsigned_int (buf, sign ? -val : val);
223 objc_write_int (struct objc_typed_stream* stream, int value)
225 unsigned char buf[sizeof(int)+1];
226 int len = __objc_code_int (buf, value);
227 return (*stream->write)(stream->physical, buf, len);
230 static __inline__ int
231 __objc_code_unsigned_long (unsigned char* buf, unsigned long val)
233 if ((val&_B_VALUE) == val)
235 buf[0] = val|_B_SINT;
244 for (c= sizeof(long); c != 0; c -= 1)
245 if (((val>>(8*(c-1)))%0x100) != 0)
250 for (b = 1; c != 0; c--, b++)
252 buf[b] = (val >> (8*(c-1)))%0x100;
260 objc_write_unsigned_long (struct objc_typed_stream* stream,
263 unsigned char buf[sizeof(unsigned long)+1];
264 int len = __objc_code_unsigned_long (buf, value);
265 return (*stream->write)(stream->physical, buf, len);
268 static __inline__ int
269 __objc_code_long (unsigned char* buf, long val)
271 int sign = (val < 0);
272 int size = __objc_code_unsigned_long (buf, sign ? -val : val);
279 objc_write_long (struct objc_typed_stream* stream, long value)
281 unsigned char buf[sizeof(long)+1];
282 int len = __objc_code_long (buf, value);
283 return (*stream->write)(stream->physical, buf, len);
288 objc_write_string (struct objc_typed_stream* stream,
289 const unsigned char* string, unsigned int nbytes)
291 unsigned char buf[sizeof(unsigned int)+1];
292 int len = __objc_code_unsigned_int (buf, nbytes);
294 if ((buf[0]&_B_CODE) == _B_SINT)
295 buf[0] = (buf[0]&_B_VALUE)|_B_SSTR;
298 buf[0] = (buf[0]&_B_VALUE)|_B_NSTR;
300 if ((*stream->write)(stream->physical, buf, len) != 0)
301 return (*stream->write)(stream->physical, string, nbytes);
307 objc_write_string_atomic (struct objc_typed_stream* stream,
308 unsigned char* string, unsigned int nbytes)
311 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string))))
312 return objc_write_use_common (stream, key);
316 hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string);
317 if ((length = objc_write_register_common (stream, key)))
318 return objc_write_string (stream, string, nbytes);
324 objc_write_register_common (struct objc_typed_stream* stream,
327 unsigned char buf[sizeof (unsigned long)+2];
328 int len = __objc_code_unsigned_long (buf+1, key);
331 buf[0] = _B_RCOMM|0x01;
333 return (*stream->write)(stream->physical, buf, len+1);
337 buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM;
338 return (*stream->write)(stream->physical, buf+1, len);
343 objc_write_use_common (struct objc_typed_stream* stream, unsigned long key)
345 unsigned char buf[sizeof (unsigned long)+2];
346 int len = __objc_code_unsigned_long (buf+1, key);
349 buf[0] = _B_UCOMM|0x01;
351 return (*stream->write)(stream->physical, buf, 2);
355 buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM;
356 return (*stream->write)(stream->physical, buf+1, len);
360 static __inline__ int
361 __objc_write_extension (struct objc_typed_stream* stream, unsigned char code)
363 if (code <= _B_VALUE)
365 unsigned char buf = code|_B_EXT;
366 return (*stream->write)(stream->physical, &buf, 1);
370 objc_error(nil, OBJC_ERR_BAD_OPCODE,
371 "__objc_write_extension: bad opcode %c\n", code);
377 __objc_write_object (struct objc_typed_stream* stream, id object)
379 unsigned char buf = '\0';
380 SEL write_sel = sel_get_any_uid ("write:");
383 __objc_write_extension (stream, _BX_OBJECT);
384 objc_write_class (stream, object->class_pointer);
385 (*objc_msg_lookup(object, write_sel))(object, write_sel, stream);
386 return (*stream->write)(stream->physical, &buf, 1);
389 return objc_write_use_common(stream, 0);
393 objc_write_object_reference (struct objc_typed_stream* stream, id object)
396 if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
397 return objc_write_use_common (stream, key);
399 __objc_write_extension (stream, _BX_OBJREF);
400 return objc_write_unsigned_long (stream, PTR2LONG (object));
404 objc_write_root_object (struct objc_typed_stream* stream, id object)
407 if (stream->writing_root_p)
408 objc_error (nil, OBJC_ERR_RECURSE_ROOT,
409 "objc_write_root_object called recursively");
412 stream->writing_root_p = 1;
413 __objc_write_extension (stream, _BX_OBJROOT);
414 if((len = objc_write_object (stream, object)))
415 __objc_finish_write_root_object(stream);
416 stream->writing_root_p = 0;
422 objc_write_object (struct objc_typed_stream* stream, id object)
425 if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
426 return objc_write_use_common (stream, key);
428 else if (object == nil)
429 return objc_write_use_common(stream, 0);
434 hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object);
435 if ((length = objc_write_register_common (stream, key)))
436 return __objc_write_object (stream, object);
442 __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class)
444 __objc_write_extension (stream, _BX_CLASS);
445 objc_write_string_atomic(stream, (char*)class->name,
446 strlen((char*)class->name));
447 return objc_write_unsigned_long (stream, class->version);
452 objc_write_class (struct objc_typed_stream* stream,
453 struct objc_class* class)
456 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class))))
457 return objc_write_use_common (stream, key);
461 hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class);
462 if ((length = objc_write_register_common (stream, key)))
463 return __objc_write_class (stream, class);
470 __objc_write_selector (struct objc_typed_stream* stream, SEL selector)
472 const char* sel_name;
473 __objc_write_extension (stream, _BX_SEL);
474 /* to handle NULL selectors */
475 if ((SEL)0 == selector)
476 return objc_write_string (stream, "", 0);
477 sel_name = sel_get_name (selector);
478 return objc_write_string (stream, sel_name, strlen ((char*)sel_name));
482 objc_write_selector (struct objc_typed_stream* stream, SEL selector)
484 const char* sel_name;
487 /* to handle NULL selectors */
488 if ((SEL)0 == selector)
489 return __objc_write_selector (stream, selector);
491 sel_name = sel_get_name (selector);
492 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name))))
493 return objc_write_use_common (stream, key);
497 hash_add (&stream->stream_table,
498 LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
499 if ((length = objc_write_register_common (stream, key)))
500 return __objc_write_selector (stream, selector);
512 objc_read_char (struct objc_typed_stream* stream, char* val)
516 len = (*stream->read)(stream->physical, &buf, 1);
519 if ((buf & _B_CODE) == _B_SINT)
520 (*val) = (buf & _B_VALUE);
522 else if ((buf & _B_NUMBER) == 1)
524 len = (*stream->read)(stream->physical, val, 1);
530 objc_error(nil, OBJC_ERR_BAD_DATA,
531 "expected 8bit signed int, got %dbit int",
532 (int)(buf&_B_NUMBER)*8);
539 objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val)
543 if ((len = (*stream->read)(stream->physical, &buf, 1)))
545 if ((buf & _B_CODE) == _B_SINT)
546 (*val) = (buf & _B_VALUE);
548 else if ((buf & _B_NUMBER) == 1)
549 len = (*stream->read)(stream->physical, val, 1);
552 objc_error(nil, OBJC_ERR_BAD_DATA,
553 "expected 8bit unsigned int, got %dbit int",
554 (int)(buf&_B_NUMBER)*8);
560 objc_read_short (struct objc_typed_stream* stream, short* value)
562 unsigned char buf[sizeof(short)+1];
564 if ((len = (*stream->read)(stream->physical, buf, 1)))
566 if ((buf[0] & _B_CODE) == _B_SINT)
567 (*value) = (buf[0] & _B_VALUE);
572 int nbytes = buf[0] & _B_NUMBER;
573 if (nbytes > sizeof (short))
574 objc_error(nil, OBJC_ERR_BAD_DATA,
575 "expected short, got bigger (%dbits)", nbytes*8);
576 len = (*stream->read)(stream->physical, buf+1, nbytes);
578 while (pos <= nbytes)
579 (*value) = ((*value)*0x100) + buf[pos++];
580 if (buf[0] & _B_SIGN)
581 (*value) = -(*value);
588 objc_read_unsigned_short (struct objc_typed_stream* stream,
589 unsigned short* value)
591 unsigned char buf[sizeof(unsigned short)+1];
593 if ((len = (*stream->read)(stream->physical, buf, 1)))
595 if ((buf[0] & _B_CODE) == _B_SINT)
596 (*value) = (buf[0] & _B_VALUE);
601 int nbytes = buf[0] & _B_NUMBER;
602 if (nbytes > sizeof (short))
603 objc_error(nil, OBJC_ERR_BAD_DATA,
604 "expected short, got int or bigger");
605 len = (*stream->read)(stream->physical, buf+1, nbytes);
607 while (pos <= nbytes)
608 (*value) = ((*value)*0x100) + buf[pos++];
616 objc_read_int (struct objc_typed_stream* stream, int* value)
618 unsigned char buf[sizeof(int)+1];
620 if ((len = (*stream->read)(stream->physical, buf, 1)))
622 if ((buf[0] & _B_CODE) == _B_SINT)
623 (*value) = (buf[0] & _B_VALUE);
628 int nbytes = buf[0] & _B_NUMBER;
629 if (nbytes > sizeof (int))
630 objc_error(nil, OBJC_ERR_BAD_DATA, "expected int, got bigger");
631 len = (*stream->read)(stream->physical, buf+1, nbytes);
633 while (pos <= nbytes)
634 (*value) = ((*value)*0x100) + buf[pos++];
635 if (buf[0] & _B_SIGN)
636 (*value) = -(*value);
643 objc_read_long (struct objc_typed_stream* stream, long* value)
645 unsigned char buf[sizeof(long)+1];
647 if ((len = (*stream->read)(stream->physical, buf, 1)))
649 if ((buf[0] & _B_CODE) == _B_SINT)
650 (*value) = (buf[0] & _B_VALUE);
655 int nbytes = buf[0] & _B_NUMBER;
656 if (nbytes > sizeof (long))
657 objc_error(nil, OBJC_ERR_BAD_DATA, "expected long, got bigger");
658 len = (*stream->read)(stream->physical, buf+1, nbytes);
660 while (pos <= nbytes)
661 (*value) = ((*value)*0x100) + buf[pos++];
662 if (buf[0] & _B_SIGN)
663 (*value) = -(*value);
670 __objc_read_nbyte_uint (struct objc_typed_stream* stream,
671 unsigned int nbytes, unsigned int* val)
674 unsigned char buf[sizeof(unsigned int)+1];
676 if (nbytes > sizeof (int))
677 objc_error(nil, OBJC_ERR_BAD_DATA, "expected int, got bigger");
679 len = (*stream->read)(stream->physical, buf, nbytes);
682 (*val) = ((*val)*0x100) + buf[pos++];
688 objc_read_unsigned_int (struct objc_typed_stream* stream,
691 unsigned char buf[sizeof(unsigned int)+1];
693 if ((len = (*stream->read)(stream->physical, buf, 1)))
695 if ((buf[0] & _B_CODE) == _B_SINT)
696 (*value) = (buf[0] & _B_VALUE);
699 len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value);
706 __objc_read_nbyte_ulong (struct objc_typed_stream* stream,
707 unsigned int nbytes, unsigned long* val)
710 unsigned char buf[sizeof(unsigned long)+1];
712 if (nbytes > sizeof (long))
713 objc_error(nil, OBJC_ERR_BAD_DATA, "expected long, got bigger");
715 len = (*stream->read)(stream->physical, buf, nbytes);
718 (*val) = ((*val)*0x100) + buf[pos++];
724 objc_read_unsigned_long (struct objc_typed_stream* stream,
725 unsigned long* value)
727 unsigned char buf[sizeof(unsigned long)+1];
729 if ((len = (*stream->read)(stream->physical, buf, 1)))
731 if ((buf[0] & _B_CODE) == _B_SINT)
732 (*value) = (buf[0] & _B_VALUE);
735 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value);
742 objc_read_string (struct objc_typed_stream* stream,
745 unsigned char buf[sizeof(unsigned int)+1];
747 if ((len = (*stream->read)(stream->physical, buf, 1)))
749 unsigned long key = 0;
751 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
753 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
754 len = (*stream->read)(stream->physical, buf, 1);
757 switch (buf[0]&_B_CODE) {
760 int length = buf[0]&_B_VALUE;
761 (*string) = (char*)objc_malloc(length+1);
763 hash_add (&stream->stream_table, LONG2PTR(key), *string);
764 len = (*stream->read)(stream->physical, *string, length);
765 (*string)[length] = '\0';
772 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
773 tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key));
774 *string = objc_malloc (strlen(tmp) + 1);
775 strcpy (*string, tmp);
781 unsigned int nbytes = buf[0]&_B_VALUE;
782 len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
784 (*string) = (char*)objc_malloc(nbytes+1);
786 hash_add (&stream->stream_table, LONG2PTR(key), *string);
787 len = (*stream->read)(stream->physical, *string, nbytes);
788 (*string)[nbytes] = '\0';
794 objc_error(nil, OBJC_ERR_BAD_DATA,
795 "expected string, got opcode %c\n", (buf[0]&_B_CODE));
804 objc_read_object (struct objc_typed_stream* stream, id* object)
806 unsigned char buf[sizeof (unsigned int)];
808 if ((len = (*stream->read)(stream->physical, buf, 1)))
810 SEL read_sel = sel_get_any_uid ("read:");
811 unsigned long key = 0;
813 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
815 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
816 len = (*stream->read)(stream->physical, buf, 1);
819 if (buf[0] == (_B_EXT | _BX_OBJECT))
824 len = objc_read_class (stream, &class);
826 /* create instance */
827 (*object) = class_create_instance(class);
831 hash_add (&stream->object_table, LONG2PTR(key), *object);
834 if (__objc_responds_to (*object, read_sel))
835 (*get_imp(class, read_sel))(*object, read_sel, stream);
837 /* check null-byte */
838 len = (*stream->read)(stream->physical, buf, 1);
840 objc_error(nil, OBJC_ERR_BAD_DATA,
841 "expected null-byte, got opcode %c", buf[0]);
844 else if ((buf[0]&_B_CODE) == _B_UCOMM)
847 objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
848 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
849 (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
852 else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
854 struct objc_list* other;
855 len = objc_read_unsigned_long (stream, &key);
856 other = (struct objc_list*)hash_value_for_key (stream->object_refs,
858 hash_add (&stream->object_refs, LONG2PTR(key),
859 (void*)list_cons(object, other));
862 else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
865 objc_error(nil, OBJC_ERR_BAD_KEY,
866 "cannot register root object...");
867 len = objc_read_object (stream, object);
868 __objc_finish_read_root_object (stream);
872 objc_error(nil, OBJC_ERR_BAD_DATA,
873 "expected object, got opcode %c", buf[0]);
879 objc_read_class (struct objc_typed_stream* stream, Class* class)
881 unsigned char buf[sizeof (unsigned int)];
883 if ((len = (*stream->read)(stream->physical, buf, 1)))
885 unsigned long key = 0;
887 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
889 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
890 len = (*stream->read)(stream->physical, buf, 1);
893 if (buf[0] == (_B_EXT | _BX_CLASS))
896 unsigned long version;
899 len = objc_read_string (stream, &class_name);
900 (*class) = objc_get_class(class_name);
901 objc_free(class_name);
905 hash_add (&stream->stream_table, LONG2PTR(key), *class);
907 objc_read_unsigned_long(stream, &version);
908 hash_add (&stream->class_table, (*class)->name, (void*)version);
911 else if ((buf[0]&_B_CODE) == _B_UCOMM)
914 objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
915 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
916 (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
918 objc_error(nil, OBJC_ERR_BAD_CLASS,
919 "cannot find class for key %lu", key);
923 objc_error(nil, OBJC_ERR_BAD_DATA,
924 "expected class, got opcode %c", buf[0]);
930 objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
932 unsigned char buf[sizeof (unsigned int)];
934 if ((len = (*stream->read)(stream->physical, buf, 1)))
936 unsigned long key = 0;
938 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
940 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
941 len = (*stream->read)(stream->physical, buf, 1);
944 if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
949 len = objc_read_string (stream, &selector_name);
950 /* To handle NULL selectors */
951 if (0 == strlen(selector_name))
953 (*selector) = (SEL)0;
957 (*selector) = sel_get_any_uid(selector_name);
958 objc_free(selector_name);
962 hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
965 else if ((buf[0]&_B_CODE) == _B_UCOMM)
968 objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
969 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
970 (*selector) = hash_value_for_key (stream->stream_table,
975 objc_error(nil, OBJC_ERR_BAD_DATA,
976 "expected selector, got opcode %c", buf[0]);
982 ** USER LEVEL FUNCTIONS
986 ** Write one object, encoded in TYPE and pointed to by DATA to the
987 ** typed stream STREAM.
991 objc_write_type(TypedStream* stream, const char* type, const void* data)
995 return objc_write_object (stream, *(id*)data);
999 return objc_write_class (stream, *(Class*)data);
1003 return objc_write_selector (stream, *(SEL*)data);
1007 return objc_write_char(stream, *(char*)data);
1011 return objc_write_unsigned_char(stream, *(unsigned char*)data);
1015 return objc_write_short(stream, *(short*)data);
1019 return objc_write_unsigned_short(stream, *(unsigned short*)data);
1023 return objc_write_int(stream, *(int*)data);
1027 return objc_write_unsigned_int(stream, *(unsigned int*)data);
1031 return objc_write_long(stream, *(long*)data);
1035 return objc_write_unsigned_long(stream, *(unsigned long*)data);
1039 return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
1043 return objc_write_string_atomic (stream, *(char**)data,
1044 strlen(*(char**)data));
1049 int len = atoi(type+1);
1050 while (isdigit((int)*++type))
1052 return objc_write_array (stream, type, len, data);
1060 while (*type != _C_STRUCT_E && *type++ != '=')
1061 ; /* skip "<name>=" */
1062 while (*type != _C_STRUCT_E)
1064 align = objc_alignof_type (type); /* padd to alignment */
1065 acc_size += ROUND (acc_size, align);
1066 objc_write_type (stream, type, ((char*)data)+acc_size);
1067 acc_size += objc_sizeof_type (type); /* add component size */
1068 type = objc_skip_typespec (type); /* skip component */
1075 objc_error(nil, OBJC_ERR_BAD_TYPE,
1076 "objc_write_type: cannot parse typespec: %s\n", type);
1083 ** Read one object, encoded in TYPE and pointed to by DATA to the
1084 ** typed stream STREAM. DATA specifies the address of the types to
1085 ** read. Expected type is checked against the type actually present
1090 objc_read_type(TypedStream* stream, const char* type, void* data)
1095 return objc_read_object (stream, (id*)data);
1099 return objc_read_class (stream, (Class*)data);
1103 return objc_read_selector (stream, (SEL*)data);
1107 return objc_read_char (stream, (char*)data);
1111 return objc_read_unsigned_char (stream, (unsigned char*)data);
1115 return objc_read_short (stream, (short*)data);
1119 return objc_read_unsigned_short (stream, (unsigned short*)data);
1123 return objc_read_int (stream, (int*)data);
1127 return objc_read_unsigned_int (stream, (unsigned int*)data);
1131 return objc_read_long (stream, (long*)data);
1135 return objc_read_unsigned_long (stream, (unsigned long*)data);
1140 return objc_read_string (stream, (char**)data);
1145 int len = atoi(type+1);
1146 while (isdigit((int)*++type))
1148 return objc_read_array (stream, type, len, data);
1156 while (*type != _C_STRUCT_E && *type++ != '=')
1157 ; /* skip "<name>=" */
1158 while (*type != _C_STRUCT_E)
1160 align = objc_alignof_type (type); /* padd to alignment */
1161 acc_size += ROUND (acc_size, align);
1162 objc_read_type (stream, type, ((char*)data)+acc_size);
1163 acc_size += objc_sizeof_type (type); /* add component size */
1164 type = objc_skip_typespec (type); /* skip component */
1171 objc_error(nil, OBJC_ERR_BAD_TYPE,
1172 "objc_read_type: cannot parse typespec: %s\n", type);
1179 ** Write the object specified by the template TYPE to STREAM. Last
1180 ** arguments specify addresses of values to be written. It might
1181 ** seem surprising to specify values by address, but this is extremely
1182 ** convenient for copy-paste with objc_read_types calls. A more
1183 ** down-to-the-earth cause for this passing of addresses is that values
1184 ** of arbitrary size is not well supported in ANSI C for functions with
1185 ** variable number of arguments.
1189 objc_write_types (TypedStream* stream, const char* type, ...)
1195 va_start(args, type);
1197 for (c = type; *c; c = objc_skip_typespec (c))
1201 res = objc_write_object (stream, *va_arg (args, id*));
1205 res = objc_write_class (stream, *va_arg(args, Class*));
1209 res = objc_write_selector (stream, *va_arg(args, SEL*));
1213 res = objc_write_char (stream, *va_arg (args, char*));
1217 res = objc_write_unsigned_char (stream,
1218 *va_arg (args, unsigned char*));
1222 res = objc_write_short (stream, *va_arg(args, short*));
1226 res = objc_write_unsigned_short (stream,
1227 *va_arg(args, unsigned short*));
1231 res = objc_write_int(stream, *va_arg(args, int*));
1235 res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
1239 res = objc_write_long(stream, *va_arg(args, long*));
1243 res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*));
1248 char** str = va_arg(args, char**);
1249 res = objc_write_string (stream, *str, strlen(*str));
1255 char** str = va_arg(args, char**);
1256 res = objc_write_string_atomic (stream, *str, strlen(*str));
1262 int len = atoi(c+1);
1264 while (isdigit((int)*++t))
1266 res = objc_write_array (stream, t, len, va_arg(args, void*));
1267 t = objc_skip_typespec (t);
1269 objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
1274 objc_error(nil, OBJC_ERR_BAD_TYPE,
1275 "objc_write_types: cannot parse typespec: %s\n", type);
1284 ** Last arguments specify addresses of values to be read. Expected
1285 ** type is checked against the type actually present on the stream.
1289 objc_read_types(TypedStream* stream, const char* type, ...)
1295 va_start(args, type);
1297 for (c = type; *c; c = objc_skip_typespec(c))
1301 res = objc_read_object(stream, va_arg(args, id*));
1305 res = objc_read_class(stream, va_arg(args, Class*));
1309 res = objc_read_selector(stream, va_arg(args, SEL*));
1313 res = objc_read_char(stream, va_arg(args, char*));
1317 res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
1321 res = objc_read_short(stream, va_arg(args, short*));
1325 res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
1329 res = objc_read_int(stream, va_arg(args, int*));
1333 res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
1337 res = objc_read_long(stream, va_arg(args, long*));
1341 res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*));
1347 char** str = va_arg(args, char**);
1348 res = objc_read_string (stream, str);
1354 int len = atoi(c+1);
1356 while (isdigit((int)*++t))
1358 res = objc_read_array (stream, t, len, va_arg(args, void*));
1359 t = objc_skip_typespec (t);
1361 objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
1366 objc_error(nil, OBJC_ERR_BAD_TYPE,
1367 "objc_read_types: cannot parse typespec: %s\n", type);
1375 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1376 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1380 objc_write_array (TypedStream* stream, const char* type,
1381 int count, const void* data)
1383 int off = objc_sizeof_type(type);
1384 const char* where = data;
1388 objc_write_type(stream, type, where);
1395 ** Read an array of COUNT elements of TYPE into the memory address
1396 ** DATA. The memory pointed to by data is supposed to be allocated
1397 ** by the callee. This is equivalent of
1398 ** objc_read_type (stream, "[N<type>]", data)
1402 objc_read_array (TypedStream* stream, const char* type,
1403 int count, void* data)
1405 int off = objc_sizeof_type(type);
1406 char* where = (char*)data;
1410 objc_read_type(stream, type, where);
1417 __objc_fread(FILE* file, char* data, int len)
1419 return fread(data, len, 1, file);
1423 __objc_fwrite(FILE* file, char* data, int len)
1425 return fwrite(data, len, 1, file);
1429 __objc_feof(FILE* file)
1435 __objc_no_write(FILE* file, char* data, int len)
1437 objc_error (nil, OBJC_ERR_NO_WRITE, "TypedStream not open for writing");
1442 __objc_no_read(FILE* file, char* data, int len)
1444 objc_error (nil, OBJC_ERR_NO_READ, "TypedStream not open for reading");
1449 __objc_read_typed_stream_signature (TypedStream* stream)
1454 (*stream->read)(stream->physical, buffer+pos, 1);
1455 while (buffer[pos++] != '\0')
1457 sscanf (buffer, "GNU TypedStream %d", &stream->version);
1458 if (stream->version != OBJC_TYPED_STREAM_VERSION)
1459 objc_error (nil, OBJC_ERR_STREAM_VERSION,
1460 "cannot handle TypedStream version %d", stream->version);
1465 __objc_write_typed_stream_signature (TypedStream* stream)
1468 sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
1469 stream->version = OBJC_TYPED_STREAM_VERSION;
1470 (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
1474 static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
1476 hash_delete (stream->object_table);
1477 stream->object_table = ptrhash_new(64);
1480 static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
1483 SEL awake_sel = sel_get_any_uid ("awake");
1484 cache_ptr free_list = ptrhash_new(64);
1486 /* resolve object forward references */
1487 for (node = hash_next (stream->object_refs, NULL); node;
1488 node = hash_next (stream->object_refs, node))
1490 struct objc_list* reflist = node->value;
1491 const void* key = node->key;
1492 id object = hash_value_for_key (stream->object_table, key);
1495 *((id*)reflist->head) = object;
1496 if (hash_value_for_key (free_list,reflist) == NULL)
1497 hash_add (&free_list,reflist,reflist);
1499 reflist = reflist->tail;
1503 /* apply __objc_free to all objects stored in free_list */
1504 for (node = hash_next (free_list, NULL); node;
1505 node = hash_next (free_list, node))
1506 objc_free ((void *) node->key);
1508 hash_delete (free_list);
1510 /* empty object reference table */
1511 hash_delete (stream->object_refs);
1512 stream->object_refs = ptrhash_new(8);
1514 /* call -awake for all objects read */
1517 for (node = hash_next (stream->object_table, NULL); node;
1518 node = hash_next (stream->object_table, node))
1520 id object = node->value;
1521 if (__objc_responds_to (object, awake_sel))
1522 (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
1526 /* empty object table */
1527 hash_delete (stream->object_table);
1528 stream->object_table = ptrhash_new(64);
1532 ** Open the stream PHYSICAL in MODE
1536 objc_open_typed_stream (FILE* physical, int mode)
1538 TypedStream* s = (TypedStream*)objc_malloc(sizeof(TypedStream));
1541 s->physical = physical;
1542 s->stream_table = ptrhash_new(64);
1543 s->object_table = ptrhash_new(64);
1544 s->eof = (objc_typed_eof_func)__objc_feof;
1545 s->flush = (objc_typed_flush_func)fflush;
1546 s->writing_root_p = 0;
1547 if (mode == OBJC_READONLY)
1549 s->class_table = strhash_new(8);
1550 s->object_refs = ptrhash_new(8);
1551 s->read = (objc_typed_read_func)__objc_fread;
1552 s->write = (objc_typed_write_func)__objc_no_write;
1553 __objc_read_typed_stream_signature (s);
1555 else if (mode == OBJC_WRITEONLY)
1559 s->read = (objc_typed_read_func)__objc_no_read;
1560 s->write = (objc_typed_write_func)__objc_fwrite;
1561 __objc_write_typed_stream_signature (s);
1565 objc_close_typed_stream (s);
1568 s->type = OBJC_FILE_STREAM;
1573 ** Open the file named by FILE_NAME in MODE
1577 objc_open_typed_stream_for_file (const char* file_name, int mode)
1582 if (mode == OBJC_READONLY)
1583 file = fopen (file_name, "r");
1585 file = fopen (file_name, "w");
1589 s = objc_open_typed_stream (file, mode);
1591 s->type |= OBJC_MANAGED_STREAM;
1599 ** Close STREAM freeing the structure it self. If it was opened with
1600 ** objc_open_typed_stream_for_file, the file will also be closed.
1604 objc_close_typed_stream (TypedStream* stream)
1606 if (stream->mode == OBJC_READONLY)
1608 __objc_finish_read_root_object (stream); /* Just in case... */
1609 hash_delete (stream->class_table);
1610 hash_delete (stream->object_refs);
1613 hash_delete (stream->stream_table);
1614 hash_delete (stream->object_table);
1616 if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1617 fclose ((FILE*)stream->physical);
1623 objc_end_of_typed_stream (TypedStream* stream)
1625 return (*stream->eof)(stream->physical);
1629 objc_flush_typed_stream (TypedStream* stream)
1631 (*stream->flush)(stream->physical);
1635 objc_get_stream_class_version (TypedStream* stream, Class class)
1637 if (stream->class_table)
1638 return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
1640 return class_get_version (class);