Skip to content
Snippets Groups Projects
Commit 9b561775 authored by George Nachman's avatar George Nachman
Browse files

Release URL codes when they're no longer needed. A mark is placed at the...

Release URL codes when they're no longer needed. A mark is placed at the beginning and end of the URL. The one at the beginning is needed to keep the reference count to the code around until the one at the end is added. These marks are saved and restored.
parent 048464c5
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -1746,6 +1746,9 @@
A6A2699C190319A000437DA9 /* ProfilesAdvancedPreferencesViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = A6A2699A190319A000437DA9 /* ProfilesAdvancedPreferencesViewController.h */; };
A6A51A401B45CEA9007891F3 /* VT100DCSParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A6A51A3F1B45CEA9007891F3 /* VT100DCSParserTest.m */; };
A6A5991D1887C63700CB4209 /* ToolCommandHistoryView.h in Headers */ = {isa = PBXBuildFile; fileRef = A6A5991B1887C63700CB4209 /* ToolCommandHistoryView.h */; };
A6AC5D211E9036D70097C0A7 /* iTermURLMark.h in Headers */ = {isa = PBXBuildFile; fileRef = A6AC5D1F1E9036D70097C0A7 /* iTermURLMark.h */; };
A6AC5D221E9036D70097C0A7 /* iTermURLMark.h in Headers */ = {isa = PBXBuildFile; fileRef = A6AC5D1F1E9036D70097C0A7 /* iTermURLMark.h */; };
A6AC5D241E9036D70097C0A7 /* iTermURLMark.m in Sources */ = {isa = PBXBuildFile; fileRef = A6AC5D201E9036D70097C0A7 /* iTermURLMark.m */; };
A6AC81931D4923DC006F2ADC /* iTermPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = A6E7137D18F1DB1E008D94DD /* iTermPreferences.h */; };
A6ACD1F81B62F2210095CB57 /* iTermRuleTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A6ACD1F71B62F2210095CB57 /* iTermRuleTest.m */; };
A6AE1ECF191FFA1C00780C19 /* iTermMouseCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = A6AE1ECE191FFA1C00780C19 /* iTermMouseCursor.h */; };
Loading
Loading
@@ -3669,6 +3672,8 @@
A6A51A3F1B45CEA9007891F3 /* VT100DCSParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VT100DCSParserTest.m; sourceTree = "<group>"; };
A6A5991B1887C63700CB4209 /* ToolCommandHistoryView.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ToolCommandHistoryView.h; sourceTree = "<group>"; tabWidth = 4; };
A6A5991C1887C63700CB4209 /* ToolCommandHistoryView.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = ToolCommandHistoryView.m; sourceTree = "<group>"; tabWidth = 4; };
A6AC5D1F1E9036D70097C0A7 /* iTermURLMark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTermURLMark.h; sourceTree = "<group>"; };
A6AC5D201E9036D70097C0A7 /* iTermURLMark.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iTermURLMark.m; sourceTree = "<group>"; };
A6ACD1F71B62F2210095CB57 /* iTermRuleTest.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = iTermRuleTest.m; sourceTree = "<group>"; };
A6AE1ECC191FF9DB00780C19 /* iTermMouseCursor.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = iTermMouseCursor.m; sourceTree = "<group>"; tabWidth = 4; };
A6AE1ECE191FFA1C00780C19 /* iTermMouseCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = iTermMouseCursor.h; sourceTree = "<group>"; tabWidth = 4; };
Loading
Loading
@@ -4458,6 +4463,8 @@
A6A13AB918C34F6400B241ED /* VT100XtermParser.h */,
1DCA5ECD13EE507800B7725E /* WindowArrangements.h */,
1DCBC810126DD98200D5B961 /* WindowControllerInterface.h */,
A6AC5D1F1E9036D70097C0A7 /* iTermURLMark.h */,
A6AC5D201E9036D70097C0A7 /* iTermURLMark.m */,
);
name = Headers;
path = sources/;
Loading
Loading
@@ -6491,6 +6498,7 @@
1D5FDD721208E8F000C46BA3 /* CGSNotifications.h in Headers */,
A6A13AA218C2D23300B241ED /* iTermColorMap.h in Headers */,
1D5FDD731208E8F000C46BA3 /* CGSRegion.h in Headers */,
A6AC5D211E9036D70097C0A7 /* iTermURLMark.h in Headers */,
1D5FDD741208E8F000C46BA3 /* CGSSession.h in Headers */,
1D5FDD751208E8F000C46BA3 /* CGSTransitions.h in Headers */,
1D5FDD761208E8F000C46BA3 /* CGSWindow.h in Headers */,
Loading
Loading
@@ -6802,6 +6810,7 @@
A66719351DCE36C3000CE608 /* iTermClearView.h in Headers */,
A66719361DCE36C3000CE608 /* iTermHostRecordMO.h in Headers */,
A66719371DCE36C3000CE608 /* iTermToolbeltSplitView.h in Headers */,
A6AC5D221E9036D70097C0A7 /* iTermURLMark.h in Headers */,
A66719381DCE36C3000CE608 /* iTermDirectoryTreeNode.h in Headers */,
A66719391DCE36C3000CE608 /* iTermColorPresets.h in Headers */,
A667193A1DCE36C3000CE608 /* iTermProfileHotKey.h in Headers */,
Loading
Loading
@@ -8321,6 +8330,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A6AC5D241E9036D70097C0A7 /* iTermURLMark.m in Sources */,
A66719621DCE3772000CE608 /* iTermSocketAddress.m in Sources */,
53AFFC8E1DD2A04100E6CEC6 /* iTermLSOF.m in Sources */,
A66719671DCE3772000CE608 /* iTermWebSocketFrameBuilder.m in Sources */,
Loading
Loading
@@ -12,6 +12,7 @@
#import "iTermGrowlDelegate.h"
#import "iTermImage.h"
#import "iTermImageMark.h"
#import "iTermURLMark.h"
#import "iTermPreferences.h"
#import "iTermSelection.h"
#import "iTermShellHistoryController.h"
Loading
Loading
@@ -3523,6 +3524,24 @@ static NSString *const kInilineFileInset = @"inset"; // NSValue of NSEdgeInsets
[delegate_ screenNeedsRedraw];
}
 
