Files
HTMLKit/Sources/HTMLListOfActiveFormattingElements.m
iska 47ec0867a8 Improve reverseObjectEnumerator usage while parsing HTML
Do not use the `allObjects` call on the reverse enumerators in the Parser
and the List of Active Formatting Elements to prevent allocating a new
array of the unenumerated objects.

This should reduce memory consumption while parsing, see issue #10
2017-04-25 00:12:39 +02:00

159 lines
2.9 KiB
Objective-C

//
// HTMLListOfActiveFormattingElements.m
// HTMLKit
//
// Created by Iska on 22/03/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import "HTMLListOfActiveFormattingElements.h"
#import "HTMLMarker.h"
@interface HTMLListOfActiveFormattingElements ()
{
NSMutableArray *_list;
}
@end
@implementation HTMLListOfActiveFormattingElements
- (instancetype)init
{
self = [super init];
if (self) {
_list = [NSMutableArray new];
}
return self;
}
#pragma mark - Access
- (id)objectAtIndexedSubscript:(NSUInteger)index;
{
return [_list objectAtIndex:index];
}
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx
{
[_list setObject:obj atIndexedSubscript:idx];
}
- (NSUInteger)indexOfElement:(id)node
{
return [_list indexOfObject:node];
}
- (void)addElement:(HTMLElement *)element
{
NSUInteger existing = 0;
for (HTMLElement *node in _list.reverseObjectEnumerator) {
if ([node isEqual:[HTMLMarker marker]]) {
break;
}
if (node.htmlNamespace == element.htmlNamespace &&
[node.tagName isEqualToString:element.tagName] &&
[node.attributes isEqual:element.attributes]) {
existing++;
}
if (existing == 3) {
[_list removeObject:node];
break;
}
}
[_list addObject:element];
}
- (void)removeElement:(id)element
{
[_list removeObject:element];
}
- (BOOL)containsElement:(id)element
{
return [_list containsObject:element];
}
- (void)insertElement:(HTMLElement *)element atIndex:(NSUInteger)index
{
if (index > _list.count) {
index = _list.count;
}
[_list insertObject:element atIndex:index];
}
- (void)replaceElementAtIndex:(NSUInteger)index withElement:(HTMLElement *)element
{
[_list replaceObjectAtIndex:index withObject:element];
}
- (id)lastEntry
{
return _list.lastObject;
}
#pragma mark - Acrions
- (void)addMarker
{
[_list addObject:[HTMLMarker marker]];
}
- (void)clearUptoLastMarker
{
while (_list.lastObject && _list.lastObject != [HTMLMarker marker]) {
[_list removeLastObject];
}
[_list removeLastObject];
}
- (HTMLElement *)formattingElementWithTagName:(NSString *)tagName
{
for (HTMLElement *element in _list.reverseObjectEnumerator) {
if ([element isEqual:[HTMLMarker marker]]) return nil;
if ([element.tagName isEqualToString:tagName]) {
return element;
}
}
return nil;
}
#pragma mark - Count
- (NSUInteger)count
{
return _list.count;
}
- (BOOL)isEmpty
{
return _list.count == 0;
}
#pragma mark - Enumeraiton
- (NSEnumerator *)enumerator
{
return _list.objectEnumerator;
}
- (NSEnumerator *)reverseObjectEnumerator
{
return _list.reverseObjectEnumerator;
}
#pragma mark - NSFastEnumeration
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len
{
return [_list countByEnumeratingWithState:state objects:buffer count:len];
}
#pragma mark - Description
- (NSString *)description
{
return _list.description;
}
@end