SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
HexFiend/HFSharedMemoryByteSlice.m
1 //
2 // HFSharedMemoryByteSlice.m
3 // HexFiend_2
4 //
5 // Copyright 2008 ridiculous_fish. All rights reserved.
6 //
7
8 #import <HexFiend/HFByteSlice_Private.h>
9 #import <HexFiend/HFSharedMemoryByteSlice.h>
10
11 #define MAX_FAST_PATH_SIZE (1 << 13)
12
13 #define MAX_TAIL_LENGTH (sizeof ((HFSharedMemoryByteSlice *)NULL)->inlineTail / sizeof *((HFSharedMemoryByteSlice *)NULL)->inlineTail)
14
15 @implementation HFSharedMemoryByteSlice
16
17 - (instancetype)initWithUnsharedData:(NSData *)unsharedData {
18 self = [super init];
19 REQUIRE_NOT_NULL(unsharedData);
20 NSUInteger dataLength = [unsharedData length];
21 NSUInteger inlineAmount = MIN(dataLength, MAX_TAIL_LENGTH);
22 NSUInteger sharedAmount = dataLength - inlineAmount;
23 HFASSERT(inlineAmount <= UCHAR_MAX);
24 inlineTailLength = (unsigned char)inlineAmount;
25 length = sharedAmount;
26 if (inlineAmount > 0) {
27 [unsharedData getBytes:inlineTail range:NSMakeRange(dataLength - inlineAmount, inlineAmount)];
28 }
29 if (sharedAmount > 0) {
30 data = [[NSMutableData alloc] initWithBytes:[unsharedData bytes] length:sharedAmount];
31 }
32 return self;
33 }
34
35 // retains, does not copy
36 - (instancetype)initWithData:(NSMutableData *)dat {
37 REQUIRE_NOT_NULL(dat);
38 return [self initWithData:dat offset:0 length:[dat length]];
39 }
40
41 - (instancetype)initWithData:(NSMutableData *)dat offset:(NSUInteger)off length:(NSUInteger)len {
42 self = [super init];
43 REQUIRE_NOT_NULL(dat);
44 HFASSERT(off + len >= off); //check for overflow
45 HFASSERT(off + len <= [dat length]);
46 offset = off;
47 length = len;
48 data = [dat retain];
49 return self;
50 }
51
52 - (instancetype)initWithSharedData:(NSMutableData *)dat offset:(NSUInteger)off length:(NSUInteger)len tail:(const void *)tail tailLength:(NSUInteger)tailLen {
53 self = [super init];
54 if (off || len) REQUIRE_NOT_NULL(dat);
55 if (tailLen) REQUIRE_NOT_NULL(tail);
56 HFASSERT(tailLen <= MAX_TAIL_LENGTH);
57 HFASSERT(off + len >= off);
58 HFASSERT(off + len <= [dat length]);
59 offset = off;
60 length = len;
61 data = [dat retain];
62 HFASSERT(tailLen <= UCHAR_MAX);
63 inlineTailLength = (unsigned char)tailLen;
64 memcpy(inlineTail, tail, tailLen);
65 HFASSERT([self length] == tailLen + len);
66 return self;
67 }
68
69 - (void)dealloc {
70 [data release];
71 [super dealloc];
72 }
73
74 - (unsigned long long)length {
75 return length + inlineTailLength;
76 }
77
78 - (void)copyBytes:(unsigned char *)dst range:(HFRange)lrange {
79 HFASSERT(HFSum(length, inlineTailLength) >= HFMaxRange(lrange));
80 NSRange requestedRange = NSMakeRange(ll2l(lrange.location), ll2l(lrange.length));
81 NSRange dataRange = NSMakeRange(0, length);
82 NSRange tailRange = NSMakeRange(length, inlineTailLength);
83 NSRange dataRangeToCopy = NSIntersectionRange(requestedRange, dataRange);
84 NSRange tailRangeToCopy = NSIntersectionRange(requestedRange, tailRange);
85 HFASSERT(HFSum(dataRangeToCopy.length, tailRangeToCopy.length) == lrange.length);
86
87 if (dataRangeToCopy.length > 0) {
88 HFASSERT(HFSum(NSMaxRange(dataRangeToCopy), offset) <= [data length]);
89 const void *bytes = [data bytes];
90 memcpy(dst, bytes + dataRangeToCopy.location + offset, dataRangeToCopy.length);
91 }
92 if (tailRangeToCopy.length > 0) {
93 HFASSERT(tailRangeToCopy.location >= length);
94 HFASSERT(NSMaxRange(tailRangeToCopy) - length <= inlineTailLength);
95 memcpy(dst + dataRangeToCopy.length, inlineTail + tailRangeToCopy.location - length, tailRangeToCopy.length);
96 }
97 }
98
99 - (HFByteSlice *)subsliceWithRange:(HFRange)lrange {
100 if (HFRangeEqualsRange(lrange, HFRangeMake(0, HFSum(length, inlineTailLength)))) return [[self retain] autorelease];
101
102 HFByteSlice *result;
103 HFASSERT(lrange.length > 0);
104 HFASSERT(HFSum(length, inlineTailLength) >= HFMaxRange(lrange));
105 NSRange requestedRange = NSMakeRange(ll2l(lrange.location), ll2l(lrange.length));
106 NSRange dataRange = NSMakeRange(0, length);
107 NSRange tailRange = NSMakeRange(length, inlineTailLength);
108 NSRange dataRangeToCopy = NSIntersectionRange(requestedRange, dataRange);
109 NSRange tailRangeToCopy = NSIntersectionRange(requestedRange, tailRange);
110 HFASSERT(HFSum(dataRangeToCopy.length, tailRangeToCopy.length) == lrange.length);
111
112 NSMutableData *resultData = NULL;
113 NSUInteger resultOffset = 0;
114 NSUInteger resultLength = 0;
115 const unsigned char *tail = NULL;
116 NSUInteger tailLength = 0;
117 if (dataRangeToCopy.length > 0) {
118 resultData = data;
119 HFASSERT(resultData != NULL);
120 resultOffset = offset + dataRangeToCopy.location;
121 resultLength = dataRangeToCopy.length;
122 HFASSERT(HFSum(resultOffset, resultLength) <= [data length]);
123 }
124 if (tailRangeToCopy.length > 0) {
125 tail = inlineTail + tailRangeToCopy.location - length;
126 tailLength = tailRangeToCopy.length;
127 HFASSERT(tail >= inlineTail && tail + tailLength <= inlineTail + inlineTailLength);
128 }
129 HFASSERT(resultLength + tailLength == lrange.length);
130 result = [[[[self class] alloc] initWithSharedData:resultData offset:resultOffset length:resultLength tail:tail tailLength:tailLength] autorelease];
131 HFASSERT([result length] == lrange.length);
132 return result;
133 }
134
135 - (HFByteSlice *)byteSliceByAppendingSlice:(HFByteSlice *)slice {
136 REQUIRE_NOT_NULL(slice);
137 const unsigned long long sliceLength = [slice length];
138 if (sliceLength == 0) return self;
139
140 const unsigned long long thisLength = [self length];
141
142 HFASSERT(inlineTailLength <= MAX_TAIL_LENGTH);
143 NSUInteger spaceRemainingInTail = MAX_TAIL_LENGTH - inlineTailLength;
144
145 if (sliceLength <= spaceRemainingInTail) {
146 /* We can do our work entirely within the tail */
147 NSUInteger newTailLength = (NSUInteger)sliceLength + inlineTailLength;
148 unsigned char newTail[MAX_TAIL_LENGTH];
149 memcpy(newTail, inlineTail, inlineTailLength);
150 [slice copyBytes:newTail + inlineTailLength range:HFRangeMake(0, sliceLength)];
151 HFByteSlice *result = [[[[self class] alloc] initWithSharedData:data offset:offset length:length tail:newTail tailLength:newTailLength] autorelease];
152 HFASSERT([result length] == HFSum(sliceLength, thisLength));
153 return result;
154 }
155 else {
156 /* We can't do our work entirely in the tail; see if we can append some shared data. */
157 HFASSERT(offset + length >= offset);
158 if (offset + length == [data length]) {
159 /* We can append some shared data. But impose some reasonable limit on how big our slice can get; this is 16 MB */
160 if (HFSum(thisLength, sliceLength) < (1ULL << 24)) {
161 NSUInteger newDataOffset = offset;
162 NSUInteger newDataLength = length;
163 unsigned char newDataTail[MAX_TAIL_LENGTH];
164 unsigned char newDataTailLength = MAX_TAIL_LENGTH;
165 NSMutableData *newData = (data ? data : [[[NSMutableData alloc] init] autorelease]);
166
167 NSUInteger sliceLengthInt = ll2l(sliceLength);
168 NSUInteger newTotalTailLength = sliceLengthInt + inlineTailLength;
169 HFASSERT(newTotalTailLength >= MAX_TAIL_LENGTH);
170 NSUInteger amountToShiftIntoSharedData = newTotalTailLength - MAX_TAIL_LENGTH;
171 NSUInteger amountToShiftIntoSharedDataFromTail = MIN(amountToShiftIntoSharedData, inlineTailLength);
172 NSUInteger amountToShiftIntoSharedDataFromNewSlice = amountToShiftIntoSharedData - amountToShiftIntoSharedDataFromTail;
173
174 if (amountToShiftIntoSharedDataFromTail > 0) {
175 HFASSERT(amountToShiftIntoSharedDataFromTail <= inlineTailLength);
176 [newData appendBytes:inlineTail length:amountToShiftIntoSharedDataFromTail];
177 newDataLength += amountToShiftIntoSharedDataFromTail;
178 }
179 if (amountToShiftIntoSharedDataFromNewSlice > 0) {
180 HFASSERT(amountToShiftIntoSharedDataFromNewSlice <= [slice length]);
181 NSUInteger dataLength = offset + length + amountToShiftIntoSharedDataFromTail;
182 HFASSERT([newData length] == dataLength);
183 [newData setLength:dataLength + amountToShiftIntoSharedDataFromNewSlice];
184 [slice copyBytes:[newData mutableBytes] + dataLength range:HFRangeMake(0, amountToShiftIntoSharedDataFromNewSlice)];
185 newDataLength += amountToShiftIntoSharedDataFromNewSlice;
186 }
187
188 /* We've updated our data; now figure out the tail */
189 NSUInteger amountOfTailFromNewSlice = sliceLengthInt - amountToShiftIntoSharedDataFromNewSlice;
190 HFASSERT(amountOfTailFromNewSlice <= MAX_TAIL_LENGTH);
191 [slice copyBytes:newDataTail + MAX_TAIL_LENGTH - amountOfTailFromNewSlice range:HFRangeMake(sliceLengthInt - amountOfTailFromNewSlice, amountOfTailFromNewSlice)];
192
193 /* Copy the rest, if any, from the end of self */
194 NSUInteger amountOfTailFromSelf = MAX_TAIL_LENGTH - amountOfTailFromNewSlice;
195 HFASSERT(amountOfTailFromSelf <= inlineTailLength);
196 if (amountOfTailFromSelf > 0) {
197 memcpy(newDataTail, inlineTail + inlineTailLength - amountOfTailFromSelf, amountOfTailFromSelf);
198 }
199
200 HFByteSlice *result = [[[[self class] alloc] initWithSharedData:newData offset:newDataOffset length:newDataLength tail:newDataTail tailLength:newDataTailLength] autorelease];
201 HFASSERT([result length] == HFSum([slice length], [self length]));
202 return result;
203 }
204 }
205 }
206 return nil;
207 }
208
209 @end
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.