- (void)addURLMarkAtLineAfterCursorWithCode:(unsigned short)code {
long long absLine = (self.totalScrollbackOverflow +
[self numberOfScrollbackLines] +
currentGrid_.cursor.y + 1);
iTermURLMark *mark = [self addMarkStartingAtAbsoluteLine:absLine
oneLine:YES
ofClass:[iTermURLMark class]];
mark.code = code;
}
- (void)terminalWillStartLinkWithCode:(unsigned short)code {
[self addURLMarkAtLineAfterCursorWithCode:code];
}
- (void)terminalWillEndLinkWithCode:(unsigned short)code {
[self addURLMarkAtLineAfterCursorWithCode:code];
}
- (void)terminalDidFinishReceivingFile {
if (inlineFileInfo_) {
// TODO: Handle objects other than images.
Loading
Loading
Loading
Loading
@@ -2122,11 +2122,22 @@ static const int kMaxScreenRows = 4096;
}
self.url = urlString.length ? [NSURL URLWithUserSuppliedString:urlString] : nil;
if (self.url == nil) {
if (_currentURLCode) {
[delegate_ terminalWillEndLinkWithCode:_currentURLCode];
}
_currentURLCode = 0;
self.urlParams = nil;
} else {
self.urlParams = params;
_currentURLCode = [[iTermURLStore sharedInstance] codeForURL:self.url withParams:params];
unsigned short code = [[iTermURLStore sharedInstance] codeForURL:self.url withParams:params];
if (code) {
if (_currentURLCode) {
[delegate_ terminalWillEndLinkWithCode:_currentURLCode];
} else {
[delegate_ terminalWillStartLinkWithCode:code];
}
_currentURLCode = code;
}
}
}
 
