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) {