Reputation: 305
I have a value stored as as a uint64_t (the maximum needed for the app). I need to do integer math with the number, but the size depends on what the user specifies.
I need a function that takes a uint64_t and a bit-size that casts to the proper primitive and returns it.
@interface EAEIntegerValue : NSObject <NSCopying>
@property uint64_t storageObject;
- (id)init;
- (id)initWithValue:(uint64_t)value;
- (uint64_t)getValueUInt64t;
- (int64_t)getValueInt64t;
- (uint32_t)getValueUInt32t;
- (int32_t)getValueInt32t;
- (uint16_t)getValueUInt16t;
- (int16_t)getValueInt16t;
- (uint8_t)getValueUInt8t;
- (int8_t)getValueInt8t;
// This is the function I am concerned with:
- (id)getValue:(uint8_t)bitSize;
@end
Pseudocode for getValue:
- (id)getValue:(uint8_t)bitSize {
if (bitSize == 8) return [self getValueInt8t];
if (bitSize == 16) return [self getValueInt16t];
if (bitSize == 32) return [self getValueInt32t];
if (bitSize == 64) return [self getValueInt64t];
//...Unsigned...
@throw...
}
I am getting a complaint about returning a primitive as id. I understand why I get the error, but I don't see a way to wrap the value as an object and retain the dynamic nature of the function. It is necessary to retain the correct size integer, and the function which calls this should not be expected to do this manually. The calling function might look like this:
- (EAEIntegerValue*)doMath:(int)bitSize {
// It is important for this to be done in the correct bit size mode.
uint64_t value = [val1 getValue:bitSize] / [val1 getValue:bitSize];
// I don't care that it is casted back to a 64-bit int later.
return [[EAEIntegerValue alloc] initWithValue:value];
}
Worst case, I can do this (hopefully you can appreciate why I'm trying to avoid it. I have 20-30 of these functions):
- (EAEIntegerValue*)doMath:(int)bitSize :(bool)isSigned {
uint64_t value;
if (bitSize == 8 && isSigned) value = [val1 getValueInt8t] / [val1 getValueInt8t];
else if (bitSize == 8) value = [val1 getValueUInt8t] / [val1 getValueUInt8t];
else if (bitSize == 16 && isSigned) value = [val1 getValueInt16t] / [val1 getValueInt16t];
else if (bitSize == 16) value = [val1 getValueUInt16t] / [val1 getValueUInt16t];
else if (bitSize == 32 && isSigned) value = [val1 getValueInt32t] / [val1 getValueInt32t];
else if (bitSize == 32) value = [val1 getValueUInt32t] / [val1 getValueUInt32t];
else if (bitSize == 64 && isSigned) value = [val1 getValueInt64t] / [val1 getValueInt64t];
else if (bitSize == 64) value = [val1 getValueUInt64t] / [val1 getValueUInt64t];
return [[EAEIntegerValue alloc] initWithValue:value];
}
Wow, that's a lot of code and a lot of unit tests!
Upvotes: 2
Views: 109
Reputation: 1338
You might be able to do this with pre-processor macros. It would be a long macro to check the values being passed in, but you could do something along the lines of...
#define getValue(obj, bitSize) ((bitSize) == 8 ? [obj getValueInt8t] : (...))
Upvotes: 1