diff options
author | hashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-08 04:32:24 +0000 |
---|---|---|
committer | hashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-08 04:32:24 +0000 |
commit | 67512c7eb8d859c2b7b22f38cce2d9562ac049ca (patch) | |
tree | 29fdaed6d0592fbfe72646494737bfde8eadf589 /views/ime | |
parent | e11fc5c84da681143194e9b576ce5c96d86b3e75 (diff) | |
download | chromium_src-67512c7eb8d859c2b7b22f38cce2d9562ac049ca.zip chromium_src-67512c7eb8d859c2b7b22f38cce2d9562ac049ca.tar.gz chromium_src-67512c7eb8d859c2b7b22f38cce2d9562ac049ca.tar.bz2 |
CL for readability review
BUG=NONE
TEST=NONE
Review URL: http://codereview.chromium.org/7264015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@91808 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/ime')
-rw-r--r-- | views/ime/character_composer.cc | 260 | ||||
-rw-r--r-- | views/ime/character_composer.h | 12 | ||||
-rw-r--r-- | views/ime/character_composer_unittest.cc | 36 | ||||
-rw-r--r-- | views/ime/input_method_ibus.cc | 2 |
4 files changed, 198 insertions, 112 deletions
diff --git a/views/ime/character_composer.cc b/views/ime/character_composer.cc index 3618477..fb162f1 100644 --- a/views/ime/character_composer.cc +++ b/views/ime/character_composer.cc @@ -4,25 +4,100 @@ #include "character_composer.h" -#include <cstdlib> +#include <algorithm> +#include <iterator> #include "third_party/gtk+/gdk/gdkkeysyms.h" +#include "ui/base/gtk/gtk_integers.h" namespace { -inline int CompareSequenceValue(unsigned int key, uint16 value) { - return (key > value) ? 1 : ((key < value) ? -1 : 0); +typedef std::vector<unsigned int> ComposeBufferType; + +// An iterator class to apply std::lower_bound for composition table. +class SequenceIterator + : public std::iterator<std::random_access_iterator_tag, const uint16*> { + public: + SequenceIterator() : ptr_(NULL), stride_(0) {} + SequenceIterator(const uint16* ptr, int stride) + : ptr_(ptr), stride_(stride) {} + + const uint16* ptr() const {return ptr_;} + int stride() const {return stride_;} + + SequenceIterator& operator++() { + ptr_ += stride_; + return *this; + } + SequenceIterator& operator+=(int n) { + ptr_ += stride_*n; + return *this; + } + + const uint16* operator*() const {return ptr_;} + + private: + const uint16* ptr_; + int stride_; +}; + +inline SequenceIterator operator+(const SequenceIterator& l, int r) { + return SequenceIterator(l) += r; +} + +inline int operator-(const SequenceIterator& l, const SequenceIterator& r) { + const int d = l.ptr() - r.ptr(); + DCHECK(l.stride() == r.stride() && l.stride() > 0 && d%l.stride() == 0); + return d/l.stride(); +} + +inline bool operator==(const SequenceIterator& l, const SequenceIterator& r) { + DCHECK(l.stride() == r.stride()); + return l.ptr() == r.ptr(); +} + +inline bool operator!=(const SequenceIterator& l, const SequenceIterator& r) { + return !(l == r); } +// A function to compare keycode value. +inline int CompareSequenceValue(unsigned int l, unsigned int r) { + return (l > r) ? 1 : ((l < r) ? -1 : 0); +} + +// A template to make |CompareFunc| work like operator<. +// |CompareFunc| is required to implement a member function, +// int operator()(const ComposeBufferType& l, const uint16* r) const. +template<typename CompareFunc> +struct ComparatorAdoptor { + bool operator()(const ComposeBufferType& l, const uint16* r) const { + return CompareFunc()(l, r) == -1; + } + bool operator()(const uint16* l, const ComposeBufferType& r) const { + return CompareFunc()(r, l) == 1; + } +}; + class ComposeChecker { public: + // This class does not take the ownership of |data|, |data| should be alive + // for the lifetime of the object. + // |data| is a pointer to the head of an array of + // length (|max_sequence_length| + 2)*|n_sequences|. + // Every (|max_sequence_length| + 2) elements of |data| represent an entry. + // First |max_sequence_length| elements of an entry is the sequecne which + // composes the character represented by the last two elements of the entry. ComposeChecker(const uint16* data, int max_sequence_length, int n_sequences); - bool CheckSequence(const std::vector<unsigned int>& sequence, + bool CheckSequence(const ComposeBufferType& sequence, uint32* composed_character) const; private: - static int CompareSequence(const void* key_void, const void* value_void); + struct CompareSequence { + int operator()(const ComposeBufferType& l, const uint16* r) const; + }; + // This class does not take the ownership of |data_|, + // the dtor does not delete |data_|. const uint16* data_; int max_sequence_length_; int n_sequences_; @@ -40,46 +115,38 @@ ComposeChecker::ComposeChecker(const uint16* data, row_stride_(max_sequence_length + 2) { } -bool ComposeChecker::CheckSequence( - const std::vector<unsigned int>& sequence, - uint32* composed_character) const { +bool ComposeChecker::CheckSequence(const ComposeBufferType& sequence, + uint32* composed_character) const { const int sequence_length = sequence.size(); if (sequence_length > max_sequence_length_) return false; - // Find sequence in the table - const uint16* found = static_cast<const uint16*>( - bsearch(&sequence, data_, n_sequences_, - sizeof(uint16)*row_stride_, CompareSequence)); - if (!found) + // Find sequence in the table. + const SequenceIterator begin(data_, row_stride_); + const SequenceIterator end = begin + n_sequences_; + const SequenceIterator found = std::lower_bound( + begin, end, sequence, ComparatorAdoptor<CompareSequence>()); + if (found == end || CompareSequence()(sequence, *found) != 0) return false; - // Ensure |found| is pointing the first matching element - while (found > data_ && - CompareSequence(&sequence, found - row_stride_) == 0) - found -= row_stride_; - - if (sequence_length == max_sequence_length_ || found[sequence_length] == 0) { - // |found| is not partially matching. It's fully matching - const uint16* data_end = data_ + row_stride_*n_sequences_; - if (found + row_stride_ >= data_end || - CompareSequence(&sequence, found + row_stride_) != 0) { - // There is no composition longer than |found| which matches to |sequence| - const uint32 value = (found[max_sequence_length_] << 16) | - found[max_sequence_length_ + 1]; + + if (sequence_length == max_sequence_length_ || + (*found)[sequence_length] == 0) { + // |found| is not partially matching. It's fully matching. + if (found + 1 == end || + CompareSequence()(sequence, *(found + 1)) != 0) { + // There is no composition longer than |found| which matches to + // |sequence|. + const uint32 value = ((*found)[max_sequence_length_] << 16) | + (*found)[max_sequence_length_ + 1]; *composed_character = value; } } return true; } -// static -int ComposeChecker::CompareSequence(const void* key_void, - const void* value_void) { - typedef std::vector<unsigned int> KeyType; - const KeyType& key = *static_cast<const KeyType*>(key_void); - const uint16* value = static_cast<const uint16*>(value_void); - - for(size_t i = 0; i < key.size(); ++i) { - const int compare_result = CompareSequenceValue(key[i], value[i]); +int ComposeChecker::CompareSequence::operator()(const ComposeBufferType& l, + const uint16* r) const { + for(size_t i = 0; i < l.size(); ++i) { + const int compare_result = CompareSequenceValue(l[i], r[i]); if(compare_result) return compare_result; } @@ -89,18 +156,33 @@ int ComposeChecker::CompareSequence(const void* key_void, class ComposeCheckerWithCompactTable { public: + // This class does not take the ownership of |data|, |data| should be alive + // for the lifetime of the object. + // First |index_size|*|index_stride| elements of |data| are an index table. + // Every |index_stride| elements of an index table are an index entry. + // If you are checking with a sequence of length N beginning with character C, + // you have to find an index entry whose first element is C, then get the N-th + // element of the index entry as the index. + // The index is pointing the element of |data| where the composition table for + // sequences of length N beginning with C is placed. + ComposeCheckerWithCompactTable(const uint16* data, int max_sequence_length, int index_size, int index_stride); - bool CheckSequence(const std::vector<unsigned int>& sequence, + bool CheckSequence(const ComposeBufferType& sequence, uint32* composed_character) const; private: - static int CompareSequenceFront(const void* key_void, const void* value_void); - static int CompareSequenceSkipFront(const void* key_void, - const void* value_void); - + struct CompareSequenceFront { + int operator()(const ComposeBufferType& l, const uint16* r) const; + }; + struct CompareSequenceSkipFront { + int operator()(const ComposeBufferType& l, const uint16* r) const; + }; + + // This class does not take the ownership of |data_|, + // the dtor does not delete |data_|. const uint16* data_; int max_sequence_length_; int index_size_; @@ -119,34 +201,39 @@ ComposeCheckerWithCompactTable::ComposeCheckerWithCompactTable( } bool ComposeCheckerWithCompactTable::CheckSequence( - const std::vector<unsigned int>& sequence, + const ComposeBufferType& sequence, uint32* composed_character) const { const int compose_length = sequence.size(); if (compose_length > max_sequence_length_) return false; - // Find corresponding index for the first keypress - const uint16* index = static_cast<const uint16*>( - bsearch(&sequence, data_, index_size_, - sizeof(uint16)*index_stride_, CompareSequenceFront)); - if (!index) + // Find corresponding index for the first keypress. + const SequenceIterator index_begin(data_, index_stride_); + const SequenceIterator index_end = index_begin + index_size_; + const SequenceIterator index = + std::lower_bound(index_begin, index_end, sequence, + ComparatorAdoptor<CompareSequenceFront>()); + if (index == index_end || CompareSequenceFront()(sequence, *index) != 0) return false; if (compose_length == 1) return true; - // Check for composition sequences + // Check for composition sequences. for (int length = compose_length - 1; length < max_sequence_length_; ++length) { - const uint16* table = data_ + index[length]; - const uint16* table_next = data_ + index[length + 1]; + const uint16* table = data_ + (*index)[length]; + const uint16* table_next = data_ + (*index)[length + 1]; if (table_next > table) { - // There are composition sequences for this |length| + // There are composition sequences for this |length|. const int row_stride = length + 1; const int n_sequences = (table_next - table)/row_stride; - const uint16* seq = static_cast<const uint16*>( - bsearch(&sequence, table, n_sequences, - sizeof(uint16)*row_stride, CompareSequenceSkipFront)); - if (seq) { - if (length == compose_length - 1) // exact match - *composed_character = seq[length]; + const SequenceIterator table_begin(table, row_stride); + const SequenceIterator table_end = table_begin + n_sequences; + const SequenceIterator found = + std::lower_bound(table_begin, table_end, sequence, + ComparatorAdoptor<CompareSequenceSkipFront>()); + if (found != table_end && + CompareSequenceSkipFront()(sequence, *found) == 0) { + if (length == compose_length - 1) // Exact match. + *composed_character = (*found)[length]; return true; } } @@ -154,38 +241,31 @@ bool ComposeCheckerWithCompactTable::CheckSequence( return false; } -// static -int ComposeCheckerWithCompactTable::CompareSequenceFront( - const void* key_void, - const void* value_void) { - typedef std::vector<unsigned int> KeyType; - const KeyType& key = *static_cast<const KeyType*>(key_void); - const uint16* value = static_cast<const uint16*>(value_void); - - return CompareSequenceValue(key[0], value[0]); +int ComposeCheckerWithCompactTable::CompareSequenceFront::operator()( + const ComposeBufferType& l, const uint16* r) const { + return CompareSequenceValue(l[0], r[0]); } -// static -int ComposeCheckerWithCompactTable::CompareSequenceSkipFront( - const void* key_void, - const void* value_void) { - typedef std::vector<unsigned int> KeyType; - const KeyType& key = *static_cast<const KeyType*>(key_void); - const uint16* value = static_cast<const uint16*>(value_void); - - for(size_t i = 1; i < key.size(); ++i) { - const int compare_result = CompareSequenceValue(key[i], value[i - 1]); +int ComposeCheckerWithCompactTable::CompareSequenceSkipFront::operator()( + const ComposeBufferType& l, const uint16* r) const { + for(size_t i = 1; i < l.size(); ++i) { + const int compare_result = CompareSequenceValue(l[i], r[i - 1]); if(compare_result) return compare_result; } return 0; } -// Main table -typedef uint16 guint16; + +// Main table. + +// This file is included here intentionally, instead of the top of the file, +// because including this file outside the anonymous namespace will define a +// global constant and contaminate the global namespace. #include "third_party/gtk+/gtk/gtkimcontextsimpleseqs.h" -// Additional table + +// Additional table. // The difference between this and the default input method is the handling // of C+acute - this method produces C WITH CEDILLA rather than C WITH ACUTE. @@ -232,24 +312,24 @@ bool KeypressShouldBeIgnored(unsigned int keycode) { } } -bool CheckCharacterComposeTable(const std::vector<unsigned int>& sequence, +bool CheckCharacterComposeTable(const ComposeBufferType& sequence, uint32* composed_character) { - // Check cedilla compose table + // Check cedilla compose table. const ComposeChecker kCedillaComposeChecker( - cedilla_compose_seqs, 4, arraysize(cedilla_compose_seqs)/(4 + 2)); + cedilla_compose_seqs, 4, arraysize(cedilla_compose_seqs)/(4 + 2)); if (kCedillaComposeChecker.CheckSequence(sequence, composed_character)) return true; - // Check main compose table + // Check main compose table. const ComposeCheckerWithCompactTable kMainComposeChecker( - gtk_compose_seqs_compact, 5, 26, 6); + gtk_compose_seqs_compact, 5, 24, 6); if (kMainComposeChecker.CheckSequence(sequence, composed_character)) return true; return false; } -} // anonymous namespace +} // namespace namespace views { @@ -268,22 +348,22 @@ bool CharacterComposer::FilterKeyPress(unsigned int keycode) { compose_buffer_.push_back(keycode); - // Check compose table + // Check compose table. composed_character_.clear(); uint32 composed_character_utf32 = 0; if (CheckCharacterComposeTable(compose_buffer_, &composed_character_utf32)) { - // Key press is recognized as a part of composition + // Key press is recognized as a part of composition. if (composed_character_utf32 !=0) { - // We get a composed character + // We get a composed character. compose_buffer_.clear(); - // We assume that composed character is in BMP + // We assume that composed character is in BMP. if (composed_character_utf32 <= 0xffff) composed_character_ += static_cast<char16>(composed_character_utf32); } return true; } - // Key press is not a part of composition - compose_buffer_.pop_back(); // remove the keypress added this time + // Key press is not a part of composition. + compose_buffer_.pop_back(); // Remove the keypress added this time. if (!compose_buffer_.empty()) { compose_buffer_.clear(); return true; diff --git a/views/ime/character_composer.h b/views/ime/character_composer.h index d0dcc5c..291e80a 100644 --- a/views/ime/character_composer.h +++ b/views/ime/character_composer.h @@ -7,6 +7,7 @@ #pragma once #include <vector> + #include "base/basictypes.h" #include "base/string_util.h" @@ -24,17 +25,22 @@ class CharacterComposer { void Reset(); - // Filters keypress. Returns true if the keypress is handled. + // Filters keypress. + // Returns true if the keypress is recognized as a part of composition + // sequence. bool FilterKeyPress(unsigned int keycode); // Returns a string consisting of composed character. - // Empty is returned when there is no composition result. - const string16& GetComposedCharacter() const { + // Empty string is returned when there is no composition result. + const string16& composed_character() const { return composed_character_; } private: + // Remembers keypresses previously filtered. std::vector<unsigned int> compose_buffer_; + + // A string representing the composed character. string16 composed_character_; DISALLOW_COPY_AND_ASSIGN(CharacterComposer); diff --git a/views/ime/character_composer_unittest.cc b/views/ime/character_composer_unittest.cc index ed2b4d1..5e09719 100644 --- a/views/ime/character_composer_unittest.cc +++ b/views/ime/character_composer_unittest.cc @@ -12,29 +12,29 @@ namespace views { namespace { -// Expects key is not filtered and no character is composed +// Expects key is not filtered and no character is composed. void ExpectKeyNotFiltered(CharacterComposer* character_composer, uint key) { EXPECT_FALSE(character_composer->FilterKeyPress(key)); - EXPECT_TRUE(character_composer->GetComposedCharacter().empty()); + EXPECT_TRUE(character_composer->composed_character().empty()); } -// Expects key is filtered and no character is composed +// Expects key is filtered and no character is composed. void ExpectKeyFiltered(CharacterComposer* character_composer, uint key) { EXPECT_TRUE(character_composer->FilterKeyPress(key)); - EXPECT_TRUE(character_composer->GetComposedCharacter().empty()); + EXPECT_TRUE(character_composer->composed_character().empty()); } -// Expects |expected_character| is composed after sequence [key1, key2] +// Expects |expected_character| is composed after sequence [key1, key2]. void ExpectCharacterComposed(CharacterComposer* character_composer, uint key1, uint key2, const string16& expected_character) { ExpectKeyFiltered(character_composer, key1); EXPECT_TRUE(character_composer->FilterKeyPress(key2)); - EXPECT_EQ(character_composer->GetComposedCharacter(), expected_character); + EXPECT_EQ(character_composer->composed_character(), expected_character); } -// Expects |expected_character| is composed after sequence [key1, key2, key3] +// Expects |expected_character| is composed after sequence [key1, key2, key3]. void ExpectCharacterComposed(CharacterComposer* character_composer, uint key1, uint key2, @@ -45,7 +45,7 @@ void ExpectCharacterComposed(CharacterComposer* character_composer, } // Expects |expected_character| is composed after sequence [key1, key2, key3, -// key 4] +// key 4]. void ExpectCharacterComposed(CharacterComposer* character_composer, uint key1, uint key2, @@ -57,11 +57,11 @@ void ExpectCharacterComposed(CharacterComposer* character_composer, expected_character); } -} // anonymous namespace +} // namespace TEST(CharacterComposerTest, InitialState) { CharacterComposer character_composer; - EXPECT_TRUE(character_composer.GetComposedCharacter().empty()); + EXPECT_TRUE(character_composer.composed_character().empty()); } TEST(CharacterComposerTest, NormalKeyIsNotFiltered) { @@ -78,16 +78,16 @@ TEST(CharacterComposerTest, NormalKeyIsNotFiltered) { TEST(CharacterComposerTest, PartiallyMatchingSequence) { CharacterComposer character_composer; - // Composition with sequence ['dead acute', '1'] will fail + // Composition with sequence ['dead acute', '1'] will fail. ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute); EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_1)); - EXPECT_TRUE(character_composer.GetComposedCharacter().empty()); + EXPECT_TRUE(character_composer.composed_character().empty()); - // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail + // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail. ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute); ExpectKeyFiltered(&character_composer, GDK_KEY_dead_circumflex); EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_1)); - EXPECT_TRUE(character_composer.GetComposedCharacter().empty()); + EXPECT_TRUE(character_composer.composed_character().empty()); } TEST(CharacterComposerTest, FullyMatchingSequences) { @@ -118,11 +118,11 @@ TEST(CharacterComposerTest, FullyMatchingSequences) { TEST(CharacterComposerTest, FullyMatchingSequencesAfterMatchingFailure) { CharacterComposer character_composer; - // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail + // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail. ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute); ExpectKeyFiltered(&character_composer, GDK_KEY_dead_circumflex); EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_1)); - EXPECT_TRUE(character_composer.GetComposedCharacter().empty()); + EXPECT_TRUE(character_composer.composed_character().empty()); // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_dead_circumflex, GDK_KEY_a, @@ -134,7 +134,7 @@ TEST(CharacterComposerTest, ComposedCharacterIsClearedAfterReset) { ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, string16(1, 0x00E1)); character_composer.Reset(); - EXPECT_TRUE(character_composer.GetComposedCharacter().empty()); + EXPECT_TRUE(character_composer.composed_character().empty()); } TEST(CharacterComposerTest, CompositionStateIsClearedAfterReset) { @@ -144,7 +144,7 @@ TEST(CharacterComposerTest, CompositionStateIsClearedAfterReset) { ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute); character_composer.Reset(); EXPECT_FALSE(character_composer.FilterKeyPress(GDK_KEY_a)); - EXPECT_TRUE(character_composer.GetComposedCharacter().empty()); + EXPECT_TRUE(character_composer.composed_character().empty()); } // ComposeCheckerWithCompactTable in character_composer.cc is depending on the diff --git a/views/ime/input_method_ibus.cc b/views/ime/input_method_ibus.cc index 7fe3e61..d3d4982 100644 --- a/views/ime/input_method_ibus.cc +++ b/views/ime/input_method_ibus.cc @@ -727,7 +727,7 @@ void InputMethodIBus::ProcessUnfilteredKeyPressEvent(const KeyEvent& key, // Process compose and dead keys if (character_composer_.FilterKeyPress(ibus_keyval)) { - string16 composed = character_composer_.GetComposedCharacter(); + string16 composed = character_composer_.composed_character(); if (!composed.empty()) { TextInputClient* client = GetTextInputClient(); if (client) |