This is NSData.m in view mode; [Download] [Up]
/* NSData.m Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro> This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #include <Foundation/common.h> #include <Foundation/NSData.h> #include <Foundation/NSString.h> #include <Foundation/NSPosixFileDescriptor.h> #include <Foundation/NSCoder.h> #include <Foundation/NSException.h> #include <Foundation/NSAutoreleasePool.h> #include <Foundation/exceptions/GeneralExceptions.h> #include <extensions/objc-runtime.h> #include "byte_order.h" #include "NSConcreteData.h" @implementation NSData + (id)allocWithZone:(NSZone*)zone { return NSAllocateObject(((self == [NSData class]) ? [NSConcreteData class] : self), 0, zone); } + (id)data { return [[[self allocWithZone:NSDefaultMallocZone()] initWithBytes:NULL length:0] autorelease]; } + (id)dataWithBytes:(const void*)bytes length:(unsigned int)length { return [[[self allocWithZone:NSDefaultMallocZone()] initWithBytes:bytes length:length] autorelease]; } + (id)dataWithBytesNoCopy:(void*)bytes length:(unsigned int)length { return [[[self allocWithZone:NSDefaultMallocZone()] initWithBytesNoCopy:bytes length:length] autorelease]; } + (id)dataWithContentsOfFile:(NSString*)path { return [[[self allocWithZone:NSDefaultMallocZone()] initWithContentsOfFile:path] autorelease]; } + (id)dataWithContentsOfMappedFile:(NSString*)path { NSPosixFileDescriptor* descriptor; NSRange range = {0, 0}; descriptor = [[[NSPosixFileDescriptor alloc] initWithPath:path] autorelease]; range.length = [descriptor fileLength]; return [descriptor mapFileRange:range]; } + (id)dataWithData:(NSData*)aData { return [[[self alloc] initWithData:aData] autorelease]; } - (id)initWithBytes:(const void*)bytes length:(unsigned int)length { [self subclassResponsibility:_cmd]; return nil; } - (id)initWithBytesNoCopy:(void*)bytes length:(unsigned int)length { [self subclassResponsibility:_cmd]; return nil; } - (id)initWithContentsOfFile:(NSString*)path { NSRange range = {0, 0}; char* content = NULL; NSPosixFileDescriptor* descriptor = [[NSPosixFileDescriptor alloc] initWithPath:path]; /* Take the address of range to force the compiler to do not allocate it in registers */ (&range)->length = 0; TRY { range.length = [descriptor fileLength]; content = descriptor ? NSZoneMalloc([self zone], range.length) : NULL; [descriptor readBytes:content range:range]; } END_TRY OTHERWISE { Free(content); content = NULL; descriptor = [descriptor self]; } END_CATCH [descriptor release]; if (!content) { [self autorelease]; return nil; } return [self initWithBytesNoCopy:content length:range.length]; } - (id)initWithContentsOfMappedFile:(NSString*)path { NSPosixFileDescriptor* descriptor; NSRange range = {0, 0}; descriptor = [[[NSPosixFileDescriptor alloc] initWithPath:path] autorelease]; range.length = [descriptor fileLength]; [self release]; return [descriptor mapFileRange:range]; } - (id)initWithData:(NSData*)data { return [self initWithBytes:[data bytes] length:[data length]]; } - copy { return [self copyWithZone:NSDefaultMallocZone()]; } - (id)copyWithZone:(NSZone*)zone { return [[NSData allocWithZone:zone] initWithData:self]; } - mutableCopy { return [self mutableCopyWithZone:NSDefaultMallocZone()]; } - (id)mutableCopyWithZone:(NSZone*)zone { return [[NSMutableData allocWithZone:zone] initWithData:self]; } - (const void*)bytes { [self subclassResponsibility:_cmd]; return NULL; } - (NSString*)description { int i; unsigned int length = [self length]; const char* bytes = [self bytes]; unsigned int final_length = 4 + 2 * length + 1 + length / 4; char* description = Malloc(final_length); char* temp = description + 1; description[0] = 0; Strcat(description, "<"); for(i = 0; i < length; i++, temp += 2) { if (i % 4 == 0) *temp++ = ' '; sprintf (temp, "%02X", (unsigned char)((char*)bytes)[i]); } strcat(temp, " >"); *(temp += 2) = 0; return [NSString stringWithCStringNoCopy:description freeWhenDone:YES]; } - (void)getBytes:(void*)buffer { memcpy(buffer, [self bytes], [self length]); } - (void)getBytes:(void*)buffer length:(unsigned int)_length { if(_length > [self length]) THROW([RangeException new]); else memcpy(buffer, [self bytes], _length); } - (void)getBytes:(void*)buffer range:(NSRange)aRange { unsigned int length = [self length]; if(aRange.location > length || aRange.length > length || aRange.location + aRange.length > length) THROW([RangeException new]); else memcpy(buffer, [self bytes] + aRange.location, aRange.length); } - (NSData*)subdataWithRange:(NSRange)aRange { return [[[NSConcreteDataRange allocWithZone:NSDefaultMallocZone()] initWithData:self range:aRange] autorelease]; } - (BOOL)isEqualToData:(NSData*)other { if([self length] == [other length]) return memcmp([self bytes], [other bytes], [self length]) == 0; else return NO; } - (BOOL)isEqual:(id)anObject { if([anObject isKindOfClass:[NSData class]]) return [self isEqualToData:anObject]; else return NO; } - (unsigned int)length { [self subclassResponsibility:_cmd]; return 0; } - (BOOL)writeToFile:(NSString*)path atomically:(BOOL)useAuxiliaryFile { return writeToFile(path, self, useAuxiliaryFile); } - (unsigned int)deserializeAlignedBytesLengthAtCursor:(unsigned int*)cursor { return *cursor; } - (void)deserializeBytes:(void*)buffer length:(unsigned int)bytes atCursor:(unsigned int*)cursor { NSRange range = { *cursor, bytes }; [self getBytes:buffer range:range]; *cursor += bytes; } - (void)deserializeDataAt:(void*)data ofObjCType:(const char*)type atCursor:(unsigned int*)cursor context:(id <NSObjCTypeSerializationCallBack>)callback { if(!type || !data) return; switch(*type) { case _C_ID: { [callback deserializeObjectAt:data ofObjCType:type fromData:self atCursor:cursor]; break; } case _C_CHARPTR: { volatile int len = [self deserializeIntAtCursor:cursor]; id adr = nil; /* This statement, by taking the address of `type', forces the compiler to not allocate `type' into a register */ *(void**)data = &type; if(len == -1) { *(const char**)data = NULL; return; } else { *(char**)data = Malloc(len + 1); /* Autorelease *data in case of exceptions */ adr = [NSAutoreleasedPointer autoreleasePointer:*(char**)data]; } [self deserializeBytes:*(char**)data length:len atCursor:cursor]; /* Save the *data from destruction */ [adr retain]; break; } case _C_ARY_B: { int i, count, offset, itemSize; const char* itemType; count = Atoi(type + 1); itemType = type; while(isdigit(*++itemType)); itemSize = objc_sizeof_type(itemType); for(i = offset = 0; i < count; i++, offset += itemSize) [self deserializeDataAt:(char*)data + offset ofObjCType:itemType atCursor:cursor context:callback]; break; } case _C_STRUCT_B: { int offset = 0; int align, rem; while(*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */ while(1) { [self deserializeDataAt:((char*)data) + offset ofObjCType:type atCursor:cursor context:callback]; offset += objc_sizeof_type(type); type = objc_skip_typespec(type); if(*type != _C_STRUCT_E) { align = objc_alignof_type(type); if((rem = offset % align)) offset += align - rem; } else break; } break; } case _C_PTR: { id addr; *(char**)data = Malloc(objc_sizeof_type(++type)); /* Autorelease *data in case of exceptions */ addr = [NSAutoreleasedPointer autoreleasePointer:*(char**)data]; [self deserializeDataAt:*(char**)data ofObjCType:type atCursor:cursor context:callback]; /* Save the *data from destruction */ [addr retain]; break; } case _C_CHR: case _C_UCHR: { [self deserializeBytes:data length:sizeof(unsigned char) atCursor:cursor]; break; } case _C_SHT: case _C_USHT: { unsigned short ns; [self deserializeBytes:&ns length:sizeof(unsigned short) atCursor:cursor]; *(unsigned short*)data = network_short_to_host (ns); break; } case _C_INT: case _C_UINT: { unsigned int ni; [self deserializeBytes:&ni length:sizeof(unsigned int) atCursor:cursor]; *(unsigned int*)data = network_int_to_host (ni); break; } case _C_LNG: case _C_ULNG: { unsigned int nl; [self deserializeBytes:&nl length:sizeof(unsigned long) atCursor:cursor]; *(unsigned long*)data = network_long_to_host (nl); break; } case _C_FLT: { network_float nf; [self deserializeBytes:&nf length:sizeof(float) atCursor:cursor]; *(float*)data = network_float_to_host (nf); break; } case _C_DBL: { network_double nd; [self deserializeBytes:&nd length:sizeof(double) atCursor:cursor]; *(double*)data = network_double_to_host (nd); break; } default: THROW([[UnknownTypeException alloc] initForType:type]); } } - (int)deserializeIntAtCursor:(unsigned int*)cursor { unsigned int ni, result; [self deserializeBytes:&ni length:sizeof(unsigned int) atCursor:cursor]; result = network_int_to_host (ni); return result; } - (int)deserializeIntAtIndex:(unsigned int)index { unsigned int ni, result; [self deserializeBytes:&ni length:sizeof(unsigned int) atCursor:&index]; result = network_int_to_host (ni); return result; } - (void)deserializeInts:(int*)intBuffer count:(unsigned int)numInts atCursor:(unsigned int*)cursor { int i; [self deserializeBytes:&intBuffer length:numInts * sizeof(unsigned int) atCursor:cursor]; for (i = 0; i < numInts; i++) intBuffer[i] = network_int_to_host (intBuffer[i]); } - (void)deserializeInts:(int*)intBuffer count:(unsigned int)numInts atIndex:(unsigned int)index { int i; [self deserializeBytes:&intBuffer length:numInts * sizeof(int) atCursor:&index]; for (i = 0; i < numInts; i++) intBuffer[i] = network_int_to_host (intBuffer[i]); } - (Class)classForCoder { return [NSData class]; } - (void)encodeWithCoder:(NSCoder*)aCoder { const char* bytes = [self bytes]; unsigned int length = [self length]; [aCoder encodeValueOfObjCType:@encode(unsigned int) at:&length]; [aCoder encodeArrayOfObjCType:@encode(char) count:length at:&bytes]; } - (id)initWithCoder:(NSCoder*)aDecoder { char* bytes; unsigned int length; [aDecoder decodeValueOfObjCType:@encode(unsigned int) at:&length]; bytes = Malloc (length); [aDecoder decodeArrayOfObjCType:@encode(char) count:length at:bytes]; [self initWithBytesNoCopy:bytes length:length]; return self; } @end /* NSData */ @implementation NSMutableData + (id)allocWithZone:(NSZone*)zone { return NSAllocateObject(((self == [NSMutableData class]) ? [NSConcreteMutableData class] : self), 0, zone); } + (id)dataWithCapacity:(unsigned int)numBytes { return [[[self allocWithZone:NSDefaultMallocZone()] initWithCapacity:numBytes] autorelease]; } + (id)dataWithLength:(unsigned int)length { return [[[self allocWithZone:NSDefaultMallocZone()] initWithLength:length] autorelease]; } - (id)initWithCapacity:(unsigned int)capacity { [self subclassResponsibility:_cmd]; return nil; } - (id)initWithLength:(unsigned int)length { [self subclassResponsibility:_cmd]; return nil; } - (NSData*)subdataWithRange:(NSRange)aRange { char* buffer = Malloc(aRange.length); [self getBytes:buffer range:aRange]; return [[NSData alloc] initWithBytesNoCopy:buffer length:aRange.length]; } - (void)increaseLengthBy:(unsigned int)extraLength { [self subclassResponsibility:_cmd]; } - (void*)mutableBytes { [self subclassResponsibility:_cmd]; return NULL; } - (void)setLength:(unsigned int)length { [self subclassResponsibility:_cmd]; } - (void)appendBytes:(const void*)_bytes length:(unsigned int)_length { [self subclassResponsibility:_cmd]; } - (void)appendData:(NSData*)other { [self appendBytes:[other bytes] length:[other length]]; } - (void)replaceBytesInRange:(NSRange)aRange withBytes:(const void*)bytes { unsigned int length = [self length]; if(aRange.location > length || aRange.length > length || aRange.location + aRange.length > length) THROW([RangeException new]); else { char* mBytes = [self mutableBytes]; memcpy(mBytes + aRange.location, bytes, aRange.length); } } - (void)setData:(NSData*)aData { [self setLength:[aData length]]; [self replaceBytesInRange:NSMakeRange(0, [self length]) withBytes:[aData bytes]]; } - (void)resetBytesInRange:(NSRange)aRange { unsigned int length = [self length]; if(aRange.location > length || aRange.length > length || aRange.location + aRange.length > length) THROW([RangeException new]); else { char* mBytes = [self mutableBytes]; memset(mBytes + aRange.location, 0, aRange.length); } } - (void)serializeAlignedBytesLength:(unsigned int)length { } - (void)serializeDataAt:(const void*)data ofObjCType:(const char*)type context:(id <NSObjCTypeSerializationCallBack>)callback { if(!data || !type) return; switch(*type) { case _C_ID: { [callback serializeObjectAt:(id*)data ofObjCType:type intoData:self]; break; } case _C_CHARPTR: { int len; if(!*(void**)data) { [self serializeInt:-1]; return; } len = Strlen(*(void**)data); [self serializeInt:len]; [self appendBytes:*(void**)data length:len]; break; } case _C_ARY_B: { int i, offset, itemSize, count = Atoi(type + 1); const char* itemType = type; while(isdigit(*++itemType)); itemSize = objc_sizeof_type(itemType); for(i = offset = 0; i < count; i++, offset += itemSize) [self serializeDataAt:(char*)data + offset ofObjCType:itemType context:callback]; break; } case _C_STRUCT_B: { int offset = 0; int align, rem; while(*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */ while(1) { [self serializeDataAt:((char*)data) + offset ofObjCType:type context:callback]; offset += objc_sizeof_type(type); type = objc_skip_typespec(type); if(*type != _C_STRUCT_E) { align = objc_alignof_type(type); if((rem = offset % align)) offset += align - rem; } else break; } break; } case _C_PTR: [self serializeDataAt:*(char**)data ofObjCType:++type context:callback]; break; case _C_CHR: case _C_UCHR: [self appendBytes:data length:sizeof(unsigned char)]; break; case _C_SHT: case _C_USHT: { unsigned short ns = host_short_to_network (*(unsigned short*)data); [self appendBytes:&ns length:sizeof(unsigned short)]; break; } case _C_INT: case _C_UINT: { unsigned int ni = host_int_to_network (*(unsigned int*)data); [self appendBytes:&ni length:sizeof(unsigned int)]; break; } case _C_LNG: case _C_ULNG: { unsigned long nl = host_long_to_network (*(unsigned long*)data); [self appendBytes:&nl length:sizeof(unsigned long)]; break; } case _C_FLT: { network_float nf = host_float_to_network (*(float*)data); [self appendBytes:&nf length:sizeof(float)]; break; } case _C_DBL: { network_double nd = host_double_to_network (*(double*)data); [self appendBytes:&nd length:sizeof(double)]; break; } default: THROW([[UnknownTypeException alloc] initForType:type]); } } - (void)serializeInt:(int)value { unsigned int ni = host_int_to_network (value); [self appendBytes:&ni length:sizeof(unsigned int)]; } - (void)serializeInt:(int)value atIndex:(unsigned int)index { unsigned int ni = host_int_to_network (value); NSRange range = { index, sizeof(int) }; [self replaceBytesInRange:range withBytes:&ni]; } - (void)serializeInts:(int*)intBuffer count:(unsigned int)numInts { int i; SEL selector = @selector (serializeInt:); IMP imp = [self methodForSelector:selector]; for (i = 0; i < numInts; i++) (*imp)(self, selector, intBuffer[i]); } - (void)serializeInts:(int*)intBuffer count:(unsigned int)numInts atIndex:(unsigned int)index { int i; SEL selector = @selector (serializeInt:atIndex:); IMP imp = [self methodForSelector:selector]; for (i = 0; i < numInts; i++) (*imp)(self, selector, intBuffer[i], index++); } - (Class)classForCoder { return [NSMutableData class]; } @end /* NSMutableData */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.