Created
August 3, 2010 23:00
-
-
Save PsychoH13/507321 to your computer and use it in GitHub Desktop.
A class enabling NSData object scanning and a category enabling NSMutableData writing.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
NSMutableData+PSYDataWriter.h | |
Created by Remy "Psy" Demarest on 22/01/2012. | |
Copyright (c) 2012. Remy "Psy" Demarest | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in | |
all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
THE SOFTWARE. | |
*/ | |
#import <Foundation/Foundation.h> | |
@interface NSMutableData (PSYDataWriter) | |
- (void)appendInt8:(uint8_t)value; | |
- (void)appendLittleEndianInt16:(uint16_t)value; | |
- (void)appendLittleEndianInt32:(uint32_t)value; | |
- (void)appendLittleEndianInt64:(uint64_t)value; | |
- (void)appendBigEndianInt16:(uint16_t)value; | |
- (void)appendBigEndianInt32:(uint32_t)value; | |
- (void)appendBigEndianInt64:(uint64_t)value; | |
// These methods append floating point values depending on the architecture of your processor | |
// they're usually not appropriate for network transmission | |
- (void)appendFloat:(float)value; | |
- (void)appendDouble:(double)value; | |
- (void)appendSwappedFloat:(float)value; | |
- (void)appendSwappedDouble:(double)value; | |
- (void)appendString:(NSString *)value usingEncoding:(NSStringEncoding)encoding; | |
- (void)replaceBytesInRange:(NSRange)range withData:(NSData *)value; | |
- (void)replaceBytesInRange:(NSRange)range withInt8:(uint8_t)value; | |
- (void)replaceBytesInRange:(NSRange)range withLittleEndianInt16:(uint16_t)value; | |
- (void)replaceBytesInRange:(NSRange)range withLittleEndianInt32:(uint32_t)value; | |
- (void)replaceBytesInRange:(NSRange)range withLittleEndianInt64:(uint64_t)value; | |
- (void)replaceBytesInRange:(NSRange)range withBigEndianInt16:(uint16_t)value; | |
- (void)replaceBytesInRange:(NSRange)range withBigEndianInt32:(uint32_t)value; | |
- (void)replaceBytesInRange:(NSRange)range withBigEndianInt64:(uint64_t)value; | |
// These methods append floating point values depending on the architecture of your processor | |
// they're usually not appropriate for network transmission | |
- (void)replaceBytesInRange:(NSRange)range withFloat:(float)value; | |
- (void)replaceBytesInRange:(NSRange)range withDouble:(double)value; | |
- (void)replaceBytesInRange:(NSRange)range withSwappedFloat:(float)value; | |
- (void)replaceBytesInRange:(NSRange)range withSwappedDouble:(double)value; | |
- (void)replaceBytesInRange:(NSRange)range withString:(NSString *)value usingEncoding:(NSStringEncoding)encoding; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
NSMutableData+PSYDataWriter.m | |
Created by Remy "Psy" Demarest on 22/01/2012. | |
Copyright (c) 2012. Remy "Psy" Demarest | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in | |
all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
THE SOFTWARE. | |
*/ | |
#import "NSMutableData+PSYDataWriter.h" | |
#define APPEND_METHOD(endian, size) \ | |
- (void)append ## endian ## EndianInt ## size:(uint ## size ## _t)value \ | |
{ \ | |
value = CFSwapInt ## size ## HostTo ## endian(value); \ | |
[self appendBytes:&value length:sizeof(value)]; \ | |
} | |
#define REPLACE_METHOD(endian, size) \ | |
- (void)replaceBytesInRange:(NSRange)range with ## endian ## EndianInt ## size:(uint ## size ## _t)value; \ | |
{ \ | |
value = CFSwapInt ## size ## HostTo ## endian(value); \ | |
[self replaceBytesInRange:range withBytes:&value length:sizeof(value)]; \ | |
} | |
@implementation NSMutableData (PSYDataWriter) | |
- (void)appendInt8:(uint8_t)value; | |
{ | |
[self appendBytes:&value length:sizeof(value)]; | |
} | |
APPEND_METHOD(Little, 16) | |
APPEND_METHOD(Little, 32) | |
APPEND_METHOD(Little, 64) | |
APPEND_METHOD(Big, 16) | |
APPEND_METHOD(Big, 32) | |
APPEND_METHOD(Big, 64) | |
- (void)appendFloat:(float)value; | |
{ | |
[self appendBytes:&value length:sizeof(value)]; | |
} | |
- (void)appendDouble:(double)value; | |
{ | |
[self appendBytes:&value length:sizeof(value)]; | |
} | |
- (void)appendSwappedFloat:(float)value; | |
{ | |
CFSwappedFloat32 v = CFConvertFloatHostToSwapped(value); | |
[self appendBytes:&v length:sizeof(value)]; | |
} | |
- (void)appendSwappedDouble:(double)value; | |
{ | |
CFSwappedFloat64 v = CFConvertDoubleHostToSwapped(value); | |
[self appendBytes:&v length:sizeof(value)]; | |
} | |
- (void)appendString:(NSString *)value usingEncoding:(NSStringEncoding)encoding; | |
{ | |
[self appendData:[value dataUsingEncoding:encoding]]; | |
} | |
- (void)replaceBytesInRange:(NSRange)range withData:(NSData *)value; | |
{ | |
[self replaceBytesInRange:range withBytes:[value bytes] length:[value length]]; | |
} | |
- (void)replaceBytesInRange:(NSRange)range withInt8:(uint8_t)value; | |
{ | |
[self replaceBytesInRange:range withBytes:&value length:sizeof(value)]; | |
} | |
REPLACE_METHOD(Little, 16) | |
REPLACE_METHOD(Little, 32) | |
REPLACE_METHOD(Little, 64) | |
REPLACE_METHOD(Big, 16) | |
REPLACE_METHOD(Big, 32) | |
REPLACE_METHOD(Big, 64) | |
- (void)replaceBytesInRange:(NSRange)range withFloat:(float)value; | |
{ | |
[self replaceBytesInRange:range withBytes:&value length:sizeof(value)]; | |
} | |
- (void)replaceBytesInRange:(NSRange)range withDouble:(double)value; | |
{ | |
[self replaceBytesInRange:range withBytes:&value length:sizeof(value)]; | |
} | |
- (void)replaceBytesInRange:(NSRange)range withSwappedFloat:(float)value; | |
{ | |
CFSwappedFloat32 v = CFConvertFloatHostToSwapped(value); | |
[self replaceBytesInRange:range withBytes:&v length:sizeof(value)]; | |
} | |
- (void)replaceBytesInRange:(NSRange)range withSwappedDouble:(double)value; | |
{ | |
CFSwappedFloat64 v = CFConvertDoubleHostToSwapped(value); | |
[self replaceBytesInRange:range withBytes:&v length:sizeof(value)]; | |
} | |
- (void)replaceBytesInRange:(NSRange)range withString:(NSString *)value usingEncoding:(NSStringEncoding)encoding; | |
{ | |
[self replaceBytesInRange:range withData:[value dataUsingEncoding:encoding]]; | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
PSYDataScanner.h | |
Created by Remy "Psy" Demarest on 20/07/2010. | |
Copyright (c) 2010 Remy "Psy" Demarest | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in | |
all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
THE SOFTWARE. | |
*/ | |
#import <Foundation/Foundation.h> | |
typedef enum _PSYDataScannerLocation | |
{ | |
PSYDataScannerLocationBegin, | |
PSYDataScannerLocationCurrent, | |
PSYDataScannerLocationEnd, | |
} PSYDataScannerLocation; | |
@interface PSYDataScanner : NSObject | |
{ | |
@private | |
NSData *_scannedData; | |
NSUInteger _dataLength; | |
NSUInteger _scanLocation; | |
} | |
+ (id)scannerWithData:(NSData *)dataToScan; | |
- (id)initWithData:(NSData *)dataToScan; | |
@property(readonly, copy, nonatomic) NSData *data; | |
@property(nonatomic) NSUInteger scanLocation; | |
- (BOOL)isAtEnd; | |
// Returns NO if the computed range is outside of the range of the data | |
- (BOOL)setScanLocation:(NSInteger)relativeLocation relativeTo:(PSYDataScannerLocation)startPoint; | |
- (BOOL)scanInt8:(uint8_t *)value; | |
- (BOOL)scanLittleEndianInt16:(uint16_t *)value; | |
- (BOOL)scanLittleEndianInt32:(uint32_t *)value; | |
- (BOOL)scanLittleEndianInt64:(uint64_t *)value; | |
- (BOOL)scanBigEndianInt16:(uint16_t *)value; | |
- (BOOL)scanBigEndianInt32:(uint32_t *)value; | |
- (BOOL)scanBigEndianInt64:(uint64_t *)value; | |
// These methods scan floating point values depending on the architecture of your processor | |
// they're usually not appropriate for network transmission | |
- (BOOL)scanFloat:(float *)value; | |
- (BOOL)scanDouble:(double *)value; | |
- (BOOL)scanSwappedFloat:(float *)value; | |
- (BOOL)scanSwappedDouble:(double *)value; | |
- (BOOL)scanData:(NSData **)data ofLength:(NSUInteger)length; | |
- (BOOL)scanData:(NSData *)data intoData:(NSData **)dataValue; | |
- (BOOL)scanUpToData:(NSData *)stopData intoData:(NSData **)dataValue; | |
- (BOOL)scanString:(NSString **)value ofLength:(NSUInteger)length usingEncoding:(NSStringEncoding)encoding; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
PSYDataScanner.m | |
Created by Remy "Psy" Demarest on 20/07/2010. | |
Copyright (c) 2010 Remy "Psy" Demarest | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in | |
all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
THE SOFTWARE. | |
*/ | |
#import "PSYDataScanner.h" | |
@implementation PSYDataScanner | |
@synthesize data = _scannedData, scanLocation = _scanLocation; | |
+ (id)scannerWithData:(NSData *)dataToScan | |
{ | |
return [[[self alloc] initWithData:dataToScan] autorelease]; | |
} | |
- (id)init | |
{ | |
[self release]; | |
return nil; | |
} | |
- (id)initWithData:(NSData *)dataToScan | |
{ | |
if((self = [super init])) | |
{ | |
_scannedData = [dataToScan copy]; | |
_dataLength = [_scannedData length]; | |
} | |
return self; | |
} | |
- (void)dealloc | |
{ | |
[_scannedData release]; | |
[super dealloc]; | |
} | |
- (BOOL)setScanLocation:(NSInteger)relativeLocation relativeTo:(PSYDataScannerLocation)startPoint; | |
{ | |
NSInteger computed = NSNotFound; | |
switch(startPoint) | |
{ | |
case PSYDataScannerLocationCurrent : computed = relativeLocation + [self scanLocation]; break; | |
case PSYDataScannerLocationEnd : computed = _dataLength - relativeLocation; break; | |
case PSYDataScannerLocationBegin : | |
default : computed = relativeLocation; break; | |
} | |
if(computed >= 0 && computed <= _dataLength) | |
{ | |
[self setScanLocation:computed]; | |
return YES; | |
} | |
return NO; | |
} | |
- (BOOL)isAtEnd; | |
{ | |
return _dataLength == _scanLocation; | |
} | |
- (BOOL)scanInt8:(uint8_t *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) [_scannedData getBytes:value range:NSMakeRange(_scanLocation, length)]; | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanLittleEndianInt16:(uint16_t *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) | |
{ | |
[_scannedData getBytes:value range:NSMakeRange(_scanLocation, length)]; | |
*value = CFSwapInt16LittleToHost(*value); | |
} | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanLittleEndianInt32:(uint32_t *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) | |
{ | |
[_scannedData getBytes:value range:NSMakeRange(_scanLocation, length)]; | |
*value = CFSwapInt32LittleToHost(*value); | |
} | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanLittleEndianInt64:(uint64_t *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) | |
{ | |
[_scannedData getBytes:value range:NSMakeRange(_scanLocation, length)]; | |
*value = CFSwapInt64LittleToHost(*value); | |
} | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanBigEndianInt16:(uint16_t *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) | |
{ | |
[_scannedData getBytes:value range:NSMakeRange(_scanLocation, length)]; | |
*value = CFSwapInt16BigToHost(*value); | |
} | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanBigEndianInt32:(uint32_t *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) | |
{ | |
[_scannedData getBytes:value range:NSMakeRange(_scanLocation, length)]; | |
*value = CFSwapInt32BigToHost(*value); | |
} | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanBigEndianInt64:(uint64_t *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) | |
{ | |
[_scannedData getBytes:value range:NSMakeRange(_scanLocation, length)]; | |
*value = CFSwapInt64BigToHost(*value); | |
} | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanFloat:(float *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) [_scannedData getBytes:value range:NSMakeRange(_scanLocation, length)]; | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanDouble:(double *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) [_scannedData getBytes:value range:NSMakeRange(_scanLocation, length)]; | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanSwappedFloat:(float *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) | |
{ | |
CFSwappedFloat32 scan; | |
[_scannedData getBytes:&scan range:NSMakeRange(_scanLocation, length)]; | |
*value = CFConvertFloatSwappedToHost(scan); | |
} | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanSwappedDouble:(double *)value | |
{ | |
NSUInteger length = sizeof(*value); | |
if(_scanLocation + length > _dataLength) return NO; | |
if(value != NULL) | |
{ | |
CFSwappedFloat64 scan; | |
[_scannedData getBytes:&scan range:NSMakeRange(_scanLocation, length)]; | |
*value = CFConvertDoubleSwappedToHost(scan); | |
} | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanData:(NSData **)data ofLength:(NSUInteger)length | |
{ | |
if(_scanLocation + length > _dataLength) return NO; | |
if(data != NULL) *data = [_scannedData subdataWithRange:NSMakeRange(_scanLocation, length)]; | |
_scanLocation += length; | |
return YES; | |
} | |
- (BOOL)scanData:(NSData *)data intoData:(NSData **)dataValue | |
{ | |
NSUInteger length = [data length]; | |
if(_scanLocation + length > _dataLength) return NO; | |
if(length > 0) | |
{ | |
NSData *subdata = [_scannedData subdataWithRange:NSMakeRange(_scanLocation, length)]; | |
if([subdata isEqualToData:data]) | |
{ | |
if(dataValue != NULL) *dataValue = subdata; | |
_scanLocation += length; | |
return YES; | |
} | |
} | |
return NO; | |
} | |
- (BOOL)scanUpToData:(NSData *)stopData intoData:(NSData **)dataValue | |
{ | |
NSUInteger length = [stopData length]; | |
NSRange scannedRange = NSMakeRange(_scanLocation, 0); | |
if(length == 0 || _scanLocation + length > _dataLength) | |
scannedRange.length = _dataLength - _scanLocation; | |
else | |
{ | |
const unsigned char *scannedBuffer = [_scannedData bytes]; | |
const unsigned char *stopBuffer = [stopData bytes]; | |
BOOL hasFoundData = NO; | |
for(NSUInteger scannedLoc = _scanLocation; scannedLoc + length <= _dataLength; scannedLoc++) | |
{ | |
hasFoundData = YES; | |
for(NSUInteger stopLoc = 0; stopLoc < length; stopLoc++) | |
if(scannedBuffer[scannedLoc + stopLoc] != stopBuffer[stopLoc]) | |
{ | |
hasFoundData = NO; | |
break; | |
} | |
if(hasFoundData) | |
{ | |
scannedRange.length = scannedLoc - _scanLocation; | |
break; | |
} | |
} | |
if(!hasFoundData) scannedRange.length = _dataLength - _scanLocation; | |
} | |
if(scannedRange.length == 0) return NO; | |
if(dataValue != NULL) *dataValue = [_scannedData subdataWithRange:scannedRange]; | |
_scanLocation = NSMaxRange(scannedRange); | |
return YES; | |
} | |
- (BOOL)scanString:(NSString **)value ofLength:(NSUInteger)length usingEncoding:(NSStringEncoding)encoding | |
{ | |
if(_scanLocation + length > _dataLength) return NO; | |
if(length > 0 && value != NULL) | |
{ | |
NSData *subdata = [_scannedData subdataWithRange:NSMakeRange(_scanLocation, length)]; | |
*value = [[[NSString alloc] initWithData:subdata encoding:encoding] autorelease]; | |
} | |
_scanLocation += length; | |
return YES; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment