diff --git a/Objective-C/BitArray.h b/Objective-C/BitArray.h new file mode 100644 index 0000000..e1c116a --- /dev/null +++ b/Objective-C/BitArray.h @@ -0,0 +1,55 @@ +// +// BitArray.h +// oneIP +// +// Created by Bret Deasy on 7/16/13. +// Copyright (c) 2013 Bret Deasy. All rights reserved. +// + +#import + +typedef enum { + Add, + Subtract +} Operation; + +typedef enum { + Lesser, + Greater, + Equal +} Comparison; + +@interface BitArray : NSObject + +@property (nonatomic) CFMutableBitVectorRef bitVector; + + +- (id)init; +- (id)initWithString:(NSString *)bitString; +- (id)initWithBitVector:(CFMutableBitVectorRef)_bitVector; +- (id)initWithInteger:(int)value; +- (id)initWithCount:(CFIndex)count; +- (id)initWithBitArray:(BitArray *)bitArray; +- (BitArray *)bitArrayByANDingWithBitArray:(BitArray *)andBitArray; +- (BitArray *)bitArrayByORingWithBitArray:(BitArray *)orBitArray; +- (BitArray *)bitArrayByNOTingBitArray; +- (int)count; +- (void)setCount:(CFIndex)count; +- (void)equalizeBitVector:(BitArray *)bitArray; +- (void)padToCapacity:(int)capacity; +- (BitArray *)bitArrayByAppendingBitArray:(BitArray *)bitArray; +- (BitArray *)bitArrayByAddingInteger:(int)value; +- (BitArray *)bitArrayBySubtractingInteger:(int)value; +- (BitArray *)performMathOperation:(Operation)op withInt:(int)value; +- (BOOL)equalToBitArray:(BitArray *)bitArray; +- (BOOL)greaterThanOrEqualToBitArray:(BitArray *)bitArray; +- (BOOL)lessThanOrEqualToBitArray:(BitArray *)bitArray; +- (BOOL)greaterThanBitArray:(BitArray *)bitArray; +- (BOOL)lessThanBitArray:(BitArray *)bitArray; +- (CFBit)bitAtIndex:(CFIndex)index; +- (int)bitsInRange:(CFRange)range; +- (void)setBitAtIndex:(CFIndex)index toValue:(CFBit)bit; +- (void)insertBitArray:(BitArray *)bitArray atIndex:(CFIndex)index; +- (NSString *)stringValue; + +@end diff --git a/Objective-C/BitArray.m b/Objective-C/BitArray.m new file mode 100644 index 0000000..0aaea2e --- /dev/null +++ b/Objective-C/BitArray.m @@ -0,0 +1,560 @@ +// +// BitArray.m +// oneIP +// +// Created by Bret Deasy on 7/16/13. +// Copyright (c) 2013 Bret Deasy. All rights reserved. +// + +#import "BitArray.h" + +@implementation BitArray + +@synthesize bitVector; + +/** + Initialize with empty bitVector + **/ +- (id)init +{ + self = [super init]; + + if (self) + { + bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 0); + } + + return self; +} + +/** + Returns a BitArray object initialized by copying the bits from another given BitArray. + **/ +- (id)initWithBitArray:(BitArray *)bitArray +{ + return [self initWithBitVector:[bitArray bitVector]]; +} + +/** + Initialize with capacity-sized bitVector containing all zeroes. + **/ +- (id)initWithCount:(CFIndex)count +{ + self = [super init]; + + if (self) + { + bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 0); + [self setCount:count]; + } + + return self; +} + +/** + Initializer from a given string of 0s and/or 1s. + */ +- (id)initWithString:(NSString *)bitString +{ + self = [super init]; + + if (self) + { + int length = [bitString length]; + CFMutableBitVectorRef _bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, length); + CFBitVectorSetCount(_bitVector, length); + + for (int i = 0; i < length; i++) + { + int bitAtIndex = [bitString characterAtIndex:i] - 48; + CFBitVectorSetBitAtIndex(_bitVector, i, bitAtIndex); + } + + bitVector = CFBitVectorCreateMutableCopy(kCFAllocatorDefault, length, _bitVector); + + CFRelease(_bitVector); + } + + return self; +} + +/** + Initializer from a given CFBitVectorRef. + */ +- (id)initWithBitVector:(CFMutableBitVectorRef)_bitVector +{ + self = [super init]; + + if (self) + { + bitVector = CFBitVectorCreateMutableCopy(kCFAllocatorDefault, CFBitVectorGetCount(_bitVector), _bitVector); + } + + return self; +} + +/** + Initialize from a given Int. Integer must be 0 or greater. + **/ +- (id)initWithInteger:(int)value +{ + self = [super init]; + + if (self) + { + int capacity; + + if (value <= 0) + { + bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 1); + CFBitVectorSetCount(bitVector, 1); + } else { + capacity = floor(log2(value))+1; + bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); + CFBitVectorSetCount(bitVector, capacity); + + for (int i = capacity - 1; i >= 0; i--) + { + CFBitVectorSetBitAtIndex(bitVector, i, (value & 1)); + value>>=1; + } + } + } + + return self; +} + +/** + Returns the AND of the receiver's bitVector and the passed BitArray's bitVector. + */ +- (BitArray *)bitArrayByANDingWithBitArray:(BitArray *)andBitArray +{ + CFBit aBit; + CFBit bBit; + CFBit resultBit; + + [self equalizeBitVector:andBitArray]; + int capacity = [self count]; + CFMutableBitVectorRef resultBitArray = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); + CFBitVectorSetCount(resultBitArray, capacity); + + for (int i = 0; i < capacity; i++) + { + aBit = CFBitVectorGetBitAtIndex(bitVector, i); + bBit = CFBitVectorGetBitAtIndex([andBitArray bitVector], i); + + resultBit = aBit & bBit; + CFBitVectorSetBitAtIndex(resultBitArray, i, resultBit); + } + + BitArray *retBitArray = [[BitArray alloc] initWithBitVector:resultBitArray]; + CFRelease(resultBitArray); + + return retBitArray; + +} + +/** + Returns the OR of the receiver's bitVector with the passed BitArray's bitVector. + **/ +- (BitArray *)bitArrayByORingWithBitArray:(BitArray *)orBitArray +{ + CFBit aBit; + CFBit bBit; + CFBit resultBit; + + [self equalizeBitVector:orBitArray]; + int capacity = [self count]; + + CFMutableBitVectorRef resultBitArray = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); + CFBitVectorSetCount(resultBitArray, capacity); + + for (int i = 0; i < capacity; i++) + { + aBit = CFBitVectorGetBitAtIndex(bitVector, i); + bBit = CFBitVectorGetBitAtIndex([orBitArray bitVector], i); + + resultBit = aBit | bBit; + CFBitVectorSetBitAtIndex(resultBitArray, i, resultBit); + } + + BitArray *retBitArray = [[BitArray alloc] initWithBitVector:resultBitArray]; + CFRelease(resultBitArray); + + return retBitArray; +} + +/** + Returns the NOT of the receiver's bitVector. + **/ +- (BitArray *)bitArrayByNOTingBitArray +{ + CFBit bit; + CFBit resultBit; + + int capacity = [self count]; + + CFMutableBitVectorRef resultBitArray = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); + CFBitVectorSetCount(resultBitArray, capacity); + + for (int i = 0; i < capacity; i++) + { + bit = CFBitVectorGetBitAtIndex(bitVector, i); + resultBit = !bit; + + CFBitVectorSetBitAtIndex(resultBitArray, i, resultBit); + } + + BitArray *retBitArray = [[BitArray alloc] initWithBitVector:resultBitArray]; + CFRelease(resultBitArray); + + return retBitArray; +} + +/** + Returns the number of bits in the receiver's bitVector. + **/ +- (int)count +{ + return CFBitVectorGetCount(bitVector); +} + +/** + Sets the size of the receiver's bitVector + **/ +- (void)setCount:(CFIndex)count +{ + CFBitVectorSetCount(bitVector, count); +} +/** + Makes the receiver's bitVector and the parameter's of equal size + **/ +- (void)equalizeBitVector:(BitArray *)bitArray +{ + int bitVectorCapacity = [self count]; + int compareBitVectorCapacity = [bitArray count]; + + if (bitVectorCapacity < compareBitVectorCapacity) + { + [self padToCapacity:compareBitVectorCapacity]; + } else if (bitVectorCapacity > compareBitVectorCapacity) { + [bitArray padToCapacity:bitVectorCapacity]; + } +} + +/** + Pads 0s to the left to make the bitVector's capacity match the parameter. + */ +- (void)padToCapacity:(int)capacity +{ + int difference = capacity - [self count]; + + if (difference <= 0) + { + return; + } + + + CFMutableBitVectorRef tempVector = CFBitVectorCreateMutable(kCFAllocatorDefault, difference); + CFBitVectorSetCount(tempVector, difference); + + BitArray *insertBitArray = [[BitArray alloc] initWithBitVector:tempVector]; + + [self insertBitArray:insertBitArray atIndex:0]; +// for (int i = difference; i < capacity; difference++) +// { +// CFBitVectorSetBitAtIndex(tempVector, i, CFBitVectorGetBitAtIndex(bitVector, currIndex)); +// currIndex++; +// } +// +// bitVector = CFBitVectorCreateMutableCopy(kCFAllocatorDefault, capacity, tempVector); +// CFRelease(tempVector); +} + +/** + Returns a new BitArray made by appending a given BitArray to the receiver. + **/ +- (BitArray *)bitArrayByAppendingBitArray:(BitArray *)bitArray +{ +// return [[[BitArray alloc] initWithBitArray:self] bitArrayByAppendingBitArray:bitArray]; + BitArray *retBitArray = [[BitArray alloc] initWithBitArray:self]; + [retBitArray insertBitArray:bitArray atIndex:[self count]]; + + return retBitArray; +} + +/** + Returns BitArray containing the bitVector of the value parameter added to the receiver's bitVector. + **/ +- (BitArray *)bitArrayByAddingInteger:(int)value +{ + return [self performMathOperation:Add withInt:value]; +} + +/** + Returns BitArray containing the bitVector of the value parameter subtracted from the receiver's bitVector. + **/ +- (BitArray *)bitArrayBySubtractingInteger:(int)value +{ + return [self performMathOperation:Subtract withInt:value]; +} + +/** + Returns BitArray represented after performing the selected math operation with the given value on the receiver. + **/ +- (BitArray *)performMathOperation:(Operation)op withInt:(int)value +{ + int capacity = [self count]; + + CFMutableBitVectorRef bits = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); + CFBitVectorSetCount(bits, capacity); + + CFMutableBitVectorRef result = CFBitVectorCreateMutable(kCFAllocatorDefault, 2); + CFBitVectorSetCount(result, 2); + + BitArray *valueBitArray = [[BitArray alloc] initWithInteger:value]; + [self equalizeBitVector:valueBitArray]; + + for (int i = capacity - 1; i >= 0; i--) + { + int aBit = CFBitVectorGetBitAtIndex(bitVector, i); + int bBit = CFBitVectorGetBitAtIndex([valueBitArray bitVector], i); + int cBit = CFBitVectorGetBitAtIndex(result, 1); + + if (op == Add) + { + result = [self fullAdderWithaBit:aBit + bBit:bBit + cBit:cBit]; + } else if (op == Subtract) { + result = [self fullSubtractorWithaBit:aBit + bBit:bBit + cBit:cBit]; + } + + CFBitVectorSetBitAtIndex(bits, i, CFBitVectorGetBitAtIndex(result, 0)); + } + + BitArray *retBitArray = [[BitArray alloc] initWithBitVector:bits]; + CFRelease(result); + CFRelease(bits); + + return retBitArray; +} + +/** + Returns the sum bit and carry bit after performing an addition operation. + **/ +- (CFMutableBitVectorRef)fullAdderWithaBit:(BOOL)aBit bBit:(BOOL)bBit cBit:(BOOL)cBit +{ + //bit0 = sum bit + //bit1 = carry bit + BOOL bit0 = (aBit ^ bBit) ^ cBit; + BOOL bit1 = (aBit & bBit) | (bBit & cBit) | (aBit & cBit); + + CFMutableBitVectorRef retBitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 2); + CFBitVectorSetCount(retBitVector, 2); + CFBitVectorSetBitAtIndex(retBitVector, 0, bit0); + CFBitVectorSetBitAtIndex(retBitVector, 1, bit1); + + return retBitVector; +} + +/** + Returns the sum bit and carry bit after performing an subtraction operation. + **/ +- (CFMutableBitVectorRef)fullSubtractorWithaBit:(BOOL)aBit bBit:(BOOL)bBit cBit:(BOOL)cBit +{ + //bit0 = sum bit + //bit1 = carry bit + BOOL bit0 = aBit ^ bBit ^ cBit; + BOOL bit1 = (cBit & (aBit ^ bBit)) | (!aBit & bBit); + + CFMutableBitVectorRef retBitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 2); + CFBitVectorSetCount(retBitVector, 2); + CFBitVectorSetBitAtIndex(retBitVector, 0, bit0); + CFBitVectorSetBitAtIndex(retBitVector, 1, bit1); + + return retBitVector; +} + +/** + Returns true if the receiver's bitVector is equal to that of the parameter's. + **/ +- (BOOL)equalToBitArray:(BitArray *)bitArray +{ + CFBit bit; + CFBit bitCompare; + + for (int i = 0; i < [self count]; i++) + { + bit = CFBitVectorGetBitAtIndex(bitVector, i); + bitCompare = CFBitVectorGetBitAtIndex([bitArray bitVector], i); + + if (bit != bitCompare) + { + return NO; + } + } + + return YES; +} + + +/** + Returns true if the receiver's bitVector is greater than or equal to that of the parameter's. + **/ +- (BOOL)greaterThanOrEqualToBitArray:(BitArray *)bitArray +{ + return ([self greaterThanBitArray:bitArray] || [self equalToBitArray:bitArray]); +} + +/** + Returns true if the receiver's bitVector is less than or equal to that of the parameter's. + **/ +- (BOOL)lessThanOrEqualToBitArray:(BitArray *)bitArray +{ + return ([self lessThanBitArray:bitArray] || [self equalToBitArray:bitArray]); +} + +/** + Returns true if the receiver's bitVector is greater than that of the parameter. + **/ +- (BOOL)greaterThanBitArray:(BitArray *)bitArray +{ + [self equalizeBitVector:bitArray]; + + CFBit bit; + CFBit compareBit; + + for (int i = [self count] - 1; i >= 0; i--) + { + bit = [self bitAtIndex:i]; + compareBit = [bitArray bitAtIndex:i]; + + if (bit > compareBit) + { + return YES; + } else if (bit < compareBit) { + return NO; + } + } + + return NO; +} + +/** + Returns true of the receiver's bitVector is less than that of the parameter's + **/ +- (BOOL)lessThanBitArray:(BitArray *)bitArray +{ + [self equalizeBitVector:bitArray]; + + CFBit bit; + CFBit compareBit; + + for (int i = [self count]; i > 0; i--) + { + bit = [self bitAtIndex:i]; + compareBit = [bitArray bitAtIndex:i]; + + if (bit < compareBit) + { + return YES; + } else if (bit > compareBit) { + return NO; + } + } + + return NO; +} + +/** + Returns the bit from the receiver's bitVector at the given index. + **/ +- (CFBit)bitAtIndex:(CFIndex)index +{ + return CFBitVectorGetBitAtIndex(bitVector, index); +} + +/** + Sets the bit of the receiver's bitVector at the given index to the given value. + **/ +- (void)setBitAtIndex:(CFIndex)index toValue:(CFBit)bit +{ + CFBitVectorSetBitAtIndex(bitVector, index, bit); +} + +/** + Inserts the given bitArray into the receiver at the given index. Receiver will expand as needed. + **/ +- (void)insertBitArray:(BitArray *)bitArray atIndex:(CFIndex)index +{ + int count = [self count]; + int newCount = count + [bitArray count]; + int difference = [bitArray count]; + int currIndex = 0; + + [self setCount:newCount]; + + for (int i = count-1; i >= index; i--) + { + [self setBitAtIndex:i+difference toValue:[self bitAtIndex:i]]; + } + + for (int i = index; i < index+difference; i++) + { + [self setBitAtIndex:i toValue:[bitArray bitAtIndex:currIndex]]; + currIndex++; + } +// if ([bitArray count] + index >= [self count]) +// { +// [self setCount:[bitArray count] + index + 1]; +// } +// for (int i = 0; i < [bitArray count]; i++) +// { +// CFBitVectorSetBitAtIndex(bitVector, index+i, [bitArray bitAtIndex:i]); +// } +} + +/** + Returns the int value of the bits in the given range of the receiver's bitVector. + **/ +- (int)bitsInRange:(CFRange)range +{ + int quotient = floor(range.length / 8); + Byte *bytes = malloc(sizeof(Byte) * quotient); + unsigned int byteValue = 0; + + CFBitVectorGetBits(bitVector, range, bytes); + memcpy(&byteValue, bytes, quotient); + //ensure big-endianness + if (quotient > 1) + { + byteValue = htons(byteValue); + } + + return byteValue; +} + +/** + Returns the string representation of the receiver. + **/ +- (NSString *)stringValue +{ + NSString *retString = @""; + + for (int i = 0; i < [self count]; i++) + { + retString = [retString stringByAppendingFormat:@"%ld", [self bitAtIndex:i]]; + } + + return retString; +} + +-(void)dealloc +{ + CFRelease(bitVector); +} + +@end diff --git a/Objective-C/OIPAddress.h b/Objective-C/OIPAddress.h new file mode 100644 index 0000000..5487a4c --- /dev/null +++ b/Objective-C/OIPAddress.h @@ -0,0 +1,42 @@ +// +// OIPAddress.h +// oneIP +// +// Created by Bret Deasy on 7/17/13. +// Copyright (c) 2013 Bret Deasy. All rights reserved. +// + +#import +#import "BitArray.h" +#import "OIPUtility.h" + +typedef enum { + kIPv4, + kIPv6 +} IPVersion; + +@interface OIPAddress : NSObject +{ + @public + IPVersion ipVersion; + @private + BitArray *cidr; + BitArray *ipAddress; +} + +- (id)init; +- (id)initWithString:(NSString *)ipAddr; +- (BOOL)isValidIPv4:(NSString *)ipAddrString; +- (BOOL)isValidIPv6:(NSString *)ipAddrString; +- (IPVersion)ipVersion; +- (NSString *)subnetMask; +- (BitArray *)ipAddressAsBitArray; +- (NSString *)ipAddress; +- (NSString *)firstAddress; +- (NSString *)lastAddress; +- (NSString *)networkAddress; +- (NSString *)broadcastAddress; +- (NSArray *)ipRange; +- (BOOL)isAddressInRange:(OIPAddress *)address; + +@end diff --git a/Objective-C/OIPAddress.m b/Objective-C/OIPAddress.m new file mode 100644 index 0000000..cb21e89 --- /dev/null +++ b/Objective-C/OIPAddress.m @@ -0,0 +1,537 @@ +// +// OIPAddress.m +// oneIP +// +// Created by Bret Deasy on 7/17/13. +// Copyright (c) 2013 Bret Deasy. All rights reserved. +// + +#import "OIPAddress.h" + +#define INVALID_IP_ERROR_NAME @"InvalidIPAddressError" +#define INVALID_IP_ERROR_REASON @"The IP address appears to be invalid." +#define INVALID_CIDR_ERROR_NAME @"InvalidCIDRError" +#define INVALID_CIDR_ERROR_REASON @"The CIDR appears to be invalid." + +@implementation OIPAddress + +/** + Returns a OIPAddress with IP address 192.168.1.1 and CIDR 24 + **/ +- (id)init +{ + return [self initWithString:@"192.168.1.1/24"]; +} + +/** + Returns a OIPAddress with specified IP address and CIDR + **/ +- (id)initWithString:(NSString *)ipAddr +{ + self = [super init]; + + if (self) + { + cidr = [[BitArray alloc] init]; + ipAddress = [[BitArray alloc] init]; + + if ([self isValidIPv4:ipAddr]) + { + [self setIPv4:ipAddr]; + } else if ([self isValidIPv6:ipAddr]) { + [self setIPv6:ipAddr]; + } else { + @throw [NSException exceptionWithName:INVALID_IP_ERROR_NAME + reason:INVALID_IP_ERROR_REASON + userInfo:nil]; + } + } + + return self; +} + +/** + Returns true if ipAddrString is a valid IPv4 address. + **/ +- (BOOL)isValidIPv4:(NSString *)ipAddrString +{ + NSArray *ipAddrArray; + + if ([ipAddrString rangeOfString:@"/"].location != NSNotFound) + { + ipAddrArray = [ipAddrString componentsSeparatedByString:@"/"]; + + if ([ipAddrArray count] == 2) + { + int _cidr = [[ipAddrArray objectAtIndex:1] intValue]; + + if (_cidr < 0 || _cidr > 32) + { + return NO; + } + } else if ([ipAddrArray count] > 2) { + return NO; + } + + ipAddrArray = [[ipAddrArray objectAtIndex:0] componentsSeparatedByString:@"."]; + + } else { + ipAddrArray = [ipAddrString componentsSeparatedByString:@"."]; + } + + for (int i = 0; i < [ipAddrArray count]; i++) + { + int oct = [[ipAddrArray objectAtIndex:i] intValue]; + + if (oct < 0 || oct > 255) + { + return NO; + } + } + + return YES; +} + +/** + Returns true if ipAddrString is a valid IPv6 address. + **/ +- (BOOL)isValidIPv6:(NSString *)ipAddrString +{ + NSArray *ipAddrArray; + + if ([ipAddrString rangeOfString:@":"].location == NSNotFound) + { + return NO; + } + if ([ipAddrString rangeOfString:@"/"].location != NSNotFound) + { + ipAddrArray = [ipAddrString componentsSeparatedByString:@"/"]; + + if ([ipAddrArray count] == 2) + { + int _cidr = [[ipAddrArray objectAtIndex:1] intValue]; + + if (_cidr < 0 || _cidr > 128) + { + return NO; + } + } else { + return NO; + } + + ipAddrArray = [[ipAddrArray objectAtIndex:0] componentsSeparatedByString:@":"]; + + } else { + ipAddrArray = [ipAddrString componentsSeparatedByString:@":"]; + } + + for (int i = 0; i < [ipAddrArray count]; i++) + { + int oct = [OIPUtility hexStringToDecimal:[ipAddrArray objectAtIndex:i]]; + + if (oct < 0 || oct > 0xffff) + { + return NO; + } + } + + return YES; +} + +/** + Sets the ipAddress, cidr, and ipVersion for IPv6 address. + **/ +- (void)setIPv6:(NSString *)ipAddrString +{ + NSArray *ipAddrArray; + NSArray *newIPAddrArray; + + if ([ipAddrString rangeOfString:@"/"].location != NSNotFound) + { + ipAddrArray = [ipAddrString componentsSeparatedByString:@"/"]; + + [self setCIDR:[[ipAddrArray objectAtIndex:1] intValue] withNumberOfBits:128]; + + ipAddrArray = [[ipAddrArray objectAtIndex:0] componentsSeparatedByString:@":"]; + } else { + ipAddrArray = [ipAddrString componentsSeparatedByString:@":"]; + } + + newIPAddrArray = [self fillIPv6Address:[ipAddrArray componentsJoinedByString:@":"]]; + + for (int i = 0; i < [ipAddrArray count]; i++) + { + CFIndex index = i * 16; + int oct = [OIPUtility hexStringToDecimal:[ipAddrArray objectAtIndex:i]]; + BitArray *octBitArray = [[BitArray alloc] initWithInteger:oct]; + [octBitArray padToCapacity:16]; + + [ipAddress insertBitArray:octBitArray atIndex:index]; + } + + ipVersion = kIPv6; +} + +/** + Sets the ipAddress, cidr, and ipVersion for IPv4 address. +**/ +- (void)setIPv4:(NSString *)ipAddrString +{ + NSArray *ipAddrArray; + + if ([ipAddrString rangeOfString:@"/"].location != NSNotFound) + { + NSArray *ipCIDRArray = [ipAddrString componentsSeparatedByString:@"/"]; + ipAddrArray = [[ipCIDRArray objectAtIndex:0] componentsSeparatedByString:@"."]; + + [self setCIDR:[[ipCIDRArray objectAtIndex:1] intValue] withNumberOfBits:32]; + } else { + ipAddrArray = [ipAddrString componentsSeparatedByString:@"."]; + } + +// [ipAddress setCount:32]; + + for (int i = 0; i < [ipAddrArray count]; i++) + { + CFIndex index = i * 8; + BitArray *octBitArray = [[BitArray alloc] initWithInteger:[[ipAddrArray objectAtIndex:i] intValue]]; + [octBitArray padToCapacity:8]; + + [ipAddress insertBitArray:octBitArray atIndex:index]; + } + + ipVersion = kIPv4; +} + + + +/** + Returns the IP Version of OIPAddress. + **/ +- (IPVersion)ipVersion +{ + return ipVersion; +} + +/** + Sets cidr + **/ +- (void)setCIDR:(int)value withNumberOfBits:(int)numOfBits +{ + [cidr setCount:numOfBits]; + CFBit bit; + + for (int i = 0; i < numOfBits; i++) + { + bit = (i < value); + [cidr setBitAtIndex:i toValue:bit]; + } +} + +/** + Returns the Subnet Mask of the receiver's IP Address + **/ +- (NSString *)subnetMask +{ + return [self calculateAddress:cidr]; +} + +/** + Returns the readable IPv4 address from the BitArray passed to the method. + **/ +- (NSString *)calculateIPv4Address:(BitArray *)bitArray +{ + int byteValue = 0; + CFRange range; + + NSString *format = (ipVersion == kIPv4) ? @"%d." : @"%x:"; + + NSMutableString *ipString = [NSMutableString stringWithString:@""]; + + for (int i = 0; i < [bitArray count] / 8; i++) + { + range = CFRangeMake(i *8, 8); + + byteValue = [bitArray bitsInRange:range]; + + [ipString appendFormat:format, byteValue]; + } + + return ipString; +} + +/** + Returns the readable IPv6 address from the BitArray passed to the method. + **/ +- (NSString *)calculateIPv6Address:(BitArray *)bitArray +{ + int byteValue = 0; + CFRange range; + + NSString *format = (ipVersion == kIPv4) ? @"%d." : @"%x:"; + + NSMutableString *ipString = [NSMutableString stringWithString:@""]; + + for (int i = 0; i < [bitArray count] / 8; i++) + { + range = CFRangeMake(i * 16, 16); + + byteValue = [bitArray bitsInRange:range]; + + [ipString appendString:[NSString stringWithFormat:format, byteValue]]; + } + + return ipString; +} + +/** + Returns the readable address from the given BitArray. + **/ +//Consolidates the previous calculate(IPv4/IPv6)Address: method +- (NSString *)calculateAddress:(BitArray *)bitArray +{ + CFRange range; + int byteValue; + NSString *format = (ipVersion == kIPv4) ? @"%d." : @"%x:"; + NSMutableString *ipString = [NSMutableString stringWithString:@""]; + + int bitSize = (ipVersion == kIPv4) ? 8 : 16; + + for (int i = 0; i < [bitArray count] / bitSize; i++) + { + + range = CFRangeMake(i * bitSize, bitSize); + + byteValue = [bitArray bitsInRange:range]; + + [ipString appendFormat:format, byteValue]; + } + + return [ipString stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:(ipVersion == kIPv4) ? @"." : @":"]];; +} + +/** + Returns the receiver's IP address as a BitArray + **/ +- (BitArray *)ipAddressAsBitArray +{ + return ipAddress; +} + +/** + Returns the receiver's readable IP address + **/ +- (NSString *)ipAddress +{ + return [self calculateAddress:ipAddress]; +} + +/** + Returns the first address in the receiver's IP range + **/ +- (NSString *)firstAddress +{ + return [self calculateAddress:[self calculateFirstAddress]]; +} + +/** + Calculates the first IP address in the receiver's IP range + **/ +- (BitArray *)calculateFirstAddress +{ + //ipv4 formula => (ip & cidr) + 1 + //ipv6 formula => (ip & cidr) + BitArray *retBitArray = [ipAddress bitArrayByANDingWithBitArray:cidr]; + + if (ipVersion == kIPv4) + { + retBitArray = [retBitArray bitArrayByAddingInteger:1]; + } + + return retBitArray; +} +/** + Calculates the first IPv4 address in the receiver's IP range + **/ +- (BitArray *)calculateIPv4FirstAddress +{ + //formula => (ip & cidr) + 1 + BitArray *retBitArray = [ipAddress bitArrayByANDingWithBitArray:cidr]; + retBitArray = [retBitArray bitArrayByAddingInteger:1]; + + return retBitArray; +} + +/** + Returns the last address in the receiver's IP range + **/ +- (NSString *)lastAddress +{ + return [self calculateAddress:[self calculateLastAddress]]; +} + +/** + Calculates the last IP address in the receiver's IP range + **/ +- (BitArray *)calculateLastAddress +{ + //formula ipv4 => (ip | !cidr) - 1 + //formula ipv6 => (ip | !cidr) + BitArray *cidrNOT = [cidr bitArrayByNOTingBitArray]; + BitArray *retBitArray = [ipAddress bitArrayByORingWithBitArray:cidrNOT]; + + if (ipVersion == kIPv4) + { + retBitArray = [retBitArray bitArrayBySubtractingInteger:1]; + } + + return retBitArray; +} + +/** + Calculates the last IPv4 address in the receiver's IP range + **/ +- (BitArray *)calculateIPv4LastAddress +{ + //formula => (ip | cidr) - 1 + BitArray *cidrNOT = [cidr bitArrayByNOTingBitArray]; + BitArray *retBitArray = [ipAddress bitArrayByORingWithBitArray:cidrNOT]; + retBitArray = [retBitArray bitArrayBySubtractingInteger:1]; + + return retBitArray; +} + +/** + Returns the receiver's network address + **/ +- (NSString *)networkAddress +{ + if (ipVersion == kIPv4) + { + return [self calculateAddress:[self calculateNetworkAddress]]; + } + + return nil; +} + +/** + Calculates the receiver's network address + **/ +- (BitArray *)calculateNetworkAddress +{ + //formula = ip & cidr + return [ipAddress bitArrayByANDingWithBitArray:cidr]; +} + +/** + Returns the receiver's broadcast address + **/ +- (NSString *)broadcastAddress +{ + if (ipVersion == kIPv4) + { + return [self calculateAddress:[self calculateBroadcastAddress]]; + } + + return nil; +} + +/** + Calculates the receiver's broadcast address + **/ +- (BitArray *)calculateBroadcastAddress +{ + BitArray *cidrNot = [cidr bitArrayByNOTingBitArray]; + BitArray *retBitArray = [ipAddress bitArrayByORingWithBitArray:cidrNot]; + + return retBitArray; +} + +/** + Returns the receiver's IP range + **/ +- (NSArray *)ipv4Range +{ + NSMutableArray *ipAddrArray = [[NSMutableArray alloc] init]; + + BitArray *currentIP = [self calculateIPv4FirstAddress]; + BitArray *lastIP = [self calculateIPv4LastAddress]; + + while ([currentIP lessThanOrEqualToBitArray:lastIP]) + { + [ipAddrArray addObject:[self calculateAddress:currentIP]]; + currentIP = [currentIP bitArrayByAddingInteger:1]; + } + + return ipAddrArray; +} + +/** + Returns the receiver's IP range + **/ +- (NSArray *)ipRange +{ + NSMutableArray *ipAddrArray = [[NSMutableArray alloc] init]; + + BitArray *currentIP = [self calculateFirstAddress]; + BitArray *lastIP = [self calculateLastAddress]; + + while ([currentIP lessThanOrEqualToBitArray:lastIP]) + { + [ipAddrArray addObject:[self calculateAddress:currentIP]]; + currentIP = [currentIP bitArrayByAddingInteger:1]; + } + + return ipAddrArray; +} + +/** + Returns true if the given IP address is in the receiver's IP range + **/ +- (BOOL)isAddressInRange:(OIPAddress *)address +{ + BitArray *_ipAddress = [address ipAddressAsBitArray]; + BitArray *_lastAddress = [self calculateLastAddress]; + BitArray *_firstAddress = [self calculateFirstAddress]; + + return ([_ipAddress greaterThanOrEqualToBitArray:_firstAddress] && [_ipAddress lessThanOrEqualToBitArray:_lastAddress]); +} + + + +/** + Returns IPv6 Array with values from shorthanded IPv6 filled in. + e.g. ffe12d::1 -> ffe12d:0000:0000:0000:0000:0000:0000:1 + **/ + +//method might need some fixing +- (NSArray *)fillIPv6Address:(NSString *)ipAddrString +{ + NSMutableArray *sectionsArray = [[NSMutableArray alloc] init]; + NSArray *ipAddrArray; + int numberOfSections = 0; + + if ([ipAddrString rangeOfString:@"::"].location != NSNotFound) + { + ipAddrArray = [ipAddrString componentsSeparatedByString:@":"]; + + for (int i = 0; i < [ipAddrArray count]; i++) + { + if ([[ipAddrArray objectAtIndex:i] isEqual:@""]) + { + numberOfSections++; + [sectionsArray addObject:@"0000"]; + } + } + + [ipAddrString stringByReplacingOccurrencesOfString:@"::" + withString:[NSString stringWithFormat:@"%@", [sectionsArray componentsJoinedByString:@":"]]]; + [ipAddrString stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":"]]; + } + + return [ipAddrString componentsSeparatedByString:@":"]; +} + + + +@end diff --git a/Objective-C/OIPUtility.h b/Objective-C/OIPUtility.h new file mode 100644 index 0000000..e200239 --- /dev/null +++ b/Objective-C/OIPUtility.h @@ -0,0 +1,15 @@ +// +// OIPUtility.h +// oneIP +// +// Created by Bret Deasy on 7/17/13. +// Copyright (c) 2013 Bret Deasy. All rights reserved. +// + +#import + +@interface OIPUtility : NSObject + ++ (int)hexStringToDecimal:(NSString *)hexString; + +@end diff --git a/Objective-C/OIPUtility.m b/Objective-C/OIPUtility.m new file mode 100644 index 0000000..34eab66 --- /dev/null +++ b/Objective-C/OIPUtility.m @@ -0,0 +1,28 @@ +// +// OIPUtility.m +// oneIP +// +// Created by Bret Deasy on 7/17/13. +// Copyright (c) 2013 Bret Deasy. All rights reserved. +// + +#import "OIPUtility.h" + +@implementation OIPUtility + +/** + Returns a string representing the decimal value of the hex string parameter. + **/ ++ (int)hexStringToDecimal:(NSString *)hexString +{ + unsigned result = 0; + NSScanner *scanner; + scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:0]; + [scanner scanHexInt:&result]; + + return result; +} + + +@end