git.y1.nz

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.