Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006 Lars Knoll <lars@trolltech.com> | 2 * Copyright (C) 2006 Lars Knoll <lars@trolltech.com> |
| 3 * Copyright (C) 2007, 2011, 2012 Apple Inc. All rights reserved. | 3 * Copyright (C) 2007, 2011, 2012 Apple Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
| 7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
| 8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
| 9 * | 9 * |
| 10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 42 WTF_MAKE_NONCOPYABLE(LineBreakIteratorPool); | 42 WTF_MAKE_NONCOPYABLE(LineBreakIteratorPool); |
| 43 public: | 43 public: |
| 44 static LineBreakIteratorPool& sharedPool() | 44 static LineBreakIteratorPool& sharedPool() |
| 45 { | 45 { |
| 46 static WTF::ThreadSpecific<LineBreakIteratorPool>* pool = new WTF::Threa dSpecific<LineBreakIteratorPool>; | 46 static WTF::ThreadSpecific<LineBreakIteratorPool>* pool = new WTF::Threa dSpecific<LineBreakIteratorPool>; |
| 47 return **pool; | 47 return **pool; |
| 48 } | 48 } |
| 49 | 49 |
| 50 static PassOwnPtr<LineBreakIteratorPool> create() { return adoptPtr(new Line BreakIteratorPool); } | 50 static PassOwnPtr<LineBreakIteratorPool> create() { return adoptPtr(new Line BreakIteratorPool); } |
| 51 | 51 |
| 52 UBreakIterator* take(const AtomicString& locale) | 52 icu::BreakIterator* take(const AtomicString& locale) |
| 53 { | 53 { |
| 54 UBreakIterator* iterator = 0; | 54 icu::BreakIterator* iterator = 0; |
| 55 for (size_t i = 0; i < m_pool.size(); ++i) { | 55 for (size_t i = 0; i < m_pool.size(); ++i) { |
| 56 if (m_pool[i].first == locale) { | 56 if (m_pool[i].first == locale) { |
| 57 iterator = m_pool[i].second; | 57 iterator = m_pool[i].second; |
| 58 m_pool.remove(i); | 58 m_pool.remove(i); |
| 59 break; | 59 break; |
| 60 } | 60 } |
| 61 } | 61 } |
| 62 | 62 |
| 63 if (!iterator) { | 63 if (!iterator) { |
| 64 UErrorCode openStatus = U_ZERO_ERROR; | 64 UErrorCode openStatus = U_ZERO_ERROR; |
| 65 bool localeIsEmpty = locale.isEmpty(); | 65 bool localeIsEmpty = locale.isEmpty(); |
| 66 iterator = ubrk_open(UBRK_LINE, localeIsEmpty ? currentTextBreakLoca leID() : locale.string().utf8().data(), 0, 0, &openStatus); | 66 iterator = icu::BreakIterator::createLineInstance(localeIsEmpty ? ic u::Locale(currentTextBreakLocaleID()) : icu::Locale(locale.string().utf8().data( )), openStatus); |
| 67 // locale comes from a web page and it can be invalid, leading ICU | 67 // locale comes from a web page and it can be invalid, leading ICU |
| 68 // to fail, in which case we fall back to the default locale. | 68 // to fail, in which case we fall back to the default locale. |
| 69 if (!localeIsEmpty && U_FAILURE(openStatus)) { | 69 if (!localeIsEmpty && U_FAILURE(openStatus)) { |
| 70 openStatus = U_ZERO_ERROR; | 70 openStatus = U_ZERO_ERROR; |
| 71 iterator = ubrk_open(UBRK_LINE, currentTextBreakLocaleID(), 0, 0 , &openStatus); | 71 iterator = icu::BreakIterator::createLineInstance(icu::Locale(cu rrentTextBreakLocaleID()), openStatus); |
| 72 } | 72 } |
| 73 | 73 |
| 74 if (U_FAILURE(openStatus)) { | 74 if (U_FAILURE(openStatus)) { |
| 75 LOG_ERROR("ubrk_open failed with status %d", openStatus); | 75 LOG_ERROR("icu::BreakIterator construction failed with status %d ", openStatus); |
| 76 return 0; | 76 return 0; |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 | 79 |
| 80 ASSERT(!m_vendedIterators.contains(iterator)); | 80 ASSERT(!m_vendedIterators.contains(iterator)); |
| 81 m_vendedIterators.set(iterator, locale); | 81 m_vendedIterators.set(iterator, locale); |
| 82 return iterator; | 82 return iterator; |
| 83 } | 83 } |
| 84 | 84 |
| 85 void put(UBreakIterator* iterator) | 85 void put(icu::BreakIterator* iterator) |
| 86 { | 86 { |
| 87 ASSERT_ARG(iterator, m_vendedIterators.contains(iterator)); | 87 ASSERT_ARG(iterator, m_vendedIterators.contains(iterator)); |
| 88 | 88 |
| 89 if (m_pool.size() == capacity) { | 89 if (m_pool.size() == capacity) { |
| 90 ubrk_close(m_pool[0].second); | 90 delete(m_pool[0].second); |
| 91 m_pool.remove(0); | 91 m_pool.remove(0); |
| 92 } | 92 } |
| 93 | 93 |
| 94 m_pool.append(Entry(m_vendedIterators.take(iterator), iterator)); | 94 m_pool.append(Entry(m_vendedIterators.take(iterator), iterator)); |
| 95 } | 95 } |
| 96 | 96 |
| 97 private: | 97 private: |
| 98 LineBreakIteratorPool() { } | 98 LineBreakIteratorPool() { } |
| 99 | 99 |
| 100 static const size_t capacity = 4; | 100 static const size_t capacity = 4; |
| 101 | 101 |
| 102 typedef pair<AtomicString, UBreakIterator*> Entry; | 102 typedef pair<AtomicString, icu::BreakIterator*> Entry; |
| 103 typedef Vector<Entry, capacity> Pool; | 103 typedef Vector<Entry, capacity> Pool; |
| 104 Pool m_pool; | 104 Pool m_pool; |
| 105 HashMap<UBreakIterator*, AtomicString> m_vendedIterators; | 105 HashMap<icu::BreakIterator*, AtomicString> m_vendedIterators; |
| 106 | 106 |
| 107 friend WTF::ThreadSpecific<LineBreakIteratorPool>::operator LineBreakIterato rPool*(); | 107 friend WTF::ThreadSpecific<LineBreakIteratorPool>::operator LineBreakIterato rPool*(); |
| 108 }; | 108 }; |
| 109 | 109 |
| 110 static TextBreakIterator* ensureIterator(bool& createdIterator, TextBreakIterato r*& iterator, UBreakIteratorType type) | 110 static TextBreakIterator* ensureIterator(bool& createdIterator, TextBreakIterato r*& iterator, UBreakIteratorType type) |
| 111 { | 111 { |
| 112 if (!createdIterator) { | 112 if (!createdIterator) { |
| 113 UErrorCode openStatus = U_ZERO_ERROR; | 113 UErrorCode openStatus = U_ZERO_ERROR; |
| 114 iterator = reinterpret_cast<TextBreakIterator*>(ubrk_open(type, currentT extBreakLocaleID(), 0, 0, &openStatus)); | 114 iterator = reinterpret_cast<TextBreakIterator*>(ubrk_open(type, currentT extBreakLocaleID(), 0, 0, &openStatus)); |
| 115 createdIterator = true; | 115 createdIterator = true; |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 479 if (U_FAILURE(*status)) { | 479 if (U_FAILURE(*status)) { |
| 480 ASSERT(!text); | 480 ASSERT(!text); |
| 481 return 0; | 481 return 0; |
| 482 } | 482 } |
| 483 textInit(text, &textUTF16Funcs, string, length, priorContext, priorContextLe ngth); | 483 textInit(text, &textUTF16Funcs, string, length, priorContext, priorContextLe ngth); |
| 484 return text; | 484 return text; |
| 485 } | 485 } |
| 486 | 486 |
| 487 static UText emptyText = UTEXT_INITIALIZER; | 487 static UText emptyText = UTEXT_INITIALIZER; |
| 488 | 488 |
| 489 static TextBreakIterator* setUpIterator(bool& createdIterator, TextBreakIterator *& iterator, UBreakIteratorType type, const UChar* string, int length) | 489 static TextBreakIterator* wordBreakIterator(const LChar* string, int length) |
| 490 { | 490 { |
| 491 if (!string) | 491 UErrorCode errorCode = U_ZERO_ERROR; |
| 492 return 0; | 492 static TextBreakIterator* breakIter = 0; |
| 493 | 493 if (!breakIter) { |
| 494 iterator = ensureIterator(createdIterator, iterator, type); | 494 breakIter = icu::BreakIterator::createWordInstance(icu::Locale(currentTe xtBreakLocaleID()), errorCode); |
| 495 if (!iterator) | 495 ASSERT_WITH_MESSAGE(U_SUCCESS(errorCode), "ICU could not open a break it erator: %s (%d)", u_errorName(errorCode), errorCode); |
| 496 return 0; | 496 if (!breakIter) |
| 497 | 497 return 0; |
| 498 UErrorCode setTextStatus = U_ZERO_ERROR; | 498 } |
| 499 ubrk_setText(reinterpret_cast<UBreakIterator*>(iterator), string, length, &s etTextStatus); | |
| 500 if (U_FAILURE(setTextStatus)) | |
| 501 return 0; | |
| 502 | |
| 503 return iterator; | |
| 504 } | |
| 505 | |
| 506 static TextBreakIterator* setUpIterator(bool& createdIterator, TextBreakIterator *& iterator, UBreakIteratorType type, const LChar* string, int length) | |
| 507 { | |
| 508 if (!string) | |
| 509 return 0; | |
| 510 | |
| 511 iterator = ensureIterator(createdIterator, iterator, type); | |
| 512 if (!iterator) | |
| 513 return 0; | |
| 514 | 499 |
| 515 UTextWithBuffer textLocal; | 500 UTextWithBuffer textLocal; |
| 516 textLocal.text = emptyText; | 501 textLocal.text = emptyText; |
| 517 textLocal.text.extraSize = sizeof(textLocal.buffer); | 502 textLocal.text.extraSize = sizeof(textLocal.buffer); |
| 518 textLocal.text.pExtra = textLocal.buffer; | 503 textLocal.text.pExtra = textLocal.buffer; |
| 519 | 504 |
| 520 UErrorCode openStatus = U_ZERO_ERROR; | 505 UErrorCode openStatus = U_ZERO_ERROR; |
| 521 UText* text = textOpenLatin1(&textLocal, string, length, 0, 0, &openStatus); | 506 UText* text = textOpenLatin1(&textLocal, string, length, 0, 0, &openStatus); |
| 522 if (U_FAILURE(openStatus)) { | 507 if (U_FAILURE(openStatus)) { |
| 523 LOG_ERROR("textOpenLatin1 failed with status %d", openStatus); | 508 LOG_ERROR("textOpenLatin1 failed with status %d", openStatus); |
| 524 return 0; | 509 return 0; |
| 525 } | 510 } |
| 526 | 511 |
| 527 UErrorCode setTextStatus = U_ZERO_ERROR; | 512 UErrorCode setTextStatus = U_ZERO_ERROR; |
| 528 ubrk_setUText(reinterpret_cast<UBreakIterator*>(iterator), text, &setTextSta tus); | 513 breakIter->setText(text, setTextStatus); |
| 529 if (U_FAILURE(setTextStatus)) { | 514 if (U_FAILURE(setTextStatus)) |
| 530 LOG_ERROR("ubrk_setUText failed with status %d", setTextStatus); | 515 LOG_ERROR("BreakIterator::seText failed with status %d", setTextStatus); |
| 531 // FIXME: Do we need to call utext_close(text) here? | |
| 532 return 0; | |
| 533 } | |
| 534 | 516 |
| 535 utext_close(text); | 517 utext_close(text); |
| 536 | 518 |
| 537 return iterator; | 519 return breakIter; |
| 538 } | 520 } |
| 539 | 521 |
| 540 static TextBreakIterator* wordBreakIterator(const LChar* string, int length) | 522 static void setText16(TextBreakIterator* iter, const UChar* string, int length) |
| 541 { | 523 { |
| 542 static bool createdWordBreakIterator8 = false; | 524 UErrorCode errorCode = U_ZERO_ERROR; |
| 543 static TextBreakIterator* staticWordBreakIterator8; | 525 UText uText = UTEXT_INITIALIZER; |
| 544 return setUpIterator(createdWordBreakIterator8, | 526 utext_openUChars(&uText, string, length, &errorCode); |
| 545 staticWordBreakIterator8, UBRK_WORD, string, length); | 527 if (U_FAILURE(errorCode)) |
| 528 return; | |
| 529 iter->setText(&uText, errorCode); | |
| 546 } | 530 } |
| 547 | 531 |
| 548 TextBreakIterator* wordBreakIterator(const UChar* string, int length) | 532 TextBreakIterator* wordBreakIterator(const UChar* string, int length) |
| 549 { | 533 { |
| 550 static bool createdWordBreakIterator16 = false; | 534 UErrorCode errorCode = U_ZERO_ERROR; |
| 551 static TextBreakIterator* staticWordBreakIterator16; | 535 static TextBreakIterator* breakIter = 0; |
| 552 return setUpIterator(createdWordBreakIterator16, | 536 if (!breakIter) { |
| 553 staticWordBreakIterator16, UBRK_WORD, string, length); | 537 breakIter = icu::BreakIterator::createWordInstance(icu::Locale(currentTe xtBreakLocaleID()), errorCode); |
| 538 ASSERT_WITH_MESSAGE(U_SUCCESS(errorCode), "ICU could not open a break it erator: %s (%d)", u_errorName(errorCode), errorCode); | |
| 539 if (!breakIter) | |
| 540 return 0; | |
| 541 } | |
| 542 setText16(breakIter, string, length); | |
| 543 return breakIter; | |
| 554 } | 544 } |
| 555 | 545 |
| 556 TextBreakIterator* wordBreakIterator(const String& string, int start, int length ) | 546 TextBreakIterator* wordBreakIterator(const String& string, int start, int length ) |
| 557 { | 547 { |
| 558 if (string.isEmpty()) | 548 if (string.isEmpty()) |
| 559 return 0; | 549 return 0; |
| 560 if (string.is8Bit()) | 550 if (string.is8Bit()) |
| 561 return wordBreakIterator(string.characters8() + start, length); | 551 return wordBreakIterator(string.characters8() + start, length); |
| 562 return wordBreakIterator(string.characters16() + start, length); | 552 return wordBreakIterator(string.characters16() + start, length); |
| 563 } | 553 } |
| 564 | 554 |
| 565 TextBreakIterator* acquireLineBreakIterator(const LChar* string, int length, con st AtomicString& locale, const UChar* priorContext, unsigned priorContextLength) | 555 TextBreakIterator* acquireLineBreakIterator(const LChar* string, int length, con st AtomicString& locale, const UChar* priorContext, unsigned priorContextLength) |
| 566 { | 556 { |
| 567 UBreakIterator* iterator = LineBreakIteratorPool::sharedPool().take(locale); | 557 TextBreakIterator* iterator = LineBreakIteratorPool::sharedPool().take(local e); |
| 568 if (!iterator) | 558 if (!iterator) |
| 569 return 0; | 559 return 0; |
| 570 | 560 |
| 571 UTextWithBuffer textLocal; | 561 UTextWithBuffer textLocal; |
| 572 textLocal.text = emptyText; | 562 textLocal.text = emptyText; |
| 573 textLocal.text.extraSize = sizeof(textLocal.buffer); | 563 textLocal.text.extraSize = sizeof(textLocal.buffer); |
| 574 textLocal.text.pExtra = textLocal.buffer; | 564 textLocal.text.pExtra = textLocal.buffer; |
| 575 | 565 |
| 576 UErrorCode openStatus = U_ZERO_ERROR; | 566 UErrorCode openStatus = U_ZERO_ERROR; |
| 577 UText* text = textOpenLatin1(&textLocal, string, length, priorContext, prior ContextLength, &openStatus); | 567 UText* text = textOpenLatin1(&textLocal, string, length, priorContext, prior ContextLength, &openStatus); |
| 578 if (U_FAILURE(openStatus)) { | 568 if (U_FAILURE(openStatus)) { |
| 579 LOG_ERROR("textOpenLatin1 failed with status %d", openStatus); | 569 LOG_ERROR("textOpenLatin1 failed with status %d", openStatus); |
| 580 return 0; | 570 return 0; |
| 581 } | 571 } |
| 582 | 572 |
| 583 UErrorCode setTextStatus = U_ZERO_ERROR; | 573 UErrorCode setTextStatus = U_ZERO_ERROR; |
| 584 ubrk_setUText(iterator, text, &setTextStatus); | 574 iterator->setText(text, setTextStatus); |
| 585 if (U_FAILURE(setTextStatus)) { | 575 if (U_FAILURE(setTextStatus)) { |
| 586 // FIXME: Do we need to call utext_close(text) here? | |
| 587 LOG_ERROR("ubrk_setUText failed with status %d", setTextStatus); | 576 LOG_ERROR("ubrk_setUText failed with status %d", setTextStatus); |
| 588 return 0; | 577 return 0; |
| 589 } | 578 } |
| 590 | 579 |
| 591 utext_close(text); | 580 utext_close(text); |
| 592 | 581 |
| 593 return reinterpret_cast<TextBreakIterator*>(iterator); | 582 return iterator; |
| 594 } | 583 } |
| 595 | 584 |
| 596 TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, con st AtomicString& locale, const UChar* priorContext, unsigned priorContextLength) | 585 TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, con st AtomicString& locale, const UChar* priorContext, unsigned priorContextLength) |
| 597 { | 586 { |
| 598 UBreakIterator* iterator = LineBreakIteratorPool::sharedPool().take(locale); | 587 TextBreakIterator* iterator = LineBreakIteratorPool::sharedPool().take(local e); |
| 599 if (!iterator) | 588 if (!iterator) |
| 600 return 0; | 589 return 0; |
| 601 | 590 |
| 602 UText textLocal = UTEXT_INITIALIZER; | 591 UText textLocal = UTEXT_INITIALIZER; |
| 603 | 592 |
| 604 UErrorCode openStatus = U_ZERO_ERROR; | 593 UErrorCode openStatus = U_ZERO_ERROR; |
| 605 UText* text = textOpenUTF16(&textLocal, string, length, priorContext, priorC ontextLength, &openStatus); | 594 UText* text = textOpenUTF16(&textLocal, string, length, priorContext, priorC ontextLength, &openStatus); |
| 606 if (U_FAILURE(openStatus)) { | 595 if (U_FAILURE(openStatus)) { |
| 607 LOG_ERROR("textOpenUTF16 failed with status %d", openStatus); | 596 LOG_ERROR("textOpenUTF16 failed with status %d", openStatus); |
| 608 return 0; | 597 return 0; |
| 609 } | 598 } |
| 610 | 599 |
| 611 UErrorCode setTextStatus = U_ZERO_ERROR; | 600 UErrorCode setTextStatus = U_ZERO_ERROR; |
| 612 ubrk_setUText(iterator, text, &setTextStatus); | 601 iterator->setText(text, setTextStatus); |
| 613 if (U_FAILURE(setTextStatus)) { | 602 if (U_FAILURE(setTextStatus)) { |
| 614 // FIXME: Do we need to call utext_close(text) here? | |
| 615 LOG_ERROR("ubrk_setUText failed with status %d", setTextStatus); | 603 LOG_ERROR("ubrk_setUText failed with status %d", setTextStatus); |
| 616 return 0; | 604 return 0; |
| 617 } | 605 } |
| 618 | 606 |
| 619 utext_close(text); | 607 utext_close(text); |
| 620 | 608 |
| 621 return reinterpret_cast<TextBreakIterator*>(iterator); | 609 return iterator; |
| 622 } | 610 } |
| 623 | 611 |
| 624 void releaseLineBreakIterator(TextBreakIterator* iterator) | 612 void releaseLineBreakIterator(TextBreakIterator* iterator) |
| 625 { | 613 { |
| 626 ASSERT_ARG(iterator, iterator); | 614 ASSERT_ARG(iterator, iterator); |
| 627 | 615 |
| 628 LineBreakIteratorPool::sharedPool().put(reinterpret_cast<UBreakIterator*>(it erator)); | 616 LineBreakIteratorPool::sharedPool().put(iterator); |
| 629 } | 617 } |
| 630 | 618 |
| 631 static TextBreakIterator* nonSharedCharacterBreakIterator; | 619 static TextBreakIterator* nonSharedCharacterBreakIterator; |
| 632 | 620 |
| 633 static inline bool compareAndSwapNonSharedCharacterBreakIterator(TextBreakIterat or* expected, TextBreakIterator* newValue) | 621 static inline bool compareAndSwapNonSharedCharacterBreakIterator(TextBreakIterat or* expected, TextBreakIterator* newValue) |
| 634 { | 622 { |
| 635 DEFINE_STATIC_LOCAL(Mutex, nonSharedCharacterBreakIteratorMutex, ()); | 623 DEFINE_STATIC_LOCAL(Mutex, nonSharedCharacterBreakIteratorMutex, ()); |
| 636 MutexLocker locker(nonSharedCharacterBreakIteratorMutex); | 624 MutexLocker locker(nonSharedCharacterBreakIteratorMutex); |
| 637 if (nonSharedCharacterBreakIterator != expected) | 625 if (nonSharedCharacterBreakIterator != expected) |
| 638 return false; | 626 return false; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 669 , m_length(0) | 657 , m_length(0) |
| 670 , m_iterator(0) | 658 , m_iterator(0) |
| 671 { | 659 { |
| 672 createIteratorForBuffer(buffer, length); | 660 createIteratorForBuffer(buffer, length); |
| 673 } | 661 } |
| 674 | 662 |
| 675 void NonSharedCharacterBreakIterator::createIteratorForBuffer(const UChar* buffe r, unsigned length) | 663 void NonSharedCharacterBreakIterator::createIteratorForBuffer(const UChar* buffe r, unsigned length) |
| 676 { | 664 { |
| 677 m_iterator = nonSharedCharacterBreakIterator; | 665 m_iterator = nonSharedCharacterBreakIterator; |
| 678 bool createdIterator = m_iterator && compareAndSwapNonSharedCharacterBreakIt erator(m_iterator, 0); | 666 bool createdIterator = m_iterator && compareAndSwapNonSharedCharacterBreakIt erator(m_iterator, 0); |
| 679 m_iterator = setUpIterator(createdIterator, m_iterator, UBRK_CHARACTER, buff er, length); | 667 if (!createdIterator) { |
| 668 UErrorCode errorCode = U_ZERO_ERROR; | |
| 669 m_iterator = icu::BreakIterator::createCharacterInstance(icu::Locale(cur rentTextBreakLocaleID()), errorCode); | |
| 670 ASSERT_WITH_MESSAGE(U_SUCCESS(errorCode), "ICU could not open a break it erator: %s (%d)", u_errorName(errorCode), errorCode); | |
| 671 } | |
| 672 | |
| 673 setText16(m_iterator, buffer, length); | |
| 680 } | 674 } |
| 681 | 675 |
| 682 NonSharedCharacterBreakIterator::~NonSharedCharacterBreakIterator() | 676 NonSharedCharacterBreakIterator::~NonSharedCharacterBreakIterator() |
| 683 { | 677 { |
| 684 if (m_is8Bit) | 678 if (m_is8Bit) |
| 685 return; | 679 return; |
| 686 if (!compareAndSwapNonSharedCharacterBreakIterator(0, m_iterator)) | 680 if (!compareAndSwapNonSharedCharacterBreakIterator(0, m_iterator)) |
| 687 ubrk_close(reinterpret_cast<UBreakIterator*>(m_iterator)); | 681 delete m_iterator; |
| 688 } | 682 } |
| 689 | 683 |
| 690 int NonSharedCharacterBreakIterator::next() | 684 int NonSharedCharacterBreakIterator::next() |
| 691 { | 685 { |
| 692 if (!m_is8Bit) | 686 if (!m_is8Bit) |
| 693 return textBreakNext(m_iterator); | 687 return m_iterator->next(); |
| 694 | 688 |
| 695 if (m_offset >= m_length) | 689 if (m_offset >= m_length) |
| 696 return TextBreakDone; | 690 return TextBreakDone; |
| 697 | 691 |
| 698 m_offset += clusterLengthStartingAt(m_offset); | 692 m_offset += clusterLengthStartingAt(m_offset); |
| 699 return m_offset; | 693 return m_offset; |
| 700 } | 694 } |
| 701 | 695 |
| 702 int NonSharedCharacterBreakIterator::current() | 696 int NonSharedCharacterBreakIterator::current() |
| 703 { | 697 { |
| 704 if (!m_is8Bit) | 698 if (!m_is8Bit) |
| 705 return textBreakCurrent(m_iterator); | 699 return m_iterator->current(); |
| 706 return m_offset; | 700 return m_offset; |
| 707 } | 701 } |
| 708 | 702 |
| 709 bool NonSharedCharacterBreakIterator::isBreak(int offset) const | 703 bool NonSharedCharacterBreakIterator::isBreak(int offset) const |
| 710 { | 704 { |
| 711 if (!m_is8Bit) | 705 if (!m_is8Bit) |
| 712 return isTextBreak(m_iterator, offset); | 706 return m_iterator->isBoundary(offset); |
| 713 return !isLFAfterCR(offset); | 707 return !isLFAfterCR(offset); |
| 714 } | 708 } |
| 715 | 709 |
| 716 int NonSharedCharacterBreakIterator::preceding(int offset) const | 710 int NonSharedCharacterBreakIterator::preceding(int offset) const |
| 717 { | 711 { |
| 718 if (!m_is8Bit) | 712 if (!m_is8Bit) |
| 719 return textBreakPreceding(m_iterator, offset); | 713 return m_iterator->preceding(offset); |
| 720 if (offset <= 0) | 714 if (offset <= 0) |
| 721 return TextBreakDone; | 715 return TextBreakDone; |
| 722 if (isLFAfterCR(offset)) | 716 if (isLFAfterCR(offset)) |
| 723 return offset - 2; | 717 return offset - 2; |
| 724 return offset - 1; | 718 return offset - 1; |
| 725 } | 719 } |
| 726 | 720 |
| 727 int NonSharedCharacterBreakIterator::following(int offset) const | 721 int NonSharedCharacterBreakIterator::following(int offset) const |
| 728 { | 722 { |
| 729 if (!m_is8Bit) | 723 if (!m_is8Bit) |
| 730 return textBreakFollowing(m_iterator, offset); | 724 return m_iterator->following(offset); |
| 731 if (static_cast<unsigned>(offset) >= m_length) | 725 if (static_cast<unsigned>(offset) >= m_length) |
| 732 return TextBreakDone; | 726 return TextBreakDone; |
| 733 return offset + clusterLengthStartingAt(offset); | 727 return offset + clusterLengthStartingAt(offset); |
| 734 } | 728 } |
| 735 | 729 |
| 736 TextBreakIterator* sentenceBreakIterator(const UChar* string, int length) | 730 TextBreakIterator* sentenceBreakIterator(const UChar* string, int length) |
| 737 { | 731 { |
| 738 static bool createdSentenceBreakIterator = false; | 732 UErrorCode openStatus = U_ZERO_ERROR; |
| 739 static TextBreakIterator* staticSentenceBreakIterator; | 733 static TextBreakIterator* iterator = 0; |
| 740 return setUpIterator(createdSentenceBreakIterator, | 734 if (!iterator) { |
| 741 staticSentenceBreakIterator, UBRK_SENTENCE, string, length); | 735 iterator = icu::BreakIterator::createSentenceInstance(icu::Locale(curre ntTextBreakLocaleID()), openStatus); |
| 742 } | 736 ASSERT_WITH_MESSAGE(U_SUCCESS(openStatus), "ICU could not open a break i terator: %s (%d)", u_errorName(openStatus), openStatus); |
| 737 if (!iterator) | |
| 738 return 0; | |
| 739 } | |
| 743 | 740 |
| 744 int textBreakFirst(TextBreakIterator* iterator) | 741 setText16(iterator, string, length); |
| 745 { | 742 return iterator; |
| 746 return ubrk_first(reinterpret_cast<UBreakIterator*>(iterator)); | |
| 747 } | |
| 748 | |
| 749 int textBreakLast(TextBreakIterator* iterator) | |
| 750 { | |
| 751 return ubrk_last(reinterpret_cast<UBreakIterator*>(iterator)); | |
| 752 } | |
| 753 | |
| 754 int textBreakNext(TextBreakIterator* iterator) | |
| 755 { | |
| 756 return ubrk_next(reinterpret_cast<UBreakIterator*>(iterator)); | |
| 757 } | |
| 758 | |
| 759 int textBreakPrevious(TextBreakIterator* iterator) | |
| 760 { | |
| 761 return ubrk_previous(reinterpret_cast<UBreakIterator*>(iterator)); | |
| 762 } | |
| 763 | |
| 764 int textBreakPreceding(TextBreakIterator* iterator, int pos) | |
| 765 { | |
| 766 return ubrk_preceding(reinterpret_cast<UBreakIterator*>(iterator), pos); | |
| 767 } | |
| 768 | |
| 769 int textBreakFollowing(TextBreakIterator* iterator, int pos) | |
| 770 { | |
| 771 return ubrk_following(reinterpret_cast<UBreakIterator*>(iterator), pos); | |
| 772 } | |
| 773 | |
| 774 int textBreakCurrent(TextBreakIterator* iterator) | |
| 775 { | |
| 776 return ubrk_current(reinterpret_cast<UBreakIterator*>(iterator)); | |
| 777 } | |
| 778 | |
| 779 bool isTextBreak(TextBreakIterator* iterator, int position) | |
| 780 { | |
| 781 return ubrk_isBoundary(reinterpret_cast<UBreakIterator*>(iterator), position ); | |
| 782 } | 743 } |
| 783 | 744 |
| 784 bool isWordTextBreak(TextBreakIterator* iterator) | 745 bool isWordTextBreak(TextBreakIterator* iterator) |
| 785 { | 746 { |
| 786 int ruleStatus = ubrk_getRuleStatus(reinterpret_cast<UBreakIterator*>(iterat or)); | 747 int ruleStatus = iterator->getRuleStatus(); |
|
jungshik at Google
2013/10/11 20:18:30
With ICU 51 or earlier (without a patch to add get
| |
| 787 return ruleStatus != UBRK_WORD_NONE; | 748 return ruleStatus != UBRK_WORD_NONE; |
| 788 } | 749 } |
| 789 | 750 |
| 790 static TextBreakIterator* setUpIteratorWithRules(bool& createdIterator, TextBrea kIterator*& iterator, | 751 static TextBreakIterator* setUpIteratorWithRules(const char* breakRules, const U Char* string, int length) |
| 791 const char* breakRules, const UChar* string, int length) | |
| 792 { | 752 { |
| 793 if (!string) | 753 if (!string) |
| 794 return 0; | 754 return 0; |
| 795 | 755 |
| 796 if (!createdIterator) { | 756 static TextBreakIterator* iterator = 0; |
| 757 if (!iterator) { | |
| 797 UParseError parseStatus; | 758 UParseError parseStatus; |
| 798 UErrorCode openStatus = U_ZERO_ERROR; | 759 UErrorCode openStatus = U_ZERO_ERROR; |
| 799 Vector<UChar> rules; | 760 Vector<UChar> rules; |
| 800 String(breakRules).appendTo(rules); | 761 String(breakRules).appendTo(rules); |
| 801 iterator = reinterpret_cast<TextBreakIterator*>(ubrk_openRules(rules.dat a(), rules.size(), 0, 0, &parseStatus, &openStatus)); | 762 |
| 802 createdIterator = true; | 763 iterator = new icu::RuleBasedBreakIterator(icu::UnicodeString(rules.data (), rules.size()), parseStatus, openStatus); |
| 803 ASSERT_WITH_MESSAGE(U_SUCCESS(openStatus), "ICU could not open a break i terator: %s (%d)", u_errorName(openStatus), openStatus); | 764 ASSERT_WITH_MESSAGE(U_SUCCESS(openStatus), "ICU could not open a break i terator: %s (%d)", u_errorName(openStatus), openStatus); |
| 765 if (!iterator) | |
| 766 return 0; | |
| 804 } | 767 } |
| 805 if (!iterator) | |
| 806 return 0; | |
| 807 | 768 |
| 808 UErrorCode setTextStatus = U_ZERO_ERROR; | 769 setText16(iterator, string, length); |
| 809 ubrk_setText(reinterpret_cast<UBreakIterator*>(iterator), string, length, &s etTextStatus); | |
| 810 if (U_FAILURE(setTextStatus)) | |
| 811 return 0; | |
| 812 | |
| 813 return iterator; | 770 return iterator; |
| 814 } | 771 } |
| 815 | 772 |
| 816 TextBreakIterator* cursorMovementIterator(const UChar* string, int length) | 773 TextBreakIterator* cursorMovementIterator(const UChar* string, int length) |
| 817 { | 774 { |
| 818 // This rule set is based on character-break iterator rules of ICU 4.0 | 775 // This rule set is based on character-break iterator rules of ICU 4.0 |
| 819 // <http://source.icu-project.org/repos/icu/icu/tags/release-4-0/source/data /brkitr/char.txt>. | 776 // <http://source.icu-project.org/repos/icu/icu/tags/release-4-0/source/data /brkitr/char.txt>. |
| 820 // The major differences from the original ones are listed below: | 777 // The major differences from the original ones are listed below: |
| 821 // * Replaced '[\p{Grapheme_Cluster_Break = SpacingMark}]' with '[\p{General _Category = Spacing Mark} - $Extend]' for ICU 3.8 or earlier; | 778 // * Replaced '[\p{Grapheme_Cluster_Break = SpacingMark}]' with '[\p{General _Category = Spacing Mark} - $Extend]' for ICU 3.8 or earlier; |
| 822 // * Removed rules that prevent a cursor from moving after prepend character s (Bug 24342); | 779 // * Removed rules that prevent a cursor from moving after prepend character s (Bug 24342); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 890 "$Hin1 $HinV $Hin0;" // Devanagari Virama (backward) | 847 "$Hin1 $HinV $Hin0;" // Devanagari Virama (backward) |
| 891 "$Ben1 $BenV $Ben0;" // Bengali Virama (backward) | 848 "$Ben1 $BenV $Ben0;" // Bengali Virama (backward) |
| 892 "$Pan1 $PanV $Pan0;" // Gurmukhi Virama (backward) | 849 "$Pan1 $PanV $Pan0;" // Gurmukhi Virama (backward) |
| 893 "$Guj1 $GujV $Guj0;" // Gujarati Virama (backward) | 850 "$Guj1 $GujV $Guj0;" // Gujarati Virama (backward) |
| 894 "$Ori1 $OriV $Ori0;" // Gujarati Virama (backward) | 851 "$Ori1 $OriV $Ori0;" // Gujarati Virama (backward) |
| 895 "$Tel1 $TelV $Tel0;" // Telugu Virama (backward) | 852 "$Tel1 $TelV $Tel0;" // Telugu Virama (backward) |
| 896 "$Kan1 $KanV $Kan0;" // Kannada Virama (backward) | 853 "$Kan1 $KanV $Kan0;" // Kannada Virama (backward) |
| 897 "$Mal1 $MalV $Mal0;" // Malayalam Virama (backward) | 854 "$Mal1 $MalV $Mal0;" // Malayalam Virama (backward) |
| 898 "!!safe_reverse;" | 855 "!!safe_reverse;" |
| 899 "!!safe_forward;"; | 856 "!!safe_forward;"; |
| 900 static bool createdCursorMovementIterator = false; | 857 |
| 901 static TextBreakIterator* staticCursorMovementIterator; | 858 return setUpIteratorWithRules(kRules, string, length); |
| 902 return setUpIteratorWithRules(createdCursorMovementIterator, staticCursorMov ementIterator, kRules, string, length); | |
| 903 } | 859 } |
| 904 | 860 |
| 905 } | 861 } |
| OLD | NEW |