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