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.
29 ** Most API function are in the bottom of this file.
33 #include <objc/objc-archive.h>
35 #define __objc_fatal(format, args...) \
36 { fprintf(stderr, "archining: "); \
37 fprintf(stderr, format, ## args); \
38 fprintf(stderr, "\n"); abort(); }
40 /* Declare some functions... */
43 objc_read_class (struct objc_typed_stream* stream, Class** class);
46 objc_sizeof_type(const char* type);
49 objc_write_use_common (struct objc_typed_stream* stream, unsigned int key);
52 objc_write_register_common (struct objc_typed_stream* stream,
56 objc_write_class (struct objc_typed_stream* stream,
57 struct objc_class* class);
60 __objc_skip_type (const char* type);
63 __objc_code_unsigned_char (unsigned char* buf, unsigned char val)
65 if ((val&_B_VALUE) == val)
72 buf[0] = _B_NINT|0x01;
79 objc_write_unsigned_char (struct objc_typed_stream* stream,
82 unsigned char buf[sizeof (unsigned char)+1];
83 int len = __objc_code_unsigned_char (buf, value);
84 return (*stream->write)(stream->physical, buf, len);
88 __objc_code_char (unsigned char* buf, char val)
91 return __objc_code_unsigned_char (buf, val);
94 buf[0] = _B_NINT|_B_SIGN|0x01;
101 objc_write_char (struct objc_typed_stream* stream, char value)
103 unsigned char buf[sizeof (char)+1];
104 int len = __objc_code_char (buf, value);
105 return (*stream->write)(stream->physical, buf, len);
108 static __inline__ int
109 __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
112 return __objc_code_unsigned_char (buf, val);
116 buf[0] = _B_NINT|0x02;
124 objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short value)
126 unsigned char buf[sizeof (unsigned short)+1];
127 int len = __objc_code_unsigned_short (buf, value);
128 return (*stream->write)(stream->physical, buf, len);
131 static __inline__ int
132 __objc_code_short (unsigned char* buf, short val)
135 return __objc_code_unsigned_short (buf, val);
137 if (val > -0x7f) /* val > -128 */
138 return __objc_code_char (buf, val);
142 int len = __objc_code_unsigned_short (buf, -val);
149 objc_write_short (struct objc_typed_stream* stream, short value)
151 unsigned char buf[sizeof (short)+1];
152 int len = __objc_code_short (buf, value);
153 return (*stream->write)(stream->physical, buf, len);
157 static __inline__ int
158 __objc_code_unsigned_int (unsigned char* buf, unsigned int val)
161 return __objc_code_unsigned_short (buf, val%0x10000);
163 else if (val < 0x1000000)
166 buf[1] = val/0x10000;
167 buf[2] = (val%0x10000)/0x100;
175 buf[1] = val/0x1000000;
176 buf[2] = (val%0x1000000)/0x10000;
177 buf[3] = (val%0x10000)/0x100;
184 objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value)
186 unsigned char buf[sizeof(unsigned int)+1];
187 int len = __objc_code_unsigned_int (buf, value);
188 return (*stream->write)(stream->physical, buf, len);
191 static __inline__ int
192 __objc_code_int (unsigned char* buf, int val)
195 return __objc_code_unsigned_int (buf, val);
198 return __objc_code_char (buf, val);
202 int len = __objc_code_unsigned_int (buf, -val);
209 objc_write_int (struct objc_typed_stream* stream, int value)
211 unsigned char buf[sizeof(int)+1];
212 int len = __objc_code_int (buf, value);
213 return (*stream->write)(stream->physical, buf, len);
217 objc_write_string (struct objc_typed_stream* stream,
218 const unsigned char* string, unsigned int nbytes)
220 unsigned char buf[sizeof(unsigned int)+1];
221 int len = __objc_code_unsigned_int (buf, nbytes);
223 if ((buf[0]&_B_CODE) == _B_SINT)
224 buf[0] = (buf[0]&_B_VALUE)|_B_SSTR;
227 buf[0] = (buf[0]&_B_VALUE)|_B_NSTR;
229 if ((*stream->write)(stream->physical, buf, len) != 0)
230 return (*stream->write)(stream->physical, string, nbytes);
236 objc_write_string_atomic (struct objc_typed_stream* stream,
237 unsigned char* string, unsigned int nbytes)
240 if ((key = (unsigned int)hash_value_for_key (stream->stream_table, string)))
241 return objc_write_use_common (stream, key);
245 hash_add (&stream->stream_table, (void*)key=(unsigned int)string, string);
246 if ((length = objc_write_register_common (stream, key)))
247 return objc_write_string (stream, string, nbytes);
253 objc_write_register_common (struct objc_typed_stream* stream, unsigned int key)
255 unsigned char buf[sizeof (unsigned int)+2];
256 int len = __objc_code_unsigned_int (buf+1, key);
259 buf[0] = _B_RCOMM|0x01;
261 return (*stream->write)(stream->physical, buf, len+1);
265 buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM;
266 return (*stream->write)(stream->physical, buf+1, len);
271 objc_write_use_common (struct objc_typed_stream* stream, unsigned int key)
273 unsigned char buf[sizeof (unsigned int)+2];
274 int len = __objc_code_unsigned_int (buf+1, key);
277 buf[0] = _B_UCOMM|0x01;
279 return (*stream->write)(stream->physical, buf, 2);
283 buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM;
284 return (*stream->write)(stream->physical, buf+1, len);
288 static __inline__ int
289 __objc_write_extension (struct objc_typed_stream* stream, unsigned char code)
291 if (code <= _B_VALUE)
293 unsigned char buf = code|_B_EXT;
294 return (*stream->write)(stream->physical, &buf, 1);
301 __objc_write_object (struct objc_typed_stream* stream, id object)
303 unsigned char buf = '\0';
304 SEL write_sel = sel_get_uid ("write:");
307 __objc_write_extension (stream, _BX_OBJECT);
308 objc_write_class (stream, object->class_pointer);
309 (*objc_msg_lookup(object, write_sel))(object, write_sel, stream);
310 return (*stream->write)(stream->physical, &buf, 1);
313 return objc_write_use_common(stream, 0);
317 objc_write_object (struct objc_typed_stream* stream, id object)
320 if ((key = (unsigned int)hash_value_for_key (stream->stream_table, object)))
321 return objc_write_use_common (stream, key);
323 else if (object == nil)
324 return objc_write_use_common(stream, 0);
329 hash_add (&stream->stream_table, (void*)key=(unsigned int)object, object);
330 if ((length = objc_write_register_common (stream, key)))
331 return __objc_write_object (stream, object);
337 __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class)
339 unsigned char buf = '\0';
340 SEL write_sel = sel_get_uid ("write:");
341 __objc_write_extension (stream, _BX_CLASS);
342 objc_write_string_atomic(stream, (char*)class->name,
343 strlen(class->name));
344 objc_write_unsigned_int (stream, CLS_GETNUMBER(class));
345 (*objc_msg_lookup(class, write_sel))(class, write_sel, stream);
346 return (*stream->write)(stream->physical, &buf, 1);
351 objc_write_class (struct objc_typed_stream* stream,
352 struct objc_class* class)
355 if ((key = (unsigned int)hash_value_for_key (stream->stream_table, class)))
356 return objc_write_use_common (stream, key);
360 hash_add (&stream->stream_table, (void*)key=(unsigned int)class, class);
361 if ((length = objc_write_register_common (stream, key)))
362 return __objc_write_class (stream, class);
369 __objc_write_selector (struct objc_typed_stream* stream, SEL selector)
371 const char* sel_name = sel_get_name (selector);
372 __objc_write_extension (stream, _BX_SEL);
373 return objc_write_string (stream, sel_name, strlen(sel_name));
377 objc_write_selector (struct objc_typed_stream* stream, SEL selector)
379 const char* sel_name = sel_get_name (selector);
381 if ((key = (unsigned int)hash_value_for_key (stream->stream_table, sel_name)))
382 return objc_write_use_common (stream, key);
386 hash_add (&stream->stream_table, (void*)key=(unsigned int)sel_name, (char*)sel_name);
387 if ((length = objc_write_register_common (stream, key)))
388 return __objc_write_selector (stream, selector);
400 objc_read_char (struct objc_typed_stream* stream, char* val)
404 len = (*stream->read)(stream->physical, &buf, 1);
407 if ((buf & _B_CODE) == _B_SINT)
408 (*val) = (buf & _B_VALUE);
410 else if ((buf & _B_NUMBER) == 1)
412 len = (*stream->read)(stream->physical, val, 1);
418 __objc_fatal("expected 8bit signed int, got %dbit int",
419 (int)(buf&_B_NUMBER)*8);
426 objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val)
430 if ((len = (*stream->read)(stream->physical, &buf, 1)))
432 if ((buf & _B_CODE) == _B_SINT)
433 (*val) = (buf & _B_VALUE);
435 else if ((buf & _B_NUMBER) == 1)
436 len = (*stream->read)(stream->physical, val, 1);
439 __objc_fatal("expected 8bit unsigned int, got %dbit int",
440 (int)(buf&_B_NUMBER)*8);
446 objc_read_short (struct objc_typed_stream* stream, short* value)
448 unsigned char buf[sizeof(short)+1];
450 if ((len = (*stream->read)(stream->physical, buf, 1)))
452 if ((buf[0] & _B_CODE) == _B_SINT)
453 (*value) = (buf[0] & _B_VALUE);
458 int nbytes = buf[0] & _B_NUMBER;
459 if (nbytes > sizeof (short))
460 __objc_fatal("expected short, got bigger (%dbits)", nbytes*8);
461 len = (*stream->read)(stream->physical, buf+1, nbytes);
463 while (pos <= nbytes)
464 (*value) = ((*value)*0x100) + buf[pos++];
465 if (buf[0] & _B_SIGN)
466 (*value) = -(*value);
473 objc_read_unsigned_short (struct objc_typed_stream* stream,
474 unsigned short* value)
476 unsigned char buf[sizeof(unsigned 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 int or bigger");
489 len = (*stream->read)(stream->physical, buf+1, nbytes);
491 while (pos <= nbytes)
492 (*value) = ((*value)*0x100) + buf[pos++];
500 objc_read_int (struct objc_typed_stream* stream, int* value)
502 unsigned char buf[sizeof(int)+1];
504 if ((len = (*stream->read)(stream->physical, buf, 1)))
506 if ((buf[0] & _B_CODE) == _B_SINT)
507 (*value) = (buf[0] & _B_VALUE);
512 int nbytes = buf[0] & _B_NUMBER;
513 if (nbytes > sizeof (int))
514 __objc_fatal("expected int, got bigger");
515 len = (*stream->read)(stream->physical, buf+1, nbytes);
517 while (pos <= nbytes)
518 (*value) = ((*value)*0x100) + buf[pos++];
519 if (buf[0] & _B_SIGN)
520 (*value) = -(*value);
527 __objc_read_nbyte_uint (struct objc_typed_stream* stream,
528 unsigned int nbytes, unsigned int* val)
531 unsigned char buf[sizeof(unsigned int)+1];
533 if (nbytes > sizeof (int))
534 __objc_fatal("expected int, got bigger");
536 len = (*stream->read)(stream->physical, buf, nbytes);
539 (*val) = ((*val)*0x100) + buf[pos++];
545 objc_read_unsigned_int (struct objc_typed_stream* stream,
548 unsigned char buf[sizeof(unsigned int)+1];
550 if ((len = (*stream->read)(stream->physical, buf, 1)))
552 if ((buf[0] & _B_CODE) == _B_SINT)
553 (*value) = (buf[0] & _B_VALUE);
556 len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value);
563 objc_read_string (struct objc_typed_stream* stream,
566 unsigned char buf[sizeof(unsigned int)+1];
568 if ((len = (*stream->read)(stream->physical, buf, 1)))
570 unsigned int key = 0;
572 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
574 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
575 len = (*stream->read)(stream->physical, buf, 1);
578 switch (buf[0]&_B_CODE) {
581 int length = buf[0]&_B_VALUE;
582 (*string) = (char*)malloc(length+1);
584 hash_add (&stream->stream_table, (void*)key, *string);
585 len = (*stream->read)(stream->physical, *string, length);
586 (*string)[length] = '\0';
592 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
593 (*string) = hash_value_for_key (stream->stream_table, (void*)key);
599 unsigned int nbytes = buf[0]&_B_VALUE;
600 len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
602 (*string) = (char*)malloc(nbytes);
604 hash_add (&stream->stream_table, (void*)key, *string);
605 len = (*stream->read)(stream->physical, *string, buf[0]&_B_VALUE);
606 (*string)[nbytes] = '\0';
612 __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE));
621 objc_read_object (struct objc_typed_stream* stream, id* object)
623 unsigned char buf[sizeof (unsigned int)];
625 if ((len = (*stream->read)(stream->physical, buf, 1)))
627 SEL read_sel = sel_get_uid ("read:");
628 unsigned int key = 0;
630 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
632 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
633 len = (*stream->read)(stream->physical, buf, 1);
636 if (buf[0] == (_B_EXT | _BX_OBJECT))
641 len = objc_read_class (stream, &class);
643 /* create instance */
644 (*object) = class_create_instance(class);
648 hash_add (&stream->stream_table, (void*)key, *object);
651 if (__objc_responds_to (*object, read_sel))
652 (*get_imp(class, read_sel))(*object, read_sel, stream);
654 /* check null-byte */
655 len = (*stream->read)(stream->physical, buf, 1);
657 __objc_fatal("expected null-byte, got opcode %c", buf[0]);
660 else if ((buf[0]&_B_CODE) == _B_UCOMM)
663 __objc_fatal("cannot register use upcode...");
664 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
665 (*object) = hash_value_for_key (stream->stream_table, (void*)key);
669 __objc_fatal("expected object, got opcode %c", buf[0]);
675 objc_read_class (struct objc_typed_stream* stream, Class** class)
677 unsigned char buf[sizeof (unsigned int)];
679 if ((len = (*stream->read)(stream->physical, buf, 1)))
681 SEL read_sel = sel_get_uid ("read:");
682 unsigned int key = 0;
684 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
686 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
687 len = (*stream->read)(stream->physical, buf, 1);
690 if (buf[0] == (_B_EXT | _BX_CLASS))
696 len = objc_read_string (stream, &class_name);
697 (*class) = objc_get_class(class_name);
702 hash_add (&stream->stream_table, (void*)key, *class);
705 (*objc_msg_lookup(*class, read_sel))(*class, read_sel, stream);
707 objc_read_unsigned_int(stream, &version);
708 hash_add (&stream->class_table, (*class)->name, (void*)version);
710 /* check null-byte */
711 len = (*stream->read)(stream->physical, buf, 1);
713 __objc_fatal("expected null-byte, got opcode %c", buf[0]);
716 else if ((buf[0]&_B_CODE) == _B_UCOMM)
719 __objc_fatal("cannot register use upcode...");
720 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
721 (*class) = hash_value_for_key (stream->stream_table, (void*)key);
723 __objc_fatal("cannot find class for key %x", key);
727 __objc_fatal("expected class, got opcode %c", buf[0]);
733 objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
735 unsigned char buf[sizeof (unsigned int)];
737 if ((len = (*stream->read)(stream->physical, buf, 1)))
739 unsigned int key = 0;
741 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
743 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
744 len = (*stream->read)(stream->physical, buf, 1);
747 if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
752 len = objc_read_string (stream, &selector_name);
753 (*selector) = sel_get_uid(selector_name);
754 free (selector_name);
758 hash_add (&stream->stream_table, (void*)key, *selector);
761 else if ((buf[0]&_B_CODE) == _B_UCOMM)
764 __objc_fatal("cannot register use upcode...");
765 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
766 (*selector) = hash_value_for_key (stream->stream_table, (void*)key);
770 __objc_fatal("expected selector, got opcode %c", buf[0]);
776 objc_sizeof_type(const char* type)
779 case _C_ID: return sizeof(id);
783 return sizeof(Class*);
795 return sizeof(unsigned char);
799 return sizeof(short);
803 return sizeof(unsigned short);
813 return sizeof(unsigned int);
818 return sizeof(char*);
822 fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
829 __objc_skip_type (const char* type)
851 while(isdigit(*++type));
852 type = __objc_skip_type(type);
853 if (*type == _C_ARY_E)
856 __objc_fatal("cannot parse typespec: %s", type);
860 fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
866 ** USER LEVEL FUNCTIONS
870 ** Write one object, encoded in TYPE and pointed to by DATA to the
871 ** typed stream STREAM.
875 objc_write_type(TypedStream* stream, const char* type, const void* data)
879 return objc_write_object (stream, *(id*)data);
883 return objc_write_class (stream, *(Class**)data);
887 return objc_write_selector (stream, *(SEL*)data);
891 return objc_write_char(stream, *(char*)data);
895 return objc_write_unsigned_char(stream, *(unsigned char*)data);
899 return objc_write_short(stream, *(short*)data);
903 return objc_write_unsigned_short(stream, *(unsigned short*)data);
908 return objc_write_int(stream, *(int*)data);
913 return objc_write_unsigned_int(stream, *(unsigned int*)data);
917 return objc_write_string (stream, (char*)data, strlen((char*)data));
921 return objc_write_string_atomic (stream, (char*)data, strlen((char*)data));
926 int len = atoi(type+1);
927 while (isdigit(*++type));
928 return objc_write_array (stream, type, len, data);
933 fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
939 ** Read one object, encoded in TYPE and pointed to by DATA to the
940 ** typed stream STREAM. DATA specifies the address of the types to
941 ** read. Expected type is checked against the type actually present
946 objc_read_type(TypedStream* stream, const char* type, void* data)
951 return objc_read_object (stream, (id*)data);
955 return objc_read_class (stream, (Class**)data);
959 return objc_read_selector (stream, (SEL*)data);
963 return objc_read_char (stream, (char*)data);
967 return objc_read_unsigned_char (stream, (unsigned char*)data);
971 return objc_read_short (stream, (short*)data);
975 return objc_read_unsigned_short (stream, (unsigned short*)data);
980 return objc_read_int (stream, (int*)data);
985 return objc_read_unsigned_int (stream, (unsigned int*)data);
990 return objc_read_string (stream, (char**)data);
995 int len = atoi(type+1);
996 while (isdigit(*++type));
997 return objc_read_array (stream, type, len, data);
1002 fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
1008 ** Write the object specified by the template TYPE to STREAM. Last
1009 ** arguments specify addresses of values to be written. It might
1010 ** seem surprising to specify values by address, but this is extremely
1011 ** convenient for copy-paste with objc_read_types calls. A more
1012 ** down-to-the-earth cause for this passing of addresses is that values
1013 ** of arbitrary size is not well supported in ANSI C for functions with
1014 ** variable number of arguments.
1018 objc_write_types (TypedStream* stream, const char* type, ...)
1024 va_start(args, type);
1026 for (c = type; *c; c = __objc_skip_type (c))
1030 res = objc_write_object (stream, *va_arg (args, id*));
1034 res = objc_write_class (stream, *va_arg(args, Class**));
1038 res = objc_write_selector (stream, *va_arg(args, SEL*));
1042 res = objc_write_char (stream, *va_arg (args, char*));
1046 res = objc_write_unsigned_char (stream,
1047 *va_arg (args, unsigned char*));
1051 res = objc_write_short (stream, *va_arg(args, short*));
1055 res = objc_write_unsigned_short (stream,
1056 *va_arg(args, unsigned short*));
1061 res = objc_write_int(stream, *va_arg(args, int*));
1066 res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
1071 char* str = va_arg(args, char*);
1072 res = objc_write_string (stream, str, strlen(str));
1078 char* str = va_arg(args, char*);
1079 res = objc_write_string_atomic (stream, str, strlen(str));
1085 int len = atoi(c+1);
1087 while (isdigit(*++t));
1088 res = objc_write_array (stream, t, len, va_arg(args, void*));
1089 t = __objc_skip_type (t);
1091 __objc_fatal("expected `]', got: %s", t);
1096 fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
1106 ** Last arguments specify addresses of values to be read. Expected
1107 ** type is checked against the type actually present on the stream.
1111 objc_read_types(TypedStream* stream, const char* type, ...)
1117 va_start(args, type);
1119 for (c = type; *c; c = __objc_skip_type(c))
1123 res = objc_read_object(stream, va_arg(args, id*));
1127 res = objc_read_class(stream, va_arg(args, Class**));
1131 res = objc_read_selector(stream, va_arg(args, SEL*));
1135 res = objc_read_char(stream, va_arg(args, char*));
1139 res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
1143 res = objc_read_short(stream, va_arg(args, short*));
1147 res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
1152 res = objc_read_int(stream, va_arg(args, int*));
1157 res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
1163 char** str = va_arg(args, char**);
1164 res = objc_read_string (stream, str);
1170 int len = atoi(c+1);
1172 while (isdigit(*++t));
1173 res = objc_read_array (stream, t, len, va_arg(args, void*));
1174 t = __objc_skip_type (t);
1176 __objc_fatal("expected `]', got: %s", t);
1181 fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
1190 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1191 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1195 objc_write_array (TypedStream* stream, const char* type,
1196 int count, const void* data)
1198 int off = objc_sizeof_type(type);
1199 const char* where = data;
1203 objc_write_type(stream, type, where);
1210 ** Read an array of COUNT elements of TYPE into the memory address
1211 ** DATA. The memory pointed to by data is supposed to be allocated
1212 ** by the callee. This is equivalent of
1213 ** objc_read_type (stream, "[N<type>]", data)
1217 objc_read_array (TypedStream* stream, const char* type,
1218 int count, void* data)
1220 int off = objc_sizeof_type(type);
1221 char* where = (char*)data;
1225 objc_read_type(stream, type, where);
1232 __objc_fread(FILE* file, char* data, int len)
1234 return fread(data, len, 1, file);
1238 __objc_fwrite(FILE* file, char* data, int len)
1240 return fwrite(data, len, 1, file);
1244 __objc_feof(FILE* file)
1250 __objc_no_write(FILE* file, char* data, int len)
1252 __objc_fatal ("TypedStream not open for writing");
1256 __objc_no_read(FILE* file, char* data, int len)
1258 __objc_fatal ("TypedStream not open for reading");
1262 __objc_read_typed_stream_signature (TypedStream* stream)
1267 (*stream->read)(stream->physical, buffer+pos, 1);
1268 while (buffer[pos++] != '\0');
1269 sscanf (buffer, "GNU TypedStream %d", &stream->version);
1270 if (stream->version != OBJC_TYPED_STREAM_VERSION)
1271 __objc_fatal ("cannot handle TypedStream version %d", stream->version);
1275 __objc_write_typed_stream_signature (TypedStream* stream)
1278 sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
1279 stream->version = OBJC_TYPED_STREAM_VERSION;
1280 (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
1284 ** Open the stream PHYSICAL in MODE
1288 objc_open_typed_stream (FILE* physical, int mode)
1292 TypedStream* s = (TypedStream*)malloc(sizeof(TypedStream));
1295 s->physical = physical;
1296 s->stream_table = hash_new(64,
1297 (hash_func_type)hash_ptr,
1298 (compare_func_type)compare_ptrs);
1299 s->eof = (objc_typed_eof_func)__objc_feof;
1300 s->flush = (objc_typed_flush_func)fflush;
1301 if (mode == OBJC_READONLY)
1303 s->class_table = hash_new(8, (hash_func_type)hash_string,
1304 (compare_func_type)compare_strings);
1305 s->read = (objc_typed_read_func)__objc_fread;
1306 s->write = (objc_typed_write_func)__objc_no_write;
1307 __objc_read_typed_stream_signature (s);
1309 else if (mode == OBJC_WRITEONLY)
1312 s->read = (objc_typed_read_func)__objc_no_read;
1313 s->write = (objc_typed_write_func)__objc_fwrite;
1314 __objc_write_typed_stream_signature (s);
1318 objc_close_typed_stream (s);
1321 s->type = OBJC_FILE_STREAM;
1326 ** Open the file named by FILE_NAME in MODE
1330 objc_open_typed_stream_for_file (const char* file_name, int mode)
1335 if (mode == OBJC_READONLY)
1336 file = fopen (file_name, "r");
1338 file = fopen (file_name, "w");
1342 s = objc_open_typed_stream (file, mode);
1344 s->type |= OBJC_MANAGED_STREAM;
1352 ** Close STREAM freeing the structure it self. If it was opened with
1353 ** objc_open_typed_stream_for_file, the file will also be closed.
1357 objc_close_typed_stream (TypedStream* stream)
1359 if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1360 fclose ((FILE*)stream->physical);
1361 hash_delete (stream->stream_table);
1362 if (stream->mode == OBJC_READONLY)
1363 hash_delete (stream->class_table);
1368 objc_end_of_typed_stream (TypedStream* stream)
1370 return (*stream->eof)(stream->physical);
1374 objc_flush_typed_stream (TypedStream* stream)
1376 (*stream->flush)(stream->physical);