ResKnife/Cocoa/Plug-Ins/Template Editor/ElementPSTR.m

167 lines
6.5 KiB
Objective-C

#import "ElementPSTR.h"
// implements PSTR, OSTR, ESTR, BSTR, WSTR, LSTR, CSTR, OCST, ECST, CHAR, TNAM
@implementation ElementPSTR
- (id)initForType:(NSString *)t withLabel:(NSString *)l
{
self = [super initForType:t withLabel:l];
if(!self) return nil;
value = [@"" retain];
if ([t isEqualToString:@"PSTR"] ||
[t isEqualToString:@"BSTR"]) { _lengthBytes = 1; _maxLength = UINT8_MAX; _minLength = 0; _terminatingByte = NO; _pad = kNoPadding; _alignment = 0; }
else if([t isEqualToString:@"WSTR"]) { _lengthBytes = 2; _maxLength = UINT16_MAX; _minLength = 0; _terminatingByte = NO; _pad = kNoPadding; _alignment = 0; }
else if([t isEqualToString:@"LSTR"]) { _lengthBytes = 4; _maxLength = UINT32_MAX; _minLength = 0; _terminatingByte = NO; _pad = kNoPadding; _alignment = 0; }
else if([t isEqualToString:@"OSTR"]) { _lengthBytes = 1; _maxLength = UINT8_MAX-1; _minLength = 0; _terminatingByte = NO; _pad = kPadToOddLength; _alignment = 0; }
else if([t isEqualToString:@"ESTR"]) { _lengthBytes = 1; _maxLength = UINT8_MAX; _minLength = 0; _terminatingByte = NO; _pad = kPadToEvenLength; _alignment = 0; }
else if([t isEqualToString:@"CSTR"]) { _lengthBytes = 0; _maxLength = 0; _minLength = 0; _terminatingByte = YES; _pad = kNoPadding; _alignment = 0; }
else if([t isEqualToString:@"OCST"]) { _lengthBytes = 0; _maxLength = 0; _minLength = 0; _terminatingByte = YES; _pad = kPadToOddLength; _alignment = 0; }
else if([t isEqualToString:@"ECST"]) { _lengthBytes = 0; _maxLength = 0; _minLength = 0; _terminatingByte = YES; _pad = kPadToEvenLength; _alignment = 0; }
else if([t isEqualToString:@"CHAR"]) { _lengthBytes = 0; _maxLength = 1; _minLength = 1; _terminatingByte = NO; _pad = kNoPadding; _alignment = 0; }
else if([t isEqualToString:@"TNAM"]) { _lengthBytes = 0; _maxLength = 4; _minLength = 4; _terminatingByte = NO; _pad = kNoPadding; _alignment = 0; }
// temp until keyed values are implemented
else if([t isEqualToString:@"KCHR"]) { _lengthBytes = 0; _maxLength = 1; _minLength = 1; _terminatingByte = NO; _pad = kNoPadding; _alignment = 0; }
else if([t isEqualToString:@"KTYP"]) { _lengthBytes = 0; _maxLength = 4; _minLength = 4; _terminatingByte = NO; _pad = kNoPadding; _alignment = 0; }
return self;
}
- (void)dealloc
{
[value release];
[super dealloc];
}
- (id)copyWithZone:(NSZone*)zone
{
ElementPSTR *element = [super copyWithZone:zone];
[element setStringValue:value];
[element setMaxLength:_maxLength];
[element setMinLength:_minLength];
[element setPad:_pad];
[element setTerminatingByte:_terminatingByte];
[element setLengthBytes:_lengthBytes];
[element setAlignment:_alignment];
return element;
}
- (void)readDataFrom:(TemplateStream *)stream
{
// get string length
UInt32 length = 0;
if(_lengthBytes > 0)
{
[stream readAmount:_lengthBytes toBuffer:&length];
#if __BIG_ENDIAN__
length >>= (4 - _lengthBytes) << 3;
#else
#warning FIXME: This probably doesn't work for WSTR and LSTR on intel machines
#endif
}
if(_terminatingByte)
length += [stream bytesToNull];
if(_maxLength && length > _maxLength) length = _maxLength;
if(length < _minLength) length = _minLength;
// read string
void *buffer = malloc(length);
if(_minLength) memset(buffer, 0, _minLength);
[stream readAmount:length toBuffer:buffer];
if([NSString instancesRespondToSelector:@selector(initWithBytesNoCopy:length:encoding:freeWhenDone:)]) // 10.3
[self setStringValue:[[[NSString alloc] initWithBytesNoCopy:buffer length:length encoding:NSMacOSRomanStringEncoding freeWhenDone:YES] autorelease]];
else
{
[self setStringValue:[[[NSString alloc] initWithBytes:buffer length:length encoding:NSMacOSRomanStringEncoding] autorelease]];
free(buffer);
}
// skip over empty bytes
if(_terminatingByte) [stream advanceAmount:1 pad:NO];
if(_pad == kPadToOddLength && (length + _terminatingByte ? 1:0) % 2 == 0) [stream advanceAmount:1 pad:NO];
if(_pad == kPadToEvenLength && (length + _terminatingByte ? 1:0) % 2 == 1) [stream advanceAmount:1 pad:NO];
// alignment unhandled here
}
- (unsigned int)sizeOnDisk
{
UInt32 length;
if([value respondsToSelector:@selector(lengthOfBytesUsingEncoding:)]) // 10.4
length = [value lengthOfBytesUsingEncoding:NSMacOSRomanStringEncoding];
else length = [value cStringLength];
if(_maxLength && length > _maxLength) length = _maxLength;
if(length < _minLength) length = _minLength;
length += _lengthBytes + (_terminatingByte? 1:0);
if(_pad == kPadToOddLength && length % 2 == 0) length++;
if(_pad == kPadToEvenLength && length % 2 == 1) length++;
// don't know how to deal with alignment here
return length;
}
- (void)writeDataTo:(TemplateStream *)stream
{
// write string
UInt32 length = [value length], writeLength;
if(_maxLength && length > _maxLength) length = _maxLength;
#if __BIG_ENDIAN__
writeLength = length << ((4 - _lengthBytes) << 3);
#else
#warning FIXME: This probably doesn't work for WSTR and LSTR on intel machines
#endif
if(_lengthBytes)
[stream writeAmount:_lengthBytes fromBuffer:&writeLength];
if ([value canBeConvertedToEncoding:NSMacOSRomanStringEncoding])
{
const void *buffer = NULL;
if([value respondsToSelector:@selector(cStringUsingEncoding:)]) // 10.4
buffer = [value cStringUsingEncoding:NSMacOSRomanStringEncoding];
else
{
NSData *data = [value dataUsingEncoding:NSMacOSRomanStringEncoding];
buffer = [data bytes];
}
if(buffer) [stream writeAmount:length fromBuffer:buffer];
else [stream advanceAmount:length pad:YES];
}
else
{
#warning FIXME: This code should display a warning saying that the string in the PSTR is not MacOSRoman
}
// pad to minimum length with spaces
if(length < _minLength)
{
SInt32 padAmount = _minLength - length;
while(padAmount > 0)
{
UInt32 spaces = ' ';
[stream writeAmount:(padAmount < 4)? padAmount:4 fromBuffer:&spaces];
length += (padAmount < 4)? padAmount:4;
padAmount -= 4;
}
}
if(_terminatingByte) [stream advanceAmount:1 pad:YES];
if(_pad == kPadToOddLength && (length + _lengthBytes + (_terminatingByte? 1:0)) % 2 == 0) [stream advanceAmount:1 pad:YES];
if(_pad == kPadToEvenLength && (length + _lengthBytes + (_terminatingByte? 1:0)) % 2 == 1) [stream advanceAmount:1 pad:YES];
}
- (NSString *)stringValue
{
return value;
}
- (void)setStringValue:(NSString *)str
{
id old = value;
value = [str copy];
[old release];
}
- (void)setMaxLength:(UInt32)v { _maxLength = v; }
- (void)setMinLength:(UInt32)v { _minLength = v; }
- (void)setPad:(enum StringPadding)v { _pad = v; }
- (void)setTerminatingByte:(BOOL)v { _terminatingByte = v; }
- (void)setLengthBytes:(int)v { _lengthBytes = v; }
- (void)setAlignment:(int)v { _alignment = v; }
@end