tunnelkit/TunnelKit/Sources/Core/ZeroingData.m
2018-08-23 12:10:56 +02:00

261 lines
5.7 KiB
Objective-C

//
// ZeroingData.m
// TunnelKit
//
// Created by Davide De Rosa on 4/28/17.
// Copyright © 2018 London Trust Media. All rights reserved.
//
#import "ZeroingData.h"
#import "Allocation.h"
@interface ZeroingData () {
uint8_t *_bytes;
}
@end
@implementation ZeroingData
- (instancetype)init
{
return [self initWithBytes:NULL count:0];
}
- (instancetype)initWithCount:(NSInteger)count
{
if ((self = [super init])) {
_count = count;
_bytes = allocate_safely(count);
}
return self;
}
- (instancetype)initWithBytes:(const uint8_t *)bytes count:(NSInteger)count
{
// NSParameterAssert(bytes);
if ((self = [super init])) {
_count = count;
_bytes = allocate_safely(count);
memcpy(_bytes, bytes, count);
}
return self;
}
- (instancetype)initWithBytesNoCopy:(uint8_t *)bytes count:(NSInteger)count
{
NSParameterAssert(bytes);
if ((self = [super init])) {
_count = count;
_bytes = bytes;
}
return self;
}
- (instancetype)initWithUInt8:(uint8_t)uint8
{
if ((self = [super init])) {
_count = 1;
_bytes = allocate_safely(_count);
_bytes[0] = uint8;
}
return self;
}
- (instancetype)initWithUInt16:(uint16_t)uint16
{
if ((self = [super init])) {
_count = 2;
_bytes = allocate_safely(_count);
_bytes[0] = (uint16 & 0xff);
_bytes[1] = (uint16 >> 8);
}
return self;
}
- (instancetype)initWithData:(NSData *)data
{
return [self initWithData:data offset:0 count:data.length];
}
- (instancetype)initWithData:(NSData *)data offset:(NSInteger)offset count:(NSInteger)count
{
NSParameterAssert(data);
// NSParameterAssert(offset <= data.length);
NSParameterAssert(offset + count <= data.length);
if ((self = [super init])) {
_count = count;
_bytes = allocate_safely(count);
memcpy(_bytes, data.bytes + offset, count);
}
return self;
}
- (instancetype)initWithString:(NSString *)string nullTerminated:(BOOL)nullTerminated
{
NSParameterAssert(string);
if ((self = [super init])) {
const char *stringBytes = [string cStringUsingEncoding:NSASCIIStringEncoding];
const int stringLength = (int)string.length;
_count = stringLength + (nullTerminated ? 1 : 0);
_bytes = allocate_safely(_count);
memcpy(_bytes, stringBytes, stringLength);
if (nullTerminated) {
_bytes[stringLength] = '\0';
}
}
return self;
}
- (void)dealloc
{
bzero(_bytes, _count);
free(_bytes);
}
- (const uint8_t *)bytes
{
return _bytes;
}
- (uint8_t *)mutableBytes
{
return _bytes;
}
- (void)appendData:(ZeroingData *)other
{
NSParameterAssert(other);
const NSInteger newCount = _count + other.count;
uint8_t *newBytes = allocate_safely(newCount);
memcpy(newBytes, _bytes, _count);
memcpy(newBytes + _count, other.bytes, other.count);
bzero(_bytes, _count);
free(_bytes);
_bytes = newBytes;
_count = newCount;
}
- (void)truncateToSize:(NSInteger)size
{
NSParameterAssert(size <= _count);
uint8_t *newBytes = allocate_safely(size);
memcpy(newBytes, _bytes, size);
bzero(_bytes, _count);
free(_bytes);
_bytes = newBytes;
_count = size;
}
- (void)removeUntilOffset:(NSInteger)until
{
NSParameterAssert(until <= _count);
const NSInteger newCount = _count - until;
uint8_t *newBytes = allocate_safely(newCount);
memcpy(newBytes, _bytes + until, newCount);
bzero(_bytes, _count);
free(_bytes);
_bytes = newBytes;
_count = newCount;
}
- (void)zero
{
bzero(_bytes, _count);
}
- (ZeroingData *)appendingData:(ZeroingData *)other
{
NSParameterAssert(other);
const NSInteger newCount = _count + other.count;
uint8_t *newBytes = allocate_safely(newCount);
memcpy(newBytes, _bytes, _count);
memcpy(newBytes + _count, other.bytes, other.count);
return [[ZeroingData alloc] initWithBytesNoCopy:newBytes count:newCount];
}
- (ZeroingData *)withOffset:(NSInteger)offset count:(NSInteger)count
{
// NSParameterAssert(offset <= _count);
NSParameterAssert(offset + count <= _count);
uint8_t *newBytes = allocate_safely(count);
memcpy(newBytes, _bytes + offset, count);
return [[ZeroingData alloc] initWithBytesNoCopy:newBytes count:count];
}
- (uint16_t)UInt16ValueFromOffset:(NSInteger)from
{
NSParameterAssert(from + 2 <= _count);
uint16_t value = 0;
value |= _bytes[from];
value |= _bytes[from + 1] << 8;
return value;
}
- (uint16_t)networkUInt16ValueFromOffset:(NSInteger)from
{
NSParameterAssert(from + 2 <= _count);
uint16_t value = 0;
value |= _bytes[from];
value |= _bytes[from + 1] << 8;
return CFSwapInt16BigToHost(value);
}
- (NSString *)nullTerminatedStringFromOffset:(NSInteger)from
{
NSParameterAssert(from <= _count);
NSInteger nullOffset = NSNotFound;
for (NSInteger i = from; i < _count; ++i) {
if (_bytes[i] == 0) {
nullOffset = i;
break;
}
}
if (nullOffset == NSNotFound) {
return nil;
}
const NSInteger stringLength = nullOffset - from;
return [[NSString alloc] initWithBytes:_bytes length:stringLength encoding:NSASCIIStringEncoding];
}
- (BOOL)isEqualToData:(NSData *)data
{
NSParameterAssert(data);
NSParameterAssert(data.length <= _count);
return !memcmp(_bytes, data.bytes, _count);
}
- (NSString *)toHex
{
const NSUInteger capacity = _count * 2;
NSMutableString *hexString = [[NSMutableString alloc] initWithCapacity:capacity];
for (int i = 0; i < _count; ++i) {
[hexString appendFormat:@"%02x", _bytes[i]];
}
return hexString;
}
@end