[aquaskk-changes 278] CVS update: AquaSKK

Tomotaka SUWA t-suw****@users*****
2006年 12月 29日 (金) 00:37:03 JST


Index: AquaSKK/ChangeLog
diff -u AquaSKK/ChangeLog:1.35 AquaSKK/ChangeLog:1.36
--- AquaSKK/ChangeLog:1.35	Thu Dec 28 14:51:45 2006
+++ AquaSKK/ChangeLog	Fri Dec 29 00:37:03 2006
@@ -1,3 +1,11 @@
+2006-12-29  Tomotaka SUWA  <t.suw****@mac*****>
+	
+	* DictionarySet.cpp, SKKDictionary.cpp: 直前の変更を元に戻す。
+
+	* Dictionary.h: std::stringstream では変換候補に含まれる空白が消え
+	てしまうという致命的な欠陥があったため、SKKEntryParser を復活。
+	SKKOkuriHint のバグ修正部分だけは維持。
+
 2006-12-28  Tomotaka SUWA  <t.suw****@mac*****>
 
 	* DictionarySet.cpp, SKKDictionary.cpp: SKKEntry::CreateOkuri* と
Index: AquaSKK/Dictionary.h
diff -u AquaSKK/Dictionary.h:1.6 AquaSKK/Dictionary.h:1.7
--- AquaSKK/Dictionary.h:1.6	Thu Dec 28 14:51:45 2006
+++ AquaSKK/Dictionary.h	Fri Dec 29 00:37:03 2006
@@ -1,5 +1,5 @@
 /* -*- C++ -*-
-  $Id: Dictionary.h,v 1.6 2006/12/28 05:51:45 t-suwa Exp $
+  $Id: Dictionary.h,v 1.7 2006/12/28 15:37:03 t-suwa Exp $
 
   MacOS X implementation of the SKK input method.
 
@@ -26,7 +26,6 @@
 
 #include <vector>
 #include <string>
-#include <sstream>
 #include <numeric>
 
 // ======================================================================
@@ -70,7 +69,7 @@
 #pragma mark -- Utility --
 
 // ======================================================================
-// 連結用ファンクタ
+// オブジェクトを連結するファンクタ
 // ======================================================================
 struct ConcatDescription {
     char delimiter_;
@@ -95,16 +94,42 @@
 };
 
 // ======================================================================
-// 置換ユーティリティ
+// 部分文字列を返していく単純なパーサ
 // ======================================================================
-template<unsigned char target, unsigned char replacement>
-std::string replace_all(const std::string& str) {
-    std::string tmp(str);
+class SKKEntryParser {
+    const std::string& target_;
+    const bool isOkuriAri_;	// 対象が「送りあり」かどうか
+    std::string::size_type pos1_;
+    std::string::size_type pos2_;
+
+    std::string fetch(bool first = false) {
+	if(first) {
+	    pos1_ = pos2_ = 0;
+	}
 
-    std::replace_if(tmp.begin(), tmp.end(), std::bind1st(std::equal_to<unsigned char>(), target), replacement);
+	pos1_ = target_.find_first_not_of('/', pos2_);
+	pos2_ = target_.find_first_of('/', pos1_);
 
-    return tmp;
-}
+	// 見つかった?
+	if(pos1_ != std::string::npos && pos2_ != std::string::npos) {
+	    if(!isOkuriAri_ || target_[pos1_] != '[') {
+		return target_.substr(pos1_, pos2_ - pos1_);
+	    }
+	}
+	return std::string();
+    }
+
+public:
+    SKKEntryParser(const std::string& str, bool isOkuriAri = false) : target_(str), isOkuriAri_(isOkuriAri) {
+	// empty
+    }
+    std::string First() {
+	return fetch(true);
+    }
+    std::string Next() {
+	return fetch();
+    }
+};
 
 // ======================================================================
 // 単一の変換候補(/候補;註釈/ → /word_;annotation_/ → Description())
@@ -127,15 +152,15 @@
     SKKCandidate() : word_(std::string()), annotation_(std::string()) {
 	// empty
     }
-    SKKCandidate(const SKKCandidate& src) : word_(src.word_), annotation_(src.annotation_) {
-	// empty
-    }
     SKKCandidate(const std::string& word, const std::string& annotation) : word_(word), annotation_(annotation) {
 	// empty
     }
     SKKCandidate(const std::string& candidate) {
 	setup(candidate);
     }
+    SKKCandidate(const SKKCandidate& src) : word_(src.word_), annotation_(src.annotation_) {
+	// empty
+    }
 
     bool IsEmpty() const {
 	return word_.empty();
@@ -167,6 +192,16 @@
     SKKCandidateContainer candidates_;
     int pos_;
 
+    void setup(const std::string& str) {
+	std::string ret;
+	SKKEntryParser parser(str);
+
+	kana_ = parser.First();
+	for(ret = parser.Next(); !ret.empty(); ret = parser.Next()) {
+	    candidates_.push_back(ret);
+	}
+    }
+
     SKKCandidate fetchCandidate(bool first = false) {
 	if(first) {
 	    pos_ = 0;
@@ -179,21 +214,18 @@
     }
 
 public:
-    SKKOkuriHint() {}
-    SKKOkuriHint(const SKKOkuriHint& src) : kana_(src.kana_), candidates_(src.candidates_) {}
-    SKKOkuriHint(const std::string& str) {
-	std::stringstream stream(replace_all<'[', ' '>(replace_all<'/', ' '>(replace_all<']', ' '>(str))));
-
-	if(stream >> kana_) {
-	    std::string tmp;
-	    while(stream >> tmp) {
-		candidates_.push_back(tmp);
-	    }
-	}
+    SKKOkuriHint() {
+	// empty
     }
     SKKOkuriHint(const std::string& kana, const SKKCandidate& candidate) : kana_(kana) {
 	candidates_.push_back(candidate);
     }
+    SKKOkuriHint(const std::string& str) {
+	setup(str);
+    }
+    SKKOkuriHint(const SKKOkuriHint& src) : kana_(src.kana_), candidates_(src.candidates_) {
+	// empty
+    }
 
     bool IsEmpty() const {
 	return kana_.empty();
@@ -228,7 +260,6 @@
     void Remove(const SKKCandidate& theCandidate) {
 	candidates_.erase(std::remove(candidates_.begin(), candidates_.end(), theCandidate), candidates_.end());
     }
-
     std::string Description() const {
 	std::string ret;
 
@@ -256,6 +287,7 @@
 // SKK 辞書の一行を表現するクラス
 // ======================================================================
 class SKKEntry {
+    bool isOkuriAri_;		// 送りありかどうか
     std::string key_;		// 見出し語
     SKKCandidateContainer candidates_; // 変換候補
     SKKOkuriHintContainer hints_;      // 送りありエントリのヒント情報
@@ -264,6 +296,38 @@
     int cand_pos_;
     int hint_pos_;
 
+    std::string firstHint(const std::string& str) {
+	pos1_ = pos2_ = str.find("/[");
+	return nextHint(str);
+    }
+    std::string nextHint(const std::string& str) {
+	pos1_ = str.find_first_not_of("/[", pos2_ + 1);
+	pos2_ = str.find_first_of(']', pos1_);
+
+	// 見つかった?
+	if(pos1_ != std::string::npos && pos2_ != std::string::npos) {
+	    return str.substr(pos1_, pos2_ - pos1_);
+	}
+	return std::string();
+    }
+
+    void setup(const std::string& str) {
+	std::string ret;
+	SKKEntryParser parser(str, isOkuriAri_);
+
+	// まず通常の候補を抜き出す
+	for(ret = parser.First(); !ret.empty(); ret = parser.Next()) {
+	    candidates_.push_back(ret);
+	}
+
+	if(!isOkuriAri_) return;
+
+	// 次に、送りありエントリのヒント情報を抜き出す
+	for(ret = firstHint(str); !ret.empty(); ret = nextHint(str)) {
+	    hints_.push_back(ret);
+	}
+    }
+
     SKKCandidate fetchCandidate(bool first = false) {
 	if(first) {
 	    cand_pos_ = 0;
@@ -326,24 +390,35 @@
 
     SKKEntry() {}
 
+    SKKEntry(bool isOkuriAri, const std::string& key, const std::string& cand) : isOkuriAri_(isOkuriAri), key_(key) {
+	setup(cand);
+    }
+
+    SKKEntry(bool isOkuriAri, const std::string& key) : isOkuriAri_(isOkuriAri), key_(key) {
+	// empry
+    }
+
 public:
-    SKKEntry(const std::string& key) : key_(key) {}
-    SKKEntry(const SKKEntry& src) : key_(src.key_), candidates_(src.candidates_), hints_(src.hints_),
-				    pos1_(src.pos1_), pos2_(src.pos2_) {}
-    SKKEntry(const std::string& key, const std::string& candidate) : key_(key) {
-	std::stringstream stream(replace_all<'[', ' '>(candidate));
-	std::string tmp;
-
-	if(stream >> tmp) {
-	    std::stringstream splitter(replace_all<'/', ' '>(tmp));
-	    while(splitter >> tmp) {
-		candidates_.push_back(tmp);
-	    }
+    // 辞書のエントリをパースしてエントリを作成する
+    static SKKEntry ParseOkuriAri(const std::string& key, const std::string& candidate) {
+	return SKKEntry(true, key, candidate);
+    }
+    static SKKEntry ParseOkuriNasi(const std::string& key, const std::string& candidate) {
+	return SKKEntry(false, key, candidate);
+    }
 
-	    while(stream >> tmp) {
-		hints_.push_back(tmp);
-	    }
-	}
+    // キーだけのエントリを作成する
+    static SKKEntry CreateOkuriAri(const std::string& key) {
+	return SKKEntry(true, key);
+    }
+    static SKKEntry CreateOkuriNasi(const std::string& key) {
+	return SKKEntry(false, key);
+    }
+
+    // コピーコンストラクタ
+    SKKEntry(const SKKEntry& src) : isOkuriAri_(src.isOkuriAri_), key_(src.key_),
+	candidates_(src.candidates_), hints_(src.hints_), pos1_(src.pos1_), pos2_(src.pos2_) {
+	// empty
     }
 
     // 候補に関する操作
Index: AquaSKK/DictionarySet.cpp
diff -u AquaSKK/DictionarySet.cpp:1.7 AquaSKK/DictionarySet.cpp:1.8
--- AquaSKK/DictionarySet.cpp:1.7	Thu Dec 28 14:51:45 2006
+++ AquaSKK/DictionarySet.cpp	Fri Dec 29 00:37:03 2006
@@ -1,5 +1,5 @@
 /*
-  $Id: DictionarySet.cpp,v 1.7 2006/12/28 05:51:45 t-suwa Exp $
+  $Id: DictionarySet.cpp,v 1.8 2006/12/28 15:37:03 t-suwa Exp $
 
   MacOS X implementation of the SKK input method.
 
@@ -194,7 +194,7 @@
 }
 
 std::string DictionarySet::FindOkuriAri(const std::string& key, const std::string& okuri, char result_delimiter) {
-    SKKEntry strict_match(key);
+    SKKEntry strict_match = SKKEntry::CreateOkuriAri(key);
     SKKEntry normal_match = strict_match;
 
     for(DictionaryPrefIterator iter = prefs_.begin(); iter != prefs_.end(); ++ iter) {
@@ -210,7 +210,7 @@
 	}
 
 	// 分解
-	SKKEntry entry(key, result);
+	SKKEntry entry = SKKEntry::ParseOkuriAri(key, result);
 
 	// ヒント情報を使う
 	for(SKKOkuriHint hint = entry.FirstHint(); !hint.IsEmpty(); hint = entry.NextHint()) {
@@ -243,7 +243,7 @@
 }
 
 std::string DictionarySet::FindOkuriNasi(const std::string& key, char result_delimiter) {
-    SKKEntry match(key);
+    SKKEntry match = SKKEntry::CreateOkuriNasi(key);
 
     for(DictionaryPrefIterator iter = prefs_.begin(); iter != prefs_.end(); ++ iter) {
 	// グループ辞書の場合、既に候補が見つかっていれば検索をやめる
@@ -258,7 +258,7 @@
 	}
 
 	// 追加
-	match.Add(SKKEntry(key, result));
+	match.Add(SKKEntry::ParseOkuriNasi(key, result));
     }
 
     return match.Join(result_delimiter);
Index: AquaSKK/SKKDictionary.cpp
diff -u AquaSKK/SKKDictionary.cpp:1.14 AquaSKK/SKKDictionary.cpp:1.15
--- AquaSKK/SKKDictionary.cpp:1.14	Thu Dec 28 14:51:45 2006
+++ AquaSKK/SKKDictionary.cpp	Fri Dec 29 00:37:03 2006
@@ -1,5 +1,5 @@
 /*
-  $Id: SKKDictionary.cpp,v 1.14 2006/12/28 05:51:45 t-suwa Exp $
+  $Id: SKKDictionary.cpp,v 1.15 2006/12/28 15:37:03 t-suwa Exp $
 
   MacOS X implementation of the SKK input method.
 
@@ -456,12 +456,12 @@
 }
 
 void SKKUserDictionary::registerOkuriAri(const std::string& index, const std::string& okuri, const std::string& kanji) {
-    SKKEntry entry(index);
+    SKKEntry entry = SKKEntry::CreateOkuriAri(index);
     EntryIterator i = std::find_if(okuriAri_.begin(), okuriAri_.end(), skkdic::UserEntryCompare(index));
 
     // 見つかった?
     if(i != okuriAri_.end()) {
-	entry = SKKEntry(i->first, i->second);
+	entry = SKKEntry::ParseOkuriAri(i->first, i->second);
 	okuriAri_.erase(std::remove(okuriAri_.begin(), okuriAri_.end(), *i), okuriAri_.end());
     }
 
@@ -473,12 +473,12 @@
 }
 
 void SKKUserDictionary::registerOkuriNasi(const std::string& index, const std::string& kanji) {
-    SKKEntry entry(index);
+    SKKEntry entry = SKKEntry::CreateOkuriNasi(index);
     EntryIterator i = std::find_if(okuriNasi_.begin(), okuriNasi_.end(), skkdic::UserEntryCompare(index));
 
     // 見つかった?
     if(i != okuriNasi_.end()) {
-	entry = SKKEntry(i->first, i->second);
+	entry = SKKEntry::ParseOkuriNasi(i->first, i->second);
 	okuriNasi_.erase(std::remove(okuriNasi_.begin(), okuriNasi_.end(), *i), okuriNasi_.end());
     }
 
@@ -497,7 +497,7 @@
 	return;
     }
 
-    SKKEntry entry(i->first, i->second);
+    SKKEntry entry = SKKEntry::ParseOkuriAri(i->first, i->second);
     entry.Remove(SKKCandidate(kanji));
 
     // まだ候補が残っている?
@@ -521,7 +521,7 @@
 	return;
     }
 
-    SKKEntry entry(i->first, i->second);
+    SKKEntry entry = SKKEntry::ParseOkuriNasi(i->first, i->second);
     entry.Remove(SKKCandidate(kanji));
 
     // まだ候補が残っている?


aquaskk-changes メーリングリストの案内