summaryrefslogtreecommitdiffstats
path: root/views/ime
diff options
context:
space:
mode:
authorhashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-08 04:32:24 +0000
committerhashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-08 04:32:24 +0000
commit67512c7eb8d859c2b7b22f38cce2d9562ac049ca (patch)
tree29fdaed6d0592fbfe72646494737bfde8eadf589 /views/ime
parente11fc5c84da681143194e9b576ce5c96d86b3e75 (diff)
downloadchromium_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.cc260
-rw-r--r--views/ime/character_composer.h12
-rw-r--r--views/ime/character_composer_unittest.cc36
-rw-r--r--views/ime/input_method_ibus.cc2
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)