File: HFByteArray.m

package info (click to toggle)
sameboy 1.0.2%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 10,528 kB
  • sloc: ansic: 29,948; objc: 22,249; asm: 1,424; pascal: 1,373; makefile: 1,065; xml: 111
file content (218 lines) | stat: -rw-r--r-- 7,614 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//
//  HFByteArray.m
//  HexFiend_2
//
//  Copyright 2007 ridiculous_fish. All rights reserved.
//

#import <HexFiend/HFByteArray_Internal.h>
#import <HexFiend/HFFullMemoryByteSlice.h>


@implementation HFByteArray

- (instancetype)init {
    if ([self class] == [HFByteArray class]) {
        [NSException raise:NSInvalidArgumentException format:@"init sent to HFByteArray, but HFByteArray is an abstract class.  Instantiate one of its subclasses instead, like HFBTreeByteArray."];
    }
    return [super init];
}

- (instancetype)initWithByteSlice:(HFByteSlice *)slice {
    if(!(self = [self init])) return nil;
    self = [self init];
    [self insertByteSlice:slice inRange:HFRangeMake(0, 0)];
    return self;
}

- (instancetype)initWithByteArray:(HFByteArray *)array {
    if(!(self = [self init])) return nil;
    NSEnumerator *e = [array byteSliceEnumerator];
    HFByteSlice *slice;
    while((slice = [e nextObject])) {
        [self insertByteSlice:slice inRange:HFRangeMake([self length], 0)];
    }
    return self;
}

- (NSArray *)byteSlices { UNIMPLEMENTED(); }
- (unsigned long long)length { UNIMPLEMENTED(); }
- (void)copyBytes:(unsigned char *)dst range:(HFRange)range { USE(dst); USE(range); UNIMPLEMENTED_VOID(); }
- (void)insertByteSlice:(HFByteSlice *)slice inRange:(HFRange)lrange { USE(slice); USE(lrange); UNIMPLEMENTED_VOID(); }

- (NSEnumerator *)byteSliceEnumerator {
    return [[self byteSlices] objectEnumerator];
}

- (HFByteSlice *)sliceContainingByteAtIndex:(unsigned long long)offset beginningOffset:(unsigned long long *)actualOffset {
    HFByteSlice *slice;
    unsigned long long current = 0;
    NSEnumerator *enumer = [self byteSliceEnumerator];
    while ((slice = [enumer nextObject])) {
        unsigned long long sum = HFSum([slice length], current);
        if (sum > offset) break;
        current = sum;
    }
    if (actualOffset) *actualOffset = current;
    return slice;
}

- (void)insertByteArray:(HFByteArray*)array inRange:(HFRange)lrange {
    REQUIRE_NOT_NULL(array);
    HFASSERT(HFRangeIsSubrangeOfRange(lrange, HFRangeMake(0, [self length])));
#ifndef NDEBUG
    unsigned long long expectedLength = [self length] - lrange.length + [array length];
#endif
    [self incrementGenerationOrRaiseIfLockedForSelector:_cmd];
    NSEnumerator *sliceEnumerator;
    HFByteSlice *byteSlice;
    if (array == self) {
        /* Guard against self insertion */
        sliceEnumerator = [[array byteSlices] objectEnumerator];
    }
    else {
        sliceEnumerator = [array byteSliceEnumerator];
    }
    while ((byteSlice = [sliceEnumerator nextObject])) {
        [self insertByteSlice:byteSlice inRange:lrange];
        lrange.location += [byteSlice length];
        lrange.length = 0;
    }
    /* If there were no slices, delete the lrange */
    if (lrange.length > 0) {
        [self deleteBytesInRange:lrange];
    }
#ifndef NDEBUG
    HFASSERT(expectedLength == [self length]);
#endif
}

- (HFByteArray *)subarrayWithRange:(HFRange)range { USE(range); UNIMPLEMENTED(); }

- (id)mutableCopyWithZone:(NSZone *)zone {
    USE(zone);
    return [[self subarrayWithRange:HFRangeMake(0, [self length])] retain];
}

- (id)copyWithZone:(NSZone *)zone {
    USE(zone);
    return [[self subarrayWithRange:HFRangeMake(0, [self length])] retain];
}

- (void)deleteBytesInRange:(HFRange)lrange {
    [self incrementGenerationOrRaiseIfLockedForSelector:_cmd];
    HFByteSlice* slice = [[HFFullMemoryByteSlice alloc] initWithData:[NSData data]];
    [self insertByteSlice:slice inRange:lrange];
    [slice release];
}

