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 icu::RuleBasedBreakIterator* ruleBasedBreakIterator = static_cast<icu::RuleB
asedBreakIterator*>(iterator); |
| 748 int ruleStatus = ruleBasedBreakIterator->getRuleStatus(); |
787 return ruleStatus != UBRK_WORD_NONE; | 749 return ruleStatus != UBRK_WORD_NONE; |
788 } | 750 } |
789 | 751 |
790 static TextBreakIterator* setUpIteratorWithRules(bool& createdIterator, TextBrea
kIterator*& iterator, | 752 static TextBreakIterator* setUpIteratorWithRules(const char* breakRules, const U
Char* string, int length) |
791 const char* breakRules, const UChar* string, int length) | |
792 { | 753 { |
793 if (!string) | 754 if (!string) |
794 return 0; | 755 return 0; |
795 | 756 |
796 if (!createdIterator) { | 757 static TextBreakIterator* iterator = 0; |
| 758 if (!iterator) { |
797 UParseError parseStatus; | 759 UParseError parseStatus; |
798 UErrorCode openStatus = U_ZERO_ERROR; | 760 UErrorCode openStatus = U_ZERO_ERROR; |
799 Vector<UChar> rules; | 761 Vector<UChar> rules; |
800 String(breakRules).appendTo(rules); | 762 String(breakRules).appendTo(rules); |
801 iterator = reinterpret_cast<TextBreakIterator*>(ubrk_openRules(rules.dat
a(), rules.size(), 0, 0, &parseStatus, &openStatus)); | 763 |
802 createdIterator = true; | 764 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); | 765 ASSERT_WITH_MESSAGE(U_SUCCESS(openStatus), "ICU could not open a break i
terator: %s (%d)", u_errorName(openStatus), openStatus); |
| 766 if (!iterator) |
| 767 return 0; |
804 } | 768 } |
805 if (!iterator) | |
806 return 0; | |
807 | 769 |
808 UErrorCode setTextStatus = U_ZERO_ERROR; | 770 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; | 771 return iterator; |
814 } | 772 } |
815 | 773 |
816 TextBreakIterator* cursorMovementIterator(const UChar* string, int length) | 774 TextBreakIterator* cursorMovementIterator(const UChar* string, int length) |
817 { | 775 { |
818 // This rule set is based on character-break iterator rules of ICU 4.0 | 776 // 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>. | 777 // <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: | 778 // 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; | 779 // * 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); | 780 // * 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) | 848 "$Hin1 $HinV $Hin0;" // Devanagari Virama (backward) |
891 "$Ben1 $BenV $Ben0;" // Bengali Virama (backward) | 849 "$Ben1 $BenV $Ben0;" // Bengali Virama (backward) |
892 "$Pan1 $PanV $Pan0;" // Gurmukhi Virama (backward) | 850 "$Pan1 $PanV $Pan0;" // Gurmukhi Virama (backward) |
893 "$Guj1 $GujV $Guj0;" // Gujarati Virama (backward) | 851 "$Guj1 $GujV $Guj0;" // Gujarati Virama (backward) |
894 "$Ori1 $OriV $Ori0;" // Gujarati Virama (backward) | 852 "$Ori1 $OriV $Ori0;" // Gujarati Virama (backward) |
895 "$Tel1 $TelV $Tel0;" // Telugu Virama (backward) | 853 "$Tel1 $TelV $Tel0;" // Telugu Virama (backward) |
896 "$Kan1 $KanV $Kan0;" // Kannada Virama (backward) | 854 "$Kan1 $KanV $Kan0;" // Kannada Virama (backward) |
897 "$Mal1 $MalV $Mal0;" // Malayalam Virama (backward) | 855 "$Mal1 $MalV $Mal0;" // Malayalam Virama (backward) |
898 "!!safe_reverse;" | 856 "!!safe_reverse;" |
899 "!!safe_forward;"; | 857 "!!safe_forward;"; |
900 static bool createdCursorMovementIterator = false; | 858 |
901 static TextBreakIterator* staticCursorMovementIterator; | 859 return setUpIteratorWithRules(kRules, string, length); |
902 return setUpIteratorWithRules(createdCursorMovementIterator, staticCursorMov
ementIterator, kRules, string, length); | |
903 } | 860 } |
904 | 861 |
905 } | 862 } |
OLD | NEW |