Ticket #198: multiple_values.patch
File multiple_values.patch, 13.1 KB (added by , 15 years ago) |
---|
-
xapian-core/tests/internaltest.cc
32 32 33 33 #include <string> 34 34 #include <list> 35 #include <map> 35 36 36 37 using namespace std; 37 38 … … 527 528 return true; 528 529 } 529 530 531 // The C++ standard doesn't specify the ordering of inserts when a key with the 532 // existing value exists, but we want to be able to rely on this. A future C++ 533 // standard is likely to specify that inserts (without a hint) always happen at 534 // the upper_bound of the equal range for the key, and all known 535 // implementations obey this, but we'd better check that whatever 536 // implementation we're compiling with also obeys this. 537 // 538 // See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html 539 static bool test_multimapinsert1() 540 { 541 multimap<int, string> m; 542 vector<string> v; 543 544 int i; 545 for (i = 0; i != 100; ++i) { 546 string val("val"); 547 val += om_tostring(i); 548 v.push_back(val); 549 m.insert(pair<int, string>(3, val)); 550 } 551 552 multimap<int, string>::const_iterator mi; 553 for (i = 1, mi = m.begin(); i != 100; ++i, ++mi) { 554 TEST_EQUAL(v[i], mi.second); 555 } 556 557 return true; 558 } 559 530 560 // ################################################################## 531 561 // # End of actual tests # 532 562 // ################################################################## … … 543 573 {"omstringstream1", test_omstringstream1}, 544 574 {"tostring1", test_tostring1}, 545 575 {"serialisedouble1", test_serialisedouble1}, 576 {"multimapinsert1", test_multimapinsert1}, 546 577 #ifdef XAPIAN_HAS_REMOTE_BACKEND 547 578 {"serialiselength1", test_serialiselength1}, 548 579 {"serialiselength2", test_serialiselength2}, -
xapian-core/include/xapian/document.h
66 66 67 67 /** Get value by number. 68 68 * 69 * Returns an empty string if no value with the given number is present70 * in the document.69 * Returns an empty string if no value with the given number is 70 * present in the document. 71 71 * 72 * If multiple values are present with the given number, this will 73 * only return the first of them. Use values_begin(valueno) to get an 74 * iterator over all such values. 75 * 72 76 * @param valueno The number of the value. 73 77 */ 74 78 std::string get_value(Xapian::valueno valueno) const; 75 79 76 /** Add a new value. It will replace any existing value with the 80 /** Get an iterator over all values with a given number. 81 */ 82 ValueIterator values_begin(Xapian::valueno valueno) const; 83 84 /// End iterator corresponding to values_begin(valueno). 85 ValueIterator values_end(Xapian::valueno valueno) const; 86 87 /** Add a new value. It will replace any existing values with the 77 88 * same number. 78 89 */ 79 90 void add_value(Xapian::valueno valueno, const std::string &value); 80 91 81 /// Remove any value with the given number. 92 /** Append a value. Unlike add_value(), existing values with the same 93 * number will not be replaced. 94 */ 95 void append_value(Xapian::valueno valueno, const std::string &value); 96 97 /// Remove any values with the given number. 82 98 void remove_value(Xapian::valueno valueno); 83 99 84 100 /// Remove all values associated with the document. … … 169 185 return TermIterator(NULL); 170 186 } 171 187 172 /// Count the values in this document. 188 /** Count the values in this document. 189 * 190 * This counts the number of non-empty values held in the document, 191 * which is the same as the number of entries returned by the 192 * values_begin() iterator. This is not the same as the number of 193 * value slots which are used, because multiple values may be stored 194 * in a single slot. 195 */ 173 196 Xapian::termcount values_count() const; 174 197 175 198 /// Iterator for the values in this document. -
xapian-core/include/xapian/valueiterator.h
27 27 #define OM_HGUARD_OMVALUEITERATOR_H 28 28 29 29 #include <iterator> 30 #include <map> 30 31 #include <string> 31 32 #include <xapian/types.h> 32 33 #include <xapian/document.h> … … 42 43 friend bool operator==(const ValueIterator &a, const ValueIterator &b); 43 44 friend bool operator!=(const ValueIterator &a, const ValueIterator &b); 44 45 45 ValueIterator(Xapian::valueno index_, const Document & doc_) 46 : index(index_), doc(doc_) { } 46 ValueIterator(multimap<Xapian::valueno, string>::const_iterator pos_, 47 const Document & doc_) 48 : pos(pos_), doc(doc_) { } 47 49 48 Xapian::valueno index;50 multimap<Xapian::valueno, string>::const_iterator pos; 49 51 Document doc; 50 52 51 53 public: 52 54 /** Create an uninitialised iterator; this cannot be used, but is 53 55 * convenient syntactically. 54 56 */ 55 ValueIterator() : index(0), doc() { }57 ValueIterator() : pos(), doc() { } 56 58 57 59 ~ValueIterator() { } 58 60 59 61 /// Copying is allowed (and is cheap). 60 62 ValueIterator(const ValueIterator &other) { 61 index = other.index;63 pos = other.pos; 62 64 doc = other.doc; 63 65 } 64 66 65 67 /// Assignment is allowed (and is cheap). 66 68 void operator=(const ValueIterator &other) { 67 index = other.index;69 pos = other.pos; 68 70 doc = other.doc; 69 71 } 70 72 71 73 /// Advance the iterator. 72 74 ValueIterator & operator++() { 73 ++ index;75 ++pos; 74 76 return *this; 75 77 } 76 78 77 79 /// Advance the iterator (postfix variant). 78 80 ValueIterator operator++(int) { 79 81 ValueIterator tmp = *this; 80 ++ index;82 ++pos; 81 83 return tmp; 82 84 } 83 85 84 86 /// Get the value for the current position. 85 const std::string & operator*() const; 87 const std::string & operator*() const { 88 return pos->second; 89 } 86 90 87 91 /// Get the value for the current position. 88 const std::string * operator->() const; 92 const std::string * operator->() const { 93 return &(pos->second); 94 } 89 95 90 96 /// Get the number of the value at the current position 91 Xapian::valueno get_valueno() const; 97 Xapian::valueno get_valueno() const { 98 return pos->first; 99 } 92 100 93 101 /** Returns a string describing this object. 94 102 * Introspection method. … … 107 115 108 116 inline bool operator==(const ValueIterator &a, const ValueIterator &b) 109 117 { 110 return (a. index == b.index);118 return (a.pos == b.pos); 111 119 } 112 120 113 121 inline bool operator!=(const ValueIterator &a, const ValueIterator &b) 114 122 { 115 return (a. index != b.index);123 return (a.pos != b.pos); 116 124 } 117 125 118 126 } -
xapian-core/common/document.h
37 37 class Xapian::Document::Internal : public Xapian::Internal::RefCntBase { 38 38 friend class Xapian::ValueIterator; 39 39 public: 40 /// Type to store values in. 41 typedef map<Xapian::valueno, string> document_values; 40 /** Type to store values in. 41 * 42 * Note that we rely on multimaps being stable (ie, preserving the 43 * order of items with equal keys). This is not currently guaranteed 44 * by the standard, but an amendment to guarantee it was accepted for 45 * the working paper in April 2006, and all known implementations 46 * guarantee it. 47 * 48 * See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#371 49 * 50 * We also rely on the insertion order being preserved for items added 51 * without a hint. This is also not currently guaranteed by the 52 * standard, but an amendment to guarantee it was accepted for the 53 * working paper in March 2007, and all known implementations guarantee 54 * it. 55 * 56 * See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233 57 * and 58 * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html 59 * 60 * Note that we cannot rely on insertions using a "hint" iterator to 61 * use the iterator, or to use it in a reliable way. In particular, 62 * some implementations will insert before the hint, and some will 63 * insert after the hint, if the hint points to an existing item with 64 * the specified key. Amendment #233 will standardise this when 65 * adopted, but existing implementations differ on how this is handled. 66 */ 67 typedef multimap<Xapian::valueno, string> document_values; 42 68 43 69 /// Type to store terms in. 44 70 typedef map<string, OmDocumentTerm> document_terms; … … 78 104 private: 79 105 // Functions for backend to implement 80 106 virtual string do_get_value(Xapian::valueno /*valueno*/) const { return ""; } 81 virtual m ap<Xapian::valueno, string> do_get_all_values() const {82 m ap<Xapian::valueno, string> none;107 virtual multimap<Xapian::valueno, string> do_get_all_values() const { 108 multimap<Xapian::valueno, string> none; 83 109 return none; 84 110 } 85 111 virtual string do_get_data() const { return ""; } … … 107 133 * 108 134 * Values are quickly accessible fields, for use during the match 109 135 * operation. Each document may have a set of values, each of which 110 * ha ving a different valueid. Duplicate values with the same valueid111 * are not supported in a single document.136 * has a valueid. Multiple values with the same valueid may be 137 * contained in a single document. 112 138 * 113 * @return A m ap of strings containing all the values.139 * @return A multimap of strings containing all the values. 114 140 */ 115 m ap<Xapian::valueno, string> get_all_values() const;141 multimap<Xapian::valueno, string> get_all_values() const; 116 142 117 143 Xapian::valueno values_count() const; 118 144 void add_value(Xapian::valueno, const string &); 145 void append_value(Xapian::valueno, const string &); 119 146 void remove_value(Xapian::valueno); 120 147 void clear_values(); 121 148 void add_posting(const string &, Xapian::termpos, Xapian::termcount); -
xapian-core/api/omdocument.cc
54 54 RETURN(internal->get_value(value)); 55 55 } 56 56 57 ValueIterator 58 Document::values_begin(Xapian::valueno valueno) const 59 { 60 DEBUGAPICALL(ValueIterator, "Document::values_begin", ""); 61 need_values(); 62 RETURN(ValueIterator(internal->document_values, *this)); 63 } 64 65 ValueIterator 66 Document::values_end(Xapian::valueno valueno) const 67 { 68 DEBUGAPICALL(ValueIterator, "Document::values_end", ""); 69 RETURN(ValueIterator(FIXME, *this)); 70 } 71 72 57 73 string 58 74 Document::get_data() const 59 75 { … … 98 114 } 99 115 100 116 void 117 Document::append_value(Xapian::valueno valueno, const string &value) 118 { 119 DEBUGAPICALL(void, "Document::add_value", valueno << ", " << value); 120 internal->append_value(valueno, value); 121 } 122 123 void 101 124 Document::remove_value(Xapian::valueno valueno) 102 125 { 103 126 DEBUGAPICALL(void, "Document::remove_value", valueno); … … 306 329 void 307 330 Xapian::Document::Internal::add_value(Xapian::valueno valueno, const string &value) 308 331 { 332 FIXME 309 333 need_values(); 310 334 values[valueno] = value; 311 335 value_nos.clear(); 312 336 } 313 337 314 338 void 339 Xapian::Document::Internal::append_value(Xapian::valueno valueno, const string &value) 340 { 341 FIXME 342 need_values(); 343 values[valueno] = value; 344 value_nos.clear(); 345 } 346 347 void 315 348 Xapian::Document::Internal::remove_value(Xapian::valueno valueno) 316 349 { 317 350 need_values(); -
xapian-core/api/omvalueiterator.cc
28 28 29 29 namespace Xapian { 30 30 31 const string &32 ValueIterator::operator *() const33 {34 DEBUGAPICALL(const string &, "ValueIterator::operator*", "");35 Xapian::Internal::RefCntPtr<Xapian::Document::Internal> d(doc.internal);36 if (d->value_nos.empty()) {37 d->value_nos.reserve(d->values.size());38 map<Xapian::valueno, string>::const_iterator i;39 for (i = d->values.begin(); i != d->values.end(); ++i) {40 d->value_nos.push_back(i->first);41 }42 }43 Assert(index < d->value_nos.size());44 RETURN(d->values[d->value_nos[index]]);45 }46 47 const string *48 ValueIterator::operator->() const49 {50 DEBUGAPICALL(const string *, "ValueIterator::operator->", "");51 Xapian::Internal::RefCntPtr<Xapian::Document::Internal> d(doc.internal);52 if (d->value_nos.empty()) {53 d->value_nos.reserve(d->values.size());54 map<Xapian::valueno, string>::const_iterator i;55 for (i = d->values.begin(); i != d->values.end(); ++i) {56 d->value_nos.push_back(i->first);57 }58 }59 Assert(index < d->value_nos.size());60 RETURN(&(d->values[d->value_nos[index]]));61 }62 63 Xapian::valueno64 ValueIterator::get_valueno() const65 {66 DEBUGAPICALL(Xapian::valueno, "ValueIterator::get_valueno", "");67 Xapian::Internal::RefCntPtr<Xapian::Document::Internal> d(doc.internal);68 if (d->value_nos.empty()) {69 d->value_nos.reserve(d->values.size());70 map<Xapian::valueno, string>::const_iterator i;71 for (i = d->values.begin(); i != d->values.end(); ++i) {72 d->value_nos.push_back(i->first);73 }74 }75 Assert(index < d->value_nos.size());76 RETURN(d->value_nos[index]);77 }78 79 31 std::string 80 32 ValueIterator::get_description() const 81 33 {