1 // Copyright (C) 2019 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef ICING_INDEX_HIT_DOC_HIT_INFO_H_ 16 #define ICING_INDEX_HIT_DOC_HIT_INFO_H_ 17 18 #include <limits> 19 20 #include "icing/index/hit/hit.h" 21 #include "icing/legacy/core/icing-packed-pod.h" 22 #include "icing/schema/section.h" 23 #include "icing/store/document-id.h" 24 25 namespace icing { 26 namespace lib { 27 28 // DocHitInfo provides a collapsed view of all hits for a specific doc. 29 // Hits contain a document_id and section_id. The information in multiple hits 30 // is collapse into a DocHitInfo by providing a SectionIdMask of all sections 31 // that contained a hit for this term. 32 class DocHitInfo { 33 public: 34 explicit DocHitInfo(DocumentId document_id_in = kInvalidDocumentId, 35 SectionIdMask hit_section_ids_mask = kSectionIdMaskNone) document_id_(document_id_in)36 : document_id_(document_id_in), 37 hit_section_ids_mask_(hit_section_ids_mask) {} 38 document_id()39 DocumentId document_id() const { return document_id_; } 40 set_document_id(DocumentId document_id)41 void set_document_id(DocumentId document_id) { document_id_ = document_id; } 42 hit_section_ids_mask()43 SectionIdMask hit_section_ids_mask() const { return hit_section_ids_mask_; } 44 set_hit_section_ids_mask(SectionIdMask section_id_mask)45 void set_hit_section_ids_mask(SectionIdMask section_id_mask) { 46 hit_section_ids_mask_ = section_id_mask; 47 } 48 49 bool operator<(const DocHitInfo& other) const { 50 if (document_id() != other.document_id()) { 51 // Sort by document_id descending. This mirrors how the individual hits 52 // that are collapsed into this DocHitInfo would sort with other hits - 53 // document_ids are inverted when encoded in hits. Hits are encoded this 54 // way because they are appended to posting lists and the most recent 55 // value appended to a posting list must have the smallest encoded value 56 // of any hit on the posting list. 57 return document_id() > other.document_id(); 58 } 59 return hit_section_ids_mask() < other.hit_section_ids_mask(); 60 } 61 bool operator==(const DocHitInfo& other) const { 62 return document_id_ == other.document_id_ && 63 hit_section_ids_mask_ == other.hit_section_ids_mask_; 64 } 65 66 // Updates the hit_section_ids_mask for the section, if necessary. UpdateSection(SectionId section_id)67 void UpdateSection(SectionId section_id) { 68 hit_section_ids_mask_ |= (UINT64_C(1) << section_id); 69 } 70 71 // Merges the sections of other into this. The hit_section_ids_masks are or'd. 72 // 73 // This does not affect the DocumentId of this or other. If callers care about 74 // only merging sections for DocHitInfos with the same DocumentId, callers 75 // should check this themselves. MergeSectionsFrom(const SectionIdMask & other_hit_section_ids_mask)76 void MergeSectionsFrom(const SectionIdMask& other_hit_section_ids_mask) { 77 hit_section_ids_mask_ |= other_hit_section_ids_mask; 78 } 79 80 private: 81 DocumentId document_id_; 82 SectionIdMask hit_section_ids_mask_; 83 } __attribute__((packed)); 84 static_assert(sizeof(DocHitInfo) == 12, ""); 85 // TODO(b/138991332) decide how to remove/replace all is_packed_pod assertions. 86 static_assert(icing_is_packed_pod<DocHitInfo>::value, "go/icing-ubsan"); 87 88 } // namespace lib 89 } // namespace icing 90 91 #endif // ICING_INDEX_HIT_DOC_HIT_INFO_H_ 92