diff --git a/HTMLKit/CSSInputStream.h b/HTMLKit/CSSInputStream.h
index 32c08ee..a1e9512 100644
--- a/HTMLKit/CSSInputStream.h
+++ b/HTMLKit/CSSInputStream.h
@@ -7,17 +7,12 @@
//
#import
+#import "HTMLInputStreamReader.h"
-@interface CSSInputStream : NSObject
+@interface CSSInputStream : HTMLInputStreamReader
-@property (nonatomic, readonly) NSUInteger location;
-
-- (instancetype)initWithString:(NSString *)string;
-
-- (UniChar)currentCodePoint;
-- (UniChar)nextCodePoint;
-- (UniChar)nextCodePointAtOffset:(NSUInteger)offset;
-- (UniChar)consumeNextCodePoint;
-- (void)reconsumeCurrentCodePoint;
+- (void)consumeWhitespace;
+- (NSString *)consumeIdentifier;
+- (UTF32Char)consumeEscapedCodePoint;
@end
diff --git a/HTMLKit/CSSInputStream.m b/HTMLKit/CSSInputStream.m
index 3dc56cb..cb54a2d 100644
--- a/HTMLKit/CSSInputStream.m
+++ b/HTMLKit/CSSInputStream.m
@@ -7,59 +7,65 @@
//
#import "CSSInputStream.h"
-
-@interface CSSInputStream ()
-{
- CFStringInlineBuffer _buffer;
- NSUInteger _location;
- UniChar _currentCodePoint;
-}
-@end
+#import "CSSTokenizerCodePoints.h"
@implementation CSSInputStream
-@synthesize location = _location;
-- (instancetype)initWithString:(NSString *)string
+- (void)consumeWhitespace
{
- self = [super init];
- if (self) {
- CFStringInitInlineBuffer((CFStringRef)string, &_buffer, CFRangeMake(0, string.length));
- _location = 0;
- _currentCodePoint = 0;
+ while (isWhitespace(self.nextInputCharacter)) {
+ [self consumeNextInputCharacter];
}
- return self;
}
-- (UniChar)currentCodePoint
+- (NSString *)consumeIdentifier
{
- return _currentCodePoint;
+ CFMutableStringRef value = CFStringCreateMutable(kCFAllocatorDefault, 0);
+
+ while (YES) {
+ UniChar codePoint = [self consumeNextInputCharacter];
+ if (isName(codePoint)) {
+ CFStringAppendCharacters(value, &codePoint, 1);
+ } else if (isValidEscape(self.nextInputCharacter, [self inputCharacterPointAtOffset:1])) {
+ UTF32Char escapedCodePoint = [self consumeNextInputCharacter];
+ AppendCodePoint(value, escapedCodePoint);
+ } else {
+ [self reconsumeCurrentInputCharacter];
+ break;
+ }
+ }
+
+ return (__bridge NSString *)(CFStringGetLength(value) > 0 ? value : nil);
}
-- (UniChar)nextCodePointAtOffset:(NSUInteger)offset;
+- (UTF32Char)consumeEscapedCodePoint
{
- UniChar codePoint = CFStringGetCharacterFromInlineBuffer(&_buffer, _location + offset);
- return codePoint;
-}
+ UniChar codePoint = [self consumeNextInputCharacter];
-- (UniChar)nextCodePoint
-{
- return [self nextCodePointAtOffset:0];
-}
+ if (isHexDigit(codePoint)) {
+ CFMutableStringRef hexString = CFStringCreateMutable(kCFAllocatorDefault, 6);
+ CFStringAppendCharacters(hexString, &codePoint, 1);
-- (UniChar)consumeNextCodePoint
-{
- UniChar codePoint = [self nextCodePoint];
- _currentCodePoint = codePoint;
- if (codePoint != 0) {
- _location++;
+ while (isHexDigit(self.nextInputCharacter) && CFStringGetLength(hexString) <= 6) {
+ UniChar codePoint = [self consumeNextInputCharacter];
+ CFStringAppendCharacters(hexString, &codePoint, 1);
+ }
+
+ if (isWhitespace(self.nextInputCharacter)) {
+ [self consumeNextInputCharacter];
+ }
+
+ NSScanner *scanner = [NSScanner scannerWithString:(__bridge NSString *)(hexString)];
+ UTF32Char number;
+ [scanner scanHexInt:&number];
+
+ return isValidEscapedCodePoint(number) ? number : REPLACEMENT_CHARACTER;
+ } else if (codePoint == EOF_CHARACTER) {
+ return REPLACEMENT_CHARACTER;
}
return codePoint;
}
-- (void)reconsumeCurrentCodePoint
-{
- _location = _location - 1;
-}
@end
diff --git a/HTMLKit/HTMLInputStreamReader.h b/HTMLKit/HTMLInputStreamReader.h
index 1ffdce8..0d7a0b8 100644
--- a/HTMLKit/HTMLInputStreamReader.h
+++ b/HTMLKit/HTMLInputStreamReader.h
@@ -24,6 +24,7 @@ typedef void (^ HTMLStreamReaderErrorCallback)(NSString *reason);
- (UTF32Char)currentInputCharacter;
- (UTF32Char)nextInputCharacter;
+- (UTF32Char)inputCharacterPointAtOffset:(NSUInteger)offset;
- (UTF32Char)consumeNextInputCharacter;
- (void)reconsumeCurrentInputCharacter;
diff --git a/HTMLKit/HTMLInputStreamReader.m b/HTMLKit/HTMLInputStreamReader.m
index 2e5b393..21229c2 100644
--- a/HTMLKit/HTMLInputStreamReader.m
+++ b/HTMLKit/HTMLInputStreamReader.m
@@ -107,6 +107,11 @@
return nextInputCharacter;
}
+- (UTF32Char)inputCharacterPointAtOffset:(NSUInteger)offset
+{
+ return CFStringGetCharacterFromInlineBuffer(&_buffer, _location + offset);
+}
+
- (UTF32Char)consumeNextInputCharacter
{
if (_reconsume) {