DecodeSignal: Sort annotations by start sample and length
authorSoeren Apel <soeren@apelpie.net>
Wed, 22 Apr 2020 17:56:08 +0000 (19:56 +0200)
committerUwe Hermann <uwe@hermann-uwe.de>
Sun, 3 May 2020 15:20:55 +0000 (17:20 +0200)
pv/data/decodesignal.cpp

index 77784de07f84dcdce9431ef03fc634de56aed02e..1de4a3297ef92f53562372d0d29d356b3f86d417 100644 (file)
@@ -1456,10 +1456,39 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa
        // Add the annotation to the row
        const Annotation* ann = row_data.emplace_annotation(pdata);
 
-       // Add the annotation to the global annotation list
+       // We insert the annotation into the global annotation list in a way so that
+       // the annotation list is sorted by start sample and length. Otherwise, we'd
+       // have to sort the model, which is expensive
        deque<const Annotation*>& all_annotations =
                ds->segments_[ds->current_segment_id_].all_annotations;
-       all_annotations.emplace_back(ann);
+
+       if (all_annotations.empty()) {
+               all_annotations.emplace_back(ann);
+       } else {
+               const uint64_t new_ann_len = (pdata->end_sample - pdata->start_sample);
+               bool ann_has_earlier_start = (pdata->start_sample < all_annotations.back()->start_sample());
+               bool ann_is_longer = (new_ann_len >
+                       (all_annotations.back()->end_sample() - all_annotations.back()->start_sample()));
+
+               if (ann_has_earlier_start && ann_is_longer) {
+                       bool ann_has_same_start;
+                       auto it = all_annotations.end();
+
+                       do {
+                               it--;
+                               ann_has_earlier_start = (pdata->start_sample < (*it)->start_sample());
+                               ann_has_same_start = (pdata->start_sample == (*it)->start_sample());
+                               ann_is_longer = (new_ann_len > ((*it)->end_sample() - (*it)->start_sample()));
+                       } while ((ann_has_earlier_start || (ann_has_same_start && ann_is_longer)) && (it != all_annotations.begin()));
+
+                       // Allow inserting at the front
+                       if (it != all_annotations.begin())
+                               it++;
+
+                       all_annotations.emplace(it, ann);
+               } else
+                       all_annotations.emplace_back(ann);
+       }
 
        // When emplace_annotation() inserts instead of appends an annotation,
        // the pointers in all_annotations that follow the inserted annotation and