From aa95bbd9f2efbbc2c839b5c753d3525a7c0ce684 Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 22 Jun 2015 20:55:33 +0200 Subject: [PATCH] Add Unicode Range CSS Token parsing --- HTMLKit/CSSToken.h | 12 ++++++-- HTMLKit/CSSToken.m | 7 +++++ HTMLKit/CSSTokenizer.m | 62 +++++++++++++++++++++++++++++++++--------- 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/HTMLKit/CSSToken.h b/HTMLKit/CSSToken.h index cc06fdb..bc3383e 100644 --- a/HTMLKit/CSSToken.h +++ b/HTMLKit/CSSToken.h @@ -47,14 +47,21 @@ typedef NS_ENUM(NSUInteger, CSSTokenType) @interface CSSToken : NSObject @property (nonatomic, assign) CSSTokenType type; -@property (nonatomic, assign) NSUInteger start; -@property (nonatomic, assign) NSUInteger end; +@property (nonatomic, assign) NSUInteger location; +@property (nonatomic, assign) NSUInteger length; @property (nonatomic, copy) NSString *text; + (instancetype)tokenWithType:(CSSTokenType)type; @end +#pragma mark - Unicode Range + +@interface CSSUnicodeRangeToken : CSSToken +@property (nonatomic, assign) unsigned int start; +@property (nonatomic, assign) unsigned int end; +@end + #pragma mark - Numeric Tokens typedef NS_ENUM(NSUInteger, CSSNumericTokenType) @@ -63,7 +70,6 @@ typedef NS_ENUM(NSUInteger, CSSNumericTokenType) CSSNumericTokenTypeNumber }; - @interface CSSNumericToken : CSSToken @property (nonatomic, assign) CSSNumericTokenType numericType; @property (nonatomic, strong) NSNumber *value; diff --git a/HTMLKit/CSSToken.m b/HTMLKit/CSSToken.m index 22bf324..c91fb0a 100644 --- a/HTMLKit/CSSToken.m +++ b/HTMLKit/CSSToken.m @@ -28,6 +28,13 @@ @end +#pragma mark - Unicode Range + +@implementation CSSUnicodeRangeToken +@end + +#pragma mark - Numeric + @implementation CSSNumericToken @end diff --git a/HTMLKit/CSSTokenizer.m b/HTMLKit/CSSTokenizer.m index a0c73a3..1cb1275 100644 --- a/HTMLKit/CSSTokenizer.m +++ b/HTMLKit/CSSTokenizer.m @@ -231,9 +231,9 @@ token = [CSSToken tokenWithType:CSSTokenTypeDelim]; } - token.start = start; - token.end = _inputStream.location; - token.text = [_string substringWithRange:NSMakeRange(token.start, token.end - token.start)]; + token.location = start; + token.length = _inputStream.location - start; + token.text = [_string substringWithRange:NSMakeRange(token.location, token.length)]; return token; } @@ -434,24 +434,60 @@ - (CSSToken *)consumeUnicodeRange { - CFMutableStringRef hexDigits = CFStringCreateMutable(kCFAllocatorDefault, 6); - while (isHexDigit([_inputStream nextCodePoint]) && CFStringGetLength(hexDigits) < 6) { - UniChar codePoint = [_inputStream consumeNextCodePoint]; - CFStringAppendCharacters(hexDigits, &codePoint, 1); - } + unsigned int (^ parseHexInt) (NSString *) = ^ unsigned int (NSString *string) { + NSScanner *scanner = [NSScanner scannerWithString:string]; + unsigned int num; + [scanner scanHexInt:&num]; + return num; + }; - if (CFStringGetLength(hexDigits) < 6) { + void (^ consumeHexDigits)(CFMutableStringRef) = ^ (CFMutableStringRef ref) { + while (isHexDigit([_inputStream nextCodePoint]) && CFStringGetLength(ref) < 6) { + UniChar codePoint = [_inputStream consumeNextCodePoint]; + CFStringAppendCharacters(ref, &codePoint, 1); + } + }; + + CFMutableStringRef hexDigits = CFStringCreateMutable(kCFAllocatorDefault, 6); + consumeHexDigits(hexDigits); + + unsigned int rangeStart = 0; + unsigned int rangeEnd = 0; + + CFIndex length = CFStringGetLength(hexDigits); + if (length < 6) { while ([_inputStream nextCodePoint] == QUESTION_MARK && CFStringGetLength(hexDigits) < 6) { UniChar codePoint = [_inputStream consumeNextCodePoint]; CFStringAppendCharacters(hexDigits, &codePoint, 1); } - NSScanner *scanner = [NSScanner scannerWithString:(__bridge NSString *)(hexDigits)]; - UTF32Char number; - [scanner scanHexInt:&number]; + NSString *string = (__bridge NSString *)(hexDigits); + + if (string.length > length) { + rangeStart = parseHexInt([string stringByReplacingOccurrencesOfString:@"?" withString:@"0"]); + rangeEnd = parseHexInt([string stringByReplacingOccurrencesOfString:@"?" withString:@"F"]); + + CSSUnicodeRangeToken *token = [CSSUnicodeRangeToken new]; + token.start = rangeStart; + token.end = rangeEnd; + return token; + } else { + rangeStart = parseHexInt(string); + } } - return nil; + if ([_inputStream nextCodePoint] == HYPHEN_MINUS && isDigit([_inputStream nextCodePointAtOffset:1])) { + [_inputStream consumeNextCodePoint]; + consumeHexDigits(hexDigits); + rangeEnd = parseHexInt((__bridge NSString *)(hexDigits)); + } else { + rangeEnd = rangeStart; + } + + CSSUnicodeRangeToken *token = [CSSUnicodeRangeToken new]; + token.start = rangeStart; + token.end = rangeEnd; + return token; } - (UTF32Char)consumeEscapedCodePoint