?? archive.c
字號:
case _C_CHR: return objc_read_char (stream, (char*)data); break; case _C_UCHR: return objc_read_unsigned_char (stream, (unsigned char*)data); break; case _C_SHT: return objc_read_short (stream, (short*)data); break; case _C_USHT: return objc_read_unsigned_short (stream, (unsigned short*)data); break; case _C_INT: return objc_read_int (stream, (int*)data); break; case _C_UINT: return objc_read_unsigned_int (stream, (unsigned int*)data); break; case _C_LNG: return objc_read_long (stream, (long*)data); break; case _C_ULNG: return objc_read_unsigned_long (stream, (unsigned long*)data); break; case _C_CHARPTR: case _C_ATOM: return objc_read_string (stream, (char**)data); break; case _C_ARY_B: { int len = atoi(type+1); while (isdigit(*++type)) ; return objc_read_array (stream, type, len, data); } break; case _C_STRUCT_B: { int acc_size = 0; int align; while (*type != _C_STRUCT_E && *type++ != '=') ; /* skip "<name>=" */ while (*type != _C_STRUCT_E) { align = objc_alignof_type (type); /* padd to alignment */ acc_size += ROUND (acc_size, align); objc_read_type (stream, type, ((char*)data)+acc_size); acc_size += objc_sizeof_type (type); /* add component size */ type = objc_skip_typespec (type); /* skip component */ } return 1; } default: { objc_error(nil, OBJC_ERR_BAD_TYPE, "objc_read_type: cannot parse typespec: %s\n", type); return 0; } }}/*** Write the object specified by the template TYPE to STREAM. Last** arguments specify addresses of values to be written. It might ** seem surprising to specify values by address, but this is extremely** convenient for copy-paste with objc_read_types calls. A more** down-to-the-earth cause for this passing of addresses is that values** of arbitrary size is not well supported in ANSI C for functions with** variable number of arguments.*/int objc_write_types (TypedStream* stream, const char* type, ...){ va_list args; const char *c; int res = 0; va_start(args, type); for (c = type; *c; c = objc_skip_typespec (c)) { switch(*c) { case _C_ID: res = objc_write_object (stream, *va_arg (args, id*)); break; case _C_CLASS: res = objc_write_class (stream, *va_arg(args, Class*)); break; case _C_SEL: res = objc_write_selector (stream, *va_arg(args, SEL*)); break; case _C_CHR: res = objc_write_char (stream, *va_arg (args, char*)); break; case _C_UCHR: res = objc_write_unsigned_char (stream, *va_arg (args, unsigned char*)); break; case _C_SHT: res = objc_write_short (stream, *va_arg(args, short*)); break; case _C_USHT: res = objc_write_unsigned_short (stream, *va_arg(args, unsigned short*)); break; case _C_INT: res = objc_write_int(stream, *va_arg(args, int*)); break; case _C_UINT: res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*)); break; case _C_LNG: res = objc_write_long(stream, *va_arg(args, long*)); break; case _C_ULNG: res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*)); break; case _C_CHARPTR: { char** str = va_arg(args, char**); res = objc_write_string (stream, *str, strlen(*str)); } break; case _C_ATOM: { char** str = va_arg(args, char**); res = objc_write_string_atomic (stream, *str, strlen(*str)); } break; case _C_ARY_B: { int len = atoi(c+1); const char* t = c; while (isdigit(*++t)) ; res = objc_write_array (stream, t, len, va_arg(args, void*)); t = objc_skip_typespec (t); if (*t != _C_ARY_E) objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t); } break; default: objc_error(nil, OBJC_ERR_BAD_TYPE, "objc_write_types: cannot parse typespec: %s\n", type); } } va_end(args); return res;}/* ** Last arguments specify addresses of values to be read. Expected** type is checked against the type actually present on the stream. */int objc_read_types(TypedStream* stream, const char* type, ...){ va_list args; const char *c; int res = 0; va_start(args, type); for (c = type; *c; c = objc_skip_typespec(c)) { switch(*c) { case _C_ID: res = objc_read_object(stream, va_arg(args, id*)); break; case _C_CLASS: res = objc_read_class(stream, va_arg(args, Class*)); break; case _C_SEL: res = objc_read_selector(stream, va_arg(args, SEL*)); break; case _C_CHR: res = objc_read_char(stream, va_arg(args, char*)); break; case _C_UCHR: res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*)); break; case _C_SHT: res = objc_read_short(stream, va_arg(args, short*)); break; case _C_USHT: res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*)); break; case _C_INT: res = objc_read_int(stream, va_arg(args, int*)); break; case _C_UINT: res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*)); break; case _C_LNG: res = objc_read_long(stream, va_arg(args, long*)); break; case _C_ULNG: res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*)); break; case _C_CHARPTR: case _C_ATOM: { char** str = va_arg(args, char**); res = objc_read_string (stream, str); } break; case _C_ARY_B: { int len = atoi(c+1); const char* t = c; while (isdigit(*++t)) ; res = objc_read_array (stream, t, len, va_arg(args, void*)); t = objc_skip_typespec (t); if (*t != _C_ARY_E) objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t); } break; default: objc_error(nil, OBJC_ERR_BAD_TYPE, "objc_read_types: cannot parse typespec: %s\n", type); } } va_end(args); return res;}/*** Write an array of COUNT elements of TYPE from the memory address DATA.** This is equivalent of objc_write_type (stream, "[N<type>]", data)*/intobjc_write_array (TypedStream* stream, const char* type, int count, const void* data){ int off = objc_sizeof_type(type); const char* where = data; while (count-- > 0) { objc_write_type(stream, type, where); where += off; } return 1;}/*** Read an array of COUNT elements of TYPE into the memory address** DATA. The memory pointed to by data is supposed to be allocated** by the callee. This is equivalent of ** objc_read_type (stream, "[N<type>]", data)*/intobjc_read_array (TypedStream* stream, const char* type, int count, void* data){ int off = objc_sizeof_type(type); char* where = (char*)data; while (count-- > 0) { objc_read_type(stream, type, where); where += off; } return 1;}static int __objc_fread(FILE* file, char* data, int len){ return fread(data, len, 1, file);}static int __objc_fwrite(FILE* file, char* data, int len){ return fwrite(data, len, 1, file);}static int__objc_feof(FILE* file){ return feof(file);}static int __objc_no_write(FILE* file, char* data, int len){ objc_error (nil, OBJC_ERR_NO_WRITE, "TypedStream not open for writing"); return 0;}static int __objc_no_read(FILE* file, char* data, int len){ objc_error (nil, OBJC_ERR_NO_READ, "TypedStream not open for reading"); return 0;}static int__objc_read_typed_stream_signature (TypedStream* stream){ char buffer[80]; int pos = 0; do (*stream->read)(stream->physical, buffer+pos, 1); while (buffer[pos++] != '\0') ; sscanf (buffer, "GNU TypedStream %d", &stream->version); if (stream->version != OBJC_TYPED_STREAM_VERSION) objc_error (nil, OBJC_ERR_STREAM_VERSION, "cannot handle TypedStream version %d", stream->version); return 1;}static int__objc_write_typed_stream_signature (TypedStream* stream){ char buffer[80]; sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION); stream->version = OBJC_TYPED_STREAM_VERSION; (*stream->write)(stream->physical, buffer, strlen(buffer)+1); return 1;}static void __objc_finish_write_root_object(struct objc_typed_stream* stream){ hash_delete (stream->object_table); stream->object_table = hash_new(64, (hash_func_type)hash_ptr, (compare_func_type)compare_ptrs);}static void __objc_finish_read_root_object(struct objc_typed_stream* stream){ node_ptr node; SEL awake_sel = sel_get_any_uid ("awake"); cache_ptr free_list = hash_new (64, (hash_func_type) hash_ptr, (compare_func_type) compare_ptrs); /* resolve object forward references */ for (node = hash_next (stream->object_refs, NULL); node; node = hash_next (stream->object_refs, node)) { struct objc_list* reflist = node->value; const void* key = node->key; id object = hash_value_for_key (stream->object_table, key); while(reflist) { *((id*)reflist->head) = object; if (hash_value_for_key (free_list,reflist) == NULL) hash_add (&free_list,reflist,reflist); reflist = reflist->tail; } } /* apply __objc_free to all objects stored in free_list */ for (node = hash_next (free_list, NULL); node; node = hash_next (free_list, node)) objc_free ((void *) node->key); hash_delete (free_list); /* empty object reference table */ hash_delete (stream->object_refs); stream->object_refs = hash_new(8, (hash_func_type)hash_ptr, (compare_func_type)compare_ptrs); /* call -awake for all objects read */ if (awake_sel) { for (node = hash_next (stream->object_table, NULL); node; node = hash_next (stream->object_table, node)) { id object = node->value; if (__objc_responds_to (object, awake_sel)) (*objc_msg_lookup(object, awake_sel))(object, awake_sel); } } /* empty object table */ hash_delete (stream->object_table); stream->object_table = hash_new(64, (hash_func_type)hash_ptr, (compare_func_type)compare_ptrs);}/*** Open the stream PHYSICAL in MODE*/TypedStream* objc_open_typed_stream (FILE* physical, int mode){ TypedStream* s = (TypedStream*)objc_malloc(sizeof(TypedStream)); s->mode = mode; s->physical = physical; s->stream_table = hash_new(64, (hash_func_type)hash_ptr, (compare_func_type)compare_ptrs); s->object_table = hash_new(64, (hash_func_type)hash_ptr, (compare_func_type)compare_ptrs); s->eof = (objc_typed_eof_func)__objc_feof; s->flush = (objc_typed_flush_func)fflush; s->writing_root_p = 0; if (mode == OBJC_READONLY) { s->class_table = hash_new(8, (hash_func_type)hash_string, (compare_func_type)compare_strings); s->object_refs = hash_new(8, (hash_func_type)hash_ptr, (compare_func_type)compare_ptrs); s->read = (objc_typed_read_func)__objc_fread; s->write = (objc_typed_write_func)__objc_no_write; __objc_read_typed_stream_signature (s); } else if (mode == OBJC_WRITEONLY) { s->class_table = 0; s->object_refs = 0; s->read = (objc_typed_read_func)__objc_no_read; s->write = (objc_typed_write_func)__objc_fwrite; __objc_write_typed_stream_signature (s); } else { objc_close_typed_stream (s); return NULL; } s->type = OBJC_FILE_STREAM; return s;}/*** Open the file named by FILE_NAME in MODE*/TypedStream*objc_open_typed_stream_for_file (const char* file_name, int mode){ FILE* file = NULL; TypedStream* s; if (mode == OBJC_READONLY) file = fopen (file_name, "r"); else file = fopen (file_name, "w"); if (file) { s = objc_open_typed_stream (file, mode); if (s) s->type |= OBJC_MANAGED_STREAM; return s; } else return NULL;}/*** Close STREAM freeing the structure it self. If it was opened with ** objc_open_typed_stream_for_file, the file will also be closed.*/voidobjc_close_typed_stream (TypedStream* stream){ if (stream->mode == OBJC_READONLY) { __objc_finish_read_root_object (stream); /* Just in case... */ hash_delete (stream->class_table); hash_delete (stream->object_refs); } hash_delete (stream->stream_table); hash_delete (stream->object_table); if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM)) fclose ((FILE*)stream->physical); objc_free(stream);}BOOLobjc_end_of_typed_stream (TypedStream* stream){ return (*stream->eof)(stream->physical);}voidobjc_flush_typed_stream (TypedStream* stream){ (*stream->flush)(stream->physical);}longobjc_get_stream_class_version (TypedStream* stream, Class class){ if (stream->class_table) return PTR2LONG(hash_value_for_key (stream->class_table, class->name)); else return class_get_version (class);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -