1 /* 2 * Copyright (C) 2011 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 #ifndef LineBreakIteratorPoolICU_h 27 #define LineBreakIteratorPoolICU_h 28 29 #include <unicode/ubrk.h> 30 #include "core/platform/text/TextBreakIteratorInternalICU.h" 31 #include "wtf/Assertions.h" 32 #include "wtf/HashMap.h" 33 #include "wtf/PassOwnPtr.h" 34 #include "wtf/text/AtomicString.h" 35 #include "wtf/text/CString.h" 36 #include "wtf/ThreadSpecific.h" 37 38 namespace WebCore { 39 40 class LineBreakIteratorPool { 41 WTF_MAKE_NONCOPYABLE(LineBreakIteratorPool); 42 public: 43 static LineBreakIteratorPool& sharedPool() 44 { 45 static WTF::ThreadSpecific<LineBreakIteratorPool>* pool = new WTF::ThreadSpecific<LineBreakIteratorPool>; 46 return **pool; 47 } 48 49 static PassOwnPtr<LineBreakIteratorPool> create() { return adoptPtr(new LineBreakIteratorPool); } 50 51 UBreakIterator* take(const AtomicString& locale) 52 { 53 UBreakIterator* iterator = 0; 54 for (size_t i = 0; i < m_pool.size(); ++i) { 55 if (m_pool[i].first == locale) { 56 iterator = m_pool[i].second; 57 m_pool.remove(i); 58 break; 59 } 60 } 61 62 if (!iterator) { 63 UErrorCode openStatus = U_ZERO_ERROR; 64 bool localeIsEmpty = locale.isEmpty(); 65 iterator = ubrk_open(UBRK_LINE, localeIsEmpty ? currentTextBreakLocaleID() : locale.string().utf8().data(), 0, 0, &openStatus); 66 // locale comes from a web page and it can be invalid, leading ICU 67 // to fail, in which case we fall back to the default locale. 68 if (!localeIsEmpty && U_FAILURE(openStatus)) { 69 openStatus = U_ZERO_ERROR; 70 iterator = ubrk_open(UBRK_LINE, currentTextBreakLocaleID(), 0, 0, &openStatus); 71 } 72 73 if (U_FAILURE(openStatus)) { 74 LOG_ERROR("ubrk_open failed with status %d", openStatus); 75 return 0; 76 } 77 } 78 79 ASSERT(!m_vendedIterators.contains(iterator)); 80 m_vendedIterators.set(iterator, locale); 81 return iterator; 82 } 83 84 void put(UBreakIterator* iterator) 85 { 86 ASSERT_ARG(iterator, m_vendedIterators.contains(iterator)); 87 88 if (m_pool.size() == capacity) { 89 ubrk_close(m_pool[0].second); 90 m_pool.remove(0); 91 } 92 93 m_pool.append(Entry(m_vendedIterators.take(iterator), iterator)); 94 } 95 96 private: 97 LineBreakIteratorPool() { } 98 99 static const size_t capacity = 4; 100 101 typedef pair<AtomicString, UBreakIterator*> Entry; 102 typedef Vector<Entry, capacity> Pool; 103 Pool m_pool; 104 HashMap<UBreakIterator*, AtomicString> m_vendedIterators; 105 106 friend WTF::ThreadSpecific<LineBreakIteratorPool>::operator LineBreakIteratorPool*(); 107 }; 108 109 } 110 111 #endif 112