- (BOOL)isEqual:v {
    REQUIRE_NOT_NULL(v);
    if (self == v) return YES;
    else if (! [v isKindOfClass:[HFByteArray class]]) return NO;
    else {
        HFByteArray* obj = v;
        unsigned long long length = [self length];
        if (length != [obj length]) return NO;
        unsigned long long offset;
        unsigned char buffer1[1024];
        unsigned char buffer2[sizeof buffer1 / sizeof *buffer1];
        for (offset = 0; offset < length; offset += sizeof buffer1) {
            size_t amountToGrab = sizeof buffer1;
            if (amountToGrab > length - offset) amountToGrab = ll2l(length - offset);
            [self copyBytes:buffer1 range:HFRangeMake(offset, amountToGrab)];
            [obj copyBytes:buffer2 range:HFRangeMake(offset, amountToGrab)];
            if (memcmp(buffer1, buffer2, amountToGrab)) return NO;
        }
    }
    return YES;
}

- (unsigned long long)indexOfBytesEqualToBytes:(HFByteArray *)findBytes inRange:(HFRange)range searchingForwards:(BOOL)forwards trackingProgress:(id)progressTracker {
    UNIMPLEMENTED();
}

- (BOOL)_debugIsEqual:(HFByteArray *)v {
    REQUIRE_NOT_NULL(v);
    if (! [v isKindOfClass:[HFByteArray class]]) return NO;
    HFByteArray* obj = v;
    unsigned long long length = [self length];
    if (length != [obj length]) {
        printf("Lengths differ: %llu versus %llu\n", length, [obj length]);
        abort();
        return NO;
    }
    
    unsigned long long offset;
    unsigned char buffer1[1024];
    unsigned char buffer2[sizeof buffer1 / sizeof *buffer1];
    for (offset = 0; offset < length; offset += sizeof buffer1) {
        memset(buffer1, 0, sizeof buffer1);
        memset(buffer2, 0, sizeof buffer2);
        size_t amountToGrab = sizeof buffer1;
        if (amountToGrab > length - offset) amountToGrab = ll2l(length - offset);
        [self copyBytes:buffer1 range:HFRangeMake(offset, amountToGrab)];
        [obj copyBytes:buffer2 range:HFRangeMake(offset, amountToGrab)];
        size_t i;
        for (i=0; i < amountToGrab; i++) {
            if (buffer1[i] != buffer2[i]) {
                printf("Inconsistency found at %llu (%02x versus %02x)\n", i + offset, buffer1[i], buffer2[i]);
                abort();
                return NO;
            }
        }
    }
    return YES;
}

- (NSData *)_debugData {
    NSMutableData *data = [NSMutableData dataWithLength:(NSUInteger)[self length]];
    [self copyBytes:[data mutableBytes] range:HFRangeMake(0, [self length])];
    return data;
}

- (BOOL)_debugIsEqualToData:(NSData *)val {
    REQUIRE_NOT_NULL(val);
    HFByteArray *byteArray = [[NSClassFromString(@"HFFullMemoryByteArray") alloc] init];
    HFByteSlice *byteSlice = [[HFFullMemoryByteSlice alloc] initWithData:val];
    [byteArray insertByteSlice:byteSlice inRange:HFRangeMake(0, 0)];
    [byteSlice release];
    BOOL result = [self _debugIsEqual:byteArray];
    [byteArray release];
    return result;
}

- (void)incrementChangeLockCounter {
    [self willChangeValueForKey:@"changesAreLocked"];
    if (HFAtomicIncrement(&changeLockCounter, NO) == 0) {
        [NSException raise:NSInvalidArgumentException format:@"change lock counter overflow for %@", self];
    }
    [self didChangeValueForKey:@"changesAreLocked"];
}

- (void)decrementChangeLockCounter {
    [self willChangeValueForKey:@"changesAreLocked"];
    if (HFAtomicDecrement(&changeLockCounter, NO) == NSUIntegerMax) {
        [NSException raise:NSInvalidArgumentException format:@"change lock counter underflow for %@", self];
    }
    [self didChangeValueForKey:@"changesAreLocked"];
}

- (BOOL)changesAreLocked {
    return !! changeLockCounter;
}

- (NSUInteger)changeGenerationCount {
    return changeGenerationCount;
}

- (void)incrementGenerationOrRaiseIfLockedForSelector:(SEL)sel {
    if (changeLockCounter) {
        [NSException raise:NSInvalidArgumentException format:@"Selector %@ sent to a locked byte array %@", NSStringFromSelector(sel), self];
    }
    else {
        HFAtomicIncrement(&changeGenerationCount, YES);
    }
}

@end