git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

HexFiend/HFHexTextRepresenter.m

      1 //
      2 //  HFHexTextRepresenter.m
      3 //  HexFiend_2
      4 //
      5 //  Copyright 2007 ridiculous_fish. All rights reserved.
      6 //
      7 
      8 #import <HexFiend/HFHexTextRepresenter.h>
      9 #import <HexFiend/HFRepresenterHexTextView.h>
     10 #import <HexFiend/HFPasteboardOwner.h>
     11 
     12 @interface HFHexPasteboardOwner : HFPasteboardOwner {
     13     NSUInteger _bytesPerColumn;
     14 }
     15 @property (nonatomic) NSUInteger bytesPerColumn;
     16 @end
     17 
     18 static inline unsigned char hex2char(NSUInteger c) {
     19     HFASSERT(c < 16);
     20     return "0123456789ABCDEF"[c];
     21 }
     22 
     23 @implementation HFHexPasteboardOwner
     24 
     25 @synthesize bytesPerColumn = _bytesPerColumn;
     26 
     27 - (unsigned long long)stringLengthForDataLength:(unsigned long long)dataLength {
     28     if(!dataLength) return 0;
     29     // -1 because no trailing space for an exact multiple.
     30     unsigned long long spaces = _bytesPerColumn ? (dataLength-1)/_bytesPerColumn : 0;
     31     if ((ULLONG_MAX - spaces)/2 <= dataLength) return ULLONG_MAX;
     32     else return dataLength*2 + spaces;
     33 }
     34 
     35 - (void)writeDataInBackgroundToPasteboard:(NSPasteboard *)pboard ofLength:(unsigned long long)length forType:(NSString *)type trackingProgress:(id)tracker {
     36     HFASSERT([type isEqual:NSStringPboardType]);
     37     if(length == 0) {
     38         [pboard setString:@"" forType:type];
     39         return;
     40     }
     41     HFByteArray *byteArray = [self byteArray];
     42     HFASSERT(length <= NSUIntegerMax);
     43     NSUInteger dataLength = ll2l(length);
     44     NSUInteger stringLength = ll2l([self stringLengthForDataLength:length]);
     45     HFASSERT(stringLength < ULLONG_MAX);
     46     NSUInteger offset = 0, stringOffset = 0, remaining = dataLength;
     47     unsigned char * restrict const stringBuffer = check_malloc(stringLength);
     48     while (remaining > 0) {
     49         unsigned char dataBuffer[64 * 1024];
     50         NSUInteger amountToCopy = MIN(sizeof dataBuffer, remaining);
     51         NSUInteger bound = offset + amountToCopy - 1;
     52         [byteArray copyBytes:dataBuffer range:HFRangeMake(offset, amountToCopy)];
     53         
     54         if(_bytesPerColumn > 0 && offset > 0) { // ensure offset > 0 to skip adding a leading space
     55             NSUInteger left = _bytesPerColumn - (offset % _bytesPerColumn);
     56             if(left != _bytesPerColumn) {
     57                 while(left-- > 0 && offset <= bound) {
     58                     unsigned char c = dataBuffer[offset++];
     59                     stringBuffer[stringOffset] = hex2char(c >> 4);
     60                     stringBuffer[stringOffset + 1] = hex2char(c & 0xF);
     61                     stringOffset += 2;
     62                 }
     63             }
     64             if(offset <= bound)
     65                 stringBuffer[stringOffset++] = ' ';
     66         }
     67         
     68         if(_bytesPerColumn > 0) while(offset+_bytesPerColumn <= bound) {
     69             for(NSUInteger j = 0; j < _bytesPerColumn; j++) {
     70                 unsigned char c = dataBuffer[offset++];
     71                 stringBuffer[stringOffset] = hex2char(c >> 4);
     72                 stringBuffer[stringOffset + 1] = hex2char(c & 0xF);
     73                 stringOffset += 2;
     74             }
     75             stringBuffer[stringOffset++] = ' ';
     76         }
     77         
     78         while (offset <= bound) {
     79             unsigned char c = dataBuffer[offset++];
     80             stringBuffer[stringOffset] = hex2char(c >> 4);
     81             stringBuffer[stringOffset + 1] = hex2char(c & 0xF);
     82             stringOffset += 2;
     83         }
     84         
     85         remaining -= amountToCopy;
     86     }
     87 
     88     NSString *string = [[NSString alloc] initWithBytesNoCopy:stringBuffer length:stringLength encoding:NSASCIIStringEncoding freeWhenDone:YES];
     89     [pboard setString:string forType:type];
     90     [string release];
     91 }
     92 
     93 @end
     94 
     95 @implementation HFHexTextRepresenter
     96 
     97 /* No extra NSCoder support needed */
     98 
     99 - (Class)_textViewClass {
    100     return [HFRepresenterHexTextView class];
    101 }
    102 
    103 - (void)initializeView {
    104     [super initializeView];
    105     [[self view] setBytesBetweenVerticalGuides:4];
    106     unpartneredLastNybble = UCHAR_MAX;
    107     omittedNybbleLocation = ULLONG_MAX;
    108 }
    109 
    110 + (NSPoint)defaultLayoutPosition {
    111     return NSMakePoint(0, 0);
    112 }
    113 
    114 - (void)_clearOmittedNybble {
    115     unpartneredLastNybble = UCHAR_MAX;
    116     omittedNybbleLocation = ULLONG_MAX;
    117 }
    118 
    119 - (BOOL)_insertionShouldDeleteLastNybble {
    120     /* Either both the omittedNybbleLocation and unpartneredLastNybble are invalid (set to their respective maxima), or neither are */
    121     HFASSERT((omittedNybbleLocation == ULLONG_MAX) == (unpartneredLastNybble == UCHAR_MAX));
    122     /* We should delete the last nybble if our omittedNybbleLocation is the point where we would insert */
    123     BOOL result = NO;
    124     if (omittedNybbleLocation != ULLONG_MAX) {
    125         HFController *controller = [self controller];
    126         NSArray *selectedRanges = [controller selectedContentsRanges];
    127         if ([selectedRanges count] == 1) {
    128             HFRange selectedRange = [selectedRanges[0] HFRange];
    129             result = (selectedRange.length == 0 && selectedRange.location > 0 && selectedRange.location - 1 == omittedNybbleLocation);
    130         }
    131     }
    132     return result;
    133 }
    134 
    135 - (BOOL)_canInsertText:(NSString *)text {
    136     REQUIRE_NOT_NULL(text);
    137     NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFabcdef"];
    138     return [text rangeOfCharacterFromSet:characterSet].location != NSNotFound;
    139 }
    140 
    141 - (void)insertText:(NSString *)text {
    142     REQUIRE_NOT_NULL(text);
    143     if (! [self _canInsertText:text]) {
    144         /* The user typed invalid data, and we can ignore it */
    145         return;
    146     }
    147     
    148     BOOL shouldReplacePriorByte = [self _insertionShouldDeleteLastNybble];
    149     if (shouldReplacePriorByte) {
    150         HFASSERT(unpartneredLastNybble < 16);
    151         /* Prepend unpartneredLastNybble as a nybble */
    152         text = [NSString stringWithFormat:@"%1X%@", unpartneredLastNybble, text];
    153     }
    154     BOOL isMissingLastNybble;
    155     NSData *data = HFDataFromHexString(text, &isMissingLastNybble);
    156     HFASSERT([data length] > 0);
    157     HFASSERT(shouldReplacePriorByte != isMissingLastNybble);
    158     HFController *controller = [self controller];
    159     BOOL success = [controller insertData:data replacingPreviousBytes: (shouldReplacePriorByte ? 1 : 0) allowUndoCoalescing:YES];
    160     if (isMissingLastNybble && success) {
    161         HFASSERT([data length] > 0);
    162         HFASSERT(unpartneredLastNybble == UCHAR_MAX);
    163         [data getBytes:&unpartneredLastNybble range:NSMakeRange([data length] - 1, 1)];
    164         NSArray *selectedRanges = [controller selectedContentsRanges];
    165         HFASSERT([selectedRanges count] >= 1);
    166         HFRange selectedRange = [selectedRanges[0] HFRange];
    167         HFASSERT(selectedRange.location > 0);
    168         omittedNybbleLocation = HFSubtract(selectedRange.location, 1);
    169     }
    170     else {
    171         [self _clearOmittedNybble];
    172     }
    173 }
    174 
    175 - (NSData *)dataFromPasteboardString:(NSString *)string {
    176     REQUIRE_NOT_NULL(string);
    177     return HFDataFromHexString(string, NULL);
    178 }
    179 
    180 - (void)controllerDidChange:(HFControllerPropertyBits)bits {
    181     if (bits & HFControllerHideNullBytes) {
    182         [[self view] setHidesNullBytes:[[self controller] shouldHideNullBytes]];
    183     }
    184     [super controllerDidChange:bits];
    185     if (bits & (HFControllerSelectedRanges)) {
    186         [self _clearOmittedNybble];
    187     }
    188 }
    189 
    190 - (void)copySelectedBytesToPasteboard:(NSPasteboard *)pb {
    191     REQUIRE_NOT_NULL(pb);
    192     HFByteArray *selection = [[self controller] byteArrayForSelectedContentsRanges];
    193     HFASSERT(selection != NULL);
    194     if ([selection length] == 0) {
    195         NSBeep();
    196     } else {
    197         HFHexPasteboardOwner *owner = [HFHexPasteboardOwner ownPasteboard:pb forByteArray:selection withTypes:@[HFPrivateByteArrayPboardType, NSStringPboardType]];
    198         [owner setBytesPerLine:[self bytesPerLine]];
    199         owner.bytesPerColumn = self.bytesPerColumn;
    200     }
    201 }
    202 
    203 @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.