-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathKMSRegExResponder.m
140 lines (116 loc) · 4.52 KB
/
KMSRegExResponder.m
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
//
// Created by Sam Deane on 06/11/2012.
// Copyright 2012 Karelia Software. All rights reserved.
//
#import "KMSRegExResponder.h"
#import "KMSServer.h"
#import "KMSCommand.h"
@interface KMSRegExResponder()
@property (strong, nonatomic) NSArray* requests;
@property (strong, nonatomic) NSArray* responses;
@property (copy, nonatomic, readwrite) NSArray* initialResponse;
@end
@implementation KMSRegExResponder
@synthesize initialResponse = _initialResponse;
@synthesize requests = _requests;
@synthesize responses = _responses;
#pragma mark - Object Lifecycle
+ (KMSRegExResponder*)responderWithResponses:(NSArray *)responses
{
KMSRegExResponder* server = [[KMSRegExResponder alloc] initWithResponses:responses];
return [server autorelease];
}
- (id)initWithResponses:(NSArray *)responses
{
if ((self = [super init]) != nil)
{
// process responses array - we pull out some special responses, and pre-calculate all the regular expressions
NSRegularExpressionOptions options = NSRegularExpressionDotMatchesLineSeparators;
NSMutableArray* processed = [NSMutableArray arrayWithCapacity:[responses count]];
NSMutableArray* expressions = [NSMutableArray arrayWithCapacity:[responses count]];
for (NSArray* response in responses)
{
NSUInteger length = [response count];
if (length > 0)
{
NSString* pattern = response[0];
NSArray* commands = [KMSCommand commandArrayFromObjectArray:[response subarrayWithRange:NSMakeRange(1, length - 1)]];
if ([pattern isEqualToString:InitialResponsePattern])
{
self.initialResponse = commands;
}
else
{
NSError* error = nil;
NSRegularExpression* expression = [NSRegularExpression regularExpressionWithPattern:pattern options:options error:&error];
if (expression)
{
[expressions addObject:expression];
[processed addObject:commands];
}
}
}
}
self.requests = expressions;
self.responses = processed;
}
return self;
}
- (void)dealloc
{
[_initialResponse release];
[_responses release];
[_requests release];
[super dealloc];
}
#pragma mark - Public API
- (NSArray*)responseForRequest:(NSString*)request substitutions:(NSDictionary*)substitutions
{
NSArray* commands = nil;
NSRange wholeString = NSMakeRange(0, [request length]);
NSUInteger count = [self.requests count];
for (NSUInteger n = 0; n < count; ++n)
{
NSRegularExpression* expression = self.requests[n];
NSTextCheckingResult* match = [expression firstMatchInString:request options:0 range:wholeString];
if (match)
{
KMSLogDetail(@"matched with request pattern %@", expression);
NSArray* rawCommands = self.responses[n];
commands = [self substitutedCommands:rawCommands match:match request:request substitutions:substitutions];
break;
}
}
return commands;
}
- (void)addSubstitutionsForMatch:(NSTextCheckingResult*)match request:(NSString*)request toDictionary:(NSMutableDictionary*)dictionary
{
// always add the request as $0
[dictionary setObject:request forKey:@"$0"];
// add any matched subgroups
if (match)
{
NSUInteger count = match.numberOfRanges;
for (NSUInteger n = 1; n < count; ++n)
{
NSString* token = [NSString stringWithFormat:@"$%ld", (long) n];
NSRange range = [match rangeAtIndex:n];
NSString* replacement = [request substringWithRange:range];
[dictionary setObject:replacement forKey:token];
}
}
}
- (NSArray*)substitutedCommands:(NSArray*)commands match:(NSTextCheckingResult*)match request:(NSString*)request substitutions:(NSDictionary*)serverSubstitutions
{
NSMutableDictionary* substitutions = [NSMutableDictionary dictionary];
[substitutions addEntriesFromDictionary:serverSubstitutions];
[self addSubstitutionsForMatch:match request:request toDictionary:substitutions];
NSMutableArray* substitutedCommands = [NSMutableArray arrayWithCapacity:[commands count]];
for (id command in commands)
{
KMSCommand* substituted = [command substitutedWithValues:substitutions];
[substitutedCommands addObject:substituted];
}
return substitutedCommands;
}
@end