@@ -30,6 +30,122 @@ @implementation DTLocalizableStringScanner
3030
3131@synthesize entryFoundCallback=_entryFoundCallback;
3232
33+
34+ - (void ) rebuildPattern : (NSMutableString *) pattern withDictionary : (NSDictionary *) node {
35+ NSUInteger count = [node count ];
36+ if (count == 0 ) {
37+ return ;
38+ } else if (count == 1 ) {
39+ for (NSNumber *key in node) {
40+ unichar c = [key unsignedShortValue ];
41+ if (c == ' |' ) {
42+ return ;
43+ }
44+
45+ CFStringAppendCharacters ((__bridge CFMutableStringRef) pattern, &c, 1 );
46+
47+ NSDictionary *dict = [node objectForKey: key];
48+ if (dict) {
49+ [self rebuildPattern: pattern withDictionary: dict];
50+ }
51+ }
52+ } else {
53+ BOOL isFirst = [pattern length ] == 0 ;
54+ if (!isFirst) {
55+ [pattern appendString: @" (?:" ];
56+ }
57+
58+ BOOL ender = NO ;
59+ BOOL firstKey = YES ;
60+
61+ NSArray *keys = [[node allKeys ] sortedArrayUsingSelector: @selector (compare: )];
62+ for (NSNumber *key in keys) {
63+ unichar c = [key unsignedShortValue ];
64+
65+ if (c == ' |' ) {
66+ ender = YES ;
67+ } else {
68+ if (!firstKey) {
69+ [pattern appendString: @" |" ];
70+ }
71+ firstKey = NO ;
72+
73+ CFStringAppendCharacters ((__bridge CFMutableStringRef) pattern, &c, 1 );
74+
75+ NSDictionary *dict = [node objectForKey: key];
76+ if (dict) {
77+ [self rebuildPattern: pattern withDictionary: dict];
78+ }
79+ }
80+ }
81+
82+ if (!isFirst) {
83+ [pattern appendString: @" )" ];
84+ if (ender) {
85+ [pattern appendString: @" ?" ];
86+ }
87+ }
88+ }
89+ }
90+
91+ - (NSString *) optimizedAlternationPatternStringWithValidMacros : (NSDictionary *) validMacros {
92+ NSArray *orderedKeys = [[validMacros allKeys ] sortedArrayUsingSelector: @selector (compare: )];
93+
94+ NSMutableDictionary *root = [NSMutableDictionary dictionary ];
95+ NSMutableDictionary *node;
96+
97+ for (NSString *key in orderedKeys) {
98+ node = root;
99+
100+ NSUInteger keyLength = [key length ];
101+
102+ for (NSUInteger i = 0 ; i <= keyLength; i++) {
103+ unichar c;
104+ if (i < keyLength) {
105+ c = [key characterAtIndex: i];
106+ } else {
107+ c = ' |' ;
108+ }
109+
110+ // find node for this character
111+ NSMutableDictionary *thisNode = [node objectForKey: [NSNumber numberWithUnsignedShort: c]];
112+ if (!thisNode) {
113+ thisNode = [NSMutableDictionary dictionary ];
114+ [node setObject: thisNode forKey: [NSNumber numberWithUnsignedShort: c]];
115+ }
116+
117+ node = thisNode;
118+ }
119+ }
120+
121+ NSMutableString *pattern = [NSMutableString string ];
122+ [self rebuildPattern: pattern withDictionary: root];
123+
124+ return pattern;
125+ }
126+
127+ - (NSRegularExpression *) regularExpressionWithValidMacros : (NSDictionary *)validMacros {
128+ @synchronized ([self class ]) {
129+ static NSDictionary *lastValidMacrosDictionary = nil ;
130+ static NSRegularExpression *lastRegularExpression = nil ;
131+
132+ if (lastValidMacrosDictionary == validMacros) {
133+ return lastRegularExpression;
134+ } else {
135+ // build regex to find macro words
136+ NSString *innerPatternPart = [self optimizedAlternationPatternStringWithValidMacros: validMacros];
137+ NSString *pattern = [NSString stringWithFormat: @" \\ b(%@ )\\ b" , innerPatternPart];
138+
139+ // NSLog(@"optimized pattern: %@", pattern);
140+
141+ lastValidMacrosDictionary = validMacros;
142+ lastRegularExpression = [NSRegularExpression regularExpressionWithPattern: pattern options: 0 error: NULL ];
143+
144+ return lastRegularExpression;
145+ }
146+ }
147+ }
148+
33149- (id )initWithContentsOfURL : (NSURL *)url encoding : (NSStringEncoding )encoding validMacros : (NSDictionary *)validMacros
34150{
35151 self = [super init ];
@@ -48,11 +164,7 @@ - (id)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)encoding val
48164 _url = [url copy ]; // to have a reference later
49165
50166 _validMacros = validMacros;
51-
52- // build regex to find macro words
53- NSString *innerPatternPart = [[validMacros allKeys ] componentsJoinedByString: @" |" ];
54- NSString *pattern = [NSString stringWithFormat: @" \\ b(%@ )\\ b" , innerPatternPart];
55- _validMacroRegex = [NSRegularExpression regularExpressionWithPattern: pattern options: 0 error: NULL ];
167+ _validMacroRegex = [self regularExpressionWithValidMacros: validMacros];
56168 }
57169
58170 return self;
0 commit comments