1/*
2 * Copyright (C) 2008, 2009, 2014 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#import "WebTextIterator.h"
27
28#import "DOMNodeInternal.h"
29#import "DOMRangeInternal.h"
30#import "WebTypesInternal.h"
31#import <WebCore/TextIterator.h>
32#import <WebCore/WebCoreObjCExtras.h>
33#import <runtime/InitializeThreading.h>
34#import <wtf/MainThread.h>
35#import <wtf/RunLoop.h>
36#import <wtf/Vector.h>
37
38@interface WebTextIteratorPrivate : NSObject {
39@public
40    std::unique_ptr<WebCore::TextIterator> _textIterator;
41    Vector<unichar> _upconvertedText;
42}
43@end
44
45@implementation WebTextIteratorPrivate
46
47+ (void)initialize
48{
49#if !PLATFORM(IOS)
50    JSC::initializeThreading();
51    WTF::initializeMainThreadToProcessMainThread();
52    RunLoop::initializeMainRunLoop();
53#endif
54    WebCoreObjCFinalizeOnMainThread(self);
55}
56
57@end
58
59@implementation WebTextIterator
60
61- (void)dealloc
62{
63    [_private release];
64    [super dealloc];
65}
66
67- (id)initWithRange:(DOMRange *)range
68{
69    self = [super init];
70    if (!self)
71        return self;
72
73    _private = [[WebTextIteratorPrivate alloc] init];
74    _private->_textIterator = std::make_unique<WebCore::TextIterator>(core(range));
75    return self;
76}
77
78- (void)advance
79{
80    _private->_textIterator->advance();
81    _private->_upconvertedText.shrink(0);
82}
83
84- (BOOL)atEnd
85{
86    return _private->_textIterator->atEnd();
87}
88
89- (DOMRange *)currentRange
90{
91    WebCore::TextIterator& textIterator = *_private->_textIterator;
92    if (textIterator.atEnd())
93        return nullptr;
94    return kit(textIterator.range().get());
95}
96
97// FIXME: Consider deprecating this method and creating one that does not require copying 8-bit characters.
98- (const unichar*)currentTextPointer
99{
100    StringView text = _private->_textIterator->text();
101    unsigned length = text.length();
102    if (!length)
103        return nullptr;
104    if (!text.is8Bit())
105        return text.characters16();
106    if (_private->_upconvertedText.isEmpty())
107        _private->_upconvertedText.appendRange(text.characters8(), text.characters8() + length);
108    ASSERT(_private->_upconvertedText.size() == text.length());
109    return _private->_upconvertedText.data();
110}
111
112- (NSUInteger)currentTextLength
113{
114    return _private->_textIterator->text().length();
115}
116
117@end
118
119@implementation WebTextIterator (WebTextIteratorDeprecated)
120
121- (DOMNode *)currentNode
122{
123    return kit(_private->_textIterator->node());
124}
125
126- (NSString *)currentText
127{
128    return [[_private->_textIterator->text().createNSString().get() retain] autorelease];
129}
130
131@end
132