Loading
Loading
Loading
Loading
@@ -396,4 +396,8 @@ typedef NS_ENUM(NSUInteger, VT100AttentionRequestType) {
 
- (NSString *)terminalValueOfVariableNamed:(NSString *)name;
 
// Links
- (void)terminalWillEndLinkWithCode:(unsigned short)code;
- (void)terminalWillStartLinkWithCode:(unsigned short)code;
@end
Loading
Loading
@@ -11,6 +11,8 @@
 
@implementation iTermImageMark
 
#warning Serialize and deserialize these
- (void)dealloc {
if (_imageCode) {
ReleaseImage(_imageCode.integerValue);
Loading
Loading
Loading
Loading
@@ -18,4 +18,8 @@
 
// This is a base class for marks but should never be used directly.
@interface iTermMark : NSObject<iTermMark>
- (instancetype)initWithDictionary:(NSDictionary *)dict;
- (NSDictionary *)dictionaryValue;
@end
//
// iTermURLMark.h
// iTerm2
//
// Created by George Nachman on 4/1/17.
//
//
#import "iTermMark.h"
// Invisible marks used to record where URL links are located so they can be freed.
@interface iTermURLMark : iTermMark
@property (nonatomic) unsigned short code;
@end
//
// iTermURLMark.m
// iTerm2
//
// Created by George Nachman on 4/1/17.
//
//
#import "iTermURLMark.h"
#import "iTermURLStore.h"
@implementation iTermURLMark
- (instancetype)initWithDictionary:(NSDictionary *)dict {
self = [super init];
if (self) {
_code = [dict[@"code"] unsignedShortValue];
// We trust that the iTermURLStore will be restored along with the refcounts.
}
return self;
}
- (NSDictionary *)dictionaryValue {
return @{ @"code": @(_code) };
}
- (void)setCode:(unsigned short)code {
if (code == _code) {
return;
}
if (_code) {
[[iTermURLStore sharedInstance] releaseCode:_code];
}
if (code) {
[[iTermURLStore sharedInstance] retainCode:code];
}
_code = code;
}
- (void)dealloc {
if (_code) {
[[iTermURLStore sharedInstance] releaseCode:_code];
}
}
@end
Loading
Loading
@@ -15,6 +15,8 @@
- (unsigned short)codeForURL:(NSURL *)url withParams:(NSString *)params;
- (NSURL *)urlForCode:(unsigned short)code;
- (NSString *)paramWithKey:(NSString *)key forCode:(unsigned short)code;
- (void)releaseCode:(unsigned short)code;
- (void)retainCode:(unsigned short)code;
 
- (NSDictionary *)dictionaryValue;
- (void)loadFromDictionary:(NSDictionary *)dictionary;
Loading
Loading
Loading
Loading
@@ -17,6 +17,8 @@
// @(unsigned short) -> { "url": NSURL, "params": NSString }
NSMutableDictionary<NSNumber *, NSDictionary *> *_reverseStore;
 
NSCountedSet<NSNumber *> *_referenceCounts;
// Internally, the code is stored as a 64-bit integer so we don't have to think about overflow.
// The value that's exported is truncated to 16 bits and will never equal zero.
NSInteger _nextCode;
Loading
Loading
@@ -40,10 +42,28 @@
if (self) {
_store = [NSMutableDictionary dictionary];
_reverseStore = [NSMutableDictionary dictionary];
_referenceCounts = [NSCountedSet set];
}
return self;
}
 
- (void)retainCode:(unsigned short)code {
[_referenceCounts addObject:@(code)];
}
- (void)releaseCode:(unsigned short)code {
[_referenceCounts removeObject:@(code)];
if (![_referenceCounts containsObject:@(code)]) {
NSDictionary *dict = _reverseStore[@(code)];
[_reverseStore removeObjectForKey:@(code)];
NSString *url = [dict[@"url"] absoluteString];
NSString *params = dict[@"params"];
if (url) {
[_store removeObjectForKey:@{ @"url": url, @"params": params }];
}
}
}
- (unsigned short)codeForURL:(NSURL *)url withParams:(NSString *)params {
NSDictionary *key = @{ @"url": url.absoluteString, @"params": params };
NSNumber *number = _store[key];
Loading
Loading
@@ -103,11 +123,27 @@
}
 
- (NSDictionary *)dictionaryValue {
return _store;
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *coder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
coder.outputFormat = NSPropertyListBinaryFormat_v1_0;
[_referenceCounts encodeWithCoder:coder];
[coder finishEncoding];
return @{ @"store": _store,
@"refcounts": data };
}
 
- (void)loadFromDictionary:(NSDictionary *)dictionary {
[dictionary enumerateKeysAndObjectsUsingBlock:^(NSDictionary * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) {
NSDictionary *store = dictionary[@"store"];
NSData *refcounts = dictionary[@"refcounts"];
if (!store || !refcounts) {
DLog(@"URLStore restoration dictionary missing value");
DLog(@"store=%@", store);
DLog(@"refcounts=%@", refcounts);
return;
}
[store enumerateKeysAndObjectsUsingBlock:^(NSDictionary * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) {
if (![key isKindOfClass:[NSDictionary class]] ||
![obj isKindOfClass:[NSNumber class]]) {
ELog(@"Unexpected types when loading dictionary: %@ -> %@", key.class, obj.class);
Loading
Loading
@@ -124,6 +160,14 @@
_reverseStore[@(truncated)] = @{ @"url": url, @"params": key[@"params"] ?: @"" };
_nextCode = MAX(_nextCode, obj.integerValue + 1);
}];
@try {
NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:refcounts];
_referenceCounts = [[NSCountedSet alloc] initWithCoder:decoder];
}
@catch (NSException *exception) {
NSLog(@"Failed to decode refcounts from data %@", refcounts);
}
}
 
@end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment