+
+
+static bool compare_less_than(const pinyin_index_item_t & lhs,
+ const pinyin_index_item_t & rhs){
+ return 0 > strcmp(lhs.m_pinyin_input, rhs.m_pinyin_input);
+}
+
+int FullPinyinParser2::parse_one_key (guint32 options, ChewingKey & key,
+ ChewingKeyRest & key_rest,
+ const char * pinyin, int len) const {
+ /* "'" are not accepted in parse_one_key. */
+ assert(NULL == strchr(pinyin, '\''));
+ gchar * input = g_strndup(pinyin, len);
+
+ guint16 tone = CHEWING_ZERO_TONE; guint16 tone_pos = 0;
+ guint16 parsed_len = len;
+ key = ChewingKey(); key_rest = ChewingKeyRest();
+
+ /* find the tone in the last character. */
+ char chr = input[parsed_len - 1];
+ if ( '0' < chr && chr <= '5' ) {
+ tone = chr - '0';
+ parsed_len --;
+ tone_pos = parsed_len;
+ }
+
+ /* parse pinyin core staff here. */
+ pinyin_index_item_t item;
+ memset(&item, 0, sizeof(item));
+
+ for (; parsed_len > 0; --parsed_len) {
+ input[parsed_len] = '\0';
+ item.m_pinyin_input = input;
+ std_lite::pair<const pinyin_index_item_t *,
+ const pinyin_index_item_t *> range;
+ range = std_lite::equal_range
+ (pinyin_index, pinyin_index + G_N_ELEMENTS(pinyin_index),
+ item, compare_less_than);
+
+ guint16 len = range.second - range.first;
+ assert (len <= 1);
+ if ( len == 1 ) {
+ const pinyin_index_item_t * index = range.first;
+
+ if (!check_pinyin_options(options, index))
+ continue;
+
+ key_rest.m_index = index->m_table_index;
+ key = content_table[key_rest.m_index].m_chewing_key;
+ break;
+ }
+ }
+
+ /* post processing tone. */
+ if ( parsed_len == tone_pos ) {
+ if (tone != CHEWING_ZERO_TONE) {
+ key.m_tone = tone;
+ parsed_len ++;
+ }
+ }
+
+ key_rest.m_raw_begin = 0; key_rest.m_raw_end = parsed_len;
+ g_free(input);
+ return parsed_len;
+}